1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 212082Seschrock 22789Sahrens /* 233377Seschrock * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 293126Sahl #include <alloca.h> 30789Sahrens #include <assert.h> 31789Sahrens #include <ctype.h> 32789Sahrens #include <errno.h> 33789Sahrens #include <devid.h> 343126Sahl #include <dirent.h> 35789Sahrens #include <fcntl.h> 36789Sahrens #include <libintl.h> 37789Sahrens #include <stdio.h> 38789Sahrens #include <stdlib.h> 393126Sahl #include <strings.h> 40789Sahrens #include <unistd.h> 41789Sahrens #include <sys/zfs_ioctl.h> 421544Seschrock #include <sys/zio.h> 432926Sek110237 #include <strings.h> 44789Sahrens 45789Sahrens #include "zfs_namecheck.h" 46*3912Slling #include "zfs_prop.h" 47789Sahrens #include "libzfs_impl.h" 48789Sahrens 49789Sahrens /* 50789Sahrens * Validate the given pool name, optionally putting an extended error message in 51789Sahrens * 'buf'. 52789Sahrens */ 532082Seschrock static boolean_t 542082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 55789Sahrens { 56789Sahrens namecheck_err_t why; 57789Sahrens char what; 581773Seschrock int ret; 59789Sahrens 601773Seschrock ret = pool_namecheck(pool, &why, &what); 611773Seschrock 621773Seschrock /* 631773Seschrock * The rules for reserved pool names were extended at a later point. 641773Seschrock * But we need to support users with existing pools that may now be 651773Seschrock * invalid. So we only check for this expanded set of names during a 661773Seschrock * create (or import), and only in userland. 671773Seschrock */ 681773Seschrock if (ret == 0 && !isopen && 691773Seschrock (strncmp(pool, "mirror", 6) == 0 || 701773Seschrock strncmp(pool, "raidz", 5) == 0 || 711773Seschrock strncmp(pool, "spare", 5) == 0)) { 722082Seschrock zfs_error_aux(hdl, 732082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 742082Seschrock return (B_FALSE); 751773Seschrock } 761773Seschrock 771773Seschrock 781773Seschrock if (ret != 0) { 792082Seschrock if (hdl != NULL) { 80789Sahrens switch (why) { 811003Slling case NAME_ERR_TOOLONG: 822082Seschrock zfs_error_aux(hdl, 831003Slling dgettext(TEXT_DOMAIN, "name is too long")); 841003Slling break; 851003Slling 86789Sahrens case NAME_ERR_INVALCHAR: 872082Seschrock zfs_error_aux(hdl, 88789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 89789Sahrens "'%c' in pool name"), what); 90789Sahrens break; 91789Sahrens 92789Sahrens case NAME_ERR_NOLETTER: 932082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 942082Seschrock "name must begin with a letter")); 95789Sahrens break; 96789Sahrens 97789Sahrens case NAME_ERR_RESERVED: 982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 992082Seschrock "name is reserved")); 100789Sahrens break; 101789Sahrens 102789Sahrens case NAME_ERR_DISKLIKE: 1032082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1042082Seschrock "pool name is reserved")); 105789Sahrens break; 1062856Snd150628 1072856Snd150628 case NAME_ERR_LEADING_SLASH: 1082856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1092856Snd150628 "leading slash in name")); 1102856Snd150628 break; 1112856Snd150628 1122856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 1132856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1142856Snd150628 "empty component in name")); 1152856Snd150628 break; 1162856Snd150628 1172856Snd150628 case NAME_ERR_TRAILING_SLASH: 1182856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1192856Snd150628 "trailing slash in name")); 1202856Snd150628 break; 1212856Snd150628 1222856Snd150628 case NAME_ERR_MULTIPLE_AT: 1232856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1242856Snd150628 "multiple '@' delimiters in name")); 1252856Snd150628 break; 1262856Snd150628 127789Sahrens } 128789Sahrens } 1292082Seschrock return (B_FALSE); 130789Sahrens } 131789Sahrens 1322082Seschrock return (B_TRUE); 133789Sahrens } 134789Sahrens 135*3912Slling static int 136*3912Slling zpool_get_all_props(zpool_handle_t *zhp) 137*3912Slling { 138*3912Slling zfs_cmd_t zc = { 0 }; 139*3912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 140*3912Slling 141*3912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 142*3912Slling 143*3912Slling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 144*3912Slling return (-1); 145*3912Slling 146*3912Slling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 147*3912Slling if (errno == ENOMEM) { 148*3912Slling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 149*3912Slling zcmd_free_nvlists(&zc); 150*3912Slling return (-1); 151*3912Slling } 152*3912Slling } else { 153*3912Slling zcmd_free_nvlists(&zc); 154*3912Slling return (-1); 155*3912Slling } 156*3912Slling } 157*3912Slling 158*3912Slling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 159*3912Slling zcmd_free_nvlists(&zc); 160*3912Slling return (-1); 161*3912Slling } 162*3912Slling 163*3912Slling zcmd_free_nvlists(&zc); 164*3912Slling 165*3912Slling return (0); 166*3912Slling } 167*3912Slling 168789Sahrens /* 169789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 170789Sahrens * state. 171789Sahrens */ 172789Sahrens zpool_handle_t * 1732082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 174789Sahrens { 175789Sahrens zpool_handle_t *zhp; 1762142Seschrock boolean_t missing; 177789Sahrens 178789Sahrens /* 179789Sahrens * Make sure the pool name is valid. 180789Sahrens */ 1812082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 1823237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1832082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1842082Seschrock pool); 185789Sahrens return (NULL); 186789Sahrens } 187789Sahrens 1882082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1892082Seschrock return (NULL); 190789Sahrens 1912082Seschrock zhp->zpool_hdl = hdl; 192789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 193789Sahrens 1942142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1952142Seschrock zpool_close(zhp); 1962142Seschrock return (NULL); 1972142Seschrock } 1982142Seschrock 1992142Seschrock if (missing) { 2002142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2012142Seschrock "no such pool")); 2023237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 2032142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 2042142Seschrock pool); 2052142Seschrock zpool_close(zhp); 2062142Seschrock return (NULL); 207789Sahrens } 208789Sahrens 209789Sahrens return (zhp); 210789Sahrens } 211789Sahrens 212789Sahrens /* 213789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 214789Sahrens * the configuration cache may be out of date). 215789Sahrens */ 2162142Seschrock int 2172142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 218789Sahrens { 219789Sahrens zpool_handle_t *zhp; 2202142Seschrock boolean_t missing; 221789Sahrens 2222142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 2232142Seschrock return (-1); 224789Sahrens 2252082Seschrock zhp->zpool_hdl = hdl; 226789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 227789Sahrens 2282142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2292142Seschrock zpool_close(zhp); 2302142Seschrock return (-1); 231789Sahrens } 232789Sahrens 2332142Seschrock if (missing) { 2342142Seschrock zpool_close(zhp); 2352142Seschrock *ret = NULL; 2362142Seschrock return (0); 2372142Seschrock } 2382142Seschrock 2392142Seschrock *ret = zhp; 2402142Seschrock return (0); 241789Sahrens } 242789Sahrens 243789Sahrens /* 244789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 245789Sahrens * state. 246789Sahrens */ 247789Sahrens zpool_handle_t * 2482082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 249789Sahrens { 250789Sahrens zpool_handle_t *zhp; 251789Sahrens 2522082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 253789Sahrens return (NULL); 254789Sahrens 255789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2563237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 2572082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 258789Sahrens zpool_close(zhp); 259789Sahrens return (NULL); 260789Sahrens } 261789Sahrens 262789Sahrens return (zhp); 263789Sahrens } 264789Sahrens 265789Sahrens /* 266789Sahrens * Close the handle. Simply frees the memory associated with the handle. 267789Sahrens */ 268789Sahrens void 269789Sahrens zpool_close(zpool_handle_t *zhp) 270789Sahrens { 271789Sahrens if (zhp->zpool_config) 272789Sahrens nvlist_free(zhp->zpool_config); 273952Seschrock if (zhp->zpool_old_config) 274952Seschrock nvlist_free(zhp->zpool_old_config); 275*3912Slling if (zhp->zpool_props) 276*3912Slling nvlist_free(zhp->zpool_props); 277789Sahrens free(zhp); 278789Sahrens } 279789Sahrens 280789Sahrens /* 281789Sahrens * Return the name of the pool. 282789Sahrens */ 283789Sahrens const char * 284789Sahrens zpool_get_name(zpool_handle_t *zhp) 285789Sahrens { 286789Sahrens return (zhp->zpool_name); 287789Sahrens } 288789Sahrens 289789Sahrens /* 290789Sahrens * Return the GUID of the pool. 291789Sahrens */ 292789Sahrens uint64_t 293789Sahrens zpool_get_guid(zpool_handle_t *zhp) 294789Sahrens { 295789Sahrens uint64_t guid; 296789Sahrens 297789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 298789Sahrens &guid) == 0); 299789Sahrens return (guid); 300789Sahrens } 301789Sahrens 302789Sahrens /* 3032082Seschrock * Return the version of the pool. 3042082Seschrock */ 3052082Seschrock uint64_t 3062082Seschrock zpool_get_version(zpool_handle_t *zhp) 3072082Seschrock { 3082082Seschrock uint64_t version; 3092082Seschrock 3102082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3112082Seschrock &version) == 0); 3122082Seschrock 3132082Seschrock return (version); 3142082Seschrock } 3152082Seschrock 3162082Seschrock /* 317789Sahrens * Return the amount of space currently consumed by the pool. 318789Sahrens */ 319789Sahrens uint64_t 320789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 321789Sahrens { 322789Sahrens nvlist_t *nvroot; 323789Sahrens vdev_stat_t *vs; 324789Sahrens uint_t vsc; 325789Sahrens 326789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 327789Sahrens &nvroot) == 0); 328789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 329789Sahrens (uint64_t **)&vs, &vsc) == 0); 330789Sahrens 331789Sahrens return (vs->vs_alloc); 332789Sahrens } 333789Sahrens 334789Sahrens /* 335789Sahrens * Return the total space in the pool. 336789Sahrens */ 337789Sahrens uint64_t 338789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 339789Sahrens { 340789Sahrens nvlist_t *nvroot; 341789Sahrens vdev_stat_t *vs; 342789Sahrens uint_t vsc; 343789Sahrens 344789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 345789Sahrens &nvroot) == 0); 346789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 347789Sahrens (uint64_t **)&vs, &vsc) == 0); 348789Sahrens 349789Sahrens return (vs->vs_space); 350789Sahrens } 351789Sahrens 352789Sahrens /* 353789Sahrens * Return the alternate root for this pool, if any. 354789Sahrens */ 355789Sahrens int 356789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 357789Sahrens { 358789Sahrens zfs_cmd_t zc = { 0 }; 359789Sahrens 360789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3612082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3622676Seschrock zc.zc_value[0] == '\0') 363789Sahrens return (-1); 364789Sahrens 3652676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 366789Sahrens 367789Sahrens return (0); 368789Sahrens } 369789Sahrens 370789Sahrens /* 371789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 372789Sahrens */ 373789Sahrens int 374789Sahrens zpool_get_state(zpool_handle_t *zhp) 375789Sahrens { 376789Sahrens return (zhp->zpool_state); 377789Sahrens } 378789Sahrens 379789Sahrens /* 380789Sahrens * Create the named pool, using the provided vdev list. It is assumed 381789Sahrens * that the consumer has already validated the contents of the nvlist, so we 382789Sahrens * don't have to worry about error semantics. 383789Sahrens */ 384789Sahrens int 3852082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3862082Seschrock const char *altroot) 387789Sahrens { 388789Sahrens zfs_cmd_t zc = { 0 }; 3892082Seschrock char msg[1024]; 3902082Seschrock 3912082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3922082Seschrock "cannot create '%s'"), pool); 393789Sahrens 3942082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 3952082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 3962082Seschrock 3972082Seschrock if (altroot != NULL && altroot[0] != '/') 3983237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 3992082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 400789Sahrens 4012676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 402789Sahrens return (-1); 403789Sahrens 404789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 405789Sahrens 406789Sahrens if (altroot != NULL) 4072676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 408789Sahrens 4092082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4102676Seschrock zcmd_free_nvlists(&zc); 4112082Seschrock 412789Sahrens switch (errno) { 413789Sahrens case EBUSY: 414789Sahrens /* 415789Sahrens * This can happen if the user has specified the same 416789Sahrens * device multiple times. We can't reliably detect this 417789Sahrens * until we try to add it and see we already have a 418789Sahrens * label. 419789Sahrens */ 4202082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4212082Seschrock "one or more vdevs refer to the same device")); 4222082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 423789Sahrens 424789Sahrens case EOVERFLOW: 425789Sahrens /* 4262082Seschrock * This occurs when one of the devices is below 427789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 428789Sahrens * device was the problem device since there's no 429789Sahrens * reliable way to determine device size from userland. 430789Sahrens */ 431789Sahrens { 432789Sahrens char buf[64]; 433789Sahrens 434789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 435789Sahrens 4362082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4372082Seschrock "one or more devices is less than the " 4382082Seschrock "minimum size (%s)"), buf); 439789Sahrens } 4402082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 441789Sahrens 442789Sahrens case ENOSPC: 4432082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4442082Seschrock "one or more devices is out of space")); 4452082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 446789Sahrens 447789Sahrens default: 4482082Seschrock return (zpool_standard_error(hdl, errno, msg)); 449789Sahrens } 450789Sahrens } 451789Sahrens 4522676Seschrock zcmd_free_nvlists(&zc); 453789Sahrens 454789Sahrens /* 455789Sahrens * If this is an alternate root pool, then we automatically set the 4562676Seschrock * mountpoint of the root dataset to be '/'. 457789Sahrens */ 458789Sahrens if (altroot != NULL) { 459789Sahrens zfs_handle_t *zhp; 460789Sahrens 4612082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4622676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4632676Seschrock "/") == 0); 464789Sahrens 465789Sahrens zfs_close(zhp); 466789Sahrens } 467789Sahrens 468789Sahrens return (0); 469789Sahrens } 470789Sahrens 471789Sahrens /* 472789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 473789Sahrens * datasets left in the pool. 474789Sahrens */ 475789Sahrens int 476789Sahrens zpool_destroy(zpool_handle_t *zhp) 477789Sahrens { 478789Sahrens zfs_cmd_t zc = { 0 }; 479789Sahrens zfs_handle_t *zfp = NULL; 4802082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4812082Seschrock char msg[1024]; 482789Sahrens 483789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4842082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4852082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 486789Sahrens return (-1); 487789Sahrens 4882856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 489789Sahrens return (-1); 490789Sahrens 491789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 492789Sahrens 4932082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 4942082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4952082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 496789Sahrens 4972082Seschrock if (errno == EROFS) { 4982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4992082Seschrock "one or more devices is read only")); 5002082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5012082Seschrock } else { 5022082Seschrock (void) zpool_standard_error(hdl, errno, msg); 503789Sahrens } 504789Sahrens 505789Sahrens if (zfp) 506789Sahrens zfs_close(zfp); 507789Sahrens return (-1); 508789Sahrens } 509789Sahrens 510789Sahrens if (zfp) { 511789Sahrens remove_mountpoint(zfp); 512789Sahrens zfs_close(zfp); 513789Sahrens } 514789Sahrens 515789Sahrens return (0); 516789Sahrens } 517789Sahrens 518789Sahrens /* 519789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 520789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 521789Sahrens */ 522789Sahrens int 523789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 524789Sahrens { 5252676Seschrock zfs_cmd_t zc = { 0 }; 5262082Seschrock int ret; 5272082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5282082Seschrock char msg[1024]; 5292082Seschrock nvlist_t **spares; 5302082Seschrock uint_t nspares; 5312082Seschrock 5322082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5332082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5342082Seschrock 5352082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5362082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5372082Seschrock &spares, &nspares) == 0) { 5382082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5392082Seschrock "upgraded to add hot spares")); 5402082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5412082Seschrock } 542789Sahrens 5432676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5442082Seschrock return (-1); 545789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 546789Sahrens 5472082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 548789Sahrens switch (errno) { 549789Sahrens case EBUSY: 550789Sahrens /* 551789Sahrens * This can happen if the user has specified the same 552789Sahrens * device multiple times. We can't reliably detect this 553789Sahrens * until we try to add it and see we already have a 554789Sahrens * label. 555789Sahrens */ 5562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5572082Seschrock "one or more vdevs refer to the same device")); 5582082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 559789Sahrens break; 560789Sahrens 561789Sahrens case EOVERFLOW: 562789Sahrens /* 563789Sahrens * This occurrs when one of the devices is below 564789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 565789Sahrens * device was the problem device since there's no 566789Sahrens * reliable way to determine device size from userland. 567789Sahrens */ 568789Sahrens { 569789Sahrens char buf[64]; 570789Sahrens 571789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 572789Sahrens 5732082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5742082Seschrock "device is less than the minimum " 5752082Seschrock "size (%s)"), buf); 576789Sahrens } 5772082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5782082Seschrock break; 5792082Seschrock 5802082Seschrock case ENOTSUP: 5812082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5822082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5832082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 584789Sahrens break; 585789Sahrens 586*3912Slling case EDOM: 587*3912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 588*3912Slling "root pool can not have concatenated devices")); 589*3912Slling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 590*3912Slling break; 591*3912Slling 592789Sahrens default: 5932082Seschrock (void) zpool_standard_error(hdl, errno, msg); 594789Sahrens } 595789Sahrens 5962082Seschrock ret = -1; 5972082Seschrock } else { 5982082Seschrock ret = 0; 599789Sahrens } 600789Sahrens 6012676Seschrock zcmd_free_nvlists(&zc); 602789Sahrens 6032082Seschrock return (ret); 604789Sahrens } 605789Sahrens 606789Sahrens /* 607789Sahrens * Exports the pool from the system. The caller must ensure that there are no 608789Sahrens * mounted datasets in the pool. 609789Sahrens */ 610789Sahrens int 611789Sahrens zpool_export(zpool_handle_t *zhp) 612789Sahrens { 613789Sahrens zfs_cmd_t zc = { 0 }; 614789Sahrens 615789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 616789Sahrens return (-1); 617789Sahrens 618789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 619789Sahrens 6202082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6213237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 6222082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6232082Seschrock zhp->zpool_name)); 624789Sahrens return (0); 625789Sahrens } 626789Sahrens 627789Sahrens /* 628789Sahrens * Import the given pool using the known configuration. The configuration 629789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 630789Sahrens * parameters control whether the pool is imported with a different name or with 631789Sahrens * an alternate root, respectively. 632789Sahrens */ 633789Sahrens int 6342082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6352082Seschrock const char *altroot) 636789Sahrens { 6372676Seschrock zfs_cmd_t zc = { 0 }; 638789Sahrens char *thename; 639789Sahrens char *origname; 640789Sahrens int ret; 641789Sahrens 642789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 643789Sahrens &origname) == 0); 644789Sahrens 645789Sahrens if (newname != NULL) { 6462082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6473237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6482082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6492082Seschrock newname)); 650789Sahrens thename = (char *)newname; 651789Sahrens } else { 652789Sahrens thename = origname; 653789Sahrens } 654789Sahrens 6552082Seschrock if (altroot != NULL && altroot[0] != '/') 6563237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6572082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6582082Seschrock altroot)); 659789Sahrens 660789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 661789Sahrens 662789Sahrens if (altroot != NULL) 6632676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 664789Sahrens else 6652676Seschrock zc.zc_value[0] = '\0'; 666789Sahrens 667789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6681544Seschrock &zc.zc_guid) == 0); 669789Sahrens 6702676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6712082Seschrock return (-1); 672789Sahrens 673789Sahrens ret = 0; 6742082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 675789Sahrens char desc[1024]; 676789Sahrens if (newname == NULL) 677789Sahrens (void) snprintf(desc, sizeof (desc), 678789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 679789Sahrens thename); 680789Sahrens else 681789Sahrens (void) snprintf(desc, sizeof (desc), 682789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 683789Sahrens origname, thename); 684789Sahrens 685789Sahrens switch (errno) { 6861544Seschrock case ENOTSUP: 6871544Seschrock /* 6881544Seschrock * Unsupported version. 6891544Seschrock */ 6902082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6911544Seschrock break; 6921544Seschrock 6932174Seschrock case EINVAL: 6942174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6952174Seschrock break; 6962174Seschrock 697789Sahrens default: 6982082Seschrock (void) zpool_standard_error(hdl, errno, desc); 699789Sahrens } 700789Sahrens 701789Sahrens ret = -1; 702789Sahrens } else { 703789Sahrens zpool_handle_t *zhp; 704789Sahrens /* 705789Sahrens * This should never fail, but play it safe anyway. 706789Sahrens */ 7072142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7082142Seschrock ret = -1; 7092142Seschrock } else if (zhp != NULL) { 710789Sahrens ret = zpool_create_zvol_links(zhp); 711789Sahrens zpool_close(zhp); 712789Sahrens } 713789Sahrens } 714789Sahrens 7152676Seschrock zcmd_free_nvlists(&zc); 716789Sahrens return (ret); 717789Sahrens } 718789Sahrens 719789Sahrens /* 720789Sahrens * Scrub the pool. 721789Sahrens */ 722789Sahrens int 723789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 724789Sahrens { 725789Sahrens zfs_cmd_t zc = { 0 }; 726789Sahrens char msg[1024]; 7272082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 728789Sahrens 729789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 730789Sahrens zc.zc_cookie = type; 731789Sahrens 7322082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 733789Sahrens return (0); 734789Sahrens 735789Sahrens (void) snprintf(msg, sizeof (msg), 736789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 737789Sahrens 7382082Seschrock if (errno == EBUSY) 7392082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7402082Seschrock else 7412082Seschrock return (zpool_standard_error(hdl, errno, msg)); 742789Sahrens } 743789Sahrens 7442468Sek110237 /* 7452468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7462468Sek110237 * spare; but FALSE if its an INUSE spare. 7472468Sek110237 */ 7482082Seschrock static nvlist_t * 7492082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7502468Sek110237 boolean_t *avail_spare) 7511544Seschrock { 7521544Seschrock uint_t c, children; 7531544Seschrock nvlist_t **child; 7542082Seschrock uint64_t theguid, present; 7551544Seschrock char *path; 7561544Seschrock uint64_t wholedisk = 0; 7572082Seschrock nvlist_t *ret; 7581544Seschrock 7592082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7601544Seschrock 7611544Seschrock if (search == NULL && 7621544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7631544Seschrock /* 7641544Seschrock * If the device has never been present since import, the only 7651544Seschrock * reliable way to match the vdev is by GUID. 7661544Seschrock */ 7672082Seschrock if (theguid == guid) 7682082Seschrock return (nv); 7691544Seschrock } else if (search != NULL && 7701544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7711544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7721544Seschrock &wholedisk); 7731544Seschrock if (wholedisk) { 7741544Seschrock /* 7751544Seschrock * For whole disks, the internal path has 's0', but the 7761544Seschrock * path passed in by the user doesn't. 7771544Seschrock */ 7781544Seschrock if (strlen(search) == strlen(path) - 2 && 7791544Seschrock strncmp(search, path, strlen(search)) == 0) 7802082Seschrock return (nv); 7811544Seschrock } else if (strcmp(search, path) == 0) { 7822082Seschrock return (nv); 7831544Seschrock } 7841544Seschrock } 7851544Seschrock 7861544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7871544Seschrock &child, &children) != 0) 7882082Seschrock return (NULL); 7891544Seschrock 7901544Seschrock for (c = 0; c < children; c++) 7912082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7922468Sek110237 avail_spare)) != NULL) 7931544Seschrock return (ret); 7941544Seschrock 7952082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 7962082Seschrock &child, &children) == 0) { 7972082Seschrock for (c = 0; c < children; c++) { 7982082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7992468Sek110237 avail_spare)) != NULL) { 8002468Sek110237 *avail_spare = B_TRUE; 8012082Seschrock return (ret); 8022082Seschrock } 8032082Seschrock } 8042082Seschrock } 8052082Seschrock 8062082Seschrock return (NULL); 8071544Seschrock } 8081544Seschrock 8092082Seschrock nvlist_t * 8102468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8111544Seschrock { 8121544Seschrock char buf[MAXPATHLEN]; 8131544Seschrock const char *search; 8141544Seschrock char *end; 8151544Seschrock nvlist_t *nvroot; 8161544Seschrock uint64_t guid; 8171544Seschrock 8181613Seschrock guid = strtoull(path, &end, 10); 8191544Seschrock if (guid != 0 && *end == '\0') { 8201544Seschrock search = NULL; 8211544Seschrock } else if (path[0] != '/') { 8221544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8231544Seschrock search = buf; 8241544Seschrock } else { 8251544Seschrock search = path; 8261544Seschrock } 8271544Seschrock 8281544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8291544Seschrock &nvroot) == 0); 8301544Seschrock 8312468Sek110237 *avail_spare = B_FALSE; 8322468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8332468Sek110237 } 8342468Sek110237 8352468Sek110237 /* 8362468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8372468Sek110237 */ 8382468Sek110237 static boolean_t 8392468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8402468Sek110237 { 8412468Sek110237 uint64_t spare_guid; 8422468Sek110237 nvlist_t *nvroot; 8432468Sek110237 nvlist_t **spares; 8442468Sek110237 uint_t nspares; 8452468Sek110237 int i; 8462468Sek110237 8472468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8482468Sek110237 &nvroot) == 0); 8492468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8502468Sek110237 &spares, &nspares) == 0) { 8512468Sek110237 for (i = 0; i < nspares; i++) { 8522468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8532468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8542468Sek110237 if (guid == spare_guid) 8552468Sek110237 return (B_TRUE); 8562468Sek110237 } 8572468Sek110237 } 8582468Sek110237 8592468Sek110237 return (B_FALSE); 8601544Seschrock } 8611544Seschrock 862789Sahrens /* 863789Sahrens * Bring the specified vdev online 864789Sahrens */ 865789Sahrens int 866789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 867789Sahrens { 868789Sahrens zfs_cmd_t zc = { 0 }; 869789Sahrens char msg[1024]; 8702082Seschrock nvlist_t *tgt; 8712468Sek110237 boolean_t avail_spare; 8722082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 873789Sahrens 8741544Seschrock (void) snprintf(msg, sizeof (msg), 8751544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 876789Sahrens 8771544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8782468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8792082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 880789Sahrens 8812468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8822468Sek110237 8832468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8842082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8852082Seschrock 8862082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8871544Seschrock return (0); 888789Sahrens 8892082Seschrock return (zpool_standard_error(hdl, errno, msg)); 890789Sahrens } 891789Sahrens 892789Sahrens /* 893789Sahrens * Take the specified vdev offline 894789Sahrens */ 895789Sahrens int 8961485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 897789Sahrens { 898789Sahrens zfs_cmd_t zc = { 0 }; 899789Sahrens char msg[1024]; 9002082Seschrock nvlist_t *tgt; 9012468Sek110237 boolean_t avail_spare; 9022082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 903789Sahrens 9041544Seschrock (void) snprintf(msg, sizeof (msg), 9051544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9061544Seschrock 907789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9082468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9092082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9102082Seschrock 9112468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9122468Sek110237 9132468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9142082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9152082Seschrock 9161485Slling zc.zc_cookie = istmp; 9171485Slling 9182082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 919789Sahrens return (0); 920789Sahrens 921789Sahrens switch (errno) { 9222082Seschrock case EBUSY: 923789Sahrens 924789Sahrens /* 925789Sahrens * There are no other replicas of this device. 926789Sahrens */ 9272082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9282082Seschrock 9292082Seschrock default: 9302082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9312082Seschrock } 9322082Seschrock } 933789Sahrens 9342082Seschrock /* 9352082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 9362082Seschrock * a hot spare. 9372082Seschrock */ 9382082Seschrock static boolean_t 9392082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 9402082Seschrock { 9412082Seschrock nvlist_t **child; 9422082Seschrock uint_t c, children; 9432082Seschrock char *type; 9442082Seschrock 9452082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9462082Seschrock &children) == 0) { 9472082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9482082Seschrock &type) == 0); 9492082Seschrock 9502082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9512082Seschrock children == 2 && child[which] == tgt) 9522082Seschrock return (B_TRUE); 9532082Seschrock 9542082Seschrock for (c = 0; c < children; c++) 9552082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9562082Seschrock return (B_TRUE); 957789Sahrens } 9582082Seschrock 9592082Seschrock return (B_FALSE); 960789Sahrens } 961789Sahrens 962789Sahrens /* 963789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 964789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 965789Sahrens */ 966789Sahrens int 967789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 968789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 969789Sahrens { 970789Sahrens zfs_cmd_t zc = { 0 }; 971789Sahrens char msg[1024]; 972789Sahrens int ret; 9732082Seschrock nvlist_t *tgt; 9742468Sek110237 boolean_t avail_spare; 9752082Seschrock uint64_t val; 9762082Seschrock char *path; 9772082Seschrock nvlist_t **child; 9782082Seschrock uint_t children; 9792082Seschrock nvlist_t *config_root; 9802082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 981789Sahrens 9821544Seschrock if (replacing) 9831544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9841544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9851544Seschrock else 9861544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9871544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9881544Seschrock 989789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9902468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9912082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9922082Seschrock 9932468Sek110237 if (avail_spare) 9942082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9952082Seschrock 9962082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9972082Seschrock zc.zc_cookie = replacing; 9982082Seschrock 9992082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10002082Seschrock &child, &children) != 0 || children != 1) { 10012082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10022082Seschrock "new device must be a single disk")); 10032082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10041544Seschrock } 10052082Seschrock 10062082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10072082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10082082Seschrock 10092082Seschrock /* 10102082Seschrock * If the target is a hot spare that has been swapped in, we can only 10112082Seschrock * replace it with another hot spare. 10122082Seschrock */ 10132082Seschrock if (replacing && 10142082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10152082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10162468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10172468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10182082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10192082Seschrock "can only be replaced by another hot spare")); 10202082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10212082Seschrock } 10222082Seschrock 10232082Seschrock /* 10242082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10252082Seschrock * already spared device. 10262082Seschrock */ 10272082Seschrock if (replacing && 10282082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10292468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10302082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10312082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10322082Seschrock "device has already been replaced with a spare")); 10332082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10342082Seschrock } 1035789Sahrens 10362676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 10372082Seschrock return (-1); 1038789Sahrens 10392082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1040789Sahrens 10412676Seschrock zcmd_free_nvlists(&zc); 1042789Sahrens 1043789Sahrens if (ret == 0) 1044789Sahrens return (0); 1045789Sahrens 1046789Sahrens switch (errno) { 10471544Seschrock case ENOTSUP: 1048789Sahrens /* 1049789Sahrens * Can't attach to or replace this type of vdev. 1050789Sahrens */ 1051789Sahrens if (replacing) 10522082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10532082Seschrock "cannot replace a replacing device")); 1054789Sahrens else 10552082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10562082Seschrock "can only attach to mirrors and top-level " 10572082Seschrock "disks")); 10582082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1059789Sahrens break; 1060789Sahrens 10611544Seschrock case EINVAL: 1062789Sahrens /* 1063789Sahrens * The new device must be a single disk. 1064789Sahrens */ 10652082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10662082Seschrock "new device must be a single disk")); 10672082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1068789Sahrens break; 1069789Sahrens 10701544Seschrock case EBUSY: 10712082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10722082Seschrock new_disk); 10732082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1074789Sahrens break; 1075789Sahrens 10761544Seschrock case EOVERFLOW: 1077789Sahrens /* 1078789Sahrens * The new device is too small. 1079789Sahrens */ 10802082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10812082Seschrock "device is too small")); 10822082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1083789Sahrens break; 1084789Sahrens 10851544Seschrock case EDOM: 1086789Sahrens /* 1087789Sahrens * The new device has a different alignment requirement. 1088789Sahrens */ 10892082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10902082Seschrock "devices have different sector alignment")); 10912082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1092789Sahrens break; 1093789Sahrens 10941544Seschrock case ENAMETOOLONG: 1095789Sahrens /* 1096789Sahrens * The resulting top-level vdev spec won't fit in the label. 1097789Sahrens */ 10982082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1099789Sahrens break; 1100789Sahrens 11011544Seschrock default: 11022082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1103789Sahrens } 1104789Sahrens 11052082Seschrock return (-1); 1106789Sahrens } 1107789Sahrens 1108789Sahrens /* 1109789Sahrens * Detach the specified device. 1110789Sahrens */ 1111789Sahrens int 1112789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1113789Sahrens { 1114789Sahrens zfs_cmd_t zc = { 0 }; 1115789Sahrens char msg[1024]; 11162082Seschrock nvlist_t *tgt; 11172468Sek110237 boolean_t avail_spare; 11182082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1119789Sahrens 11201544Seschrock (void) snprintf(msg, sizeof (msg), 11211544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11221544Seschrock 1123789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11242468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11252082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1126789Sahrens 11272468Sek110237 if (avail_spare) 11282082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11292082Seschrock 11302082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11312082Seschrock 11322082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1133789Sahrens return (0); 1134789Sahrens 1135789Sahrens switch (errno) { 1136789Sahrens 11371544Seschrock case ENOTSUP: 1138789Sahrens /* 1139789Sahrens * Can't detach from this type of vdev. 1140789Sahrens */ 11412082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11422082Seschrock "applicable to mirror and replacing vdevs")); 11432082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1144789Sahrens break; 1145789Sahrens 11461544Seschrock case EBUSY: 1147789Sahrens /* 1148789Sahrens * There are no other replicas of this device. 1149789Sahrens */ 11502082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1151789Sahrens break; 1152789Sahrens 11531544Seschrock default: 11542082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11551544Seschrock } 11561544Seschrock 11572082Seschrock return (-1); 11582082Seschrock } 11592082Seschrock 11602082Seschrock /* 11612082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11622082Seschrock */ 11632082Seschrock int 11642082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11652082Seschrock { 11662082Seschrock zfs_cmd_t zc = { 0 }; 11672082Seschrock char msg[1024]; 11682082Seschrock nvlist_t *tgt; 11692468Sek110237 boolean_t avail_spare; 11702082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11712082Seschrock 11722082Seschrock (void) snprintf(msg, sizeof (msg), 11732082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11742082Seschrock 11752082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11762468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11772082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11782082Seschrock 11792468Sek110237 if (!avail_spare) { 11802082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11813377Seschrock "only inactive hot spares can be removed")); 11822082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11832082Seschrock } 11842082Seschrock 11852082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11862082Seschrock 11872082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11882082Seschrock return (0); 11892082Seschrock 11902082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11911544Seschrock } 11921544Seschrock 11931544Seschrock /* 11941544Seschrock * Clear the errors for the pool, or the particular device if specified. 11951544Seschrock */ 11961544Seschrock int 11971544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 11981544Seschrock { 11991544Seschrock zfs_cmd_t zc = { 0 }; 12001544Seschrock char msg[1024]; 12012082Seschrock nvlist_t *tgt; 12022468Sek110237 boolean_t avail_spare; 12032082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12041544Seschrock 12051544Seschrock if (path) 12061544Seschrock (void) snprintf(msg, sizeof (msg), 12071544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12082676Seschrock path); 12091544Seschrock else 12101544Seschrock (void) snprintf(msg, sizeof (msg), 12111544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12121544Seschrock zhp->zpool_name); 12131544Seschrock 12141544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12152082Seschrock if (path) { 12162468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12172082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12182082Seschrock 12192468Sek110237 if (avail_spare) 12202082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12212082Seschrock 12222082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12232082Seschrock &zc.zc_guid) == 0); 12241544Seschrock } 12251544Seschrock 12262082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12271544Seschrock return (0); 12281544Seschrock 12292082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1230789Sahrens } 1231789Sahrens 12323126Sahl /* 12333126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 12343126Sahl * hierarchy. 12353126Sahl */ 12363126Sahl int 12373126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 12383126Sahl void *data) 1239789Sahrens { 12403126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 12413126Sahl char (*paths)[MAXPATHLEN]; 12423126Sahl size_t size = 4; 12433126Sahl int curr, fd, base, ret = 0; 12443126Sahl DIR *dirp; 12453126Sahl struct dirent *dp; 12463126Sahl struct stat st; 12473126Sahl 12483126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 12493126Sahl return (errno == ENOENT ? 0 : -1); 12503126Sahl 12513126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 12523126Sahl int err = errno; 12533126Sahl (void) close(base); 12543126Sahl return (err == ENOENT ? 0 : -1); 12553126Sahl } 1256789Sahrens 1257789Sahrens /* 12583126Sahl * Oddly this wasn't a directory -- ignore that failure since we 12593126Sahl * know there are no links lower in the (non-existant) hierarchy. 1260789Sahrens */ 12613126Sahl if (!S_ISDIR(st.st_mode)) { 12623126Sahl (void) close(base); 12633126Sahl return (0); 12643126Sahl } 12653126Sahl 12663126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 12673126Sahl (void) close(base); 12683126Sahl return (-1); 1269789Sahrens } 1270789Sahrens 12713126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 12723126Sahl curr = 0; 12733126Sahl 12743126Sahl while (curr >= 0) { 12753126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 12763126Sahl goto err; 12773126Sahl 12783126Sahl if (S_ISDIR(st.st_mode)) { 12793126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 12803126Sahl goto err; 12813126Sahl 12823126Sahl if ((dirp = fdopendir(fd)) == NULL) { 12833126Sahl (void) close(fd); 12843126Sahl goto err; 12853126Sahl } 12863126Sahl 12873126Sahl while ((dp = readdir(dirp)) != NULL) { 12883126Sahl if (dp->d_name[0] == '.') 12893126Sahl continue; 12903126Sahl 12913126Sahl if (curr + 1 == size) { 12923126Sahl paths = zfs_realloc(hdl, paths, 12933126Sahl size * sizeof (paths[0]), 12943126Sahl size * 2 * sizeof (paths[0])); 12953126Sahl if (paths == NULL) { 12963126Sahl (void) closedir(dirp); 12973126Sahl (void) close(fd); 12983126Sahl goto err; 12993126Sahl } 13003126Sahl 13013126Sahl size *= 2; 13023126Sahl } 13033126Sahl 13043126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 13053126Sahl sizeof (paths[curr + 1])); 13063126Sahl (void) strlcat(paths[curr], "/", 13073126Sahl sizeof (paths[curr])); 13083126Sahl (void) strlcat(paths[curr], dp->d_name, 13093126Sahl sizeof (paths[curr])); 13103126Sahl curr++; 13113126Sahl } 13123126Sahl 13133126Sahl (void) closedir(dirp); 13143126Sahl 13153126Sahl } else { 13163126Sahl if ((ret = cb(paths[curr], data)) != 0) 13173126Sahl break; 13183126Sahl } 13193126Sahl 13203126Sahl curr--; 13213126Sahl } 13223126Sahl 13233126Sahl free(paths); 13243126Sahl (void) close(base); 13253126Sahl 13263126Sahl return (ret); 13273126Sahl 13283126Sahl err: 13293126Sahl free(paths); 13303126Sahl (void) close(base); 13313126Sahl return (-1); 13323126Sahl } 13333126Sahl 13343126Sahl typedef struct zvol_cb { 13353126Sahl zpool_handle_t *zcb_pool; 13363126Sahl boolean_t zcb_create; 13373126Sahl } zvol_cb_t; 13383126Sahl 13393126Sahl /*ARGSUSED*/ 13403126Sahl static int 13413126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 13423126Sahl { 13433126Sahl int ret; 13443126Sahl 13453126Sahl if (ZFS_IS_VOLUME(zhp)) 13463126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 13473126Sahl 13483126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1349789Sahrens 1350789Sahrens zfs_close(zhp); 13513126Sahl 1352789Sahrens return (ret); 1353789Sahrens } 1354789Sahrens 1355789Sahrens /* 1356789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1357789Sahrens */ 1358789Sahrens int 1359789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1360789Sahrens { 1361789Sahrens zfs_handle_t *zfp; 1362789Sahrens int ret; 1363789Sahrens 1364789Sahrens /* 1365789Sahrens * If the pool is unavailable, just return success. 1366789Sahrens */ 13672082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 13682082Seschrock zhp->zpool_name)) == NULL) 1369789Sahrens return (0); 1370789Sahrens 13713126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1372789Sahrens 1373789Sahrens zfs_close(zfp); 1374789Sahrens return (ret); 1375789Sahrens } 1376789Sahrens 13773126Sahl static int 13783126Sahl do_zvol_remove(const char *dataset, void *data) 13793126Sahl { 13803126Sahl zpool_handle_t *zhp = data; 13813126Sahl 13823126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 13833126Sahl } 13843126Sahl 1385789Sahrens /* 13863126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 13873126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 13883126Sahl * operation. 1389789Sahrens */ 1390789Sahrens int 1391789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1392789Sahrens { 13933126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1394789Sahrens } 13951354Seschrock 13961354Seschrock /* 13971354Seschrock * Convert from a devid string to a path. 13981354Seschrock */ 13991354Seschrock static char * 14001354Seschrock devid_to_path(char *devid_str) 14011354Seschrock { 14021354Seschrock ddi_devid_t devid; 14031354Seschrock char *minor; 14041354Seschrock char *path; 14051354Seschrock devid_nmlist_t *list = NULL; 14061354Seschrock int ret; 14071354Seschrock 14081354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 14091354Seschrock return (NULL); 14101354Seschrock 14111354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 14121354Seschrock 14131354Seschrock devid_str_free(minor); 14141354Seschrock devid_free(devid); 14151354Seschrock 14161354Seschrock if (ret != 0) 14171354Seschrock return (NULL); 14181354Seschrock 14192082Seschrock if ((path = strdup(list[0].devname)) == NULL) 14202082Seschrock return (NULL); 14212082Seschrock 14221354Seschrock devid_free_nmlist(list); 14231354Seschrock 14241354Seschrock return (path); 14251354Seschrock } 14261354Seschrock 14271354Seschrock /* 14281354Seschrock * Convert from a path to a devid string. 14291354Seschrock */ 14301354Seschrock static char * 14311354Seschrock path_to_devid(const char *path) 14321354Seschrock { 14331354Seschrock int fd; 14341354Seschrock ddi_devid_t devid; 14351354Seschrock char *minor, *ret; 14361354Seschrock 14371354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 14381354Seschrock return (NULL); 14391354Seschrock 14401354Seschrock minor = NULL; 14411354Seschrock ret = NULL; 14421354Seschrock if (devid_get(fd, &devid) == 0) { 14431354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 14441354Seschrock ret = devid_str_encode(devid, minor); 14451354Seschrock if (minor != NULL) 14461354Seschrock devid_str_free(minor); 14471354Seschrock devid_free(devid); 14481354Seschrock } 14491354Seschrock (void) close(fd); 14501354Seschrock 14511354Seschrock return (ret); 14521354Seschrock } 14531354Seschrock 14541354Seschrock /* 14551354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 14561354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 14571354Seschrock * type 'zpool status', and we'll display the correct information anyway. 14581354Seschrock */ 14591354Seschrock static void 14601354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 14611354Seschrock { 14621354Seschrock zfs_cmd_t zc = { 0 }; 14631354Seschrock 14641354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14652676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 14661354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14671544Seschrock &zc.zc_guid) == 0); 14681354Seschrock 14692082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 14701354Seschrock } 14711354Seschrock 14721354Seschrock /* 14731354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 14741354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 14751354Seschrock * We also check if this is a whole disk, in which case we strip off the 14761354Seschrock * trailing 's0' slice name. 14771354Seschrock * 14781354Seschrock * This routine is also responsible for identifying when disks have been 14791354Seschrock * reconfigured in a new location. The kernel will have opened the device by 14801354Seschrock * devid, but the path will still refer to the old location. To catch this, we 14811354Seschrock * first do a path -> devid translation (which is fast for the common case). If 14821354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 14831354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 14841354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 14851354Seschrock * of these checks. 14861354Seschrock */ 14871354Seschrock char * 14882082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 14891354Seschrock { 14901354Seschrock char *path, *devid; 14911544Seschrock uint64_t value; 14921544Seschrock char buf[64]; 14931354Seschrock 14941544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14951544Seschrock &value) == 0) { 14961544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14971544Seschrock &value) == 0); 14982856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 14992856Snd150628 (u_longlong_t)value); 15001544Seschrock path = buf; 15011544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 15021354Seschrock 15031354Seschrock if (zhp != NULL && 15041354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 15051354Seschrock /* 15061354Seschrock * Determine if the current path is correct. 15071354Seschrock */ 15081354Seschrock char *newdevid = path_to_devid(path); 15091354Seschrock 15101354Seschrock if (newdevid == NULL || 15111354Seschrock strcmp(devid, newdevid) != 0) { 15121354Seschrock char *newpath; 15131354Seschrock 15141354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 15151354Seschrock /* 15161354Seschrock * Update the path appropriately. 15171354Seschrock */ 15181354Seschrock set_path(zhp, nv, newpath); 15192082Seschrock if (nvlist_add_string(nv, 15202082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 15212082Seschrock verify(nvlist_lookup_string(nv, 15222082Seschrock ZPOOL_CONFIG_PATH, 15232082Seschrock &path) == 0); 15241354Seschrock free(newpath); 15251354Seschrock } 15261354Seschrock } 15271354Seschrock 15282082Seschrock if (newdevid) 15292082Seschrock devid_str_free(newdevid); 15301354Seschrock } 15311354Seschrock 15321354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 15331354Seschrock path += 9; 15341354Seschrock 15351354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 15361544Seschrock &value) == 0 && value) { 15372082Seschrock char *tmp = zfs_strdup(hdl, path); 15382082Seschrock if (tmp == NULL) 15392082Seschrock return (NULL); 15401354Seschrock tmp[strlen(path) - 2] = '\0'; 15411354Seschrock return (tmp); 15421354Seschrock } 15431354Seschrock } else { 15441354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 15452082Seschrock 15462082Seschrock /* 15472082Seschrock * If it's a raidz device, we need to stick in the parity level. 15482082Seschrock */ 15492082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 15502082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 15512082Seschrock &value) == 0); 15522082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 15532856Snd150628 (u_longlong_t)value); 15542082Seschrock path = buf; 15552082Seschrock } 15561354Seschrock } 15571354Seschrock 15582082Seschrock return (zfs_strdup(hdl, path)); 15591354Seschrock } 15601544Seschrock 15611544Seschrock static int 15621544Seschrock zbookmark_compare(const void *a, const void *b) 15631544Seschrock { 15641544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 15651544Seschrock } 15661544Seschrock 15671544Seschrock /* 15681544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 15691544Seschrock * caller. 15701544Seschrock */ 15711544Seschrock int 15723444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 15731544Seschrock { 15741544Seschrock zfs_cmd_t zc = { 0 }; 15751544Seschrock uint64_t count; 15762676Seschrock zbookmark_t *zb = NULL; 15773444Sek110237 int i; 15781544Seschrock 15791544Seschrock /* 15801544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 15811544Seschrock * has increased, allocate more space and continue until we get the 15821544Seschrock * entire list. 15831544Seschrock */ 15841544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 15851544Seschrock &count) == 0); 15862676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 15872856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 15882082Seschrock return (-1); 15892676Seschrock zc.zc_nvlist_dst_size = count; 15901544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15911544Seschrock for (;;) { 15922082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 15932082Seschrock &zc) != 0) { 15942676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15951544Seschrock if (errno == ENOMEM) { 15963823Svb160487 count = zc.zc_nvlist_dst_size; 15972676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 15983823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 15993823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 16002082Seschrock return (-1); 16011544Seschrock } else { 16021544Seschrock return (-1); 16031544Seschrock } 16041544Seschrock } else { 16051544Seschrock break; 16061544Seschrock } 16071544Seschrock } 16081544Seschrock 16091544Seschrock /* 16101544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 16111544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 16122676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 16131544Seschrock * _not_ copied as part of the process. So we point the start of our 16141544Seschrock * array appropriate and decrement the total number of elements. 16151544Seschrock */ 16162676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 16172676Seschrock zc.zc_nvlist_dst_size; 16182676Seschrock count -= zc.zc_nvlist_dst_size; 16191544Seschrock 16201544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 16211544Seschrock 16223444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 16231544Seschrock 16241544Seschrock /* 16253444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 16261544Seschrock */ 16271544Seschrock for (i = 0; i < count; i++) { 16281544Seschrock nvlist_t *nv; 16291544Seschrock 16303700Sek110237 /* ignoring zb_blkid and zb_level for now */ 16313700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 16323700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 16331544Seschrock continue; 16341544Seschrock 16353444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 16363444Sek110237 goto nomem; 16373444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 16383444Sek110237 zb[i].zb_objset) != 0) { 16393444Sek110237 nvlist_free(nv); 16402082Seschrock goto nomem; 16413444Sek110237 } 16423444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 16433444Sek110237 zb[i].zb_object) != 0) { 16443444Sek110237 nvlist_free(nv); 16453444Sek110237 goto nomem; 16461544Seschrock } 16473444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 16483444Sek110237 nvlist_free(nv); 16493444Sek110237 goto nomem; 16503444Sek110237 } 16513444Sek110237 nvlist_free(nv); 16521544Seschrock } 16531544Seschrock 16543265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 16551544Seschrock return (0); 16562082Seschrock 16572082Seschrock nomem: 16582676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16592082Seschrock return (no_memory(zhp->zpool_hdl)); 16601544Seschrock } 16611760Seschrock 16621760Seschrock /* 16631760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16641760Seschrock */ 16651760Seschrock int 16661760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16671760Seschrock { 16681760Seschrock zfs_cmd_t zc = { 0 }; 16692082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16701760Seschrock 16711760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16722082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 16733237Slling return (zpool_standard_error_fmt(hdl, errno, 16742082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 16752082Seschrock zhp->zpool_name)); 16761760Seschrock 16771760Seschrock return (0); 16781760Seschrock } 16792926Sek110237 16802926Sek110237 /* 16812926Sek110237 * Log command history. 16822926Sek110237 * 16832926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 16842926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 16852926Sek110237 * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the 16862926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 16872926Sek110237 */ 16882926Sek110237 void 16892926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 1690*3912Slling boolean_t pool, boolean_t pool_create) 16912926Sek110237 { 16922926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 16932926Sek110237 char *dspath; 16942926Sek110237 zfs_cmd_t zc = { 0 }; 16952926Sek110237 int i; 16962926Sek110237 16972926Sek110237 /* construct the command string */ 16982926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 16992926Sek110237 for (i = 0; i < argc; i++) { 17002926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 17012926Sek110237 break; 17022926Sek110237 (void) strcat(cmd_buf, " "); 17032926Sek110237 (void) strcat(cmd_buf, argv[i]); 17042926Sek110237 } 17052926Sek110237 17062926Sek110237 /* figure out the poolname */ 17072926Sek110237 dspath = strpbrk(path, "/@"); 17082926Sek110237 if (dspath == NULL) { 17092926Sek110237 (void) strcpy(zc.zc_name, path); 17102926Sek110237 } else { 17112926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 17122926Sek110237 zc.zc_name[dspath-path] = '\0'; 17132926Sek110237 } 17142926Sek110237 17152926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 17162926Sek110237 zc.zc_history_len = strlen(cmd_buf); 17172926Sek110237 17182926Sek110237 /* overloading zc_history_offset */ 17192926Sek110237 zc.zc_history_offset = pool_create; 17202926Sek110237 17212926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 17222926Sek110237 } 17232926Sek110237 17242926Sek110237 /* 17252926Sek110237 * Perform ioctl to get some command history of a pool. 17262926Sek110237 * 17272926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 17282926Sek110237 * logical offset of the history buffer to start reading from. 17292926Sek110237 * 17302926Sek110237 * Upon return, 'off' is the next logical offset to read from and 17312926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 17322926Sek110237 */ 17332926Sek110237 static int 17342926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 17352926Sek110237 { 17362926Sek110237 zfs_cmd_t zc = { 0 }; 17372926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 17382926Sek110237 17392926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 17402926Sek110237 17412926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 17422926Sek110237 zc.zc_history_len = *len; 17432926Sek110237 zc.zc_history_offset = *off; 17442926Sek110237 17452926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 17462926Sek110237 switch (errno) { 17472926Sek110237 case EPERM: 17483237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 17493237Slling dgettext(TEXT_DOMAIN, 17502926Sek110237 "cannot show history for pool '%s'"), 17512926Sek110237 zhp->zpool_name)); 17522926Sek110237 case ENOENT: 17533237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 17542926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 17552926Sek110237 "'%s'"), zhp->zpool_name)); 17563863Sek110237 case ENOTSUP: 17573863Sek110237 return (zfs_error_fmt(hdl, EZFS_BADVERSION, 17583863Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 17593863Sek110237 "'%s', pool must be upgraded"), zhp->zpool_name)); 17602926Sek110237 default: 17613237Slling return (zpool_standard_error_fmt(hdl, errno, 17622926Sek110237 dgettext(TEXT_DOMAIN, 17632926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 17642926Sek110237 } 17652926Sek110237 } 17662926Sek110237 17672926Sek110237 *len = zc.zc_history_len; 17682926Sek110237 *off = zc.zc_history_offset; 17692926Sek110237 17702926Sek110237 return (0); 17712926Sek110237 } 17722926Sek110237 17732926Sek110237 /* 17742926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 17752926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 17762926Sek110237 * processed as there wasn't a complete record. 17772926Sek110237 */ 17782926Sek110237 static int 17792926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 17802926Sek110237 nvlist_t ***records, uint_t *numrecords) 17812926Sek110237 { 17822926Sek110237 uint64_t reclen; 17832926Sek110237 nvlist_t *nv; 17842926Sek110237 int i; 17852926Sek110237 17862926Sek110237 while (bytes_read > sizeof (reclen)) { 17872926Sek110237 17882926Sek110237 /* get length of packed record (stored as little endian) */ 17892926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 17902926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 17912926Sek110237 17922926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 17932926Sek110237 break; 17942926Sek110237 17952926Sek110237 /* unpack record */ 17962926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 17972926Sek110237 return (ENOMEM); 17982926Sek110237 bytes_read -= sizeof (reclen) + reclen; 17992926Sek110237 buf += sizeof (reclen) + reclen; 18002926Sek110237 18012926Sek110237 /* add record to nvlist array */ 18022926Sek110237 (*numrecords)++; 18032926Sek110237 if (ISP2(*numrecords + 1)) { 18042926Sek110237 *records = realloc(*records, 18052926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 18062926Sek110237 } 18072926Sek110237 (*records)[*numrecords - 1] = nv; 18082926Sek110237 } 18092926Sek110237 18102926Sek110237 *leftover = bytes_read; 18112926Sek110237 return (0); 18122926Sek110237 } 18132926Sek110237 18142926Sek110237 #define HIS_BUF_LEN (128*1024) 18152926Sek110237 18162926Sek110237 /* 18172926Sek110237 * Retrieve the command history of a pool. 18182926Sek110237 */ 18192926Sek110237 int 18202926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 18212926Sek110237 { 18222926Sek110237 char buf[HIS_BUF_LEN]; 18232926Sek110237 uint64_t off = 0; 18242926Sek110237 nvlist_t **records = NULL; 18252926Sek110237 uint_t numrecords = 0; 18262926Sek110237 int err, i; 18272926Sek110237 18282926Sek110237 do { 18292926Sek110237 uint64_t bytes_read = sizeof (buf); 18302926Sek110237 uint64_t leftover; 18312926Sek110237 18322926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 18332926Sek110237 break; 18342926Sek110237 18352926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 18362926Sek110237 if (!bytes_read) 18372926Sek110237 break; 18382926Sek110237 18392926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 18402926Sek110237 &leftover, &records, &numrecords)) != 0) 18412926Sek110237 break; 18422926Sek110237 off -= leftover; 18432926Sek110237 18442926Sek110237 /* CONSTCOND */ 18452926Sek110237 } while (1); 18462926Sek110237 18472926Sek110237 if (!err) { 18482926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 18492926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 18502926Sek110237 records, numrecords) == 0); 18512926Sek110237 } 18522926Sek110237 for (i = 0; i < numrecords; i++) 18532926Sek110237 nvlist_free(records[i]); 18542926Sek110237 free(records); 18552926Sek110237 18562926Sek110237 return (err); 18572926Sek110237 } 18583444Sek110237 18593444Sek110237 void 18603444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 18613444Sek110237 char *pathname, size_t len) 18623444Sek110237 { 18633444Sek110237 zfs_cmd_t zc = { 0 }; 18643444Sek110237 boolean_t mounted = B_FALSE; 18653444Sek110237 char *mntpnt = NULL; 18663444Sek110237 char dsname[MAXNAMELEN]; 18673444Sek110237 18683444Sek110237 if (dsobj == 0) { 18693444Sek110237 /* special case for the MOS */ 18703444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 18713444Sek110237 return; 18723444Sek110237 } 18733444Sek110237 18743444Sek110237 /* get the dataset's name */ 18753444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18763444Sek110237 zc.zc_obj = dsobj; 18773444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 18783444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 18793444Sek110237 /* just write out a path of two object numbers */ 18803444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 18813444Sek110237 dsobj, obj); 18823444Sek110237 return; 18833444Sek110237 } 18843444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 18853444Sek110237 18863444Sek110237 /* find out if the dataset is mounted */ 18873444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 18883444Sek110237 18893444Sek110237 /* get the corrupted object's path */ 18903444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 18913444Sek110237 zc.zc_obj = obj; 18923444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 18933444Sek110237 &zc) == 0) { 18943444Sek110237 if (mounted) { 18953444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 18963444Sek110237 zc.zc_value); 18973444Sek110237 } else { 18983444Sek110237 (void) snprintf(pathname, len, "%s:%s", 18993444Sek110237 dsname, zc.zc_value); 19003444Sek110237 } 19013444Sek110237 } else { 19023444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 19033444Sek110237 } 19043444Sek110237 free(mntpnt); 19053444Sek110237 } 1906*3912Slling 1907*3912Slling int 1908*3912Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 1909*3912Slling { 1910*3912Slling zfs_cmd_t zc = { 0 }; 1911*3912Slling int ret = -1; 1912*3912Slling char errbuf[1024]; 1913*3912Slling nvlist_t *nvl = NULL; 1914*3912Slling nvlist_t *realprops; 1915*3912Slling 1916*3912Slling (void) snprintf(errbuf, sizeof (errbuf), 1917*3912Slling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 1918*3912Slling zhp->zpool_name); 1919*3912Slling 1920*3912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 1921*3912Slling zfs_error_aux(zhp->zpool_hdl, 1922*3912Slling dgettext(TEXT_DOMAIN, "pool must be " 1923*3912Slling "upgraded to support pool properties")); 1924*3912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, errbuf)); 1925*3912Slling } 1926*3912Slling 1927*3912Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 1928*3912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); 1929*3912Slling 1930*3912Slling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 1931*3912Slling nvlist_add_string(nvl, propname, propval) != 0) { 1932*3912Slling return (no_memory(zhp->zpool_hdl)); 1933*3912Slling } 1934*3912Slling 1935*3912Slling if ((realprops = zfs_validate_properties(zhp->zpool_hdl, ZFS_TYPE_POOL, 1936*3912Slling zhp->zpool_name, nvl, 0, NULL, errbuf)) == NULL) { 1937*3912Slling nvlist_free(nvl); 1938*3912Slling return (-1); 1939*3912Slling } 1940*3912Slling 1941*3912Slling nvlist_free(nvl); 1942*3912Slling nvl = realprops; 1943*3912Slling 1944*3912Slling /* 1945*3912Slling * Execute the corresponding ioctl() to set this property. 1946*3912Slling */ 1947*3912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1948*3912Slling 1949*3912Slling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl, NULL) != 0) 1950*3912Slling return (-1); 1951*3912Slling 1952*3912Slling ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SET_PROPS, &zc); 1953*3912Slling zcmd_free_nvlists(&zc); 1954*3912Slling 1955*3912Slling if (ret) 1956*3912Slling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 1957*3912Slling 1958*3912Slling return (ret); 1959*3912Slling } 1960*3912Slling 1961*3912Slling int 1962*3912Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, 1963*3912Slling size_t proplen, zfs_source_t *srctype) 1964*3912Slling { 1965*3912Slling uint64_t value; 1966*3912Slling char msg[1024], *strvalue; 1967*3912Slling nvlist_t *nvp; 1968*3912Slling zfs_source_t src = ZFS_SRC_NONE; 1969*3912Slling 1970*3912Slling (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1971*3912Slling "cannot get property '%s'"), zpool_prop_to_name(prop)); 1972*3912Slling 1973*3912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 1974*3912Slling zfs_error_aux(zhp->zpool_hdl, 1975*3912Slling dgettext(TEXT_DOMAIN, "pool must be " 1976*3912Slling "upgraded to support pool properties")); 1977*3912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); 1978*3912Slling } 1979*3912Slling 1980*3912Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 1981*3912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); 1982*3912Slling 1983*3912Slling /* 1984*3912Slling * the "name" property is special cased 1985*3912Slling */ 1986*3912Slling if (!zfs_prop_valid_for_type(prop, ZFS_TYPE_POOL) && 1987*3912Slling prop != ZFS_PROP_NAME) 1988*3912Slling return (-1); 1989*3912Slling 1990*3912Slling switch (prop) { 1991*3912Slling case ZFS_PROP_NAME: 1992*3912Slling (void) strlcpy(propbuf, zhp->zpool_name, proplen); 1993*3912Slling break; 1994*3912Slling 1995*3912Slling case ZFS_PROP_BOOTFS: 1996*3912Slling if (nvlist_lookup_nvlist(zhp->zpool_props, 1997*3912Slling zpool_prop_to_name(prop), &nvp) != 0) { 1998*3912Slling strvalue = (char *)zfs_prop_default_string(prop); 1999*3912Slling if (strvalue == NULL) 2000*3912Slling strvalue = "-"; 2001*3912Slling src = ZFS_SRC_DEFAULT; 2002*3912Slling } else { 2003*3912Slling VERIFY(nvlist_lookup_uint64(nvp, 2004*3912Slling ZFS_PROP_SOURCE, &value) == 0); 2005*3912Slling src = value; 2006*3912Slling VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE, 2007*3912Slling &strvalue) == 0); 2008*3912Slling if (strlen(strvalue) >= proplen) 2009*3912Slling return (-1); 2010*3912Slling } 2011*3912Slling (void) strcpy(propbuf, strvalue); 2012*3912Slling break; 2013*3912Slling 2014*3912Slling default: 2015*3912Slling return (-1); 2016*3912Slling } 2017*3912Slling if (srctype) 2018*3912Slling *srctype = src; 2019*3912Slling return (0); 2020*3912Slling } 2021*3912Slling 2022*3912Slling int 2023*3912Slling zpool_get_proplist(libzfs_handle_t *hdl, char *fields, zpool_proplist_t **listp) 2024*3912Slling { 2025*3912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_POOL)); 2026*3912Slling } 2027*3912Slling 2028*3912Slling 2029*3912Slling int 2030*3912Slling zpool_expand_proplist(zpool_handle_t *zhp, zpool_proplist_t **plp) 2031*3912Slling { 2032*3912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 2033*3912Slling zpool_proplist_t *entry; 2034*3912Slling char buf[ZFS_MAXPROPLEN]; 2035*3912Slling 2036*3912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_POOL) != 0) 2037*3912Slling return (-1); 2038*3912Slling 2039*3912Slling for (entry = *plp; entry != NULL; entry = entry->pl_next) { 2040*3912Slling 2041*3912Slling if (entry->pl_fixed) 2042*3912Slling continue; 2043*3912Slling 2044*3912Slling if (entry->pl_prop != ZFS_PROP_INVAL && 2045*3912Slling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 2046*3912Slling NULL) == 0) { 2047*3912Slling if (strlen(buf) > entry->pl_width) 2048*3912Slling entry->pl_width = strlen(buf); 2049*3912Slling } 2050*3912Slling } 2051*3912Slling 2052*3912Slling return (0); 2053*3912Slling } 2054