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 /* 231354Seschrock * Copyright 2006 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" 46789Sahrens #include "libzfs_impl.h" 47789Sahrens 48789Sahrens /* 49789Sahrens * Validate the given pool name, optionally putting an extended error message in 50789Sahrens * 'buf'. 51789Sahrens */ 522082Seschrock static boolean_t 532082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 54789Sahrens { 55789Sahrens namecheck_err_t why; 56789Sahrens char what; 571773Seschrock int ret; 58789Sahrens 591773Seschrock ret = pool_namecheck(pool, &why, &what); 601773Seschrock 611773Seschrock /* 621773Seschrock * The rules for reserved pool names were extended at a later point. 631773Seschrock * But we need to support users with existing pools that may now be 641773Seschrock * invalid. So we only check for this expanded set of names during a 651773Seschrock * create (or import), and only in userland. 661773Seschrock */ 671773Seschrock if (ret == 0 && !isopen && 681773Seschrock (strncmp(pool, "mirror", 6) == 0 || 691773Seschrock strncmp(pool, "raidz", 5) == 0 || 701773Seschrock strncmp(pool, "spare", 5) == 0)) { 712082Seschrock zfs_error_aux(hdl, 722082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 732082Seschrock return (B_FALSE); 741773Seschrock } 751773Seschrock 761773Seschrock 771773Seschrock if (ret != 0) { 782082Seschrock if (hdl != NULL) { 79789Sahrens switch (why) { 801003Slling case NAME_ERR_TOOLONG: 812082Seschrock zfs_error_aux(hdl, 821003Slling dgettext(TEXT_DOMAIN, "name is too long")); 831003Slling break; 841003Slling 85789Sahrens case NAME_ERR_INVALCHAR: 862082Seschrock zfs_error_aux(hdl, 87789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 88789Sahrens "'%c' in pool name"), what); 89789Sahrens break; 90789Sahrens 91789Sahrens case NAME_ERR_NOLETTER: 922082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 932082Seschrock "name must begin with a letter")); 94789Sahrens break; 95789Sahrens 96789Sahrens case NAME_ERR_RESERVED: 972082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 982082Seschrock "name is reserved")); 99789Sahrens break; 100789Sahrens 101789Sahrens case NAME_ERR_DISKLIKE: 1022082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1032082Seschrock "pool name is reserved")); 104789Sahrens break; 1052856Snd150628 1062856Snd150628 case NAME_ERR_LEADING_SLASH: 1072856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1082856Snd150628 "leading slash in name")); 1092856Snd150628 break; 1102856Snd150628 1112856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 1122856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1132856Snd150628 "empty component in name")); 1142856Snd150628 break; 1152856Snd150628 1162856Snd150628 case NAME_ERR_TRAILING_SLASH: 1172856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1182856Snd150628 "trailing slash in name")); 1192856Snd150628 break; 1202856Snd150628 1212856Snd150628 case NAME_ERR_MULTIPLE_AT: 1222856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1232856Snd150628 "multiple '@' delimiters in name")); 1242856Snd150628 break; 1252856Snd150628 126789Sahrens } 127789Sahrens } 1282082Seschrock return (B_FALSE); 129789Sahrens } 130789Sahrens 1312082Seschrock return (B_TRUE); 132789Sahrens } 133789Sahrens 134789Sahrens /* 135789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 136789Sahrens */ 1372082Seschrock int 138789Sahrens set_pool_health(nvlist_t *config) 139789Sahrens { 140789Sahrens nvlist_t *nvroot; 141789Sahrens vdev_stat_t *vs; 142789Sahrens uint_t vsc; 143789Sahrens char *health; 144789Sahrens 145789Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 146789Sahrens &nvroot) == 0); 147789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 148789Sahrens (uint64_t **)&vs, &vsc) == 0); 149789Sahrens 150789Sahrens switch (vs->vs_state) { 151789Sahrens 152789Sahrens case VDEV_STATE_CLOSED: 153789Sahrens case VDEV_STATE_CANT_OPEN: 154789Sahrens case VDEV_STATE_OFFLINE: 155789Sahrens health = dgettext(TEXT_DOMAIN, "FAULTED"); 156789Sahrens break; 157789Sahrens 158789Sahrens case VDEV_STATE_DEGRADED: 159789Sahrens health = dgettext(TEXT_DOMAIN, "DEGRADED"); 160789Sahrens break; 161789Sahrens 162789Sahrens case VDEV_STATE_HEALTHY: 163789Sahrens health = dgettext(TEXT_DOMAIN, "ONLINE"); 164789Sahrens break; 165789Sahrens 166789Sahrens default: 1672082Seschrock abort(); 168789Sahrens } 169789Sahrens 1702082Seschrock return (nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, health)); 171789Sahrens } 172789Sahrens 173789Sahrens /* 174789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 175789Sahrens * state. 176789Sahrens */ 177789Sahrens zpool_handle_t * 1782082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 179789Sahrens { 180789Sahrens zpool_handle_t *zhp; 1812142Seschrock boolean_t missing; 182789Sahrens 183789Sahrens /* 184789Sahrens * Make sure the pool name is valid. 185789Sahrens */ 1862082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 187*3237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1882082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1892082Seschrock pool); 190789Sahrens return (NULL); 191789Sahrens } 192789Sahrens 1932082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1942082Seschrock return (NULL); 195789Sahrens 1962082Seschrock zhp->zpool_hdl = hdl; 197789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 198789Sahrens 1992142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2002142Seschrock zpool_close(zhp); 2012142Seschrock return (NULL); 2022142Seschrock } 2032142Seschrock 2042142Seschrock if (missing) { 2052142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2062142Seschrock "no such pool")); 207*3237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 2082142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 2092142Seschrock pool); 2102142Seschrock zpool_close(zhp); 2112142Seschrock return (NULL); 212789Sahrens } 213789Sahrens 214789Sahrens return (zhp); 215789Sahrens } 216789Sahrens 217789Sahrens /* 218789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 219789Sahrens * the configuration cache may be out of date). 220789Sahrens */ 2212142Seschrock int 2222142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 223789Sahrens { 224789Sahrens zpool_handle_t *zhp; 2252142Seschrock boolean_t missing; 226789Sahrens 2272142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 2282142Seschrock return (-1); 229789Sahrens 2302082Seschrock zhp->zpool_hdl = hdl; 231789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 232789Sahrens 2332142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2342142Seschrock zpool_close(zhp); 2352142Seschrock return (-1); 236789Sahrens } 237789Sahrens 2382142Seschrock if (missing) { 2392142Seschrock zpool_close(zhp); 2402142Seschrock *ret = NULL; 2412142Seschrock return (0); 2422142Seschrock } 2432142Seschrock 2442142Seschrock *ret = zhp; 2452142Seschrock return (0); 246789Sahrens } 247789Sahrens 248789Sahrens /* 249789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 250789Sahrens * state. 251789Sahrens */ 252789Sahrens zpool_handle_t * 2532082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 254789Sahrens { 255789Sahrens zpool_handle_t *zhp; 256789Sahrens 2572082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 258789Sahrens return (NULL); 259789Sahrens 260789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 261*3237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 2622082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 263789Sahrens zpool_close(zhp); 264789Sahrens return (NULL); 265789Sahrens } 266789Sahrens 267789Sahrens return (zhp); 268789Sahrens } 269789Sahrens 270789Sahrens /* 271789Sahrens * Close the handle. Simply frees the memory associated with the handle. 272789Sahrens */ 273789Sahrens void 274789Sahrens zpool_close(zpool_handle_t *zhp) 275789Sahrens { 276789Sahrens if (zhp->zpool_config) 277789Sahrens nvlist_free(zhp->zpool_config); 278952Seschrock if (zhp->zpool_old_config) 279952Seschrock nvlist_free(zhp->zpool_old_config); 2801544Seschrock if (zhp->zpool_error_log) { 2811544Seschrock int i; 2821544Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 2832082Seschrock nvlist_free(zhp->zpool_error_log[i]); 2841544Seschrock free(zhp->zpool_error_log); 2851544Seschrock } 286789Sahrens free(zhp); 287789Sahrens } 288789Sahrens 289789Sahrens /* 290789Sahrens * Return the name of the pool. 291789Sahrens */ 292789Sahrens const char * 293789Sahrens zpool_get_name(zpool_handle_t *zhp) 294789Sahrens { 295789Sahrens return (zhp->zpool_name); 296789Sahrens } 297789Sahrens 298789Sahrens /* 299789Sahrens * Return the GUID of the pool. 300789Sahrens */ 301789Sahrens uint64_t 302789Sahrens zpool_get_guid(zpool_handle_t *zhp) 303789Sahrens { 304789Sahrens uint64_t guid; 305789Sahrens 306789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 307789Sahrens &guid) == 0); 308789Sahrens return (guid); 309789Sahrens } 310789Sahrens 311789Sahrens /* 3122082Seschrock * Return the version of the pool. 3132082Seschrock */ 3142082Seschrock uint64_t 3152082Seschrock zpool_get_version(zpool_handle_t *zhp) 3162082Seschrock { 3172082Seschrock uint64_t version; 3182082Seschrock 3192082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3202082Seschrock &version) == 0); 3212082Seschrock 3222082Seschrock return (version); 3232082Seschrock } 3242082Seschrock 3252082Seschrock /* 326789Sahrens * Return the amount of space currently consumed by the pool. 327789Sahrens */ 328789Sahrens uint64_t 329789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 330789Sahrens { 331789Sahrens nvlist_t *nvroot; 332789Sahrens vdev_stat_t *vs; 333789Sahrens uint_t vsc; 334789Sahrens 335789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 336789Sahrens &nvroot) == 0); 337789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 338789Sahrens (uint64_t **)&vs, &vsc) == 0); 339789Sahrens 340789Sahrens return (vs->vs_alloc); 341789Sahrens } 342789Sahrens 343789Sahrens /* 344789Sahrens * Return the total space in the pool. 345789Sahrens */ 346789Sahrens uint64_t 347789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 348789Sahrens { 349789Sahrens nvlist_t *nvroot; 350789Sahrens vdev_stat_t *vs; 351789Sahrens uint_t vsc; 352789Sahrens 353789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 354789Sahrens &nvroot) == 0); 355789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 356789Sahrens (uint64_t **)&vs, &vsc) == 0); 357789Sahrens 358789Sahrens return (vs->vs_space); 359789Sahrens } 360789Sahrens 361789Sahrens /* 362789Sahrens * Return the alternate root for this pool, if any. 363789Sahrens */ 364789Sahrens int 365789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 366789Sahrens { 367789Sahrens zfs_cmd_t zc = { 0 }; 368789Sahrens 369789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3702082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3712676Seschrock zc.zc_value[0] == '\0') 372789Sahrens return (-1); 373789Sahrens 3742676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 375789Sahrens 376789Sahrens return (0); 377789Sahrens } 378789Sahrens 379789Sahrens /* 380789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 381789Sahrens */ 382789Sahrens int 383789Sahrens zpool_get_state(zpool_handle_t *zhp) 384789Sahrens { 385789Sahrens return (zhp->zpool_state); 386789Sahrens } 387789Sahrens 388789Sahrens /* 389789Sahrens * Create the named pool, using the provided vdev list. It is assumed 390789Sahrens * that the consumer has already validated the contents of the nvlist, so we 391789Sahrens * don't have to worry about error semantics. 392789Sahrens */ 393789Sahrens int 3942082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3952082Seschrock const char *altroot) 396789Sahrens { 397789Sahrens zfs_cmd_t zc = { 0 }; 3982082Seschrock char msg[1024]; 3992082Seschrock 4002082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4012082Seschrock "cannot create '%s'"), pool); 402789Sahrens 4032082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 4042082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 4052082Seschrock 4062082Seschrock if (altroot != NULL && altroot[0] != '/') 407*3237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 4082082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 409789Sahrens 4102676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 411789Sahrens return (-1); 412789Sahrens 413789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 414789Sahrens 415789Sahrens if (altroot != NULL) 4162676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 417789Sahrens 4182082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4192676Seschrock zcmd_free_nvlists(&zc); 4202082Seschrock 421789Sahrens switch (errno) { 422789Sahrens case EBUSY: 423789Sahrens /* 424789Sahrens * This can happen if the user has specified the same 425789Sahrens * device multiple times. We can't reliably detect this 426789Sahrens * until we try to add it and see we already have a 427789Sahrens * label. 428789Sahrens */ 4292082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4302082Seschrock "one or more vdevs refer to the same device")); 4312082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 432789Sahrens 433789Sahrens case EOVERFLOW: 434789Sahrens /* 4352082Seschrock * This occurs when one of the devices is below 436789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 437789Sahrens * device was the problem device since there's no 438789Sahrens * reliable way to determine device size from userland. 439789Sahrens */ 440789Sahrens { 441789Sahrens char buf[64]; 442789Sahrens 443789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 444789Sahrens 4452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4462082Seschrock "one or more devices is less than the " 4472082Seschrock "minimum size (%s)"), buf); 448789Sahrens } 4492082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 450789Sahrens 451789Sahrens case ENOSPC: 4522082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4532082Seschrock "one or more devices is out of space")); 4542082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 455789Sahrens 456789Sahrens default: 4572082Seschrock return (zpool_standard_error(hdl, errno, msg)); 458789Sahrens } 459789Sahrens } 460789Sahrens 4612676Seschrock zcmd_free_nvlists(&zc); 462789Sahrens 463789Sahrens /* 464789Sahrens * If this is an alternate root pool, then we automatically set the 4652676Seschrock * mountpoint of the root dataset to be '/'. 466789Sahrens */ 467789Sahrens if (altroot != NULL) { 468789Sahrens zfs_handle_t *zhp; 469789Sahrens 4702082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4712676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4722676Seschrock "/") == 0); 473789Sahrens 474789Sahrens zfs_close(zhp); 475789Sahrens } 476789Sahrens 477789Sahrens return (0); 478789Sahrens } 479789Sahrens 480789Sahrens /* 481789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 482789Sahrens * datasets left in the pool. 483789Sahrens */ 484789Sahrens int 485789Sahrens zpool_destroy(zpool_handle_t *zhp) 486789Sahrens { 487789Sahrens zfs_cmd_t zc = { 0 }; 488789Sahrens zfs_handle_t *zfp = NULL; 4892082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4902082Seschrock char msg[1024]; 491789Sahrens 492789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4932082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4942082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 495789Sahrens return (-1); 496789Sahrens 4972856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 498789Sahrens return (-1); 499789Sahrens 500789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 501789Sahrens 5022082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 5032082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5042082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 505789Sahrens 5062082Seschrock if (errno == EROFS) { 5072082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5082082Seschrock "one or more devices is read only")); 5092082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5102082Seschrock } else { 5112082Seschrock (void) zpool_standard_error(hdl, errno, msg); 512789Sahrens } 513789Sahrens 514789Sahrens if (zfp) 515789Sahrens zfs_close(zfp); 516789Sahrens return (-1); 517789Sahrens } 518789Sahrens 519789Sahrens if (zfp) { 520789Sahrens remove_mountpoint(zfp); 521789Sahrens zfs_close(zfp); 522789Sahrens } 523789Sahrens 524789Sahrens return (0); 525789Sahrens } 526789Sahrens 527789Sahrens /* 528789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 529789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 530789Sahrens */ 531789Sahrens int 532789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 533789Sahrens { 5342676Seschrock zfs_cmd_t zc = { 0 }; 5352082Seschrock int ret; 5362082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5372082Seschrock char msg[1024]; 5382082Seschrock nvlist_t **spares; 5392082Seschrock uint_t nspares; 5402082Seschrock 5412082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5422082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5432082Seschrock 5442082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5452082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5462082Seschrock &spares, &nspares) == 0) { 5472082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5482082Seschrock "upgraded to add hot spares")); 5492082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5502082Seschrock } 551789Sahrens 5522676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5532082Seschrock return (-1); 554789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 555789Sahrens 5562082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 557789Sahrens switch (errno) { 558789Sahrens case EBUSY: 559789Sahrens /* 560789Sahrens * This can happen if the user has specified the same 561789Sahrens * device multiple times. We can't reliably detect this 562789Sahrens * until we try to add it and see we already have a 563789Sahrens * label. 564789Sahrens */ 5652082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5662082Seschrock "one or more vdevs refer to the same device")); 5672082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 568789Sahrens break; 569789Sahrens 570789Sahrens case EOVERFLOW: 571789Sahrens /* 572789Sahrens * This occurrs when one of the devices is below 573789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 574789Sahrens * device was the problem device since there's no 575789Sahrens * reliable way to determine device size from userland. 576789Sahrens */ 577789Sahrens { 578789Sahrens char buf[64]; 579789Sahrens 580789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 581789Sahrens 5822082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5832082Seschrock "device is less than the minimum " 5842082Seschrock "size (%s)"), buf); 585789Sahrens } 5862082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5872082Seschrock break; 5882082Seschrock 5892082Seschrock case ENOTSUP: 5902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5912082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5922082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 593789Sahrens break; 594789Sahrens 595789Sahrens default: 5962082Seschrock (void) zpool_standard_error(hdl, errno, msg); 597789Sahrens } 598789Sahrens 5992082Seschrock ret = -1; 6002082Seschrock } else { 6012082Seschrock ret = 0; 602789Sahrens } 603789Sahrens 6042676Seschrock zcmd_free_nvlists(&zc); 605789Sahrens 6062082Seschrock return (ret); 607789Sahrens } 608789Sahrens 609789Sahrens /* 610789Sahrens * Exports the pool from the system. The caller must ensure that there are no 611789Sahrens * mounted datasets in the pool. 612789Sahrens */ 613789Sahrens int 614789Sahrens zpool_export(zpool_handle_t *zhp) 615789Sahrens { 616789Sahrens zfs_cmd_t zc = { 0 }; 617789Sahrens 618789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 619789Sahrens return (-1); 620789Sahrens 621789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 622789Sahrens 6232082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 624*3237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 6252082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6262082Seschrock zhp->zpool_name)); 627789Sahrens 628789Sahrens return (0); 629789Sahrens } 630789Sahrens 631789Sahrens /* 632789Sahrens * Import the given pool using the known configuration. The configuration 633789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 634789Sahrens * parameters control whether the pool is imported with a different name or with 635789Sahrens * an alternate root, respectively. 636789Sahrens */ 637789Sahrens int 6382082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6392082Seschrock const char *altroot) 640789Sahrens { 6412676Seschrock zfs_cmd_t zc = { 0 }; 642789Sahrens char *thename; 643789Sahrens char *origname; 644789Sahrens int ret; 645789Sahrens 646789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 647789Sahrens &origname) == 0); 648789Sahrens 649789Sahrens if (newname != NULL) { 6502082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 651*3237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6522082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6532082Seschrock newname)); 654789Sahrens thename = (char *)newname; 655789Sahrens } else { 656789Sahrens thename = origname; 657789Sahrens } 658789Sahrens 6592082Seschrock if (altroot != NULL && altroot[0] != '/') 660*3237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6612082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6622082Seschrock altroot)); 663789Sahrens 664789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 665789Sahrens 666789Sahrens if (altroot != NULL) 6672676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 668789Sahrens else 6692676Seschrock zc.zc_value[0] = '\0'; 670789Sahrens 671789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6721544Seschrock &zc.zc_guid) == 0); 673789Sahrens 6742676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6752082Seschrock return (-1); 676789Sahrens 677789Sahrens ret = 0; 6782082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 679789Sahrens char desc[1024]; 680789Sahrens if (newname == NULL) 681789Sahrens (void) snprintf(desc, sizeof (desc), 682789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 683789Sahrens thename); 684789Sahrens else 685789Sahrens (void) snprintf(desc, sizeof (desc), 686789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 687789Sahrens origname, thename); 688789Sahrens 689789Sahrens switch (errno) { 6901544Seschrock case ENOTSUP: 6911544Seschrock /* 6921544Seschrock * Unsupported version. 6931544Seschrock */ 6942082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6951544Seschrock break; 6961544Seschrock 6972174Seschrock case EINVAL: 6982174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6992174Seschrock break; 7002174Seschrock 701789Sahrens default: 7022082Seschrock (void) zpool_standard_error(hdl, errno, desc); 703789Sahrens } 704789Sahrens 705789Sahrens ret = -1; 706789Sahrens } else { 707789Sahrens zpool_handle_t *zhp; 708789Sahrens /* 709789Sahrens * This should never fail, but play it safe anyway. 710789Sahrens */ 7112142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7122142Seschrock ret = -1; 7132142Seschrock } else if (zhp != NULL) { 714789Sahrens ret = zpool_create_zvol_links(zhp); 715789Sahrens zpool_close(zhp); 716789Sahrens } 717789Sahrens } 718789Sahrens 7192676Seschrock zcmd_free_nvlists(&zc); 720789Sahrens return (ret); 721789Sahrens } 722789Sahrens 723789Sahrens /* 724789Sahrens * Scrub the pool. 725789Sahrens */ 726789Sahrens int 727789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 728789Sahrens { 729789Sahrens zfs_cmd_t zc = { 0 }; 730789Sahrens char msg[1024]; 7312082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 732789Sahrens 733789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 734789Sahrens zc.zc_cookie = type; 735789Sahrens 7362082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 737789Sahrens return (0); 738789Sahrens 739789Sahrens (void) snprintf(msg, sizeof (msg), 740789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 741789Sahrens 7422082Seschrock if (errno == EBUSY) 7432082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7442082Seschrock else 7452082Seschrock return (zpool_standard_error(hdl, errno, msg)); 746789Sahrens } 747789Sahrens 7482468Sek110237 /* 7492468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7502468Sek110237 * spare; but FALSE if its an INUSE spare. 7512468Sek110237 */ 7522082Seschrock static nvlist_t * 7532082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7542468Sek110237 boolean_t *avail_spare) 7551544Seschrock { 7561544Seschrock uint_t c, children; 7571544Seschrock nvlist_t **child; 7582082Seschrock uint64_t theguid, present; 7591544Seschrock char *path; 7601544Seschrock uint64_t wholedisk = 0; 7612082Seschrock nvlist_t *ret; 7621544Seschrock 7632082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7641544Seschrock 7651544Seschrock if (search == NULL && 7661544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7671544Seschrock /* 7681544Seschrock * If the device has never been present since import, the only 7691544Seschrock * reliable way to match the vdev is by GUID. 7701544Seschrock */ 7712082Seschrock if (theguid == guid) 7722082Seschrock return (nv); 7731544Seschrock } else if (search != NULL && 7741544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7751544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7761544Seschrock &wholedisk); 7771544Seschrock if (wholedisk) { 7781544Seschrock /* 7791544Seschrock * For whole disks, the internal path has 's0', but the 7801544Seschrock * path passed in by the user doesn't. 7811544Seschrock */ 7821544Seschrock if (strlen(search) == strlen(path) - 2 && 7831544Seschrock strncmp(search, path, strlen(search)) == 0) 7842082Seschrock return (nv); 7851544Seschrock } else if (strcmp(search, path) == 0) { 7862082Seschrock return (nv); 7871544Seschrock } 7881544Seschrock } 7891544Seschrock 7901544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7911544Seschrock &child, &children) != 0) 7922082Seschrock return (NULL); 7931544Seschrock 7941544Seschrock for (c = 0; c < children; c++) 7952082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7962468Sek110237 avail_spare)) != NULL) 7971544Seschrock return (ret); 7981544Seschrock 7992082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 8002082Seschrock &child, &children) == 0) { 8012082Seschrock for (c = 0; c < children; c++) { 8022082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 8032468Sek110237 avail_spare)) != NULL) { 8042468Sek110237 *avail_spare = B_TRUE; 8052082Seschrock return (ret); 8062082Seschrock } 8072082Seschrock } 8082082Seschrock } 8092082Seschrock 8102082Seschrock return (NULL); 8111544Seschrock } 8121544Seschrock 8132082Seschrock nvlist_t * 8142468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8151544Seschrock { 8161544Seschrock char buf[MAXPATHLEN]; 8171544Seschrock const char *search; 8181544Seschrock char *end; 8191544Seschrock nvlist_t *nvroot; 8201544Seschrock uint64_t guid; 8211544Seschrock 8221613Seschrock guid = strtoull(path, &end, 10); 8231544Seschrock if (guid != 0 && *end == '\0') { 8241544Seschrock search = NULL; 8251544Seschrock } else if (path[0] != '/') { 8261544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8271544Seschrock search = buf; 8281544Seschrock } else { 8291544Seschrock search = path; 8301544Seschrock } 8311544Seschrock 8321544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8331544Seschrock &nvroot) == 0); 8341544Seschrock 8352468Sek110237 *avail_spare = B_FALSE; 8362468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8372468Sek110237 } 8382468Sek110237 8392468Sek110237 /* 8402468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8412468Sek110237 */ 8422468Sek110237 static boolean_t 8432468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8442468Sek110237 { 8452468Sek110237 uint64_t spare_guid; 8462468Sek110237 nvlist_t *nvroot; 8472468Sek110237 nvlist_t **spares; 8482468Sek110237 uint_t nspares; 8492468Sek110237 int i; 8502468Sek110237 8512468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8522468Sek110237 &nvroot) == 0); 8532468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8542468Sek110237 &spares, &nspares) == 0) { 8552468Sek110237 for (i = 0; i < nspares; i++) { 8562468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8572468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8582468Sek110237 if (guid == spare_guid) 8592468Sek110237 return (B_TRUE); 8602468Sek110237 } 8612468Sek110237 } 8622468Sek110237 8632468Sek110237 return (B_FALSE); 8641544Seschrock } 8651544Seschrock 866789Sahrens /* 867789Sahrens * Bring the specified vdev online 868789Sahrens */ 869789Sahrens int 870789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 871789Sahrens { 872789Sahrens zfs_cmd_t zc = { 0 }; 873789Sahrens char msg[1024]; 8742082Seschrock nvlist_t *tgt; 8752468Sek110237 boolean_t avail_spare; 8762082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 877789Sahrens 8781544Seschrock (void) snprintf(msg, sizeof (msg), 8791544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 880789Sahrens 8811544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8822468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8832082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 884789Sahrens 8852468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8862468Sek110237 8872468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8882082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8892082Seschrock 8902082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8911544Seschrock return (0); 892789Sahrens 8932082Seschrock return (zpool_standard_error(hdl, errno, msg)); 894789Sahrens } 895789Sahrens 896789Sahrens /* 897789Sahrens * Take the specified vdev offline 898789Sahrens */ 899789Sahrens int 9001485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 901789Sahrens { 902789Sahrens zfs_cmd_t zc = { 0 }; 903789Sahrens char msg[1024]; 9042082Seschrock nvlist_t *tgt; 9052468Sek110237 boolean_t avail_spare; 9062082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 907789Sahrens 9081544Seschrock (void) snprintf(msg, sizeof (msg), 9091544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9101544Seschrock 911789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9122468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9132082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9142082Seschrock 9152468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9162468Sek110237 9172468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9182082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9192082Seschrock 9201485Slling zc.zc_cookie = istmp; 9211485Slling 9222082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 923789Sahrens return (0); 924789Sahrens 925789Sahrens switch (errno) { 9262082Seschrock case EBUSY: 927789Sahrens 928789Sahrens /* 929789Sahrens * There are no other replicas of this device. 930789Sahrens */ 9312082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9322082Seschrock 9332082Seschrock default: 9342082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9352082Seschrock } 9362082Seschrock } 937789Sahrens 9382082Seschrock /* 9392082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 9402082Seschrock * a hot spare. 9412082Seschrock */ 9422082Seschrock static boolean_t 9432082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 9442082Seschrock { 9452082Seschrock nvlist_t **child; 9462082Seschrock uint_t c, children; 9472082Seschrock char *type; 9482082Seschrock 9492082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9502082Seschrock &children) == 0) { 9512082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9522082Seschrock &type) == 0); 9532082Seschrock 9542082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9552082Seschrock children == 2 && child[which] == tgt) 9562082Seschrock return (B_TRUE); 9572082Seschrock 9582082Seschrock for (c = 0; c < children; c++) 9592082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9602082Seschrock return (B_TRUE); 961789Sahrens } 9622082Seschrock 9632082Seschrock return (B_FALSE); 964789Sahrens } 965789Sahrens 966789Sahrens /* 967789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 968789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 969789Sahrens */ 970789Sahrens int 971789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 972789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 973789Sahrens { 974789Sahrens zfs_cmd_t zc = { 0 }; 975789Sahrens char msg[1024]; 976789Sahrens int ret; 9772082Seschrock nvlist_t *tgt; 9782468Sek110237 boolean_t avail_spare; 9792082Seschrock uint64_t val; 9802082Seschrock char *path; 9812082Seschrock nvlist_t **child; 9822082Seschrock uint_t children; 9832082Seschrock nvlist_t *config_root; 9842082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 985789Sahrens 9861544Seschrock if (replacing) 9871544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9881544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9891544Seschrock else 9901544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9911544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9921544Seschrock 993789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9942468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9952082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9962082Seschrock 9972468Sek110237 if (avail_spare) 9982082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9992082Seschrock 10002082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 10012082Seschrock zc.zc_cookie = replacing; 10022082Seschrock 10032082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10042082Seschrock &child, &children) != 0 || children != 1) { 10052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10062082Seschrock "new device must be a single disk")); 10072082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10081544Seschrock } 10092082Seschrock 10102082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10112082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10122082Seschrock 10132082Seschrock /* 10142082Seschrock * If the target is a hot spare that has been swapped in, we can only 10152082Seschrock * replace it with another hot spare. 10162082Seschrock */ 10172082Seschrock if (replacing && 10182082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10192082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10202468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10212468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10222082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10232082Seschrock "can only be replaced by another hot spare")); 10242082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10252082Seschrock } 10262082Seschrock 10272082Seschrock /* 10282082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10292082Seschrock * already spared device. 10302082Seschrock */ 10312082Seschrock if (replacing && 10322082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10332468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10342082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10352082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10362082Seschrock "device has already been replaced with a spare")); 10372082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10382082Seschrock } 1039789Sahrens 10402676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 10412082Seschrock return (-1); 1042789Sahrens 10432082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1044789Sahrens 10452676Seschrock zcmd_free_nvlists(&zc); 1046789Sahrens 1047789Sahrens if (ret == 0) 1048789Sahrens return (0); 1049789Sahrens 1050789Sahrens switch (errno) { 10511544Seschrock case ENOTSUP: 1052789Sahrens /* 1053789Sahrens * Can't attach to or replace this type of vdev. 1054789Sahrens */ 1055789Sahrens if (replacing) 10562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10572082Seschrock "cannot replace a replacing device")); 1058789Sahrens else 10592082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10602082Seschrock "can only attach to mirrors and top-level " 10612082Seschrock "disks")); 10622082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1063789Sahrens break; 1064789Sahrens 10651544Seschrock case EINVAL: 1066789Sahrens /* 1067789Sahrens * The new device must be a single disk. 1068789Sahrens */ 10692082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10702082Seschrock "new device must be a single disk")); 10712082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1072789Sahrens break; 1073789Sahrens 10741544Seschrock case EBUSY: 10752082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10762082Seschrock new_disk); 10772082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1078789Sahrens break; 1079789Sahrens 10801544Seschrock case EOVERFLOW: 1081789Sahrens /* 1082789Sahrens * The new device is too small. 1083789Sahrens */ 10842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10852082Seschrock "device is too small")); 10862082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1087789Sahrens break; 1088789Sahrens 10891544Seschrock case EDOM: 1090789Sahrens /* 1091789Sahrens * The new device has a different alignment requirement. 1092789Sahrens */ 10932082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10942082Seschrock "devices have different sector alignment")); 10952082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1096789Sahrens break; 1097789Sahrens 10981544Seschrock case ENAMETOOLONG: 1099789Sahrens /* 1100789Sahrens * The resulting top-level vdev spec won't fit in the label. 1101789Sahrens */ 11022082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1103789Sahrens break; 1104789Sahrens 11051544Seschrock default: 11062082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1107789Sahrens } 1108789Sahrens 11092082Seschrock return (-1); 1110789Sahrens } 1111789Sahrens 1112789Sahrens /* 1113789Sahrens * Detach the specified device. 1114789Sahrens */ 1115789Sahrens int 1116789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1117789Sahrens { 1118789Sahrens zfs_cmd_t zc = { 0 }; 1119789Sahrens char msg[1024]; 11202082Seschrock nvlist_t *tgt; 11212468Sek110237 boolean_t avail_spare; 11222082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1123789Sahrens 11241544Seschrock (void) snprintf(msg, sizeof (msg), 11251544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11261544Seschrock 1127789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11282468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11292082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1130789Sahrens 11312468Sek110237 if (avail_spare) 11322082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11332082Seschrock 11342082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11352082Seschrock 11362082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1137789Sahrens return (0); 1138789Sahrens 1139789Sahrens switch (errno) { 1140789Sahrens 11411544Seschrock case ENOTSUP: 1142789Sahrens /* 1143789Sahrens * Can't detach from this type of vdev. 1144789Sahrens */ 11452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11462082Seschrock "applicable to mirror and replacing vdevs")); 11472082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1148789Sahrens break; 1149789Sahrens 11501544Seschrock case EBUSY: 1151789Sahrens /* 1152789Sahrens * There are no other replicas of this device. 1153789Sahrens */ 11542082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1155789Sahrens break; 1156789Sahrens 11571544Seschrock default: 11582082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11591544Seschrock } 11601544Seschrock 11612082Seschrock return (-1); 11622082Seschrock } 11632082Seschrock 11642082Seschrock /* 11652082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11662082Seschrock */ 11672082Seschrock int 11682082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11692082Seschrock { 11702082Seschrock zfs_cmd_t zc = { 0 }; 11712082Seschrock char msg[1024]; 11722082Seschrock nvlist_t *tgt; 11732468Sek110237 boolean_t avail_spare; 11742082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11752082Seschrock 11762082Seschrock (void) snprintf(msg, sizeof (msg), 11772082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11782082Seschrock 11792082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11802468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11812082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11822082Seschrock 11832468Sek110237 if (!avail_spare) { 11842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11852082Seschrock "only hot spares can be removed")); 11862082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11872082Seschrock } 11882082Seschrock 11892082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11902082Seschrock 11912082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11922082Seschrock return (0); 11932082Seschrock 11942082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11951544Seschrock } 11961544Seschrock 11971544Seschrock /* 11981544Seschrock * Clear the errors for the pool, or the particular device if specified. 11991544Seschrock */ 12001544Seschrock int 12011544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 12021544Seschrock { 12031544Seschrock zfs_cmd_t zc = { 0 }; 12041544Seschrock char msg[1024]; 12052082Seschrock nvlist_t *tgt; 12062468Sek110237 boolean_t avail_spare; 12072082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12081544Seschrock 12091544Seschrock if (path) 12101544Seschrock (void) snprintf(msg, sizeof (msg), 12111544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12122676Seschrock path); 12131544Seschrock else 12141544Seschrock (void) snprintf(msg, sizeof (msg), 12151544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12161544Seschrock zhp->zpool_name); 12171544Seschrock 12181544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12192082Seschrock if (path) { 12202468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12212082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12222082Seschrock 12232468Sek110237 if (avail_spare) 12242082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12252082Seschrock 12262082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12272082Seschrock &zc.zc_guid) == 0); 12281544Seschrock } 12291544Seschrock 12302082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12311544Seschrock return (0); 12321544Seschrock 12332082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1234789Sahrens } 1235789Sahrens 12363126Sahl /* 12373126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 12383126Sahl * hierarchy. 12393126Sahl */ 12403126Sahl int 12413126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 12423126Sahl void *data) 1243789Sahrens { 12443126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 12453126Sahl char (*paths)[MAXPATHLEN]; 12463126Sahl size_t size = 4; 12473126Sahl int curr, fd, base, ret = 0; 12483126Sahl DIR *dirp; 12493126Sahl struct dirent *dp; 12503126Sahl struct stat st; 12513126Sahl 12523126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 12533126Sahl return (errno == ENOENT ? 0 : -1); 12543126Sahl 12553126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 12563126Sahl int err = errno; 12573126Sahl (void) close(base); 12583126Sahl return (err == ENOENT ? 0 : -1); 12593126Sahl } 1260789Sahrens 1261789Sahrens /* 12623126Sahl * Oddly this wasn't a directory -- ignore that failure since we 12633126Sahl * know there are no links lower in the (non-existant) hierarchy. 1264789Sahrens */ 12653126Sahl if (!S_ISDIR(st.st_mode)) { 12663126Sahl (void) close(base); 12673126Sahl return (0); 12683126Sahl } 12693126Sahl 12703126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 12713126Sahl (void) close(base); 12723126Sahl return (-1); 1273789Sahrens } 1274789Sahrens 12753126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 12763126Sahl curr = 0; 12773126Sahl 12783126Sahl while (curr >= 0) { 12793126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 12803126Sahl goto err; 12813126Sahl 12823126Sahl if (S_ISDIR(st.st_mode)) { 12833126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 12843126Sahl goto err; 12853126Sahl 12863126Sahl if ((dirp = fdopendir(fd)) == NULL) { 12873126Sahl (void) close(fd); 12883126Sahl goto err; 12893126Sahl } 12903126Sahl 12913126Sahl while ((dp = readdir(dirp)) != NULL) { 12923126Sahl if (dp->d_name[0] == '.') 12933126Sahl continue; 12943126Sahl 12953126Sahl if (curr + 1 == size) { 12963126Sahl paths = zfs_realloc(hdl, paths, 12973126Sahl size * sizeof (paths[0]), 12983126Sahl size * 2 * sizeof (paths[0])); 12993126Sahl if (paths == NULL) { 13003126Sahl (void) closedir(dirp); 13013126Sahl (void) close(fd); 13023126Sahl goto err; 13033126Sahl } 13043126Sahl 13053126Sahl size *= 2; 13063126Sahl } 13073126Sahl 13083126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 13093126Sahl sizeof (paths[curr + 1])); 13103126Sahl (void) strlcat(paths[curr], "/", 13113126Sahl sizeof (paths[curr])); 13123126Sahl (void) strlcat(paths[curr], dp->d_name, 13133126Sahl sizeof (paths[curr])); 13143126Sahl curr++; 13153126Sahl } 13163126Sahl 13173126Sahl (void) closedir(dirp); 13183126Sahl 13193126Sahl } else { 13203126Sahl if ((ret = cb(paths[curr], data)) != 0) 13213126Sahl break; 13223126Sahl } 13233126Sahl 13243126Sahl curr--; 13253126Sahl } 13263126Sahl 13273126Sahl free(paths); 13283126Sahl (void) close(base); 13293126Sahl 13303126Sahl return (ret); 13313126Sahl 13323126Sahl err: 13333126Sahl free(paths); 13343126Sahl (void) close(base); 13353126Sahl return (-1); 13363126Sahl } 13373126Sahl 13383126Sahl typedef struct zvol_cb { 13393126Sahl zpool_handle_t *zcb_pool; 13403126Sahl boolean_t zcb_create; 13413126Sahl } zvol_cb_t; 13423126Sahl 13433126Sahl /*ARGSUSED*/ 13443126Sahl static int 13453126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 13463126Sahl { 13473126Sahl int ret; 13483126Sahl 13493126Sahl if (ZFS_IS_VOLUME(zhp)) 13503126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 13513126Sahl 13523126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1353789Sahrens 1354789Sahrens zfs_close(zhp); 13553126Sahl 1356789Sahrens return (ret); 1357789Sahrens } 1358789Sahrens 1359789Sahrens /* 1360789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1361789Sahrens */ 1362789Sahrens int 1363789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1364789Sahrens { 1365789Sahrens zfs_handle_t *zfp; 1366789Sahrens int ret; 1367789Sahrens 1368789Sahrens /* 1369789Sahrens * If the pool is unavailable, just return success. 1370789Sahrens */ 13712082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 13722082Seschrock zhp->zpool_name)) == NULL) 1373789Sahrens return (0); 1374789Sahrens 13753126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1376789Sahrens 1377789Sahrens zfs_close(zfp); 1378789Sahrens return (ret); 1379789Sahrens } 1380789Sahrens 13813126Sahl static int 13823126Sahl do_zvol_remove(const char *dataset, void *data) 13833126Sahl { 13843126Sahl zpool_handle_t *zhp = data; 13853126Sahl 13863126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 13873126Sahl } 13883126Sahl 1389789Sahrens /* 13903126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 13913126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 13923126Sahl * operation. 1393789Sahrens */ 1394789Sahrens int 1395789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1396789Sahrens { 13973126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1398789Sahrens } 13991354Seschrock 14001354Seschrock /* 14011354Seschrock * Convert from a devid string to a path. 14021354Seschrock */ 14031354Seschrock static char * 14041354Seschrock devid_to_path(char *devid_str) 14051354Seschrock { 14061354Seschrock ddi_devid_t devid; 14071354Seschrock char *minor; 14081354Seschrock char *path; 14091354Seschrock devid_nmlist_t *list = NULL; 14101354Seschrock int ret; 14111354Seschrock 14121354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 14131354Seschrock return (NULL); 14141354Seschrock 14151354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 14161354Seschrock 14171354Seschrock devid_str_free(minor); 14181354Seschrock devid_free(devid); 14191354Seschrock 14201354Seschrock if (ret != 0) 14211354Seschrock return (NULL); 14221354Seschrock 14232082Seschrock if ((path = strdup(list[0].devname)) == NULL) 14242082Seschrock return (NULL); 14252082Seschrock 14261354Seschrock devid_free_nmlist(list); 14271354Seschrock 14281354Seschrock return (path); 14291354Seschrock } 14301354Seschrock 14311354Seschrock /* 14321354Seschrock * Convert from a path to a devid string. 14331354Seschrock */ 14341354Seschrock static char * 14351354Seschrock path_to_devid(const char *path) 14361354Seschrock { 14371354Seschrock int fd; 14381354Seschrock ddi_devid_t devid; 14391354Seschrock char *minor, *ret; 14401354Seschrock 14411354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 14421354Seschrock return (NULL); 14431354Seschrock 14441354Seschrock minor = NULL; 14451354Seschrock ret = NULL; 14461354Seschrock if (devid_get(fd, &devid) == 0) { 14471354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 14481354Seschrock ret = devid_str_encode(devid, minor); 14491354Seschrock if (minor != NULL) 14501354Seschrock devid_str_free(minor); 14511354Seschrock devid_free(devid); 14521354Seschrock } 14531354Seschrock (void) close(fd); 14541354Seschrock 14551354Seschrock return (ret); 14561354Seschrock } 14571354Seschrock 14581354Seschrock /* 14591354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 14601354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 14611354Seschrock * type 'zpool status', and we'll display the correct information anyway. 14621354Seschrock */ 14631354Seschrock static void 14641354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 14651354Seschrock { 14661354Seschrock zfs_cmd_t zc = { 0 }; 14671354Seschrock 14681354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14692676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 14701354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14711544Seschrock &zc.zc_guid) == 0); 14721354Seschrock 14732082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 14741354Seschrock } 14751354Seschrock 14761354Seschrock /* 14771354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 14781354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 14791354Seschrock * We also check if this is a whole disk, in which case we strip off the 14801354Seschrock * trailing 's0' slice name. 14811354Seschrock * 14821354Seschrock * This routine is also responsible for identifying when disks have been 14831354Seschrock * reconfigured in a new location. The kernel will have opened the device by 14841354Seschrock * devid, but the path will still refer to the old location. To catch this, we 14851354Seschrock * first do a path -> devid translation (which is fast for the common case). If 14861354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 14871354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 14881354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 14891354Seschrock * of these checks. 14901354Seschrock */ 14911354Seschrock char * 14922082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 14931354Seschrock { 14941354Seschrock char *path, *devid; 14951544Seschrock uint64_t value; 14961544Seschrock char buf[64]; 14971354Seschrock 14981544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14991544Seschrock &value) == 0) { 15001544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 15011544Seschrock &value) == 0); 15022856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 15032856Snd150628 (u_longlong_t)value); 15041544Seschrock path = buf; 15051544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 15061354Seschrock 15071354Seschrock if (zhp != NULL && 15081354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 15091354Seschrock /* 15101354Seschrock * Determine if the current path is correct. 15111354Seschrock */ 15121354Seschrock char *newdevid = path_to_devid(path); 15131354Seschrock 15141354Seschrock if (newdevid == NULL || 15151354Seschrock strcmp(devid, newdevid) != 0) { 15161354Seschrock char *newpath; 15171354Seschrock 15181354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 15191354Seschrock /* 15201354Seschrock * Update the path appropriately. 15211354Seschrock */ 15221354Seschrock set_path(zhp, nv, newpath); 15232082Seschrock if (nvlist_add_string(nv, 15242082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 15252082Seschrock verify(nvlist_lookup_string(nv, 15262082Seschrock ZPOOL_CONFIG_PATH, 15272082Seschrock &path) == 0); 15281354Seschrock free(newpath); 15291354Seschrock } 15301354Seschrock } 15311354Seschrock 15322082Seschrock if (newdevid) 15332082Seschrock devid_str_free(newdevid); 15341354Seschrock } 15351354Seschrock 15361354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 15371354Seschrock path += 9; 15381354Seschrock 15391354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 15401544Seschrock &value) == 0 && value) { 15412082Seschrock char *tmp = zfs_strdup(hdl, path); 15422082Seschrock if (tmp == NULL) 15432082Seschrock return (NULL); 15441354Seschrock tmp[strlen(path) - 2] = '\0'; 15451354Seschrock return (tmp); 15461354Seschrock } 15471354Seschrock } else { 15481354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 15492082Seschrock 15502082Seschrock /* 15512082Seschrock * If it's a raidz device, we need to stick in the parity level. 15522082Seschrock */ 15532082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 15542082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 15552082Seschrock &value) == 0); 15562082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 15572856Snd150628 (u_longlong_t)value); 15582082Seschrock path = buf; 15592082Seschrock } 15601354Seschrock } 15611354Seschrock 15622082Seschrock return (zfs_strdup(hdl, path)); 15631354Seschrock } 15641544Seschrock 15651544Seschrock static int 15661544Seschrock zbookmark_compare(const void *a, const void *b) 15671544Seschrock { 15681544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 15691544Seschrock } 15701544Seschrock 15711544Seschrock /* 15721544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 15731544Seschrock * caller. 15741544Seschrock */ 15751544Seschrock int 15761544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem) 15771544Seschrock { 15781544Seschrock zfs_cmd_t zc = { 0 }; 15791544Seschrock uint64_t count; 15802676Seschrock zbookmark_t *zb = NULL; 15812676Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 15821544Seschrock int i, j; 15831544Seschrock 15841544Seschrock if (zhp->zpool_error_log != NULL) { 15851544Seschrock *list = zhp->zpool_error_log; 15861544Seschrock *nelem = zhp->zpool_error_count; 15871544Seschrock return (0); 15881544Seschrock } 15891544Seschrock 15901544Seschrock /* 15911544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 15921544Seschrock * has increased, allocate more space and continue until we get the 15931544Seschrock * entire list. 15941544Seschrock */ 15951544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 15961544Seschrock &count) == 0); 15972676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 15982856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 15992082Seschrock return (-1); 16002676Seschrock zc.zc_nvlist_dst_size = count; 16011544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16021544Seschrock for (;;) { 16032082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 16042082Seschrock &zc) != 0) { 16052676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16061544Seschrock if (errno == ENOMEM) { 16072676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 16082082Seschrock zfs_alloc(zhp->zpool_hdl, 16092856Snd150628 zc.zc_nvlist_dst_size)) == (uintptr_t)NULL) 16102082Seschrock return (-1); 16111544Seschrock } else { 16121544Seschrock return (-1); 16131544Seschrock } 16141544Seschrock } else { 16151544Seschrock break; 16161544Seschrock } 16171544Seschrock } 16181544Seschrock 16191544Seschrock /* 16201544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 16211544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 16222676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 16231544Seschrock * _not_ copied as part of the process. So we point the start of our 16241544Seschrock * array appropriate and decrement the total number of elements. 16251544Seschrock */ 16262676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 16272676Seschrock zc.zc_nvlist_dst_size; 16282676Seschrock count -= zc.zc_nvlist_dst_size; 16292676Seschrock zc.zc_nvlist_dst = 0ULL; 16301544Seschrock 16311544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 16321544Seschrock 16331544Seschrock /* 16341544Seschrock * Count the number of unique elements 16351544Seschrock */ 16361544Seschrock j = 0; 16371544Seschrock for (i = 0; i < count; i++) { 16381544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 16391544Seschrock sizeof (zbookmark_t)) == 0) 16401544Seschrock continue; 16411544Seschrock j++; 16421544Seschrock } 16431544Seschrock 16441544Seschrock /* 16451544Seschrock * If the user has only requested the number of items, return it now 16461544Seschrock * without bothering with the extra work. 16471544Seschrock */ 16481544Seschrock if (list == NULL) { 16491544Seschrock *nelem = j; 16502676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16511544Seschrock return (0); 16521544Seschrock } 16531544Seschrock 16541544Seschrock zhp->zpool_error_count = j; 16551544Seschrock 16561544Seschrock /* 16571544Seschrock * Allocate an array of nvlists to hold the results 16581544Seschrock */ 16592082Seschrock if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, 16602082Seschrock j * sizeof (nvlist_t *))) == NULL) { 16612676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16622082Seschrock return (-1); 16632082Seschrock } 16641544Seschrock 16651544Seschrock /* 16661544Seschrock * Fill in the results with names from the kernel. 16671544Seschrock */ 16681544Seschrock j = 0; 16691544Seschrock for (i = 0; i < count; i++) { 16701544Seschrock char buf[64]; 16711544Seschrock nvlist_t *nv; 16721544Seschrock 16731544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 16741544Seschrock sizeof (zbookmark_t)) == 0) 16751544Seschrock continue; 16761544Seschrock 16772676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 16782082Seschrock goto nomem; 16791544Seschrock 16801544Seschrock zc.zc_bookmark = zb[i]; 16812676Seschrock for (;;) { 16822676Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, 16832676Seschrock ZFS_IOC_BOOKMARK_NAME, &zc) != 0) { 16842676Seschrock if (errno == ENOMEM) { 16852676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) 16862676Seschrock != 0) { 16872676Seschrock zcmd_free_nvlists(&zc); 16882676Seschrock goto nomem; 16892676Seschrock } 16902676Seschrock 16912676Seschrock continue; 16922676Seschrock } else { 16932676Seschrock if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 16942676Seschrock 0) != 0) 16952676Seschrock goto nomem; 16962676Seschrock 16972676Seschrock zhp->zpool_error_log[j] = nv; 16982676Seschrock (void) snprintf(buf, sizeof (buf), 16992856Snd150628 "%llx", (longlong_t) 17002856Snd150628 zb[i].zb_objset); 17012676Seschrock if (nvlist_add_string(nv, 17022676Seschrock ZPOOL_ERR_DATASET, buf) != 0) 17032676Seschrock goto nomem; 17042676Seschrock (void) snprintf(buf, sizeof (buf), 17052856Snd150628 "%llx", (longlong_t) 17062856Snd150628 zb[i].zb_object); 17072676Seschrock if (nvlist_add_string(nv, 17082676Seschrock ZPOOL_ERR_OBJECT, buf) != 0) 17092676Seschrock goto nomem; 17102676Seschrock (void) snprintf(buf, sizeof (buf), 17112676Seschrock "lvl=%u blkid=%llu", 17122676Seschrock (int)zb[i].zb_level, 17132676Seschrock (long long)zb[i].zb_blkid); 17142676Seschrock if (nvlist_add_string(nv, 17152676Seschrock ZPOOL_ERR_RANGE, buf) != 0) 17162676Seschrock goto nomem; 17172676Seschrock } 17182676Seschrock } else { 17192676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, 17202676Seschrock &zhp->zpool_error_log[j]) != 0) { 17212676Seschrock zcmd_free_nvlists(&zc); 17222676Seschrock goto nomem; 17232676Seschrock } 17242676Seschrock } 17252676Seschrock 17262676Seschrock break; 17271544Seschrock } 17281544Seschrock 17292676Seschrock zcmd_free_nvlists(&zc); 17302676Seschrock 17311544Seschrock j++; 17321544Seschrock } 17331544Seschrock 17341544Seschrock *list = zhp->zpool_error_log; 17351544Seschrock *nelem = zhp->zpool_error_count; 17362676Seschrock free(zb); 17371544Seschrock 17381544Seschrock return (0); 17392082Seschrock 17402082Seschrock nomem: 17412676Seschrock free(zb); 17422676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 17432676Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 17442676Seschrock nvlist_free(zhp->zpool_error_log[i]); 17452082Seschrock free(zhp->zpool_error_log); 17462082Seschrock zhp->zpool_error_log = NULL; 17472082Seschrock return (no_memory(zhp->zpool_hdl)); 17481544Seschrock } 17491760Seschrock 17501760Seschrock /* 17511760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 17521760Seschrock */ 17531760Seschrock int 17541760Seschrock zpool_upgrade(zpool_handle_t *zhp) 17551760Seschrock { 17561760Seschrock zfs_cmd_t zc = { 0 }; 17572082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 17581760Seschrock 17591760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 17602082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 1761*3237Slling return (zpool_standard_error_fmt(hdl, errno, 17622082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 17632082Seschrock zhp->zpool_name)); 17641760Seschrock 17651760Seschrock return (0); 17661760Seschrock } 17672926Sek110237 17682926Sek110237 /* 17692926Sek110237 * Log command history. 17702926Sek110237 * 17712926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 17722926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 17732926Sek110237 * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the 17742926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 17752926Sek110237 */ 17762926Sek110237 void 17772926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 17782926Sek110237 boolean_t pool, boolean_t pool_create) 17792926Sek110237 { 17802926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 17812926Sek110237 char *dspath; 17822926Sek110237 zfs_cmd_t zc = { 0 }; 17832926Sek110237 int i; 17842926Sek110237 17852926Sek110237 /* construct the command string */ 17862926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 17872926Sek110237 for (i = 0; i < argc; i++) { 17882926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 17892926Sek110237 break; 17902926Sek110237 (void) strcat(cmd_buf, " "); 17912926Sek110237 (void) strcat(cmd_buf, argv[i]); 17922926Sek110237 } 17932926Sek110237 17942926Sek110237 /* figure out the poolname */ 17952926Sek110237 dspath = strpbrk(path, "/@"); 17962926Sek110237 if (dspath == NULL) { 17972926Sek110237 (void) strcpy(zc.zc_name, path); 17982926Sek110237 } else { 17992926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 18002926Sek110237 zc.zc_name[dspath-path] = '\0'; 18012926Sek110237 } 18022926Sek110237 18032926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 18042926Sek110237 zc.zc_history_len = strlen(cmd_buf); 18052926Sek110237 18062926Sek110237 /* overloading zc_history_offset */ 18072926Sek110237 zc.zc_history_offset = pool_create; 18082926Sek110237 18092926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 18102926Sek110237 } 18112926Sek110237 18122926Sek110237 /* 18132926Sek110237 * Perform ioctl to get some command history of a pool. 18142926Sek110237 * 18152926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 18162926Sek110237 * logical offset of the history buffer to start reading from. 18172926Sek110237 * 18182926Sek110237 * Upon return, 'off' is the next logical offset to read from and 18192926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 18202926Sek110237 */ 18212926Sek110237 static int 18222926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 18232926Sek110237 { 18242926Sek110237 zfs_cmd_t zc = { 0 }; 18252926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 18262926Sek110237 18272926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18282926Sek110237 18292926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 18302926Sek110237 zc.zc_history_len = *len; 18312926Sek110237 zc.zc_history_offset = *off; 18322926Sek110237 18332926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 18342926Sek110237 switch (errno) { 18352926Sek110237 case EPERM: 1836*3237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 1837*3237Slling dgettext(TEXT_DOMAIN, 18382926Sek110237 "cannot show history for pool '%s'"), 18392926Sek110237 zhp->zpool_name)); 18402926Sek110237 case ENOENT: 1841*3237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 18422926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 18432926Sek110237 "'%s'"), zhp->zpool_name)); 18442926Sek110237 default: 1845*3237Slling return (zpool_standard_error_fmt(hdl, errno, 18462926Sek110237 dgettext(TEXT_DOMAIN, 18472926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 18482926Sek110237 } 18492926Sek110237 } 18502926Sek110237 18512926Sek110237 *len = zc.zc_history_len; 18522926Sek110237 *off = zc.zc_history_offset; 18532926Sek110237 18542926Sek110237 return (0); 18552926Sek110237 } 18562926Sek110237 18572926Sek110237 /* 18582926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 18592926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 18602926Sek110237 * processed as there wasn't a complete record. 18612926Sek110237 */ 18622926Sek110237 static int 18632926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 18642926Sek110237 nvlist_t ***records, uint_t *numrecords) 18652926Sek110237 { 18662926Sek110237 uint64_t reclen; 18672926Sek110237 nvlist_t *nv; 18682926Sek110237 int i; 18692926Sek110237 18702926Sek110237 while (bytes_read > sizeof (reclen)) { 18712926Sek110237 18722926Sek110237 /* get length of packed record (stored as little endian) */ 18732926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 18742926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 18752926Sek110237 18762926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 18772926Sek110237 break; 18782926Sek110237 18792926Sek110237 /* unpack record */ 18802926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 18812926Sek110237 return (ENOMEM); 18822926Sek110237 bytes_read -= sizeof (reclen) + reclen; 18832926Sek110237 buf += sizeof (reclen) + reclen; 18842926Sek110237 18852926Sek110237 /* add record to nvlist array */ 18862926Sek110237 (*numrecords)++; 18872926Sek110237 if (ISP2(*numrecords + 1)) { 18882926Sek110237 *records = realloc(*records, 18892926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 18902926Sek110237 } 18912926Sek110237 (*records)[*numrecords - 1] = nv; 18922926Sek110237 } 18932926Sek110237 18942926Sek110237 *leftover = bytes_read; 18952926Sek110237 return (0); 18962926Sek110237 } 18972926Sek110237 18982926Sek110237 #define HIS_BUF_LEN (128*1024) 18992926Sek110237 19002926Sek110237 /* 19012926Sek110237 * Retrieve the command history of a pool. 19022926Sek110237 */ 19032926Sek110237 int 19042926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 19052926Sek110237 { 19062926Sek110237 char buf[HIS_BUF_LEN]; 19072926Sek110237 uint64_t off = 0; 19082926Sek110237 nvlist_t **records = NULL; 19092926Sek110237 uint_t numrecords = 0; 19102926Sek110237 int err, i; 19112926Sek110237 19122926Sek110237 do { 19132926Sek110237 uint64_t bytes_read = sizeof (buf); 19142926Sek110237 uint64_t leftover; 19152926Sek110237 19162926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 19172926Sek110237 break; 19182926Sek110237 19192926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 19202926Sek110237 if (!bytes_read) 19212926Sek110237 break; 19222926Sek110237 19232926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 19242926Sek110237 &leftover, &records, &numrecords)) != 0) 19252926Sek110237 break; 19262926Sek110237 off -= leftover; 19272926Sek110237 19282926Sek110237 /* CONSTCOND */ 19292926Sek110237 } while (1); 19302926Sek110237 19312926Sek110237 if (!err) { 19322926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 19332926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 19342926Sek110237 records, numrecords) == 0); 19352926Sek110237 } 19362926Sek110237 for (i = 0; i < numrecords; i++) 19372926Sek110237 nvlist_free(records[i]); 19382926Sek110237 free(records); 19392926Sek110237 19402926Sek110237 return (err); 19412926Sek110237 } 1942