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