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" 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)) { 1873237Slling (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")); 2073237Slling (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) { 2613237Slling (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); 280789Sahrens free(zhp); 281789Sahrens } 282789Sahrens 283789Sahrens /* 284789Sahrens * Return the name of the pool. 285789Sahrens */ 286789Sahrens const char * 287789Sahrens zpool_get_name(zpool_handle_t *zhp) 288789Sahrens { 289789Sahrens return (zhp->zpool_name); 290789Sahrens } 291789Sahrens 292789Sahrens /* 293789Sahrens * Return the GUID of the pool. 294789Sahrens */ 295789Sahrens uint64_t 296789Sahrens zpool_get_guid(zpool_handle_t *zhp) 297789Sahrens { 298789Sahrens uint64_t guid; 299789Sahrens 300789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 301789Sahrens &guid) == 0); 302789Sahrens return (guid); 303789Sahrens } 304789Sahrens 305789Sahrens /* 3062082Seschrock * Return the version of the pool. 3072082Seschrock */ 3082082Seschrock uint64_t 3092082Seschrock zpool_get_version(zpool_handle_t *zhp) 3102082Seschrock { 3112082Seschrock uint64_t version; 3122082Seschrock 3132082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3142082Seschrock &version) == 0); 3152082Seschrock 3162082Seschrock return (version); 3172082Seschrock } 3182082Seschrock 3192082Seschrock /* 320789Sahrens * Return the amount of space currently consumed by the pool. 321789Sahrens */ 322789Sahrens uint64_t 323789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 324789Sahrens { 325789Sahrens nvlist_t *nvroot; 326789Sahrens vdev_stat_t *vs; 327789Sahrens uint_t vsc; 328789Sahrens 329789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 330789Sahrens &nvroot) == 0); 331789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 332789Sahrens (uint64_t **)&vs, &vsc) == 0); 333789Sahrens 334789Sahrens return (vs->vs_alloc); 335789Sahrens } 336789Sahrens 337789Sahrens /* 338789Sahrens * Return the total space in the pool. 339789Sahrens */ 340789Sahrens uint64_t 341789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 342789Sahrens { 343789Sahrens nvlist_t *nvroot; 344789Sahrens vdev_stat_t *vs; 345789Sahrens uint_t vsc; 346789Sahrens 347789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 348789Sahrens &nvroot) == 0); 349789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 350789Sahrens (uint64_t **)&vs, &vsc) == 0); 351789Sahrens 352789Sahrens return (vs->vs_space); 353789Sahrens } 354789Sahrens 355789Sahrens /* 356789Sahrens * Return the alternate root for this pool, if any. 357789Sahrens */ 358789Sahrens int 359789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 360789Sahrens { 361789Sahrens zfs_cmd_t zc = { 0 }; 362789Sahrens 363789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3642082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3652676Seschrock zc.zc_value[0] == '\0') 366789Sahrens return (-1); 367789Sahrens 3682676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 369789Sahrens 370789Sahrens return (0); 371789Sahrens } 372789Sahrens 373789Sahrens /* 374789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 375789Sahrens */ 376789Sahrens int 377789Sahrens zpool_get_state(zpool_handle_t *zhp) 378789Sahrens { 379789Sahrens return (zhp->zpool_state); 380789Sahrens } 381789Sahrens 382789Sahrens /* 383789Sahrens * Create the named pool, using the provided vdev list. It is assumed 384789Sahrens * that the consumer has already validated the contents of the nvlist, so we 385789Sahrens * don't have to worry about error semantics. 386789Sahrens */ 387789Sahrens int 3882082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3892082Seschrock const char *altroot) 390789Sahrens { 391789Sahrens zfs_cmd_t zc = { 0 }; 3922082Seschrock char msg[1024]; 3932082Seschrock 3942082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3952082Seschrock "cannot create '%s'"), pool); 396789Sahrens 3972082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 3982082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 3992082Seschrock 4002082Seschrock if (altroot != NULL && altroot[0] != '/') 4013237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 4022082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 403789Sahrens 4042676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 405789Sahrens return (-1); 406789Sahrens 407789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 408789Sahrens 409789Sahrens if (altroot != NULL) 4102676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 411789Sahrens 4122082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4132676Seschrock zcmd_free_nvlists(&zc); 4142082Seschrock 415789Sahrens switch (errno) { 416789Sahrens case EBUSY: 417789Sahrens /* 418789Sahrens * This can happen if the user has specified the same 419789Sahrens * device multiple times. We can't reliably detect this 420789Sahrens * until we try to add it and see we already have a 421789Sahrens * label. 422789Sahrens */ 4232082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4242082Seschrock "one or more vdevs refer to the same device")); 4252082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 426789Sahrens 427789Sahrens case EOVERFLOW: 428789Sahrens /* 4292082Seschrock * This occurs when one of the devices is below 430789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 431789Sahrens * device was the problem device since there's no 432789Sahrens * reliable way to determine device size from userland. 433789Sahrens */ 434789Sahrens { 435789Sahrens char buf[64]; 436789Sahrens 437789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 438789Sahrens 4392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4402082Seschrock "one or more devices is less than the " 4412082Seschrock "minimum size (%s)"), buf); 442789Sahrens } 4432082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 444789Sahrens 445789Sahrens case ENOSPC: 4462082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4472082Seschrock "one or more devices is out of space")); 4482082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 449789Sahrens 450789Sahrens default: 4512082Seschrock return (zpool_standard_error(hdl, errno, msg)); 452789Sahrens } 453789Sahrens } 454789Sahrens 4552676Seschrock zcmd_free_nvlists(&zc); 456789Sahrens 457789Sahrens /* 458789Sahrens * If this is an alternate root pool, then we automatically set the 4592676Seschrock * mountpoint of the root dataset to be '/'. 460789Sahrens */ 461789Sahrens if (altroot != NULL) { 462789Sahrens zfs_handle_t *zhp; 463789Sahrens 4642082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4652676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4662676Seschrock "/") == 0); 467789Sahrens 468789Sahrens zfs_close(zhp); 469789Sahrens } 470789Sahrens 471789Sahrens return (0); 472789Sahrens } 473789Sahrens 474789Sahrens /* 475789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 476789Sahrens * datasets left in the pool. 477789Sahrens */ 478789Sahrens int 479789Sahrens zpool_destroy(zpool_handle_t *zhp) 480789Sahrens { 481789Sahrens zfs_cmd_t zc = { 0 }; 482789Sahrens zfs_handle_t *zfp = NULL; 4832082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4842082Seschrock char msg[1024]; 485789Sahrens 486789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4872082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4882082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 489789Sahrens return (-1); 490789Sahrens 4912856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 492789Sahrens return (-1); 493789Sahrens 494789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 495789Sahrens 4962082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 4972082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4982082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 499789Sahrens 5002082Seschrock if (errno == EROFS) { 5012082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5022082Seschrock "one or more devices is read only")); 5032082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5042082Seschrock } else { 5052082Seschrock (void) zpool_standard_error(hdl, errno, msg); 506789Sahrens } 507789Sahrens 508789Sahrens if (zfp) 509789Sahrens zfs_close(zfp); 510789Sahrens return (-1); 511789Sahrens } 512789Sahrens 513789Sahrens if (zfp) { 514789Sahrens remove_mountpoint(zfp); 515789Sahrens zfs_close(zfp); 516789Sahrens } 517789Sahrens 518789Sahrens return (0); 519789Sahrens } 520789Sahrens 521789Sahrens /* 522789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 523789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 524789Sahrens */ 525789Sahrens int 526789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 527789Sahrens { 5282676Seschrock zfs_cmd_t zc = { 0 }; 5292082Seschrock int ret; 5302082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5312082Seschrock char msg[1024]; 5322082Seschrock nvlist_t **spares; 5332082Seschrock uint_t nspares; 5342082Seschrock 5352082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5362082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5372082Seschrock 5382082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5392082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5402082Seschrock &spares, &nspares) == 0) { 5412082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5422082Seschrock "upgraded to add hot spares")); 5432082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5442082Seschrock } 545789Sahrens 5462676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5472082Seschrock return (-1); 548789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 549789Sahrens 5502082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 551789Sahrens switch (errno) { 552789Sahrens case EBUSY: 553789Sahrens /* 554789Sahrens * This can happen if the user has specified the same 555789Sahrens * device multiple times. We can't reliably detect this 556789Sahrens * until we try to add it and see we already have a 557789Sahrens * label. 558789Sahrens */ 5592082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5602082Seschrock "one or more vdevs refer to the same device")); 5612082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 562789Sahrens break; 563789Sahrens 564789Sahrens case EOVERFLOW: 565789Sahrens /* 566789Sahrens * This occurrs when one of the devices is below 567789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 568789Sahrens * device was the problem device since there's no 569789Sahrens * reliable way to determine device size from userland. 570789Sahrens */ 571789Sahrens { 572789Sahrens char buf[64]; 573789Sahrens 574789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 575789Sahrens 5762082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5772082Seschrock "device is less than the minimum " 5782082Seschrock "size (%s)"), buf); 579789Sahrens } 5802082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5812082Seschrock break; 5822082Seschrock 5832082Seschrock case ENOTSUP: 5842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5852082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5862082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 587789Sahrens break; 588789Sahrens 589789Sahrens default: 5902082Seschrock (void) zpool_standard_error(hdl, errno, msg); 591789Sahrens } 592789Sahrens 5932082Seschrock ret = -1; 5942082Seschrock } else { 5952082Seschrock ret = 0; 596789Sahrens } 597789Sahrens 5982676Seschrock zcmd_free_nvlists(&zc); 599789Sahrens 6002082Seschrock return (ret); 601789Sahrens } 602789Sahrens 603789Sahrens /* 604789Sahrens * Exports the pool from the system. The caller must ensure that there are no 605789Sahrens * mounted datasets in the pool. 606789Sahrens */ 607789Sahrens int 608789Sahrens zpool_export(zpool_handle_t *zhp) 609789Sahrens { 610789Sahrens zfs_cmd_t zc = { 0 }; 611789Sahrens 612789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 613789Sahrens return (-1); 614789Sahrens 615789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 616789Sahrens 6172082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6183237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 6192082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6202082Seschrock zhp->zpool_name)); 621789Sahrens 622789Sahrens return (0); 623789Sahrens } 624789Sahrens 625789Sahrens /* 626789Sahrens * Import the given pool using the known configuration. The configuration 627789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 628789Sahrens * parameters control whether the pool is imported with a different name or with 629789Sahrens * an alternate root, respectively. 630789Sahrens */ 631789Sahrens int 6322082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6332082Seschrock const char *altroot) 634789Sahrens { 6352676Seschrock zfs_cmd_t zc = { 0 }; 636789Sahrens char *thename; 637789Sahrens char *origname; 638789Sahrens int ret; 639789Sahrens 640789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 641789Sahrens &origname) == 0); 642789Sahrens 643789Sahrens if (newname != NULL) { 6442082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6453237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6462082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6472082Seschrock newname)); 648789Sahrens thename = (char *)newname; 649789Sahrens } else { 650789Sahrens thename = origname; 651789Sahrens } 652789Sahrens 6532082Seschrock if (altroot != NULL && altroot[0] != '/') 6543237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6552082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6562082Seschrock altroot)); 657789Sahrens 658789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 659789Sahrens 660789Sahrens if (altroot != NULL) 6612676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 662789Sahrens else 6632676Seschrock zc.zc_value[0] = '\0'; 664789Sahrens 665789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6661544Seschrock &zc.zc_guid) == 0); 667789Sahrens 6682676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6692082Seschrock return (-1); 670789Sahrens 671789Sahrens ret = 0; 6722082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 673789Sahrens char desc[1024]; 674789Sahrens if (newname == NULL) 675789Sahrens (void) snprintf(desc, sizeof (desc), 676789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 677789Sahrens thename); 678789Sahrens else 679789Sahrens (void) snprintf(desc, sizeof (desc), 680789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 681789Sahrens origname, thename); 682789Sahrens 683789Sahrens switch (errno) { 6841544Seschrock case ENOTSUP: 6851544Seschrock /* 6861544Seschrock * Unsupported version. 6871544Seschrock */ 6882082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6891544Seschrock break; 6901544Seschrock 6912174Seschrock case EINVAL: 6922174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6932174Seschrock break; 6942174Seschrock 695789Sahrens default: 6962082Seschrock (void) zpool_standard_error(hdl, errno, desc); 697789Sahrens } 698789Sahrens 699789Sahrens ret = -1; 700789Sahrens } else { 701789Sahrens zpool_handle_t *zhp; 702789Sahrens /* 703789Sahrens * This should never fail, but play it safe anyway. 704789Sahrens */ 7052142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7062142Seschrock ret = -1; 7072142Seschrock } else if (zhp != NULL) { 708789Sahrens ret = zpool_create_zvol_links(zhp); 709789Sahrens zpool_close(zhp); 710789Sahrens } 711789Sahrens } 712789Sahrens 7132676Seschrock zcmd_free_nvlists(&zc); 714789Sahrens return (ret); 715789Sahrens } 716789Sahrens 717789Sahrens /* 718789Sahrens * Scrub the pool. 719789Sahrens */ 720789Sahrens int 721789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 722789Sahrens { 723789Sahrens zfs_cmd_t zc = { 0 }; 724789Sahrens char msg[1024]; 7252082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 726789Sahrens 727789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 728789Sahrens zc.zc_cookie = type; 729789Sahrens 7302082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 731789Sahrens return (0); 732789Sahrens 733789Sahrens (void) snprintf(msg, sizeof (msg), 734789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 735789Sahrens 7362082Seschrock if (errno == EBUSY) 7372082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7382082Seschrock else 7392082Seschrock return (zpool_standard_error(hdl, errno, msg)); 740789Sahrens } 741789Sahrens 7422468Sek110237 /* 7432468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7442468Sek110237 * spare; but FALSE if its an INUSE spare. 7452468Sek110237 */ 7462082Seschrock static nvlist_t * 7472082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7482468Sek110237 boolean_t *avail_spare) 7491544Seschrock { 7501544Seschrock uint_t c, children; 7511544Seschrock nvlist_t **child; 7522082Seschrock uint64_t theguid, present; 7531544Seschrock char *path; 7541544Seschrock uint64_t wholedisk = 0; 7552082Seschrock nvlist_t *ret; 7561544Seschrock 7572082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7581544Seschrock 7591544Seschrock if (search == NULL && 7601544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7611544Seschrock /* 7621544Seschrock * If the device has never been present since import, the only 7631544Seschrock * reliable way to match the vdev is by GUID. 7641544Seschrock */ 7652082Seschrock if (theguid == guid) 7662082Seschrock return (nv); 7671544Seschrock } else if (search != NULL && 7681544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7691544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7701544Seschrock &wholedisk); 7711544Seschrock if (wholedisk) { 7721544Seschrock /* 7731544Seschrock * For whole disks, the internal path has 's0', but the 7741544Seschrock * path passed in by the user doesn't. 7751544Seschrock */ 7761544Seschrock if (strlen(search) == strlen(path) - 2 && 7771544Seschrock strncmp(search, path, strlen(search)) == 0) 7782082Seschrock return (nv); 7791544Seschrock } else if (strcmp(search, path) == 0) { 7802082Seschrock return (nv); 7811544Seschrock } 7821544Seschrock } 7831544Seschrock 7841544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7851544Seschrock &child, &children) != 0) 7862082Seschrock return (NULL); 7871544Seschrock 7881544Seschrock for (c = 0; c < children; c++) 7892082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7902468Sek110237 avail_spare)) != NULL) 7911544Seschrock return (ret); 7921544Seschrock 7932082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 7942082Seschrock &child, &children) == 0) { 7952082Seschrock for (c = 0; c < children; c++) { 7962082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7972468Sek110237 avail_spare)) != NULL) { 7982468Sek110237 *avail_spare = B_TRUE; 7992082Seschrock return (ret); 8002082Seschrock } 8012082Seschrock } 8022082Seschrock } 8032082Seschrock 8042082Seschrock return (NULL); 8051544Seschrock } 8061544Seschrock 8072082Seschrock nvlist_t * 8082468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8091544Seschrock { 8101544Seschrock char buf[MAXPATHLEN]; 8111544Seschrock const char *search; 8121544Seschrock char *end; 8131544Seschrock nvlist_t *nvroot; 8141544Seschrock uint64_t guid; 8151544Seschrock 8161613Seschrock guid = strtoull(path, &end, 10); 8171544Seschrock if (guid != 0 && *end == '\0') { 8181544Seschrock search = NULL; 8191544Seschrock } else if (path[0] != '/') { 8201544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8211544Seschrock search = buf; 8221544Seschrock } else { 8231544Seschrock search = path; 8241544Seschrock } 8251544Seschrock 8261544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8271544Seschrock &nvroot) == 0); 8281544Seschrock 8292468Sek110237 *avail_spare = B_FALSE; 8302468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8312468Sek110237 } 8322468Sek110237 8332468Sek110237 /* 8342468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8352468Sek110237 */ 8362468Sek110237 static boolean_t 8372468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8382468Sek110237 { 8392468Sek110237 uint64_t spare_guid; 8402468Sek110237 nvlist_t *nvroot; 8412468Sek110237 nvlist_t **spares; 8422468Sek110237 uint_t nspares; 8432468Sek110237 int i; 8442468Sek110237 8452468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8462468Sek110237 &nvroot) == 0); 8472468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8482468Sek110237 &spares, &nspares) == 0) { 8492468Sek110237 for (i = 0; i < nspares; i++) { 8502468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8512468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8522468Sek110237 if (guid == spare_guid) 8532468Sek110237 return (B_TRUE); 8542468Sek110237 } 8552468Sek110237 } 8562468Sek110237 8572468Sek110237 return (B_FALSE); 8581544Seschrock } 8591544Seschrock 860789Sahrens /* 861789Sahrens * Bring the specified vdev online 862789Sahrens */ 863789Sahrens int 864789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 865789Sahrens { 866789Sahrens zfs_cmd_t zc = { 0 }; 867789Sahrens char msg[1024]; 8682082Seschrock nvlist_t *tgt; 8692468Sek110237 boolean_t avail_spare; 8702082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 871789Sahrens 8721544Seschrock (void) snprintf(msg, sizeof (msg), 8731544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 874789Sahrens 8751544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8762468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8772082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 878789Sahrens 8792468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8802468Sek110237 8812468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8822082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8832082Seschrock 8842082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8851544Seschrock return (0); 886789Sahrens 8872082Seschrock return (zpool_standard_error(hdl, errno, msg)); 888789Sahrens } 889789Sahrens 890789Sahrens /* 891789Sahrens * Take the specified vdev offline 892789Sahrens */ 893789Sahrens int 8941485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 895789Sahrens { 896789Sahrens zfs_cmd_t zc = { 0 }; 897789Sahrens char msg[1024]; 8982082Seschrock nvlist_t *tgt; 8992468Sek110237 boolean_t avail_spare; 9002082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 901789Sahrens 9021544Seschrock (void) snprintf(msg, sizeof (msg), 9031544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9041544Seschrock 905789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9062468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9072082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9082082Seschrock 9092468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9102468Sek110237 9112468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9122082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9132082Seschrock 9141485Slling zc.zc_cookie = istmp; 9151485Slling 9162082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 917789Sahrens return (0); 918789Sahrens 919789Sahrens switch (errno) { 9202082Seschrock case EBUSY: 921789Sahrens 922789Sahrens /* 923789Sahrens * There are no other replicas of this device. 924789Sahrens */ 9252082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9262082Seschrock 9272082Seschrock default: 9282082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9292082Seschrock } 9302082Seschrock } 931789Sahrens 9322082Seschrock /* 9332082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 9342082Seschrock * a hot spare. 9352082Seschrock */ 9362082Seschrock static boolean_t 9372082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 9382082Seschrock { 9392082Seschrock nvlist_t **child; 9402082Seschrock uint_t c, children; 9412082Seschrock char *type; 9422082Seschrock 9432082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9442082Seschrock &children) == 0) { 9452082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9462082Seschrock &type) == 0); 9472082Seschrock 9482082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9492082Seschrock children == 2 && child[which] == tgt) 9502082Seschrock return (B_TRUE); 9512082Seschrock 9522082Seschrock for (c = 0; c < children; c++) 9532082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9542082Seschrock return (B_TRUE); 955789Sahrens } 9562082Seschrock 9572082Seschrock return (B_FALSE); 958789Sahrens } 959789Sahrens 960789Sahrens /* 961789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 962789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 963789Sahrens */ 964789Sahrens int 965789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 966789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 967789Sahrens { 968789Sahrens zfs_cmd_t zc = { 0 }; 969789Sahrens char msg[1024]; 970789Sahrens int ret; 9712082Seschrock nvlist_t *tgt; 9722468Sek110237 boolean_t avail_spare; 9732082Seschrock uint64_t val; 9742082Seschrock char *path; 9752082Seschrock nvlist_t **child; 9762082Seschrock uint_t children; 9772082Seschrock nvlist_t *config_root; 9782082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 979789Sahrens 9801544Seschrock if (replacing) 9811544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9821544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9831544Seschrock else 9841544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9851544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9861544Seschrock 987789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9882468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9892082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9902082Seschrock 9912468Sek110237 if (avail_spare) 9922082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9932082Seschrock 9942082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9952082Seschrock zc.zc_cookie = replacing; 9962082Seschrock 9972082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 9982082Seschrock &child, &children) != 0 || children != 1) { 9992082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10002082Seschrock "new device must be a single disk")); 10012082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10021544Seschrock } 10032082Seschrock 10042082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10052082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10062082Seschrock 10072082Seschrock /* 10082082Seschrock * If the target is a hot spare that has been swapped in, we can only 10092082Seschrock * replace it with another hot spare. 10102082Seschrock */ 10112082Seschrock if (replacing && 10122082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10132082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10142468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10152468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10172082Seschrock "can only be replaced by another hot spare")); 10182082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10192082Seschrock } 10202082Seschrock 10212082Seschrock /* 10222082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10232082Seschrock * already spared device. 10242082Seschrock */ 10252082Seschrock if (replacing && 10262082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10272468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10282082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10292082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10302082Seschrock "device has already been replaced with a spare")); 10312082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10322082Seschrock } 1033789Sahrens 10342676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 10352082Seschrock return (-1); 1036789Sahrens 10372082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1038789Sahrens 10392676Seschrock zcmd_free_nvlists(&zc); 1040789Sahrens 1041789Sahrens if (ret == 0) 1042789Sahrens return (0); 1043789Sahrens 1044789Sahrens switch (errno) { 10451544Seschrock case ENOTSUP: 1046789Sahrens /* 1047789Sahrens * Can't attach to or replace this type of vdev. 1048789Sahrens */ 1049789Sahrens if (replacing) 10502082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10512082Seschrock "cannot replace a replacing device")); 1052789Sahrens else 10532082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10542082Seschrock "can only attach to mirrors and top-level " 10552082Seschrock "disks")); 10562082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1057789Sahrens break; 1058789Sahrens 10591544Seschrock case EINVAL: 1060789Sahrens /* 1061789Sahrens * The new device must be a single disk. 1062789Sahrens */ 10632082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10642082Seschrock "new device must be a single disk")); 10652082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1066789Sahrens break; 1067789Sahrens 10681544Seschrock case EBUSY: 10692082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10702082Seschrock new_disk); 10712082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1072789Sahrens break; 1073789Sahrens 10741544Seschrock case EOVERFLOW: 1075789Sahrens /* 1076789Sahrens * The new device is too small. 1077789Sahrens */ 10782082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10792082Seschrock "device is too small")); 10802082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1081789Sahrens break; 1082789Sahrens 10831544Seschrock case EDOM: 1084789Sahrens /* 1085789Sahrens * The new device has a different alignment requirement. 1086789Sahrens */ 10872082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10882082Seschrock "devices have different sector alignment")); 10892082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1090789Sahrens break; 1091789Sahrens 10921544Seschrock case ENAMETOOLONG: 1093789Sahrens /* 1094789Sahrens * The resulting top-level vdev spec won't fit in the label. 1095789Sahrens */ 10962082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1097789Sahrens break; 1098789Sahrens 10991544Seschrock default: 11002082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1101789Sahrens } 1102789Sahrens 11032082Seschrock return (-1); 1104789Sahrens } 1105789Sahrens 1106789Sahrens /* 1107789Sahrens * Detach the specified device. 1108789Sahrens */ 1109789Sahrens int 1110789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1111789Sahrens { 1112789Sahrens zfs_cmd_t zc = { 0 }; 1113789Sahrens char msg[1024]; 11142082Seschrock nvlist_t *tgt; 11152468Sek110237 boolean_t avail_spare; 11162082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1117789Sahrens 11181544Seschrock (void) snprintf(msg, sizeof (msg), 11191544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11201544Seschrock 1121789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11222468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11232082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1124789Sahrens 11252468Sek110237 if (avail_spare) 11262082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11272082Seschrock 11282082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11292082Seschrock 11302082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1131789Sahrens return (0); 1132789Sahrens 1133789Sahrens switch (errno) { 1134789Sahrens 11351544Seschrock case ENOTSUP: 1136789Sahrens /* 1137789Sahrens * Can't detach from this type of vdev. 1138789Sahrens */ 11392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11402082Seschrock "applicable to mirror and replacing vdevs")); 11412082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1142789Sahrens break; 1143789Sahrens 11441544Seschrock case EBUSY: 1145789Sahrens /* 1146789Sahrens * There are no other replicas of this device. 1147789Sahrens */ 11482082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1149789Sahrens break; 1150789Sahrens 11511544Seschrock default: 11522082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11531544Seschrock } 11541544Seschrock 11552082Seschrock return (-1); 11562082Seschrock } 11572082Seschrock 11582082Seschrock /* 11592082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11602082Seschrock */ 11612082Seschrock int 11622082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11632082Seschrock { 11642082Seschrock zfs_cmd_t zc = { 0 }; 11652082Seschrock char msg[1024]; 11662082Seschrock nvlist_t *tgt; 11672468Sek110237 boolean_t avail_spare; 11682082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11692082Seschrock 11702082Seschrock (void) snprintf(msg, sizeof (msg), 11712082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11722082Seschrock 11732082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11742468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11752082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11762082Seschrock 11772468Sek110237 if (!avail_spare) { 11782082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11793377Seschrock "only inactive hot spares can be removed")); 11802082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11812082Seschrock } 11822082Seschrock 11832082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11842082Seschrock 11852082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11862082Seschrock return (0); 11872082Seschrock 11882082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11891544Seschrock } 11901544Seschrock 11911544Seschrock /* 11921544Seschrock * Clear the errors for the pool, or the particular device if specified. 11931544Seschrock */ 11941544Seschrock int 11951544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 11961544Seschrock { 11971544Seschrock zfs_cmd_t zc = { 0 }; 11981544Seschrock char msg[1024]; 11992082Seschrock nvlist_t *tgt; 12002468Sek110237 boolean_t avail_spare; 12012082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12021544Seschrock 12031544Seschrock if (path) 12041544Seschrock (void) snprintf(msg, sizeof (msg), 12051544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12062676Seschrock path); 12071544Seschrock else 12081544Seschrock (void) snprintf(msg, sizeof (msg), 12091544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12101544Seschrock zhp->zpool_name); 12111544Seschrock 12121544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12132082Seschrock if (path) { 12142468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12152082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12162082Seschrock 12172468Sek110237 if (avail_spare) 12182082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12192082Seschrock 12202082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12212082Seschrock &zc.zc_guid) == 0); 12221544Seschrock } 12231544Seschrock 12242082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12251544Seschrock return (0); 12261544Seschrock 12272082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1228789Sahrens } 1229789Sahrens 12303126Sahl /* 12313126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 12323126Sahl * hierarchy. 12333126Sahl */ 12343126Sahl int 12353126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 12363126Sahl void *data) 1237789Sahrens { 12383126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 12393126Sahl char (*paths)[MAXPATHLEN]; 12403126Sahl size_t size = 4; 12413126Sahl int curr, fd, base, ret = 0; 12423126Sahl DIR *dirp; 12433126Sahl struct dirent *dp; 12443126Sahl struct stat st; 12453126Sahl 12463126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 12473126Sahl return (errno == ENOENT ? 0 : -1); 12483126Sahl 12493126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 12503126Sahl int err = errno; 12513126Sahl (void) close(base); 12523126Sahl return (err == ENOENT ? 0 : -1); 12533126Sahl } 1254789Sahrens 1255789Sahrens /* 12563126Sahl * Oddly this wasn't a directory -- ignore that failure since we 12573126Sahl * know there are no links lower in the (non-existant) hierarchy. 1258789Sahrens */ 12593126Sahl if (!S_ISDIR(st.st_mode)) { 12603126Sahl (void) close(base); 12613126Sahl return (0); 12623126Sahl } 12633126Sahl 12643126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 12653126Sahl (void) close(base); 12663126Sahl return (-1); 1267789Sahrens } 1268789Sahrens 12693126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 12703126Sahl curr = 0; 12713126Sahl 12723126Sahl while (curr >= 0) { 12733126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 12743126Sahl goto err; 12753126Sahl 12763126Sahl if (S_ISDIR(st.st_mode)) { 12773126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 12783126Sahl goto err; 12793126Sahl 12803126Sahl if ((dirp = fdopendir(fd)) == NULL) { 12813126Sahl (void) close(fd); 12823126Sahl goto err; 12833126Sahl } 12843126Sahl 12853126Sahl while ((dp = readdir(dirp)) != NULL) { 12863126Sahl if (dp->d_name[0] == '.') 12873126Sahl continue; 12883126Sahl 12893126Sahl if (curr + 1 == size) { 12903126Sahl paths = zfs_realloc(hdl, paths, 12913126Sahl size * sizeof (paths[0]), 12923126Sahl size * 2 * sizeof (paths[0])); 12933126Sahl if (paths == NULL) { 12943126Sahl (void) closedir(dirp); 12953126Sahl (void) close(fd); 12963126Sahl goto err; 12973126Sahl } 12983126Sahl 12993126Sahl size *= 2; 13003126Sahl } 13013126Sahl 13023126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 13033126Sahl sizeof (paths[curr + 1])); 13043126Sahl (void) strlcat(paths[curr], "/", 13053126Sahl sizeof (paths[curr])); 13063126Sahl (void) strlcat(paths[curr], dp->d_name, 13073126Sahl sizeof (paths[curr])); 13083126Sahl curr++; 13093126Sahl } 13103126Sahl 13113126Sahl (void) closedir(dirp); 13123126Sahl 13133126Sahl } else { 13143126Sahl if ((ret = cb(paths[curr], data)) != 0) 13153126Sahl break; 13163126Sahl } 13173126Sahl 13183126Sahl curr--; 13193126Sahl } 13203126Sahl 13213126Sahl free(paths); 13223126Sahl (void) close(base); 13233126Sahl 13243126Sahl return (ret); 13253126Sahl 13263126Sahl err: 13273126Sahl free(paths); 13283126Sahl (void) close(base); 13293126Sahl return (-1); 13303126Sahl } 13313126Sahl 13323126Sahl typedef struct zvol_cb { 13333126Sahl zpool_handle_t *zcb_pool; 13343126Sahl boolean_t zcb_create; 13353126Sahl } zvol_cb_t; 13363126Sahl 13373126Sahl /*ARGSUSED*/ 13383126Sahl static int 13393126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 13403126Sahl { 13413126Sahl int ret; 13423126Sahl 13433126Sahl if (ZFS_IS_VOLUME(zhp)) 13443126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 13453126Sahl 13463126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1347789Sahrens 1348789Sahrens zfs_close(zhp); 13493126Sahl 1350789Sahrens return (ret); 1351789Sahrens } 1352789Sahrens 1353789Sahrens /* 1354789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1355789Sahrens */ 1356789Sahrens int 1357789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1358789Sahrens { 1359789Sahrens zfs_handle_t *zfp; 1360789Sahrens int ret; 1361789Sahrens 1362789Sahrens /* 1363789Sahrens * If the pool is unavailable, just return success. 1364789Sahrens */ 13652082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 13662082Seschrock zhp->zpool_name)) == NULL) 1367789Sahrens return (0); 1368789Sahrens 13693126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1370789Sahrens 1371789Sahrens zfs_close(zfp); 1372789Sahrens return (ret); 1373789Sahrens } 1374789Sahrens 13753126Sahl static int 13763126Sahl do_zvol_remove(const char *dataset, void *data) 13773126Sahl { 13783126Sahl zpool_handle_t *zhp = data; 13793126Sahl 13803126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 13813126Sahl } 13823126Sahl 1383789Sahrens /* 13843126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 13853126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 13863126Sahl * operation. 1387789Sahrens */ 1388789Sahrens int 1389789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1390789Sahrens { 13913126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1392789Sahrens } 13931354Seschrock 13941354Seschrock /* 13951354Seschrock * Convert from a devid string to a path. 13961354Seschrock */ 13971354Seschrock static char * 13981354Seschrock devid_to_path(char *devid_str) 13991354Seschrock { 14001354Seschrock ddi_devid_t devid; 14011354Seschrock char *minor; 14021354Seschrock char *path; 14031354Seschrock devid_nmlist_t *list = NULL; 14041354Seschrock int ret; 14051354Seschrock 14061354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 14071354Seschrock return (NULL); 14081354Seschrock 14091354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 14101354Seschrock 14111354Seschrock devid_str_free(minor); 14121354Seschrock devid_free(devid); 14131354Seschrock 14141354Seschrock if (ret != 0) 14151354Seschrock return (NULL); 14161354Seschrock 14172082Seschrock if ((path = strdup(list[0].devname)) == NULL) 14182082Seschrock return (NULL); 14192082Seschrock 14201354Seschrock devid_free_nmlist(list); 14211354Seschrock 14221354Seschrock return (path); 14231354Seschrock } 14241354Seschrock 14251354Seschrock /* 14261354Seschrock * Convert from a path to a devid string. 14271354Seschrock */ 14281354Seschrock static char * 14291354Seschrock path_to_devid(const char *path) 14301354Seschrock { 14311354Seschrock int fd; 14321354Seschrock ddi_devid_t devid; 14331354Seschrock char *minor, *ret; 14341354Seschrock 14351354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 14361354Seschrock return (NULL); 14371354Seschrock 14381354Seschrock minor = NULL; 14391354Seschrock ret = NULL; 14401354Seschrock if (devid_get(fd, &devid) == 0) { 14411354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 14421354Seschrock ret = devid_str_encode(devid, minor); 14431354Seschrock if (minor != NULL) 14441354Seschrock devid_str_free(minor); 14451354Seschrock devid_free(devid); 14461354Seschrock } 14471354Seschrock (void) close(fd); 14481354Seschrock 14491354Seschrock return (ret); 14501354Seschrock } 14511354Seschrock 14521354Seschrock /* 14531354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 14541354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 14551354Seschrock * type 'zpool status', and we'll display the correct information anyway. 14561354Seschrock */ 14571354Seschrock static void 14581354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 14591354Seschrock { 14601354Seschrock zfs_cmd_t zc = { 0 }; 14611354Seschrock 14621354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14632676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 14641354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14651544Seschrock &zc.zc_guid) == 0); 14661354Seschrock 14672082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 14681354Seschrock } 14691354Seschrock 14701354Seschrock /* 14711354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 14721354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 14731354Seschrock * We also check if this is a whole disk, in which case we strip off the 14741354Seschrock * trailing 's0' slice name. 14751354Seschrock * 14761354Seschrock * This routine is also responsible for identifying when disks have been 14771354Seschrock * reconfigured in a new location. The kernel will have opened the device by 14781354Seschrock * devid, but the path will still refer to the old location. To catch this, we 14791354Seschrock * first do a path -> devid translation (which is fast for the common case). If 14801354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 14811354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 14821354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 14831354Seschrock * of these checks. 14841354Seschrock */ 14851354Seschrock char * 14862082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 14871354Seschrock { 14881354Seschrock char *path, *devid; 14891544Seschrock uint64_t value; 14901544Seschrock char buf[64]; 14911354Seschrock 14921544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14931544Seschrock &value) == 0) { 14941544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14951544Seschrock &value) == 0); 14962856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 14972856Snd150628 (u_longlong_t)value); 14981544Seschrock path = buf; 14991544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 15001354Seschrock 15011354Seschrock if (zhp != NULL && 15021354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 15031354Seschrock /* 15041354Seschrock * Determine if the current path is correct. 15051354Seschrock */ 15061354Seschrock char *newdevid = path_to_devid(path); 15071354Seschrock 15081354Seschrock if (newdevid == NULL || 15091354Seschrock strcmp(devid, newdevid) != 0) { 15101354Seschrock char *newpath; 15111354Seschrock 15121354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 15131354Seschrock /* 15141354Seschrock * Update the path appropriately. 15151354Seschrock */ 15161354Seschrock set_path(zhp, nv, newpath); 15172082Seschrock if (nvlist_add_string(nv, 15182082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 15192082Seschrock verify(nvlist_lookup_string(nv, 15202082Seschrock ZPOOL_CONFIG_PATH, 15212082Seschrock &path) == 0); 15221354Seschrock free(newpath); 15231354Seschrock } 15241354Seschrock } 15251354Seschrock 15262082Seschrock if (newdevid) 15272082Seschrock devid_str_free(newdevid); 15281354Seschrock } 15291354Seschrock 15301354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 15311354Seschrock path += 9; 15321354Seschrock 15331354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 15341544Seschrock &value) == 0 && value) { 15352082Seschrock char *tmp = zfs_strdup(hdl, path); 15362082Seschrock if (tmp == NULL) 15372082Seschrock return (NULL); 15381354Seschrock tmp[strlen(path) - 2] = '\0'; 15391354Seschrock return (tmp); 15401354Seschrock } 15411354Seschrock } else { 15421354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 15432082Seschrock 15442082Seschrock /* 15452082Seschrock * If it's a raidz device, we need to stick in the parity level. 15462082Seschrock */ 15472082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 15482082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 15492082Seschrock &value) == 0); 15502082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 15512856Snd150628 (u_longlong_t)value); 15522082Seschrock path = buf; 15532082Seschrock } 15541354Seschrock } 15551354Seschrock 15562082Seschrock return (zfs_strdup(hdl, path)); 15571354Seschrock } 15581544Seschrock 15591544Seschrock static int 15601544Seschrock zbookmark_compare(const void *a, const void *b) 15611544Seschrock { 15621544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 15631544Seschrock } 15641544Seschrock 15651544Seschrock /* 15661544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 15671544Seschrock * caller. 15681544Seschrock */ 15691544Seschrock int 15703444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 15711544Seschrock { 15721544Seschrock zfs_cmd_t zc = { 0 }; 15731544Seschrock uint64_t count; 15742676Seschrock zbookmark_t *zb = NULL; 15753444Sek110237 int i; 15761544Seschrock 15771544Seschrock /* 15781544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 15791544Seschrock * has increased, allocate more space and continue until we get the 15801544Seschrock * entire list. 15811544Seschrock */ 15821544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 15831544Seschrock &count) == 0); 15842676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 15852856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 15862082Seschrock return (-1); 15872676Seschrock zc.zc_nvlist_dst_size = count; 15881544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15891544Seschrock for (;;) { 15902082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 15912082Seschrock &zc) != 0) { 15922676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15931544Seschrock if (errno == ENOMEM) { 15942676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 15952082Seschrock zfs_alloc(zhp->zpool_hdl, 15962856Snd150628 zc.zc_nvlist_dst_size)) == (uintptr_t)NULL) 15972082Seschrock return (-1); 15981544Seschrock } else { 15991544Seschrock return (-1); 16001544Seschrock } 16011544Seschrock } else { 16021544Seschrock break; 16031544Seschrock } 16041544Seschrock } 16051544Seschrock 16061544Seschrock /* 16071544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 16081544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 16092676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 16101544Seschrock * _not_ copied as part of the process. So we point the start of our 16111544Seschrock * array appropriate and decrement the total number of elements. 16121544Seschrock */ 16132676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 16142676Seschrock zc.zc_nvlist_dst_size; 16152676Seschrock count -= zc.zc_nvlist_dst_size; 16161544Seschrock 16171544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 16181544Seschrock 16193444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 16201544Seschrock 16211544Seschrock /* 16223444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 16231544Seschrock */ 16241544Seschrock for (i = 0; i < count; i++) { 16251544Seschrock nvlist_t *nv; 16261544Seschrock 1627*3700Sek110237 /* ignoring zb_blkid and zb_level for now */ 1628*3700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 1629*3700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 16301544Seschrock continue; 16311544Seschrock 16323444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 16333444Sek110237 goto nomem; 16343444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 16353444Sek110237 zb[i].zb_objset) != 0) { 16363444Sek110237 nvlist_free(nv); 16372082Seschrock goto nomem; 16383444Sek110237 } 16393444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 16403444Sek110237 zb[i].zb_object) != 0) { 16413444Sek110237 nvlist_free(nv); 16423444Sek110237 goto nomem; 16431544Seschrock } 16443444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 16453444Sek110237 nvlist_free(nv); 16463444Sek110237 goto nomem; 16473444Sek110237 } 16483444Sek110237 nvlist_free(nv); 16491544Seschrock } 16501544Seschrock 16513265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 16521544Seschrock return (0); 16532082Seschrock 16542082Seschrock nomem: 16552676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16562082Seschrock return (no_memory(zhp->zpool_hdl)); 16571544Seschrock } 16581760Seschrock 16591760Seschrock /* 16601760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16611760Seschrock */ 16621760Seschrock int 16631760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16641760Seschrock { 16651760Seschrock zfs_cmd_t zc = { 0 }; 16662082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16671760Seschrock 16681760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16692082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 16703237Slling return (zpool_standard_error_fmt(hdl, errno, 16712082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 16722082Seschrock zhp->zpool_name)); 16731760Seschrock 16741760Seschrock return (0); 16751760Seschrock } 16762926Sek110237 16772926Sek110237 /* 16782926Sek110237 * Log command history. 16792926Sek110237 * 16802926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 16812926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 16822926Sek110237 * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the 16832926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 16842926Sek110237 */ 16852926Sek110237 void 16862926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 16872926Sek110237 boolean_t pool, boolean_t pool_create) 16882926Sek110237 { 16892926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 16902926Sek110237 char *dspath; 16912926Sek110237 zfs_cmd_t zc = { 0 }; 16922926Sek110237 int i; 16932926Sek110237 16942926Sek110237 /* construct the command string */ 16952926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 16962926Sek110237 for (i = 0; i < argc; i++) { 16972926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 16982926Sek110237 break; 16992926Sek110237 (void) strcat(cmd_buf, " "); 17002926Sek110237 (void) strcat(cmd_buf, argv[i]); 17012926Sek110237 } 17022926Sek110237 17032926Sek110237 /* figure out the poolname */ 17042926Sek110237 dspath = strpbrk(path, "/@"); 17052926Sek110237 if (dspath == NULL) { 17062926Sek110237 (void) strcpy(zc.zc_name, path); 17072926Sek110237 } else { 17082926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 17092926Sek110237 zc.zc_name[dspath-path] = '\0'; 17102926Sek110237 } 17112926Sek110237 17122926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 17132926Sek110237 zc.zc_history_len = strlen(cmd_buf); 17142926Sek110237 17152926Sek110237 /* overloading zc_history_offset */ 17162926Sek110237 zc.zc_history_offset = pool_create; 17172926Sek110237 17182926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 17192926Sek110237 } 17202926Sek110237 17212926Sek110237 /* 17222926Sek110237 * Perform ioctl to get some command history of a pool. 17232926Sek110237 * 17242926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 17252926Sek110237 * logical offset of the history buffer to start reading from. 17262926Sek110237 * 17272926Sek110237 * Upon return, 'off' is the next logical offset to read from and 17282926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 17292926Sek110237 */ 17302926Sek110237 static int 17312926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 17322926Sek110237 { 17332926Sek110237 zfs_cmd_t zc = { 0 }; 17342926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 17352926Sek110237 17362926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 17372926Sek110237 17382926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 17392926Sek110237 zc.zc_history_len = *len; 17402926Sek110237 zc.zc_history_offset = *off; 17412926Sek110237 17422926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 17432926Sek110237 switch (errno) { 17442926Sek110237 case EPERM: 17453237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 17463237Slling dgettext(TEXT_DOMAIN, 17472926Sek110237 "cannot show history for pool '%s'"), 17482926Sek110237 zhp->zpool_name)); 17492926Sek110237 case ENOENT: 17503237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 17512926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 17522926Sek110237 "'%s'"), zhp->zpool_name)); 17532926Sek110237 default: 17543237Slling return (zpool_standard_error_fmt(hdl, errno, 17552926Sek110237 dgettext(TEXT_DOMAIN, 17562926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 17572926Sek110237 } 17582926Sek110237 } 17592926Sek110237 17602926Sek110237 *len = zc.zc_history_len; 17612926Sek110237 *off = zc.zc_history_offset; 17622926Sek110237 17632926Sek110237 return (0); 17642926Sek110237 } 17652926Sek110237 17662926Sek110237 /* 17672926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 17682926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 17692926Sek110237 * processed as there wasn't a complete record. 17702926Sek110237 */ 17712926Sek110237 static int 17722926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 17732926Sek110237 nvlist_t ***records, uint_t *numrecords) 17742926Sek110237 { 17752926Sek110237 uint64_t reclen; 17762926Sek110237 nvlist_t *nv; 17772926Sek110237 int i; 17782926Sek110237 17792926Sek110237 while (bytes_read > sizeof (reclen)) { 17802926Sek110237 17812926Sek110237 /* get length of packed record (stored as little endian) */ 17822926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 17832926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 17842926Sek110237 17852926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 17862926Sek110237 break; 17872926Sek110237 17882926Sek110237 /* unpack record */ 17892926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 17902926Sek110237 return (ENOMEM); 17912926Sek110237 bytes_read -= sizeof (reclen) + reclen; 17922926Sek110237 buf += sizeof (reclen) + reclen; 17932926Sek110237 17942926Sek110237 /* add record to nvlist array */ 17952926Sek110237 (*numrecords)++; 17962926Sek110237 if (ISP2(*numrecords + 1)) { 17972926Sek110237 *records = realloc(*records, 17982926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 17992926Sek110237 } 18002926Sek110237 (*records)[*numrecords - 1] = nv; 18012926Sek110237 } 18022926Sek110237 18032926Sek110237 *leftover = bytes_read; 18042926Sek110237 return (0); 18052926Sek110237 } 18062926Sek110237 18072926Sek110237 #define HIS_BUF_LEN (128*1024) 18082926Sek110237 18092926Sek110237 /* 18102926Sek110237 * Retrieve the command history of a pool. 18112926Sek110237 */ 18122926Sek110237 int 18132926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 18142926Sek110237 { 18152926Sek110237 char buf[HIS_BUF_LEN]; 18162926Sek110237 uint64_t off = 0; 18172926Sek110237 nvlist_t **records = NULL; 18182926Sek110237 uint_t numrecords = 0; 18192926Sek110237 int err, i; 18202926Sek110237 18212926Sek110237 do { 18222926Sek110237 uint64_t bytes_read = sizeof (buf); 18232926Sek110237 uint64_t leftover; 18242926Sek110237 18252926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 18262926Sek110237 break; 18272926Sek110237 18282926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 18292926Sek110237 if (!bytes_read) 18302926Sek110237 break; 18312926Sek110237 18322926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 18332926Sek110237 &leftover, &records, &numrecords)) != 0) 18342926Sek110237 break; 18352926Sek110237 off -= leftover; 18362926Sek110237 18372926Sek110237 /* CONSTCOND */ 18382926Sek110237 } while (1); 18392926Sek110237 18402926Sek110237 if (!err) { 18412926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 18422926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 18432926Sek110237 records, numrecords) == 0); 18442926Sek110237 } 18452926Sek110237 for (i = 0; i < numrecords; i++) 18462926Sek110237 nvlist_free(records[i]); 18472926Sek110237 free(records); 18482926Sek110237 18492926Sek110237 return (err); 18502926Sek110237 } 18513444Sek110237 18523444Sek110237 void 18533444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 18543444Sek110237 char *pathname, size_t len) 18553444Sek110237 { 18563444Sek110237 zfs_cmd_t zc = { 0 }; 18573444Sek110237 boolean_t mounted = B_FALSE; 18583444Sek110237 char *mntpnt = NULL; 18593444Sek110237 char dsname[MAXNAMELEN]; 18603444Sek110237 18613444Sek110237 if (dsobj == 0) { 18623444Sek110237 /* special case for the MOS */ 18633444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 18643444Sek110237 return; 18653444Sek110237 } 18663444Sek110237 18673444Sek110237 /* get the dataset's name */ 18683444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18693444Sek110237 zc.zc_obj = dsobj; 18703444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 18713444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 18723444Sek110237 /* just write out a path of two object numbers */ 18733444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 18743444Sek110237 dsobj, obj); 18753444Sek110237 return; 18763444Sek110237 } 18773444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 18783444Sek110237 18793444Sek110237 /* find out if the dataset is mounted */ 18803444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 18813444Sek110237 18823444Sek110237 /* get the corrupted object's path */ 18833444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 18843444Sek110237 zc.zc_obj = obj; 18853444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 18863444Sek110237 &zc) == 0) { 18873444Sek110237 if (mounted) { 18883444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 18893444Sek110237 zc.zc_value); 18903444Sek110237 } else { 18913444Sek110237 (void) snprintf(pathname, len, "%s:%s", 18923444Sek110237 dsname, zc.zc_value); 18933444Sek110237 } 18943444Sek110237 } else { 18953444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 18963444Sek110237 } 18973444Sek110237 free(mntpnt); 18983444Sek110237 } 1899