1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "@(#)zfs_ioctl.c 1.56 07/12/09 SMI" 27 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/errno.h> 31 #include <sys/uio.h> 32 #include <sys/buf.h> 33 #include <sys/modctl.h> 34 #include <sys/open.h> 35 #include <sys/file.h> 36 #include <sys/kmem.h> 37 #include <sys/conf.h> 38 #include <sys/cmn_err.h> 39 #include <sys/stat.h> 40 #include <sys/zfs_ioctl.h> 41 #include <sys/zfs_znode.h> 42 #include <sys/zap.h> 43 #include <sys/spa.h> 44 #include <sys/spa_impl.h> 45 #include <sys/vdev.h> 46 #include <sys/vdev_impl.h> 47 #include <sys/dmu.h> 48 #include <sys/dsl_dir.h> 49 #include <sys/dsl_dataset.h> 50 #include <sys/dsl_prop.h> 51 #include <sys/dsl_deleg.h> 52 #include <sys/dmu_objset.h> 53 #include <sys/ddi.h> 54 #include <sys/sunddi.h> 55 #include <sys/sunldi.h> 56 #include <sys/policy.h> 57 #include <sys/zone.h> 58 #include <sys/nvpair.h> 59 #include <sys/pathname.h> 60 #include <sys/mount.h> 61 #include <sys/sdt.h> 62 #include <sys/fs/zfs.h> 63 #include <sys/zfs_ctldir.h> 64 #include <sys/zfs_dir.h> 65 #include <sys/zvol.h> 66 #include <sharefs/share.h> 67 #include <sys/dmu_objset.h> 68 69 #include "zfs_namecheck.h" 70 #include "zfs_prop.h" 71 #include "zfs_deleg.h" 72 73 extern struct modlfs zfs_modlfs; 74 75 extern void zfs_init(void); 76 extern void zfs_fini(void); 77 78 ldi_ident_t zfs_li = NULL; 79 dev_info_t *zfs_dip; 80 81 typedef int zfs_ioc_func_t(zfs_cmd_t *); 82 typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 83 84 typedef struct zfs_ioc_vec { 85 zfs_ioc_func_t *zvec_func; 86 zfs_secpolicy_func_t *zvec_secpolicy; 87 enum { 88 NO_NAME, 89 POOL_NAME, 90 DATASET_NAME 91 } zvec_namecheck; 92 boolean_t zvec_his_log; 93 } zfs_ioc_vec_t; 94 95 /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 96 void 97 __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 98 { 99 const char *newfile; 100 char buf[256]; 101 va_list adx; 102 103 /* 104 * Get rid of annoying "../common/" prefix to filename. 105 */ 106 newfile = strrchr(file, '/'); 107 if (newfile != NULL) { 108 newfile = newfile + 1; /* Get rid of leading / */ 109 } else { 110 newfile = file; 111 } 112 113 va_start(adx, fmt); 114 (void) vsnprintf(buf, sizeof (buf), fmt, adx); 115 va_end(adx); 116 117 /* 118 * To get this data, use the zfs-dprintf probe as so: 119 * dtrace -q -n 'zfs-dprintf \ 120 * /stringof(arg0) == "dbuf.c"/ \ 121 * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 122 * arg0 = file name 123 * arg1 = function name 124 * arg2 = line number 125 * arg3 = message 126 */ 127 DTRACE_PROBE4(zfs__dprintf, 128 char *, newfile, char *, func, int, line, char *, buf); 129 } 130 131 static void 132 history_str_free(char *buf) 133 { 134 kmem_free(buf, HIS_MAX_RECORD_LEN); 135 } 136 137 static char * 138 history_str_get(zfs_cmd_t *zc) 139 { 140 char *buf; 141 142 if (zc->zc_history == NULL) 143 return (NULL); 144 145 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 146 if (copyinstr((void *)(uintptr_t)zc->zc_history, 147 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 148 history_str_free(buf); 149 return (NULL); 150 } 151 152 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 153 154 return (buf); 155 } 156 157 /* 158 * zfs_check_version 159 * 160 * Return non-zero if the spa version is less than requested version. 161 */ 162 static int 163 zfs_check_version(const char *name, int version) 164 { 165 166 spa_t *spa; 167 168 if (spa_open(name, &spa, FTAG) == 0) { 169 if (spa_version(spa) < version) { 170 spa_close(spa, FTAG); 171 return (1); 172 } 173 spa_close(spa, FTAG); 174 } 175 return (0); 176 } 177 178 static void 179 zfs_log_history(zfs_cmd_t *zc) 180 { 181 spa_t *spa; 182 char *buf; 183 184 if ((buf = history_str_get(zc)) == NULL) 185 return; 186 187 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 188 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 189 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 190 spa_close(spa, FTAG); 191 } 192 history_str_free(buf); 193 } 194 195 /* 196 * Policy for top-level read operations (list pools). Requires no privileges, 197 * and can be used in the local zone, as there is no associated dataset. 198 */ 199 /* ARGSUSED */ 200 static int 201 zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 202 { 203 return (0); 204 } 205 206 /* 207 * Policy for dataset read operations (list children, get statistics). Requires 208 * no privileges, but must be visible in the local zone. 209 */ 210 /* ARGSUSED */ 211 static int 212 zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 213 { 214 if (INGLOBALZONE(curproc) || 215 zone_dataset_visible(zc->zc_name, NULL)) 216 return (0); 217 218 return (ENOENT); 219 } 220 221 static int 222 zfs_dozonecheck(const char *dataset, cred_t *cr) 223 { 224 uint64_t zoned; 225 int writable = 1; 226 227 /* 228 * The dataset must be visible by this zone -- check this first 229 * so they don't see EPERM on something they shouldn't know about. 230 */ 231 if (!INGLOBALZONE(curproc) && 232 !zone_dataset_visible(dataset, &writable)) 233 return (ENOENT); 234 235 if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 236 return (ENOENT); 237 238 if (INGLOBALZONE(curproc)) { 239 /* 240 * If the fs is zoned, only root can access it from the 241 * global zone. 242 */ 243 if (secpolicy_zfs(cr) && zoned) 244 return (EPERM); 245 } else { 246 /* 247 * If we are in a local zone, the 'zoned' property must be set. 248 */ 249 if (!zoned) 250 return (EPERM); 251 252 /* must be writable by this zone */ 253 if (!writable) 254 return (EPERM); 255 } 256 return (0); 257 } 258 259 int 260 zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 261 { 262 int error; 263 264 error = zfs_dozonecheck(name, cr); 265 if (error == 0) { 266 error = secpolicy_zfs(cr); 267 if (error) 268 error = dsl_deleg_access(name, perm, cr); 269 } 270 return (error); 271 } 272 273 static int 274 zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 275 { 276 /* 277 * Check permissions for special properties. 278 */ 279 switch (prop) { 280 case ZFS_PROP_ZONED: 281 /* 282 * Disallow setting of 'zoned' from within a local zone. 283 */ 284 if (!INGLOBALZONE(curproc)) 285 return (EPERM); 286 break; 287 288 case ZFS_PROP_QUOTA: 289 if (!INGLOBALZONE(curproc)) { 290 uint64_t zoned; 291 char setpoint[MAXNAMELEN]; 292 /* 293 * Unprivileged users are allowed to modify the 294 * quota on things *under* (ie. contained by) 295 * the thing they own. 296 */ 297 if (dsl_prop_get_integer(name, "zoned", &zoned, 298 setpoint)) 299 return (EPERM); 300 if (!zoned || strlen(name) <= strlen(setpoint)) 301 return (EPERM); 302 } 303 break; 304 } 305 306 return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 307 } 308 309 int 310 zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 311 { 312 int error; 313 314 error = zfs_dozonecheck(zc->zc_name, cr); 315 if (error) 316 return (error); 317 318 /* 319 * permission to set permissions will be evaluated later in 320 * dsl_deleg_can_allow() 321 */ 322 return (0); 323 } 324 325 int 326 zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 327 { 328 int error; 329 error = zfs_secpolicy_write_perms(zc->zc_name, 330 ZFS_DELEG_PERM_ROLLBACK, cr); 331 if (error == 0) 332 error = zfs_secpolicy_write_perms(zc->zc_name, 333 ZFS_DELEG_PERM_MOUNT, cr); 334 return (error); 335 } 336 337 int 338 zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 339 { 340 return (zfs_secpolicy_write_perms(zc->zc_name, 341 ZFS_DELEG_PERM_SEND, cr)); 342 } 343 344 int 345 zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 346 { 347 if (!INGLOBALZONE(curproc)) 348 return (EPERM); 349 350 if (secpolicy_nfs(cr) == 0) { 351 return (0); 352 } else { 353 vnode_t *vp; 354 int error; 355 356 if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 357 NO_FOLLOW, NULL, &vp)) != 0) 358 return (error); 359 360 /* Now make sure mntpnt and dataset are ZFS */ 361 362 if (vp->v_vfsp->vfs_fstype != zfsfstype || 363 (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 364 zc->zc_name) != 0)) { 365 VN_RELE(vp); 366 return (EPERM); 367 } 368 369 VN_RELE(vp); 370 return (dsl_deleg_access(zc->zc_name, 371 ZFS_DELEG_PERM_SHARE, cr)); 372 } 373 } 374 375 static int 376 zfs_get_parent(const char *datasetname, char *parent, int parentsize) 377 { 378 char *cp; 379 380 /* 381 * Remove the @bla or /bla from the end of the name to get the parent. 382 */ 383 (void) strncpy(parent, datasetname, parentsize); 384 cp = strrchr(parent, '@'); 385 if (cp != NULL) { 386 cp[0] = '\0'; 387 } else { 388 cp = strrchr(parent, '/'); 389 if (cp == NULL) 390 return (ENOENT); 391 cp[0] = '\0'; 392 } 393 394 return (0); 395 } 396 397 int 398 zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 399 { 400 int error; 401 402 if ((error = zfs_secpolicy_write_perms(name, 403 ZFS_DELEG_PERM_MOUNT, cr)) != 0) 404 return (error); 405 406 return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 407 } 408 409 static int 410 zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 411 { 412 return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 413 } 414 415 /* 416 * Must have sys_config privilege to check the iscsi permission 417 */ 418 /* ARGSUSED */ 419 static int 420 zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 421 { 422 return (secpolicy_zfs(cr)); 423 } 424 425 int 426 zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 427 { 428 char parentname[MAXNAMELEN]; 429 int error; 430 431 if ((error = zfs_secpolicy_write_perms(from, 432 ZFS_DELEG_PERM_RENAME, cr)) != 0) 433 return (error); 434 435 if ((error = zfs_secpolicy_write_perms(from, 436 ZFS_DELEG_PERM_MOUNT, cr)) != 0) 437 return (error); 438 439 if ((error = zfs_get_parent(to, parentname, 440 sizeof (parentname))) != 0) 441 return (error); 442 443 if ((error = zfs_secpolicy_write_perms(parentname, 444 ZFS_DELEG_PERM_CREATE, cr)) != 0) 445 return (error); 446 447 if ((error = zfs_secpolicy_write_perms(parentname, 448 ZFS_DELEG_PERM_MOUNT, cr)) != 0) 449 return (error); 450 451 return (error); 452 } 453 454 static int 455 zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 456 { 457 return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 458 } 459 460 static int 461 zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 462 { 463 char parentname[MAXNAMELEN]; 464 objset_t *clone; 465 int error; 466 467 error = zfs_secpolicy_write_perms(zc->zc_name, 468 ZFS_DELEG_PERM_PROMOTE, cr); 469 if (error) 470 return (error); 471 472 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 473 DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 474 475 if (error == 0) { 476 dsl_dataset_t *pclone = NULL; 477 dsl_dir_t *dd; 478 dd = clone->os->os_dsl_dataset->ds_dir; 479 480 rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 481 error = dsl_dataset_open_obj(dd->dd_pool, 482 dd->dd_phys->dd_origin_obj, NULL, 483 DS_MODE_NONE, FTAG, &pclone); 484 rw_exit(&dd->dd_pool->dp_config_rwlock); 485 if (error) { 486 dmu_objset_close(clone); 487 return (error); 488 } 489 490 error = zfs_secpolicy_write_perms(zc->zc_name, 491 ZFS_DELEG_PERM_MOUNT, cr); 492 493 dsl_dataset_name(pclone, parentname); 494 dmu_objset_close(clone); 495 dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 496 if (error == 0) 497 error = zfs_secpolicy_write_perms(parentname, 498 ZFS_DELEG_PERM_PROMOTE, cr); 499 } 500 return (error); 501 } 502 503 static int 504 zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 505 { 506 int error; 507 508 if ((error = zfs_secpolicy_write_perms(zc->zc_name, 509 ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 510 return (error); 511 512 if ((error = zfs_secpolicy_write_perms(zc->zc_name, 513 ZFS_DELEG_PERM_MOUNT, cr)) != 0) 514 return (error); 515 516 return (zfs_secpolicy_write_perms(zc->zc_name, 517 ZFS_DELEG_PERM_CREATE, cr)); 518 } 519 520 int 521 zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 522 { 523 int error; 524 525 if ((error = zfs_secpolicy_write_perms(name, 526 ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 527 return (error); 528 529 error = zfs_secpolicy_write_perms(name, 530 ZFS_DELEG_PERM_MOUNT, cr); 531 532 return (error); 533 } 534 535 static int 536 zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 537 { 538 539 return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 540 } 541 542 static int 543 zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 544 { 545 char parentname[MAXNAMELEN]; 546 int error; 547 548 if ((error = zfs_get_parent(zc->zc_name, parentname, 549 sizeof (parentname))) != 0) 550 return (error); 551 552 if (zc->zc_value[0] != '\0') { 553 if ((error = zfs_secpolicy_write_perms(zc->zc_value, 554 ZFS_DELEG_PERM_CLONE, cr)) != 0) 555 return (error); 556 } 557 558 if ((error = zfs_secpolicy_write_perms(parentname, 559 ZFS_DELEG_PERM_CREATE, cr)) != 0) 560 return (error); 561 562 error = zfs_secpolicy_write_perms(parentname, 563 ZFS_DELEG_PERM_MOUNT, cr); 564 565 return (error); 566 } 567 568 static int 569 zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 570 { 571 int error; 572 573 error = secpolicy_fs_unmount(cr, NULL); 574 if (error) { 575 error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 576 } 577 return (error); 578 } 579 580 /* 581 * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 582 * SYS_CONFIG privilege, which is not available in a local zone. 583 */ 584 /* ARGSUSED */ 585 static int 586 zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 587 { 588 if (secpolicy_sys_config(cr, B_FALSE) != 0) 589 return (EPERM); 590 591 return (0); 592 } 593 594 /* 595 * Just like zfs_secpolicy_config, except that we will check for 596 * mount permission on the dataset for permission to create/remove 597 * the minor nodes. 598 */ 599 static int 600 zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 601 { 602 if (secpolicy_sys_config(cr, B_FALSE) != 0) { 603 return (dsl_deleg_access(zc->zc_name, 604 ZFS_DELEG_PERM_MOUNT, cr)); 605 } 606 607 return (0); 608 } 609 610 /* 611 * Policy for fault injection. Requires all privileges. 612 */ 613 /* ARGSUSED */ 614 static int 615 zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 616 { 617 return (secpolicy_zinject(cr)); 618 } 619 620 static int 621 zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 622 { 623 zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 624 625 if (prop == ZPROP_INVAL) { 626 if (!zfs_prop_user(zc->zc_value)) 627 return (EINVAL); 628 return (zfs_secpolicy_write_perms(zc->zc_name, 629 ZFS_DELEG_PERM_USERPROP, cr)); 630 } else { 631 if (!zfs_prop_inheritable(prop)) 632 return (EINVAL); 633 return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 634 } 635 } 636 637 /* 638 * Returns the nvlist as specified by the user in the zfs_cmd_t. 639 */ 640 static int 641 get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 642 { 643 char *packed; 644 int error; 645 nvlist_t *list = NULL; 646 647 /* 648 * Read in and unpack the user-supplied nvlist. 649 */ 650 if (size == 0) 651 return (EINVAL); 652 653 packed = kmem_alloc(size, KM_SLEEP); 654 655 if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 656 kmem_free(packed, size); 657 return (error); 658 } 659 660 if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 661 kmem_free(packed, size); 662 return (error); 663 } 664 665 kmem_free(packed, size); 666 667 *nvp = list; 668 return (0); 669 } 670 671 static int 672 put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 673 { 674 char *packed = NULL; 675 size_t size; 676 int error; 677 678 VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 679 680 if (size > zc->zc_nvlist_dst_size) { 681 error = ENOMEM; 682 } else { 683 packed = kmem_alloc(size, KM_SLEEP); 684 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 685 KM_SLEEP) == 0); 686 error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 687 size); 688 kmem_free(packed, size); 689 } 690 691 zc->zc_nvlist_dst_size = size; 692 return (error); 693 } 694 695 static int 696 zfs_ioc_pool_create(zfs_cmd_t *zc) 697 { 698 int error; 699 nvlist_t *config, *props = NULL; 700 char *buf; 701 702 if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 703 &config)) 704 return (error); 705 706 if (zc->zc_nvlist_src_size != 0 && (error = 707 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 708 nvlist_free(config); 709 return (error); 710 } 711 712 buf = history_str_get(zc); 713 714 error = spa_create(zc->zc_name, config, props, buf); 715 716 if (buf != NULL) 717 history_str_free(buf); 718 719 nvlist_free(config); 720 721 if (props) 722 nvlist_free(props); 723 724 return (error); 725 } 726 727 static int 728 zfs_ioc_pool_destroy(zfs_cmd_t *zc) 729 { 730 int error; 731 zfs_log_history(zc); 732 error = spa_destroy(zc->zc_name); 733 return (error); 734 } 735 736 static int 737 zfs_ioc_pool_import(zfs_cmd_t *zc) 738 { 739 int error; 740 nvlist_t *config, *props = NULL; 741 uint64_t guid; 742 743 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 744 &config)) != 0) 745 return (error); 746 747 if (zc->zc_nvlist_src_size != 0 && (error = 748 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 749 nvlist_free(config); 750 return (error); 751 } 752 753 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 754 guid != zc->zc_guid) 755 error = EINVAL; 756 else 757 error = spa_import(zc->zc_name, config, props); 758 759 nvlist_free(config); 760 761 if (props) 762 nvlist_free(props); 763 764 return (error); 765 } 766 767 static int 768 zfs_ioc_pool_export(zfs_cmd_t *zc) 769 { 770 int error; 771 zfs_log_history(zc); 772 error = spa_export(zc->zc_name, NULL); 773 return (error); 774 } 775 776 static int 777 zfs_ioc_pool_configs(zfs_cmd_t *zc) 778 { 779 nvlist_t *configs; 780 int error; 781 782 if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 783 return (EEXIST); 784 785 error = put_nvlist(zc, configs); 786 787 nvlist_free(configs); 788 789 return (error); 790 } 791 792 static int 793 zfs_ioc_pool_stats(zfs_cmd_t *zc) 794 { 795 nvlist_t *config; 796 int error; 797 int ret = 0; 798 799 error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 800 sizeof (zc->zc_value)); 801 802 if (config != NULL) { 803 ret = put_nvlist(zc, config); 804 nvlist_free(config); 805 806 /* 807 * The config may be present even if 'error' is non-zero. 808 * In this case we return success, and preserve the real errno 809 * in 'zc_cookie'. 810 */ 811 zc->zc_cookie = error; 812 } else { 813 ret = error; 814 } 815 816 return (ret); 817 } 818 819 /* 820 * Try to import the given pool, returning pool stats as appropriate so that 821 * user land knows which devices are available and overall pool health. 822 */ 823 static int 824 zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 825 { 826 nvlist_t *tryconfig, *config; 827 int error; 828 829 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 830 &tryconfig)) != 0) 831 return (error); 832 833 config = spa_tryimport(tryconfig); 834 835 nvlist_free(tryconfig); 836 837 if (config == NULL) 838 return (EINVAL); 839 840 error = put_nvlist(zc, config); 841 nvlist_free(config); 842 843 return (error); 844 } 845 846 static int 847 zfs_ioc_pool_scrub(zfs_cmd_t *zc) 848 { 849 spa_t *spa; 850 int error; 851 852 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 853 return (error); 854 855 mutex_enter(&spa_namespace_lock); 856 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 857 mutex_exit(&spa_namespace_lock); 858 859 spa_close(spa, FTAG); 860 861 return (error); 862 } 863 864 static int 865 zfs_ioc_pool_freeze(zfs_cmd_t *zc) 866 { 867 spa_t *spa; 868 int error; 869 870 error = spa_open(zc->zc_name, &spa, FTAG); 871 if (error == 0) { 872 spa_freeze(spa); 873 spa_close(spa, FTAG); 874 } 875 return (error); 876 } 877 878 static int 879 zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 880 { 881 spa_t *spa; 882 int error; 883 884 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 885 return (error); 886 887 if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 888 spa_close(spa, FTAG); 889 return (EINVAL); 890 } 891 892 spa_upgrade(spa, zc->zc_cookie); 893 spa_close(spa, FTAG); 894 895 return (error); 896 } 897 898 static int 899 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 900 { 901 spa_t *spa; 902 char *hist_buf; 903 uint64_t size; 904 int error; 905 906 if ((size = zc->zc_history_len) == 0) 907 return (EINVAL); 908 909 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 910 return (error); 911 912 if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 913 spa_close(spa, FTAG); 914 return (ENOTSUP); 915 } 916 917 hist_buf = kmem_alloc(size, KM_SLEEP); 918 if ((error = spa_history_get(spa, &zc->zc_history_offset, 919 &zc->zc_history_len, hist_buf)) == 0) { 920 error = xcopyout(hist_buf, 921 (char *)(uintptr_t)zc->zc_history, 922 zc->zc_history_len); 923 } 924 925 spa_close(spa, FTAG); 926 kmem_free(hist_buf, size); 927 return (error); 928 } 929 930 static int 931 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 932 { 933 int error; 934 935 if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 936 return (error); 937 938 return (0); 939 } 940 941 static int 942 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 943 { 944 objset_t *osp; 945 int error; 946 947 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 948 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 949 return (error); 950 951 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 952 sizeof (zc->zc_value)); 953 dmu_objset_close(osp); 954 955 return (error); 956 } 957 958 static int 959 zfs_ioc_vdev_add(zfs_cmd_t *zc) 960 { 961 spa_t *spa; 962 int error; 963 nvlist_t *config, **l2cache; 964 uint_t nl2cache; 965 966 error = spa_open(zc->zc_name, &spa, FTAG); 967 if (error != 0) 968 return (error); 969 970 error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 971 &config); 972 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 973 &l2cache, &nl2cache); 974 975 /* 976 * A root pool with concatenated devices is not supported. 977 * Thus, can not add a device to a root pool with one device. 978 * Allow for l2cache devices to be added. 979 */ 980 if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && 981 nl2cache == 0) { 982 spa_close(spa, FTAG); 983 return (EDOM); 984 } 985 986 if (error == 0) { 987 error = spa_vdev_add(spa, config); 988 nvlist_free(config); 989 } 990 spa_close(spa, FTAG); 991 return (error); 992 } 993 994 static int 995 zfs_ioc_vdev_remove(zfs_cmd_t *zc) 996 { 997 spa_t *spa; 998 int error; 999 1000 error = spa_open(zc->zc_name, &spa, FTAG); 1001 if (error != 0) 1002 return (error); 1003 error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 1004 spa_close(spa, FTAG); 1005 return (error); 1006 } 1007 1008 static int 1009 zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1010 { 1011 spa_t *spa; 1012 int error; 1013 vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1014 1015 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1016 return (error); 1017 switch (zc->zc_cookie) { 1018 case VDEV_STATE_ONLINE: 1019 error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 1020 break; 1021 1022 case VDEV_STATE_OFFLINE: 1023 error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 1024 break; 1025 1026 case VDEV_STATE_FAULTED: 1027 error = vdev_fault(spa, zc->zc_guid); 1028 break; 1029 1030 case VDEV_STATE_DEGRADED: 1031 error = vdev_degrade(spa, zc->zc_guid); 1032 break; 1033 1034 default: 1035 error = EINVAL; 1036 } 1037 zc->zc_cookie = newstate; 1038 spa_close(spa, FTAG); 1039 return (error); 1040 } 1041 1042 static int 1043 zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1044 { 1045 spa_t *spa; 1046 int replacing = zc->zc_cookie; 1047 nvlist_t *config; 1048 int error; 1049 1050 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1051 return (error); 1052 1053 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 1054 &config)) == 0) { 1055 error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1056 nvlist_free(config); 1057 } 1058 1059 spa_close(spa, FTAG); 1060 return (error); 1061 } 1062 1063 static int 1064 zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1065 { 1066 spa_t *spa; 1067 int error; 1068 1069 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1070 return (error); 1071 1072 error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1073 1074 spa_close(spa, FTAG); 1075 return (error); 1076 } 1077 1078 static int 1079 zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 1080 { 1081 spa_t *spa; 1082 char *path = zc->zc_value; 1083 uint64_t guid = zc->zc_guid; 1084 int error; 1085 1086 error = spa_open(zc->zc_name, &spa, FTAG); 1087 if (error != 0) 1088 return (error); 1089 1090 error = spa_vdev_setpath(spa, guid, path); 1091 spa_close(spa, FTAG); 1092 return (error); 1093 } 1094 1095 static int 1096 zfs_os_open_retry(char *name, objset_t **os) 1097 { 1098 int error; 1099 1100 retry: 1101 error = dmu_objset_open(name, DMU_OST_ANY, 1102 DS_MODE_STANDARD | DS_MODE_READONLY, os); 1103 if (error != 0) { 1104 /* 1105 * This is ugly: dmu_objset_open() can return EBUSY if 1106 * the objset is held exclusively. Fortunately this hold is 1107 * only for a short while, so we retry here. 1108 * This avoids user code having to handle EBUSY, 1109 * for example for a "zfs list". 1110 */ 1111 if (error == EBUSY) { 1112 delay(1); 1113 goto retry; 1114 } 1115 } 1116 return (error); 1117 } 1118 1119 /* 1120 * inputs: 1121 * zc_name name of filesystem 1122 * zc_nvlist_dst_size size of buffer for property nvlist 1123 * 1124 * outputs: 1125 * zc_objset_stats stats 1126 * zc_nvlist_dst property nvlist 1127 * zc_nvlist_dst_size size of property nvlist 1128 * zc_value alternate root 1129 */ 1130 static int 1131 zfs_ioc_objset_stats(zfs_cmd_t *zc) 1132 { 1133 objset_t *os = NULL; 1134 int error