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 * Open a handle to the given pool, even if the pool is currently in the FAULTED 136789Sahrens * state. 137789Sahrens */ 138789Sahrens zpool_handle_t * 1392082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 140789Sahrens { 141789Sahrens zpool_handle_t *zhp; 1422142Seschrock boolean_t missing; 143789Sahrens 144789Sahrens /* 145789Sahrens * Make sure the pool name is valid. 146789Sahrens */ 1472082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 1483237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1492082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1502082Seschrock pool); 151789Sahrens return (NULL); 152789Sahrens } 153789Sahrens 1542082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1552082Seschrock return (NULL); 156789Sahrens 1572082Seschrock zhp->zpool_hdl = hdl; 158789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 159789Sahrens 1602142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1612142Seschrock zpool_close(zhp); 1622142Seschrock return (NULL); 1632142Seschrock } 1642142Seschrock 1652142Seschrock if (missing) { 1662142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1672142Seschrock "no such pool")); 1683237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 1692142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1702142Seschrock pool); 1712142Seschrock zpool_close(zhp); 1722142Seschrock return (NULL); 173789Sahrens } 174789Sahrens 175789Sahrens return (zhp); 176789Sahrens } 177789Sahrens 178789Sahrens /* 179789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 180789Sahrens * the configuration cache may be out of date). 181789Sahrens */ 1822142Seschrock int 1832142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 184789Sahrens { 185789Sahrens zpool_handle_t *zhp; 1862142Seschrock boolean_t missing; 187789Sahrens 1882142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1892142Seschrock return (-1); 190789Sahrens 1912082Seschrock zhp->zpool_hdl = hdl; 192789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 193789Sahrens 1942142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1952142Seschrock zpool_close(zhp); 1962142Seschrock return (-1); 197789Sahrens } 198789Sahrens 1992142Seschrock if (missing) { 2002142Seschrock zpool_close(zhp); 2012142Seschrock *ret = NULL; 2022142Seschrock return (0); 2032142Seschrock } 2042142Seschrock 2052142Seschrock *ret = zhp; 2062142Seschrock return (0); 207789Sahrens } 208789Sahrens 209789Sahrens /* 210789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 211789Sahrens * state. 212789Sahrens */ 213789Sahrens zpool_handle_t * 2142082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 215789Sahrens { 216789Sahrens zpool_handle_t *zhp; 217789Sahrens 2182082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 219789Sahrens return (NULL); 220789Sahrens 221789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2223237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 2232082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 224789Sahrens zpool_close(zhp); 225789Sahrens return (NULL); 226789Sahrens } 227789Sahrens 228789Sahrens return (zhp); 229789Sahrens } 230789Sahrens 231789Sahrens /* 232789Sahrens * Close the handle. Simply frees the memory associated with the handle. 233789Sahrens */ 234789Sahrens void 235789Sahrens zpool_close(zpool_handle_t *zhp) 236789Sahrens { 237789Sahrens if (zhp->zpool_config) 238789Sahrens nvlist_free(zhp->zpool_config); 239952Seschrock if (zhp->zpool_old_config) 240952Seschrock nvlist_free(zhp->zpool_old_config); 241789Sahrens free(zhp); 242789Sahrens } 243789Sahrens 244789Sahrens /* 245789Sahrens * Return the name of the pool. 246789Sahrens */ 247789Sahrens const char * 248789Sahrens zpool_get_name(zpool_handle_t *zhp) 249789Sahrens { 250789Sahrens return (zhp->zpool_name); 251789Sahrens } 252789Sahrens 253789Sahrens /* 254789Sahrens * Return the GUID of the pool. 255789Sahrens */ 256789Sahrens uint64_t 257789Sahrens zpool_get_guid(zpool_handle_t *zhp) 258789Sahrens { 259789Sahrens uint64_t guid; 260789Sahrens 261789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 262789Sahrens &guid) == 0); 263789Sahrens return (guid); 264789Sahrens } 265789Sahrens 266789Sahrens /* 2672082Seschrock * Return the version of the pool. 2682082Seschrock */ 2692082Seschrock uint64_t 2702082Seschrock zpool_get_version(zpool_handle_t *zhp) 2712082Seschrock { 2722082Seschrock uint64_t version; 2732082Seschrock 2742082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 2752082Seschrock &version) == 0); 2762082Seschrock 2772082Seschrock return (version); 2782082Seschrock } 2792082Seschrock 2802082Seschrock /* 281789Sahrens * Return the amount of space currently consumed by the pool. 282789Sahrens */ 283789Sahrens uint64_t 284789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 285789Sahrens { 286789Sahrens nvlist_t *nvroot; 287789Sahrens vdev_stat_t *vs; 288789Sahrens uint_t vsc; 289789Sahrens 290789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 291789Sahrens &nvroot) == 0); 292789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 293789Sahrens (uint64_t **)&vs, &vsc) == 0); 294789Sahrens 295789Sahrens return (vs->vs_alloc); 296789Sahrens } 297789Sahrens 298789Sahrens /* 299789Sahrens * Return the total space in the pool. 300789Sahrens */ 301789Sahrens uint64_t 302789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 303789Sahrens { 304789Sahrens nvlist_t *nvroot; 305789Sahrens vdev_stat_t *vs; 306789Sahrens uint_t vsc; 307789Sahrens 308789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 309789Sahrens &nvroot) == 0); 310789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 311789Sahrens (uint64_t **)&vs, &vsc) == 0); 312789Sahrens 313789Sahrens return (vs->vs_space); 314789Sahrens } 315789Sahrens 316789Sahrens /* 317789Sahrens * Return the alternate root for this pool, if any. 318789Sahrens */ 319789Sahrens int 320789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 321789Sahrens { 322789Sahrens zfs_cmd_t zc = { 0 }; 323789Sahrens 324789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3252082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3262676Seschrock zc.zc_value[0] == '\0') 327789Sahrens return (-1); 328789Sahrens 3292676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 330789Sahrens 331789Sahrens return (0); 332789Sahrens } 333789Sahrens 334789Sahrens /* 335789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 336789Sahrens */ 337789Sahrens int 338789Sahrens zpool_get_state(zpool_handle_t *zhp) 339789Sahrens { 340789Sahrens return (zhp->zpool_state); 341789Sahrens } 342789Sahrens 343789Sahrens /* 344789Sahrens * Create the named pool, using the provided vdev list. It is assumed 345789Sahrens * that the consumer has already validated the contents of the nvlist, so we 346789Sahrens * don't have to worry about error semantics. 347789Sahrens */ 348789Sahrens int 3492082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3502082Seschrock const char *altroot) 351789Sahrens { 352789Sahrens zfs_cmd_t zc = { 0 }; 3532082Seschrock char msg[1024]; 3542082Seschrock 3552082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3562082Seschrock "cannot create '%s'"), pool); 357789Sahrens 3582082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 3592082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 3602082Seschrock 3612082Seschrock if (altroot != NULL && altroot[0] != '/') 3623237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 3632082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 364789Sahrens 3652676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 366789Sahrens return (-1); 367789Sahrens 368789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 369789Sahrens 370789Sahrens if (altroot != NULL) 3712676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 372789Sahrens 3732082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 3742676Seschrock zcmd_free_nvlists(&zc); 3752082Seschrock 376789Sahrens switch (errno) { 377789Sahrens case EBUSY: 378789Sahrens /* 379789Sahrens * This can happen if the user has specified the same 380789Sahrens * device multiple times. We can't reliably detect this 381789Sahrens * until we try to add it and see we already have a 382789Sahrens * label. 383789Sahrens */ 3842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3852082Seschrock "one or more vdevs refer to the same device")); 3862082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 387789Sahrens 388789Sahrens case EOVERFLOW: 389789Sahrens /* 3902082Seschrock * This occurs when one of the devices is below 391789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 392789Sahrens * device was the problem device since there's no 393789Sahrens * reliable way to determine device size from userland. 394789Sahrens */ 395789Sahrens { 396789Sahrens char buf[64]; 397789Sahrens 398789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 399789Sahrens 4002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4012082Seschrock "one or more devices is less than the " 4022082Seschrock "minimum size (%s)"), buf); 403789Sahrens } 4042082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 405789Sahrens 406789Sahrens case ENOSPC: 4072082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4082082Seschrock "one or more devices is out of space")); 4092082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 410789Sahrens 411789Sahrens default: 4122082Seschrock return (zpool_standard_error(hdl, errno, msg)); 413789Sahrens } 414789Sahrens } 415789Sahrens 4162676Seschrock zcmd_free_nvlists(&zc); 417789Sahrens 418789Sahrens /* 419789Sahrens * If this is an alternate root pool, then we automatically set the 4202676Seschrock * mountpoint of the root dataset to be '/'. 421789Sahrens */ 422789Sahrens if (altroot != NULL) { 423789Sahrens zfs_handle_t *zhp; 424789Sahrens 4252082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4262676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4272676Seschrock "/") == 0); 428789Sahrens 429789Sahrens zfs_close(zhp); 430789Sahrens } 431789Sahrens 432789Sahrens return (0); 433789Sahrens } 434789Sahrens 435789Sahrens /* 436789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 437789Sahrens * datasets left in the pool. 438789Sahrens */ 439789Sahrens int 440789Sahrens zpool_destroy(zpool_handle_t *zhp) 441789Sahrens { 442789Sahrens zfs_cmd_t zc = { 0 }; 443789Sahrens zfs_handle_t *zfp = NULL; 4442082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4452082Seschrock char msg[1024]; 446789Sahrens 447789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4482082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4492082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 450789Sahrens return (-1); 451789Sahrens 4522856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 453789Sahrens return (-1); 454789Sahrens 455789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 456789Sahrens 4572082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 4582082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4592082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 460789Sahrens 4612082Seschrock if (errno == EROFS) { 4622082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4632082Seschrock "one or more devices is read only")); 4642082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 4652082Seschrock } else { 4662082Seschrock (void) zpool_standard_error(hdl, errno, msg); 467789Sahrens } 468789Sahrens 469789Sahrens if (zfp) 470789Sahrens zfs_close(zfp); 471789Sahrens return (-1); 472789Sahrens } 473789Sahrens 474789Sahrens if (zfp) { 475789Sahrens remove_mountpoint(zfp); 476789Sahrens zfs_close(zfp); 477789Sahrens } 478789Sahrens 479789Sahrens return (0); 480789Sahrens } 481789Sahrens 482789Sahrens /* 483789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 484789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 485789Sahrens */ 486789Sahrens int 487789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 488789Sahrens { 4892676Seschrock zfs_cmd_t zc = { 0 }; 4902082Seschrock int ret; 4912082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4922082Seschrock char msg[1024]; 4932082Seschrock nvlist_t **spares; 4942082Seschrock uint_t nspares; 4952082Seschrock 4962082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4972082Seschrock "cannot add to '%s'"), zhp->zpool_name); 4982082Seschrock 4992082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5002082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5012082Seschrock &spares, &nspares) == 0) { 5022082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5032082Seschrock "upgraded to add hot spares")); 5042082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5052082Seschrock } 506789Sahrens 5072676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5082082Seschrock return (-1); 509789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 510789Sahrens 5112082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 512789Sahrens switch (errno) { 513789Sahrens case EBUSY: 514789Sahrens /* 515789Sahrens * This can happen if the user has specified the same 516789Sahrens * device multiple times. We can't reliably detect this 517789Sahrens * until we try to add it and see we already have a 518789Sahrens * label. 519789Sahrens */ 5202082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5212082Seschrock "one or more vdevs refer to the same device")); 5222082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 523789Sahrens break; 524789Sahrens 525789Sahrens case EOVERFLOW: 526789Sahrens /* 527789Sahrens * This occurrs when one of the devices is below 528789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 529789Sahrens * device was the problem device since there's no 530789Sahrens * reliable way to determine device size from userland. 531789Sahrens */ 532789Sahrens { 533789Sahrens char buf[64]; 534789Sahrens 535789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 536789Sahrens 5372082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5382082Seschrock "device is less than the minimum " 5392082Seschrock "size (%s)"), buf); 540789Sahrens } 5412082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5422082Seschrock break; 5432082Seschrock 5442082Seschrock case ENOTSUP: 5452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5462082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5472082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 548789Sahrens break; 549789Sahrens 550789Sahrens default: 5512082Seschrock (void) zpool_standard_error(hdl, errno, msg); 552789Sahrens } 553789Sahrens 5542082Seschrock ret = -1; 5552082Seschrock } else { 5562082Seschrock ret = 0; 557789Sahrens } 558789Sahrens 5592676Seschrock zcmd_free_nvlists(&zc); 560789Sahrens 5612082Seschrock return (ret); 562789Sahrens } 563789Sahrens 564789Sahrens /* 565789Sahrens * Exports the pool from the system. The caller must ensure that there are no 566789Sahrens * mounted datasets in the pool. 567789Sahrens */ 568789Sahrens int 569789Sahrens zpool_export(zpool_handle_t *zhp) 570789Sahrens { 571789Sahrens zfs_cmd_t zc = { 0 }; 572789Sahrens 573789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 574789Sahrens return (-1); 575789Sahrens 576789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 577789Sahrens 5782082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 5793237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 5802082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 5812082Seschrock zhp->zpool_name)); 582789Sahrens 583789Sahrens return (0); 584789Sahrens } 585789Sahrens 586789Sahrens /* 587789Sahrens * Import the given pool using the known configuration. The configuration 588789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 589789Sahrens * parameters control whether the pool is imported with a different name or with 590789Sahrens * an alternate root, respectively. 591789Sahrens */ 592789Sahrens int 5932082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 5942082Seschrock const char *altroot) 595789Sahrens { 5962676Seschrock zfs_cmd_t zc = { 0 }; 597789Sahrens char *thename; 598789Sahrens char *origname; 599789Sahrens int ret; 600789Sahrens 601789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 602789Sahrens &origname) == 0); 603789Sahrens 604789Sahrens if (newname != NULL) { 6052082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6063237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6072082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6082082Seschrock newname)); 609789Sahrens thename = (char *)newname; 610789Sahrens } else { 611789Sahrens thename = origname; 612789Sahrens } 613789Sahrens 6142082Seschrock if (altroot != NULL && altroot[0] != '/') 6153237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6162082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6172082Seschrock altroot)); 618789Sahrens 619789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 620789Sahrens 621789Sahrens if (altroot != NULL) 6222676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 623789Sahrens else 6242676Seschrock zc.zc_value[0] = '\0'; 625789Sahrens 626789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6271544Seschrock &zc.zc_guid) == 0); 628789Sahrens 6292676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6302082Seschrock return (-1); 631789Sahrens 632789Sahrens ret = 0; 6332082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 634789Sahrens char desc[1024]; 635789Sahrens if (newname == NULL) 636789Sahrens (void) snprintf(desc, sizeof (desc), 637789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 638789Sahrens thename); 639789Sahrens else 640789Sahrens (void) snprintf(desc, sizeof (desc), 641789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 642789Sahrens origname, thename); 643789Sahrens 644789Sahrens switch (errno) { 6451544Seschrock case ENOTSUP: 6461544Seschrock /* 6471544Seschrock * Unsupported version. 6481544Seschrock */ 6492082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6501544Seschrock break; 6511544Seschrock 6522174Seschrock case EINVAL: 6532174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6542174Seschrock break; 6552174Seschrock 656789Sahrens default: 6572082Seschrock (void) zpool_standard_error(hdl, errno, desc); 658789Sahrens } 659789Sahrens 660789Sahrens ret = -1; 661789Sahrens } else { 662789Sahrens zpool_handle_t *zhp; 663789Sahrens /* 664789Sahrens * This should never fail, but play it safe anyway. 665789Sahrens */ 6662142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 6672142Seschrock ret = -1; 6682142Seschrock } else if (zhp != NULL) { 669789Sahrens ret = zpool_create_zvol_links(zhp); 670789Sahrens zpool_close(zhp); 671789Sahrens } 672789Sahrens } 673789Sahrens 6742676Seschrock zcmd_free_nvlists(&zc); 675789Sahrens return (ret); 676789Sahrens } 677789Sahrens 678789Sahrens /* 679789Sahrens * Scrub the pool. 680789Sahrens */ 681789Sahrens int 682789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 683789Sahrens { 684789Sahrens zfs_cmd_t zc = { 0 }; 685789Sahrens char msg[1024]; 6862082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 687789Sahrens 688789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 689789Sahrens zc.zc_cookie = type; 690789Sahrens 6912082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 692789Sahrens return (0); 693789Sahrens 694789Sahrens (void) snprintf(msg, sizeof (msg), 695789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 696789Sahrens 6972082Seschrock if (errno == EBUSY) 6982082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 6992082Seschrock else 7002082Seschrock return (zpool_standard_error(hdl, errno, msg)); 701789Sahrens } 702789Sahrens 7032468Sek110237 /* 7042468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7052468Sek110237 * spare; but FALSE if its an INUSE spare. 7062468Sek110237 */ 7072082Seschrock static nvlist_t * 7082082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7092468Sek110237 boolean_t *avail_spare) 7101544Seschrock { 7111544Seschrock uint_t c, children; 7121544Seschrock nvlist_t **child; 7132082Seschrock uint64_t theguid, present; 7141544Seschrock char *path; 7151544Seschrock uint64_t wholedisk = 0; 7162082Seschrock nvlist_t *ret; 7171544Seschrock 7182082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7191544Seschrock 7201544Seschrock if (search == NULL && 7211544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7221544Seschrock /* 7231544Seschrock * If the device has never been present since import, the only 7241544Seschrock * reliable way to match the vdev is by GUID. 7251544Seschrock */ 7262082Seschrock if (theguid == guid) 7272082Seschrock return (nv); 7281544Seschrock } else if (search != NULL && 7291544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7301544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7311544Seschrock &wholedisk); 7321544Seschrock if (wholedisk) { 7331544Seschrock /* 7341544Seschrock * For whole disks, the internal path has 's0', but the 7351544Seschrock * path passed in by the user doesn't. 7361544Seschrock */ 7371544Seschrock if (strlen(search) == strlen(path) - 2 && 7381544Seschrock strncmp(search, path, strlen(search)) == 0) 7392082Seschrock return (nv); 7401544Seschrock } else if (strcmp(search, path) == 0) { 7412082Seschrock return (nv); 7421544Seschrock } 7431544Seschrock } 7441544Seschrock 7451544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7461544Seschrock &child, &children) != 0) 7472082Seschrock return (NULL); 7481544Seschrock 7491544Seschrock for (c = 0; c < children; c++) 7502082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7512468Sek110237 avail_spare)) != NULL) 7521544Seschrock return (ret); 7531544Seschrock 7542082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 7552082Seschrock &child, &children) == 0) { 7562082Seschrock for (c = 0; c < children; c++) { 7572082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7582468Sek110237 avail_spare)) != NULL) { 7592468Sek110237 *avail_spare = B_TRUE; 7602082Seschrock return (ret); 7612082Seschrock } 7622082Seschrock } 7632082Seschrock } 7642082Seschrock 7652082Seschrock return (NULL); 7661544Seschrock } 7671544Seschrock 7682082Seschrock nvlist_t * 7692468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 7701544Seschrock { 7711544Seschrock char buf[MAXPATHLEN]; 7721544Seschrock const char *search; 7731544Seschrock char *end; 7741544Seschrock nvlist_t *nvroot; 7751544Seschrock uint64_t guid; 7761544Seschrock 7771613Seschrock guid = strtoull(path, &end, 10); 7781544Seschrock if (guid != 0 && *end == '\0') { 7791544Seschrock search = NULL; 7801544Seschrock } else if (path[0] != '/') { 7811544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 7821544Seschrock search = buf; 7831544Seschrock } else { 7841544Seschrock search = path; 7851544Seschrock } 7861544Seschrock 7871544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 7881544Seschrock &nvroot) == 0); 7891544Seschrock 7902468Sek110237 *avail_spare = B_FALSE; 7912468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 7922468Sek110237 } 7932468Sek110237 7942468Sek110237 /* 7952468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 7962468Sek110237 */ 7972468Sek110237 static boolean_t 7982468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 7992468Sek110237 { 8002468Sek110237 uint64_t spare_guid; 8012468Sek110237 nvlist_t *nvroot; 8022468Sek110237 nvlist_t **spares; 8032468Sek110237 uint_t nspares; 8042468Sek110237 int i; 8052468Sek110237 8062468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8072468Sek110237 &nvroot) == 0); 8082468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8092468Sek110237 &spares, &nspares) == 0) { 8102468Sek110237 for (i = 0; i < nspares; i++) { 8112468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8122468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8132468Sek110237 if (guid == spare_guid) 8142468Sek110237 return (B_TRUE); 8152468Sek110237 } 8162468Sek110237 } 8172468Sek110237 8182468Sek110237 return (B_FALSE); 8191544Seschrock } 8201544Seschrock 821789Sahrens /* 822789Sahrens * Bring the specified vdev online 823789Sahrens */ 824789Sahrens int 825789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 826789Sahrens { 827789Sahrens zfs_cmd_t zc = { 0 }; 828789Sahrens char msg[1024]; 8292082Seschrock nvlist_t *tgt; 8302468Sek110237 boolean_t avail_spare; 8312082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 832789Sahrens 8331544Seschrock (void) snprintf(msg, sizeof (msg), 8341544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 835789Sahrens 8361544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8372468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8382082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 839789Sahrens 8402468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8412468Sek110237 8422468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8432082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8442082Seschrock 8452082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8461544Seschrock return (0); 847789Sahrens 8482082Seschrock return (zpool_standard_error(hdl, errno, msg)); 849789Sahrens } 850789Sahrens 851789Sahrens /* 852789Sahrens * Take the specified vdev offline 853789Sahrens */ 854789Sahrens int 8551485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 856789Sahrens { 857789Sahrens zfs_cmd_t zc = { 0 }; 858789Sahrens char msg[1024]; 8592082Seschrock nvlist_t *tgt; 8602468Sek110237 boolean_t avail_spare; 8612082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 862789Sahrens 8631544Seschrock (void) snprintf(msg, sizeof (msg), 8641544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 8651544Seschrock 866789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8672468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8682082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 8692082Seschrock 8702468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8712468Sek110237 8722468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8732082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8742082Seschrock 8751485Slling zc.zc_cookie = istmp; 8761485Slling 8772082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 878789Sahrens return (0); 879789Sahrens 880789Sahrens switch (errno) { 8812082Seschrock case EBUSY: 882789Sahrens 883789Sahrens /* 884789Sahrens * There are no other replicas of this device. 885789Sahrens */ 8862082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 8872082Seschrock 8882082Seschrock default: 8892082Seschrock return (zpool_standard_error(hdl, errno, msg)); 8902082Seschrock } 8912082Seschrock } 892789Sahrens 8932082Seschrock /* 8942082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 8952082Seschrock * a hot spare. 8962082Seschrock */ 8972082Seschrock static boolean_t 8982082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 8992082Seschrock { 9002082Seschrock nvlist_t **child; 9012082Seschrock uint_t c, children; 9022082Seschrock char *type; 9032082Seschrock 9042082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9052082Seschrock &children) == 0) { 9062082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9072082Seschrock &type) == 0); 9082082Seschrock 9092082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9102082Seschrock children == 2 && child[which] == tgt) 9112082Seschrock return (B_TRUE); 9122082Seschrock 9132082Seschrock for (c = 0; c < children; c++) 9142082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9152082Seschrock return (B_TRUE); 916789Sahrens } 9172082Seschrock 9182082Seschrock return (B_FALSE); 919789Sahrens } 920789Sahrens 921789Sahrens /* 922789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 923789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 924789Sahrens */ 925789Sahrens int 926789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 927789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 928789Sahrens { 929789Sahrens zfs_cmd_t zc = { 0 }; 930789Sahrens char msg[1024]; 931789Sahrens int ret; 9322082Seschrock nvlist_t *tgt; 9332468Sek110237 boolean_t avail_spare; 9342082Seschrock uint64_t val; 9352082Seschrock char *path; 9362082Seschrock nvlist_t **child; 9372082Seschrock uint_t children; 9382082Seschrock nvlist_t *config_root; 9392082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 940789Sahrens 9411544Seschrock if (replacing) 9421544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9431544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9441544Seschrock else 9451544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9461544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9471544Seschrock 948789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9492468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9502082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9512082Seschrock 9522468Sek110237 if (avail_spare) 9532082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9542082Seschrock 9552082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9562082Seschrock zc.zc_cookie = replacing; 9572082Seschrock 9582082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 9592082Seschrock &child, &children) != 0 || children != 1) { 9602082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9612082Seschrock "new device must be a single disk")); 9622082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 9631544Seschrock } 9642082Seschrock 9652082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 9662082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 9672082Seschrock 9682082Seschrock /* 9692082Seschrock * If the target is a hot spare that has been swapped in, we can only 9702082Seschrock * replace it with another hot spare. 9712082Seschrock */ 9722082Seschrock if (replacing && 9732082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 9742082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 9752468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 9762468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 9772082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9782082Seschrock "can only be replaced by another hot spare")); 9792082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 9802082Seschrock } 9812082Seschrock 9822082Seschrock /* 9832082Seschrock * If we are attempting to replace a spare, it canot be applied to an 9842082Seschrock * already spared device. 9852082Seschrock */ 9862082Seschrock if (replacing && 9872082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 9882468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 9892082Seschrock is_replacing_spare(config_root, tgt, 0)) { 9902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9912082Seschrock "device has already been replaced with a spare")); 9922082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 9932082Seschrock } 994789Sahrens 9952676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 9962082Seschrock return (-1); 997789Sahrens 9982082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 999789Sahrens 10002676Seschrock zcmd_free_nvlists(&zc); 1001789Sahrens 1002789Sahrens if (ret == 0) 1003789Sahrens return (0); 1004789Sahrens 1005789Sahrens switch (errno) { 10061544Seschrock case ENOTSUP: 1007789Sahrens /* 1008789Sahrens * Can't attach to or replace this type of vdev. 1009789Sahrens */ 1010789Sahrens if (replacing) 10112082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10122082Seschrock "cannot replace a replacing device")); 1013789Sahrens else 10142082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10152082Seschrock "can only attach to mirrors and top-level " 10162082Seschrock "disks")); 10172082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1018789Sahrens break; 1019789Sahrens 10201544Seschrock case EINVAL: 1021789Sahrens /* 1022789Sahrens * The new device must be a single disk. 1023789Sahrens */ 10242082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10252082Seschrock "new device must be a single disk")); 10262082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1027789Sahrens break; 1028789Sahrens 10291544Seschrock case EBUSY: 10302082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10312082Seschrock new_disk); 10322082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1033789Sahrens break; 1034789Sahrens 10351544Seschrock case EOVERFLOW: 1036789Sahrens /* 1037789Sahrens * The new device is too small. 1038789Sahrens */ 10392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10402082Seschrock "device is too small")); 10412082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1042789Sahrens break; 1043789Sahrens 10441544Seschrock case EDOM: 1045789Sahrens /* 1046789Sahrens * The new device has a different alignment requirement. 1047789Sahrens */ 10482082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10492082Seschrock "devices have different sector alignment")); 10502082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1051789Sahrens break; 1052789Sahrens 10531544Seschrock case ENAMETOOLONG: 1054789Sahrens /* 1055789Sahrens * The resulting top-level vdev spec won't fit in the label. 1056789Sahrens */ 10572082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1058789Sahrens break; 1059789Sahrens 10601544Seschrock default: 10612082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1062789Sahrens } 1063789Sahrens 10642082Seschrock return (-1); 1065789Sahrens } 1066789Sahrens 1067789Sahrens /* 1068789Sahrens * Detach the specified device. 1069789Sahrens */ 1070789Sahrens int 1071789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1072789Sahrens { 1073789Sahrens zfs_cmd_t zc = { 0 }; 1074789Sahrens char msg[1024]; 10752082Seschrock nvlist_t *tgt; 10762468Sek110237 boolean_t avail_spare; 10772082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1078789Sahrens 10791544Seschrock (void) snprintf(msg, sizeof (msg), 10801544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 10811544Seschrock 1082789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 10832468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 10842082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1085789Sahrens 10862468Sek110237 if (avail_spare) 10872082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 10882082Seschrock 10892082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 10902082Seschrock 10912082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1092789Sahrens return (0); 1093789Sahrens 1094789Sahrens switch (errno) { 1095789Sahrens 10961544Seschrock case ENOTSUP: 1097789Sahrens /* 1098789Sahrens * Can't detach from this type of vdev. 1099789Sahrens */ 11002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11012082Seschrock "applicable to mirror and replacing vdevs")); 11022082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1103789Sahrens break; 1104789Sahrens 11051544Seschrock case EBUSY: 1106789Sahrens /* 1107789Sahrens * There are no other replicas of this device. 1108789Sahrens */ 11092082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1110789Sahrens break; 1111789Sahrens 11121544Seschrock default: 11132082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11141544Seschrock } 11151544Seschrock 11162082Seschrock return (-1); 11172082Seschrock } 11182082Seschrock 11192082Seschrock /* 11202082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11212082Seschrock */ 11222082Seschrock int 11232082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11242082Seschrock { 11252082Seschrock zfs_cmd_t zc = { 0 }; 11262082Seschrock char msg[1024]; 11272082Seschrock nvlist_t *tgt; 11282468Sek110237 boolean_t avail_spare; 11292082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11302082Seschrock 11312082Seschrock (void) snprintf(msg, sizeof (msg), 11322082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11332082Seschrock 11342082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11352468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11362082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11372082Seschrock 11382468Sek110237 if (!avail_spare) { 11392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11403377Seschrock "only inactive hot spares can be removed")); 11412082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11422082Seschrock } 11432082Seschrock 11442082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11452082Seschrock 11462082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11472082Seschrock return (0); 11482082Seschrock 11492082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11501544Seschrock } 11511544Seschrock 11521544Seschrock /* 11531544Seschrock * Clear the errors for the pool, or the particular device if specified. 11541544Seschrock */ 11551544Seschrock int 11561544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 11571544Seschrock { 11581544Seschrock zfs_cmd_t zc = { 0 }; 11591544Seschrock char msg[1024]; 11602082Seschrock nvlist_t *tgt; 11612468Sek110237 boolean_t avail_spare; 11622082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11631544Seschrock 11641544Seschrock if (path) 11651544Seschrock (void) snprintf(msg, sizeof (msg), 11661544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 11672676Seschrock path); 11681544Seschrock else 11691544Seschrock (void) snprintf(msg, sizeof (msg), 11701544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 11711544Seschrock zhp->zpool_name); 11721544Seschrock 11731544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11742082Seschrock if (path) { 11752468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11762082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11772082Seschrock 11782468Sek110237 if (avail_spare) 11792082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11802082Seschrock 11812082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 11822082Seschrock &zc.zc_guid) == 0); 11831544Seschrock } 11841544Seschrock 11852082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 11861544Seschrock return (0); 11871544Seschrock 11882082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1189789Sahrens } 1190789Sahrens 11913126Sahl /* 11923126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 11933126Sahl * hierarchy. 11943126Sahl */ 11953126Sahl int 11963126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 11973126Sahl void *data) 1198789Sahrens { 11993126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 12003126Sahl char (*paths)[MAXPATHLEN]; 12013126Sahl size_t size = 4; 12023126Sahl int curr, fd, base, ret = 0; 12033126Sahl DIR *dirp; 12043126Sahl struct dirent *dp; 12053126Sahl struct stat st; 12063126Sahl 12073126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 12083126Sahl return (errno == ENOENT ? 0 : -1); 12093126Sahl 12103126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 12113126Sahl int err = errno; 12123126Sahl (void) close(base); 12133126Sahl return (err == ENOENT ? 0 : -1); 12143126Sahl } 1215789Sahrens 1216789Sahrens /* 12173126Sahl * Oddly this wasn't a directory -- ignore that failure since we 12183126Sahl * know there are no links lower in the (non-existant) hierarchy. 1219789Sahrens */ 12203126Sahl if (!S_ISDIR(st.st_mode)) { 12213126Sahl (void) close(base); 12223126Sahl return (0); 12233126Sahl } 12243126Sahl 12253126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 12263126Sahl (void) close(base); 12273126Sahl return (-1); 1228789Sahrens } 1229789Sahrens 12303126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 12313126Sahl curr = 0; 12323126Sahl 12333126Sahl while (curr >= 0) { 12343126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 12353126Sahl goto err; 12363126Sahl 12373126Sahl if (S_ISDIR(st.st_mode)) { 12383126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 12393126Sahl goto err; 12403126Sahl 12413126Sahl if ((dirp = fdopendir(fd)) == NULL) { 12423126Sahl (void) close(fd); 12433126Sahl goto err; 12443126Sahl } 12453126Sahl 12463126Sahl while ((dp = readdir(dirp)) != NULL) { 12473126Sahl if (dp->d_name[0] == '.') 12483126Sahl continue; 12493126Sahl 12503126Sahl if (curr + 1 == size) { 12513126Sahl paths = zfs_realloc(hdl, paths, 12523126Sahl size * sizeof (paths[0]), 12533126Sahl size * 2 * sizeof (paths[0])); 12543126Sahl if (paths == NULL) { 12553126Sahl (void) closedir(dirp); 12563126Sahl (void) close(fd); 12573126Sahl goto err; 12583126Sahl } 12593126Sahl 12603126Sahl size *= 2; 12613126Sahl } 12623126Sahl 12633126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 12643126Sahl sizeof (paths[curr + 1])); 12653126Sahl (void) strlcat(paths[curr], "/", 12663126Sahl sizeof (paths[curr])); 12673126Sahl (void) strlcat(paths[curr], dp->d_name, 12683126Sahl sizeof (paths[curr])); 12693126Sahl curr++; 12703126Sahl } 12713126Sahl 12723126Sahl (void) closedir(dirp); 12733126Sahl 12743126Sahl } else { 12753126Sahl if ((ret = cb(paths[curr], data)) != 0) 12763126Sahl break; 12773126Sahl } 12783126Sahl 12793126Sahl curr--; 12803126Sahl } 12813126Sahl 12823126Sahl free(paths); 12833126Sahl (void) close(base); 12843126Sahl 12853126Sahl return (ret); 12863126Sahl 12873126Sahl err: 12883126Sahl free(paths); 12893126Sahl (void) close(base); 12903126Sahl return (-1); 12913126Sahl } 12923126Sahl 12933126Sahl typedef struct zvol_cb { 12943126Sahl zpool_handle_t *zcb_pool; 12953126Sahl boolean_t zcb_create; 12963126Sahl } zvol_cb_t; 12973126Sahl 12983126Sahl /*ARGSUSED*/ 12993126Sahl static int 13003126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 13013126Sahl { 13023126Sahl int ret; 13033126Sahl 13043126Sahl if (ZFS_IS_VOLUME(zhp)) 13053126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 13063126Sahl 13073126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1308789Sahrens 1309789Sahrens zfs_close(zhp); 13103126Sahl 1311789Sahrens return (ret); 1312789Sahrens } 1313789Sahrens 1314789Sahrens /* 1315789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1316789Sahrens */ 1317789Sahrens int 1318789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1319789Sahrens { 1320789Sahrens zfs_handle_t *zfp; 1321789Sahrens int ret; 1322789Sahrens 1323789Sahrens /* 1324789Sahrens * If the pool is unavailable, just return success. 1325789Sahrens */ 13262082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 13272082Seschrock zhp->zpool_name)) == NULL) 1328789Sahrens return (0); 1329789Sahrens 13303126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1331789Sahrens 1332789Sahrens zfs_close(zfp); 1333789Sahrens return (ret); 1334789Sahrens } 1335789Sahrens 13363126Sahl static int 13373126Sahl do_zvol_remove(const char *dataset, void *data) 13383126Sahl { 13393126Sahl zpool_handle_t *zhp = data; 13403126Sahl 13413126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 13423126Sahl } 13433126Sahl 1344789Sahrens /* 13453126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 13463126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 13473126Sahl * operation. 1348789Sahrens */ 1349789Sahrens int 1350789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1351789Sahrens { 13523126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1353789Sahrens } 13541354Seschrock 13551354Seschrock /* 13561354Seschrock * Convert from a devid string to a path. 13571354Seschrock */ 13581354Seschrock static char * 13591354Seschrock devid_to_path(char *devid_str) 13601354Seschrock { 13611354Seschrock ddi_devid_t devid; 13621354Seschrock char *minor; 13631354Seschrock char *path; 13641354Seschrock devid_nmlist_t *list = NULL; 13651354Seschrock int ret; 13661354Seschrock 13671354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 13681354Seschrock return (NULL); 13691354Seschrock 13701354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 13711354Seschrock 13721354Seschrock devid_str_free(minor); 13731354Seschrock devid_free(devid); 13741354Seschrock 13751354Seschrock if (ret != 0) 13761354Seschrock return (NULL); 13771354Seschrock 13782082Seschrock if ((path = strdup(list[0].devname)) == NULL) 13792082Seschrock return (NULL); 13802082Seschrock 13811354Seschrock devid_free_nmlist(list); 13821354Seschrock 13831354Seschrock return (path); 13841354Seschrock } 13851354Seschrock 13861354Seschrock /* 13871354Seschrock * Convert from a path to a devid string. 13881354Seschrock */ 13891354Seschrock static char * 13901354Seschrock path_to_devid(const char *path) 13911354Seschrock { 13921354Seschrock int fd; 13931354Seschrock ddi_devid_t devid; 13941354Seschrock char *minor, *ret; 13951354Seschrock 13961354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 13971354Seschrock return (NULL); 13981354Seschrock 13991354Seschrock minor = NULL; 14001354Seschrock ret = NULL; 14011354Seschrock if (devid_get(fd, &devid) == 0) { 14021354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 14031354Seschrock ret = devid_str_encode(devid, minor); 14041354Seschrock if (minor != NULL) 14051354Seschrock devid_str_free(minor); 14061354Seschrock devid_free(devid); 14071354Seschrock } 14081354Seschrock (void) close(fd); 14091354Seschrock 14101354Seschrock return (ret); 14111354Seschrock } 14121354Seschrock 14131354Seschrock /* 14141354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 14151354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 14161354Seschrock * type 'zpool status', and we'll display the correct information anyway. 14171354Seschrock */ 14181354Seschrock static void 14191354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 14201354Seschrock { 14211354Seschrock zfs_cmd_t zc = { 0 }; 14221354Seschrock 14231354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14242676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 14251354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14261544Seschrock &zc.zc_guid) == 0); 14271354Seschrock 14282082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 14291354Seschrock } 14301354Seschrock 14311354Seschrock /* 14321354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 14331354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 14341354Seschrock * We also check if this is a whole disk, in which case we strip off the 14351354Seschrock * trailing 's0' slice name. 14361354Seschrock * 14371354Seschrock * This routine is also responsible for identifying when disks have been 14381354Seschrock * reconfigured in a new location. The kernel will have opened the device by 14391354Seschrock * devid, but the path will still refer to the old location. To catch this, we 14401354Seschrock * first do a path -> devid translation (which is fast for the common case). If 14411354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 14421354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 14431354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 14441354Seschrock * of these checks. 14451354Seschrock */ 14461354Seschrock char * 14472082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 14481354Seschrock { 14491354Seschrock char *path, *devid; 14501544Seschrock uint64_t value; 14511544Seschrock char buf[64]; 14521354Seschrock 14531544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14541544Seschrock &value) == 0) { 14551544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14561544Seschrock &value) == 0); 14572856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 14582856Snd150628 (u_longlong_t)value); 14591544Seschrock path = buf; 14601544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 14611354Seschrock 14621354Seschrock if (zhp != NULL && 14631354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 14641354Seschrock /* 14651354Seschrock * Determine if the current path is correct. 14661354Seschrock */ 14671354Seschrock char *newdevid = path_to_devid(path); 14681354Seschrock 14691354Seschrock if (newdevid == NULL || 14701354Seschrock strcmp(devid, newdevid) != 0) { 14711354Seschrock char *newpath; 14721354Seschrock 14731354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 14741354Seschrock /* 14751354Seschrock * Update the path appropriately. 14761354Seschrock */ 14771354Seschrock set_path(zhp, nv, newpath); 14782082Seschrock if (nvlist_add_string(nv, 14792082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 14802082Seschrock verify(nvlist_lookup_string(nv, 14812082Seschrock ZPOOL_CONFIG_PATH, 14822082Seschrock &path) == 0); 14831354Seschrock free(newpath); 14841354Seschrock } 14851354Seschrock } 14861354Seschrock 14872082Seschrock if (newdevid) 14882082Seschrock devid_str_free(newdevid); 14891354Seschrock } 14901354Seschrock 14911354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 14921354Seschrock path += 9; 14931354Seschrock 14941354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 14951544Seschrock &value) == 0 && value) { 14962082Seschrock char *tmp = zfs_strdup(hdl, path); 14972082Seschrock if (tmp == NULL) 14982082Seschrock return (NULL); 14991354Seschrock tmp[strlen(path) - 2] = '\0'; 15001354Seschrock return (tmp); 15011354Seschrock } 15021354Seschrock } else { 15031354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 15042082Seschrock 15052082Seschrock /* 15062082Seschrock * If it's a raidz device, we need to stick in the parity level. 15072082Seschrock */ 15082082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 15092082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 15102082Seschrock &value) == 0); 15112082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 15122856Snd150628 (u_longlong_t)value); 15132082Seschrock path = buf; 15142082Seschrock } 15151354Seschrock } 15161354Seschrock 15172082Seschrock return (zfs_strdup(hdl, path)); 15181354Seschrock } 15191544Seschrock 15201544Seschrock static int 15211544Seschrock zbookmark_compare(const void *a, const void *b) 15221544Seschrock { 15231544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 15241544Seschrock } 15251544Seschrock 15261544Seschrock /* 15271544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 15281544Seschrock * caller. 15291544Seschrock */ 15301544Seschrock int 15313444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 15321544Seschrock { 15331544Seschrock zfs_cmd_t zc = { 0 }; 15341544Seschrock uint64_t count; 15352676Seschrock zbookmark_t *zb = NULL; 15363444Sek110237 int i; 15371544Seschrock 15381544Seschrock /* 15391544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 15401544Seschrock * has increased, allocate more space and continue until we get the 15411544Seschrock * entire list. 15421544Seschrock */ 15431544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 15441544Seschrock &count) == 0); 15452676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 15462856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 15472082Seschrock return (-1); 15482676Seschrock zc.zc_nvlist_dst_size = count; 15491544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15501544Seschrock for (;;) { 15512082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 15522082Seschrock &zc) != 0) { 15532676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15541544Seschrock if (errno == ENOMEM) { 1555*3823Svb160487 count = zc.zc_nvlist_dst_size; 15562676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 1557*3823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 1558*3823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 15592082Seschrock return (-1); 15601544Seschrock } else { 15611544Seschrock return (-1); 15621544Seschrock } 15631544Seschrock } else { 15641544Seschrock break; 15651544Seschrock } 15661544Seschrock } 15671544Seschrock 15681544Seschrock /* 15691544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 15701544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 15712676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 15721544Seschrock * _not_ copied as part of the process. So we point the start of our 15731544Seschrock * array appropriate and decrement the total number of elements. 15741544Seschrock */ 15752676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 15762676Seschrock zc.zc_nvlist_dst_size; 15772676Seschrock count -= zc.zc_nvlist_dst_size; 15781544Seschrock 15791544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 15801544Seschrock 15813444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 15821544Seschrock 15831544Seschrock /* 15843444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 15851544Seschrock */ 15861544Seschrock for (i = 0; i < count; i++) { 15871544Seschrock nvlist_t *nv; 15881544Seschrock 15893700Sek110237 /* ignoring zb_blkid and zb_level for now */ 15903700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 15913700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 15921544Seschrock continue; 15931544Seschrock 15943444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 15953444Sek110237 goto nomem; 15963444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 15973444Sek110237 zb[i].zb_objset) != 0) { 15983444Sek110237 nvlist_free(nv); 15992082Seschrock goto nomem; 16003444Sek110237 } 16013444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 16023444Sek110237 zb[i].zb_object) != 0) { 16033444Sek110237 nvlist_free(nv); 16043444Sek110237 goto nomem; 16051544Seschrock } 16063444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 16073444Sek110237 nvlist_free(nv); 16083444Sek110237 goto nomem; 16093444Sek110237 } 16103444Sek110237 nvlist_free(nv); 16111544Seschrock } 16121544Seschrock 16133265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 16141544Seschrock return (0); 16152082Seschrock 16162082Seschrock nomem: 16172676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16182082Seschrock return (no_memory(zhp->zpool_hdl)); 16191544Seschrock } 16201760Seschrock 16211760Seschrock /* 16221760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16231760Seschrock */ 16241760Seschrock int 16251760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16261760Seschrock { 16271760Seschrock zfs_cmd_t zc = { 0 }; 16282082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16291760Seschrock 16301760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16312082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 16323237Slling return (zpool_standard_error_fmt(hdl, errno, 16332082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 16342082Seschrock zhp->zpool_name)); 16351760Seschrock 16361760Seschrock return (0); 16371760Seschrock } 16382926Sek110237 16392926Sek110237 /* 16402926Sek110237 * Log command history. 16412926Sek110237 * 16422926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 16432926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 16442926Sek110237 * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the 16452926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 16462926Sek110237 */ 16472926Sek110237 void 16482926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 16492926Sek110237 boolean_t pool, boolean_t pool_create) 16502926Sek110237 { 16512926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 16522926Sek110237 char *dspath; 16532926Sek110237 zfs_cmd_t zc = { 0 }; 16542926Sek110237 int i; 16552926Sek110237 16562926Sek110237 /* construct the command string */ 16572926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 16582926Sek110237 for (i = 0; i < argc; i++) { 16592926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 16602926Sek110237 break; 16612926Sek110237 (void) strcat(cmd_buf, " "); 16622926Sek110237 (void) strcat(cmd_buf, argv[i]); 16632926Sek110237 } 16642926Sek110237 16652926Sek110237 /* figure out the poolname */ 16662926Sek110237 dspath = strpbrk(path, "/@"); 16672926Sek110237 if (dspath == NULL) { 16682926Sek110237 (void) strcpy(zc.zc_name, path); 16692926Sek110237 } else { 16702926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 16712926Sek110237 zc.zc_name[dspath-path] = '\0'; 16722926Sek110237 } 16732926Sek110237 16742926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 16752926Sek110237 zc.zc_history_len = strlen(cmd_buf); 16762926Sek110237 16772926Sek110237 /* overloading zc_history_offset */ 16782926Sek110237 zc.zc_history_offset = pool_create; 16792926Sek110237 16802926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 16812926Sek110237 } 16822926Sek110237 16832926Sek110237 /* 16842926Sek110237 * Perform ioctl to get some command history of a pool. 16852926Sek110237 * 16862926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 16872926Sek110237 * logical offset of the history buffer to start reading from. 16882926Sek110237 * 16892926Sek110237 * Upon return, 'off' is the next logical offset to read from and 16902926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 16912926Sek110237 */ 16922926Sek110237 static int 16932926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 16942926Sek110237 { 16952926Sek110237 zfs_cmd_t zc = { 0 }; 16962926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 16972926Sek110237 16982926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 16992926Sek110237 17002926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 17012926Sek110237 zc.zc_history_len = *len; 17022926Sek110237 zc.zc_history_offset = *off; 17032926Sek110237 17042926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 17052926Sek110237 switch (errno) { 17062926Sek110237 case EPERM: 17073237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 17083237Slling dgettext(TEXT_DOMAIN, 17092926Sek110237 "cannot show history for pool '%s'"), 17102926Sek110237 zhp->zpool_name)); 17112926Sek110237 case ENOENT: 17123237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 17132926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 17142926Sek110237 "'%s'"), zhp->zpool_name)); 17152926Sek110237 default: 17163237Slling return (zpool_standard_error_fmt(hdl, errno, 17172926Sek110237 dgettext(TEXT_DOMAIN, 17182926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 17192926Sek110237 } 17202926Sek110237 } 17212926Sek110237 17222926Sek110237 *len = zc.zc_history_len; 17232926Sek110237 *off = zc.zc_history_offset; 17242926Sek110237 17252926Sek110237 return (0); 17262926Sek110237 } 17272926Sek110237 17282926Sek110237 /* 17292926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 17302926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 17312926Sek110237 * processed as there wasn't a complete record. 17322926Sek110237 */ 17332926Sek110237 static int 17342926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 17352926Sek110237 nvlist_t ***records, uint_t *numrecords) 17362926Sek110237 { 17372926Sek110237 uint64_t reclen; 17382926Sek110237 nvlist_t *nv; 17392926Sek110237 int i; 17402926Sek110237 17412926Sek110237 while (bytes_read > sizeof (reclen)) { 17422926Sek110237 17432926Sek110237 /* get length of packed record (stored as little endian) */ 17442926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 17452926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 17462926Sek110237 17472926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 17482926Sek110237 break; 17492926Sek110237 17502926Sek110237 /* unpack record */ 17512926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 17522926Sek110237 return (ENOMEM); 17532926Sek110237 bytes_read -= sizeof (reclen) + reclen; 17542926Sek110237 buf += sizeof (reclen) + reclen; 17552926Sek110237 17562926Sek110237 /* add record to nvlist array */ 17572926Sek110237 (*numrecords)++; 17582926Sek110237 if (ISP2(*numrecords + 1)) { 17592926Sek110237 *records = realloc(*records, 17602926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 17612926Sek110237 } 17622926Sek110237 (*records)[*numrecords - 1] = nv; 17632926Sek110237 } 17642926Sek110237 17652926Sek110237 *leftover = bytes_read; 17662926Sek110237 return (0); 17672926Sek110237 } 17682926Sek110237 17692926Sek110237 #define HIS_BUF_LEN (128*1024) 17702926Sek110237 17712926Sek110237 /* 17722926Sek110237 * Retrieve the command history of a pool. 17732926Sek110237 */ 17742926Sek110237 int 17752926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 17762926Sek110237 { 17772926Sek110237 char buf[HIS_BUF_LEN]; 17782926Sek110237 uint64_t off = 0; 17792926Sek110237 nvlist_t **records = NULL; 17802926Sek110237 uint_t numrecords = 0; 17812926Sek110237 int err, i; 17822926Sek110237 17832926Sek110237 do { 17842926Sek110237 uint64_t bytes_read = sizeof (buf); 17852926Sek110237 uint64_t leftover; 17862926Sek110237 17872926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 17882926Sek110237 break; 17892926Sek110237 17902926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 17912926Sek110237 if (!bytes_read) 17922926Sek110237 break; 17932926Sek110237 17942926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 17952926Sek110237 &leftover, &records, &numrecords)) != 0) 17962926Sek110237 break; 17972926Sek110237 off -= leftover; 17982926Sek110237 17992926Sek110237 /* CONSTCOND */ 18002926Sek110237 } while (1); 18012926Sek110237 18022926Sek110237 if (!err) { 18032926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 18042926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 18052926Sek110237 records, numrecords) == 0); 18062926Sek110237 } 18072926Sek110237 for (i = 0; i < numrecords; i++) 18082926Sek110237 nvlist_free(records[i]); 18092926Sek110237 free(records); 18102926Sek110237 18112926Sek110237 return (err); 18122926Sek110237 } 18133444Sek110237 18143444Sek110237 void 18153444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 18163444Sek110237 char *pathname, size_t len) 18173444Sek110237 { 18183444Sek110237 zfs_cmd_t zc = { 0 }; 18193444Sek110237 boolean_t mounted = B_FALSE; 18203444Sek110237 char *mntpnt = NULL; 18213444Sek110237 char dsname[MAXNAMELEN]; 18223444Sek110237 18233444Sek110237 if (dsobj == 0) { 18243444Sek110237 /* special case for the MOS */ 18253444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 18263444Sek110237 return; 18273444Sek110237 } 18283444Sek110237 18293444Sek110237 /* get the dataset's name */ 18303444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18313444Sek110237 zc.zc_obj = dsobj; 18323444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 18333444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 18343444Sek110237 /* just write out a path of two object numbers */ 18353444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 18363444Sek110237 dsobj, obj); 18373444Sek110237 return; 18383444Sek110237 } 18393444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 18403444Sek110237 18413444Sek110237 /* find out if the dataset is mounted */ 18423444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 18433444Sek110237 18443444Sek110237 /* get the corrupted object's path */ 18453444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 18463444Sek110237 zc.zc_obj = obj; 18473444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 18483444Sek110237 &zc) == 0) { 18493444Sek110237 if (mounted) { 18503444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 18513444Sek110237 zc.zc_value); 18523444Sek110237 } else { 18533444Sek110237 (void) snprintf(pathname, len, "%s:%s", 18543444Sek110237 dsname, zc.zc_value); 18553444Sek110237 } 18563444Sek110237 } else { 18573444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 18583444Sek110237 } 18593444Sek110237 free(mntpnt); 18603444Sek110237 } 1861