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> 414276Staylor #include <sys/efi_partition.h> 424276Staylor #include <sys/vtoc.h> 43789Sahrens #include <sys/zfs_ioctl.h> 441544Seschrock #include <sys/zio.h> 452926Sek110237 #include <strings.h> 46789Sahrens 47789Sahrens #include "zfs_namecheck.h" 483912Slling #include "zfs_prop.h" 49789Sahrens #include "libzfs_impl.h" 50789Sahrens 51789Sahrens /* 52789Sahrens * Validate the given pool name, optionally putting an extended error message in 53789Sahrens * 'buf'. 54789Sahrens */ 552082Seschrock static boolean_t 562082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 57789Sahrens { 58789Sahrens namecheck_err_t why; 59789Sahrens char what; 601773Seschrock int ret; 61789Sahrens 621773Seschrock ret = pool_namecheck(pool, &why, &what); 631773Seschrock 641773Seschrock /* 651773Seschrock * The rules for reserved pool names were extended at a later point. 661773Seschrock * But we need to support users with existing pools that may now be 671773Seschrock * invalid. So we only check for this expanded set of names during a 681773Seschrock * create (or import), and only in userland. 691773Seschrock */ 701773Seschrock if (ret == 0 && !isopen && 711773Seschrock (strncmp(pool, "mirror", 6) == 0 || 721773Seschrock strncmp(pool, "raidz", 5) == 0 || 73*4527Sperrin strncmp(pool, "spare", 5) == 0 || 74*4527Sperrin strcmp(pool, "log") == 0)) { 752082Seschrock zfs_error_aux(hdl, 762082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 772082Seschrock return (B_FALSE); 781773Seschrock } 791773Seschrock 801773Seschrock 811773Seschrock if (ret != 0) { 822082Seschrock if (hdl != NULL) { 83789Sahrens switch (why) { 841003Slling case NAME_ERR_TOOLONG: 852082Seschrock zfs_error_aux(hdl, 861003Slling dgettext(TEXT_DOMAIN, "name is too long")); 871003Slling break; 881003Slling 89789Sahrens case NAME_ERR_INVALCHAR: 902082Seschrock zfs_error_aux(hdl, 91789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 92789Sahrens "'%c' in pool name"), what); 93789Sahrens break; 94789Sahrens 95789Sahrens case NAME_ERR_NOLETTER: 962082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 972082Seschrock "name must begin with a letter")); 98789Sahrens break; 99789Sahrens 100789Sahrens case NAME_ERR_RESERVED: 1012082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1022082Seschrock "name is reserved")); 103789Sahrens break; 104789Sahrens 105789Sahrens case NAME_ERR_DISKLIKE: 1062082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1072082Seschrock "pool name is reserved")); 108789Sahrens break; 1092856Snd150628 1102856Snd150628 case NAME_ERR_LEADING_SLASH: 1112856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1122856Snd150628 "leading slash in name")); 1132856Snd150628 break; 1142856Snd150628 1152856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 1162856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1172856Snd150628 "empty component in name")); 1182856Snd150628 break; 1192856Snd150628 1202856Snd150628 case NAME_ERR_TRAILING_SLASH: 1212856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1222856Snd150628 "trailing slash in name")); 1232856Snd150628 break; 1242856Snd150628 1252856Snd150628 case NAME_ERR_MULTIPLE_AT: 1262856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1272856Snd150628 "multiple '@' delimiters in name")); 1282856Snd150628 break; 1292856Snd150628 130789Sahrens } 131789Sahrens } 1322082Seschrock return (B_FALSE); 133789Sahrens } 134789Sahrens 1352082Seschrock return (B_TRUE); 136789Sahrens } 137789Sahrens 1383912Slling static int 1393912Slling zpool_get_all_props(zpool_handle_t *zhp) 1403912Slling { 1413912Slling zfs_cmd_t zc = { 0 }; 1423912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 1433912Slling 1443912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1453912Slling 1463912Slling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 1473912Slling return (-1); 1483912Slling 1493912Slling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 1503912Slling if (errno == ENOMEM) { 1513912Slling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 1523912Slling zcmd_free_nvlists(&zc); 1533912Slling return (-1); 1543912Slling } 1553912Slling } else { 1563912Slling zcmd_free_nvlists(&zc); 1573912Slling return (-1); 1583912Slling } 1593912Slling } 1603912Slling 1613912Slling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 1623912Slling zcmd_free_nvlists(&zc); 1633912Slling return (-1); 1643912Slling } 1653912Slling 1663912Slling zcmd_free_nvlists(&zc); 1673912Slling 1683912Slling return (0); 1693912Slling } 1703912Slling 171789Sahrens /* 172789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 173789Sahrens * state. 174789Sahrens */ 175789Sahrens zpool_handle_t * 1762082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 177789Sahrens { 178789Sahrens zpool_handle_t *zhp; 1792142Seschrock boolean_t missing; 180789Sahrens 181789Sahrens /* 182789Sahrens * Make sure the pool name is valid. 183789Sahrens */ 1842082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 1853237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1862082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1872082Seschrock pool); 188789Sahrens return (NULL); 189789Sahrens } 190789Sahrens 1912082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1922082Seschrock return (NULL); 193789Sahrens 1942082Seschrock zhp->zpool_hdl = hdl; 195789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 196789Sahrens 1972142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1982142Seschrock zpool_close(zhp); 1992142Seschrock return (NULL); 2002142Seschrock } 2012142Seschrock 2022142Seschrock if (missing) { 2032142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2042142Seschrock "no such pool")); 2053237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 2062142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 2072142Seschrock pool); 2082142Seschrock zpool_close(zhp); 2092142Seschrock return (NULL); 210789Sahrens } 211789Sahrens 212789Sahrens return (zhp); 213789Sahrens } 214789Sahrens 215789Sahrens /* 216789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 217789Sahrens * the configuration cache may be out of date). 218789Sahrens */ 2192142Seschrock int 2202142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 221789Sahrens { 222789Sahrens zpool_handle_t *zhp; 2232142Seschrock boolean_t missing; 224789Sahrens 2252142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 2262142Seschrock return (-1); 227789Sahrens 2282082Seschrock zhp->zpool_hdl = hdl; 229789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 230789Sahrens 2312142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2322142Seschrock zpool_close(zhp); 2332142Seschrock return (-1); 234789Sahrens } 235789Sahrens 2362142Seschrock if (missing) { 2372142Seschrock zpool_close(zhp); 2382142Seschrock *ret = NULL; 2392142Seschrock return (0); 2402142Seschrock } 2412142Seschrock 2422142Seschrock *ret = zhp; 2432142Seschrock return (0); 244789Sahrens } 245789Sahrens 246789Sahrens /* 247789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 248789Sahrens * state. 249789Sahrens */ 250789Sahrens zpool_handle_t * 2512082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 252789Sahrens { 253789Sahrens zpool_handle_t *zhp; 254789Sahrens 2552082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 256789Sahrens return (NULL); 257789Sahrens 258789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2593237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 2602082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 261789Sahrens zpool_close(zhp); 262789Sahrens return (NULL); 263789Sahrens } 264789Sahrens 265789Sahrens return (zhp); 266789Sahrens } 267789Sahrens 268789Sahrens /* 269789Sahrens * Close the handle. Simply frees the memory associated with the handle. 270789Sahrens */ 271789Sahrens void 272789Sahrens zpool_close(zpool_handle_t *zhp) 273789Sahrens { 274789Sahrens if (zhp->zpool_config) 275789Sahrens nvlist_free(zhp->zpool_config); 276952Seschrock if (zhp->zpool_old_config) 277952Seschrock nvlist_free(zhp->zpool_old_config); 2783912Slling if (zhp->zpool_props) 2793912Slling nvlist_free(zhp->zpool_props); 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, 585*4527Sperrin "pool must be upgraded to add these vdevs")); 5862082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 587789Sahrens break; 588789Sahrens 5893912Slling case EDOM: 5903912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 591*4527Sperrin "root pool can not have multiple vdevs" 592*4527Sperrin " or separate logs")); 5933912Slling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 5943912Slling break; 5953912Slling 596789Sahrens default: 5972082Seschrock (void) zpool_standard_error(hdl, errno, msg); 598789Sahrens } 599789Sahrens 6002082Seschrock ret = -1; 6012082Seschrock } else { 6022082Seschrock ret = 0; 603789Sahrens } 604789Sahrens 6052676Seschrock zcmd_free_nvlists(&zc); 606789Sahrens 6072082Seschrock return (ret); 608789Sahrens } 609789Sahrens 610789Sahrens /* 611789Sahrens * Exports the pool from the system. The caller must ensure that there are no 612789Sahrens * mounted datasets in the pool. 613789Sahrens */ 614789Sahrens int 615789Sahrens zpool_export(zpool_handle_t *zhp) 616789Sahrens { 617789Sahrens zfs_cmd_t zc = { 0 }; 618789Sahrens 619789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 620789Sahrens return (-1); 621789Sahrens 622789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 623789Sahrens 6242082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6253237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 6262082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6272082Seschrock zhp->zpool_name)); 628789Sahrens return (0); 629789Sahrens } 630789Sahrens 631789Sahrens /* 632789Sahrens * Import the given pool using the known configuration. The configuration 633789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 634789Sahrens * parameters control whether the pool is imported with a different name or with 635789Sahrens * an alternate root, respectively. 636789Sahrens */ 637789Sahrens int 6382082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6392082Seschrock const char *altroot) 640789Sahrens { 6412676Seschrock zfs_cmd_t zc = { 0 }; 642789Sahrens char *thename; 643789Sahrens char *origname; 644789Sahrens int ret; 645789Sahrens 646789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 647789Sahrens &origname) == 0); 648789Sahrens 649789Sahrens if (newname != NULL) { 6502082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6513237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6522082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6532082Seschrock newname)); 654789Sahrens thename = (char *)newname; 655789Sahrens } else { 656789Sahrens thename = origname; 657789Sahrens } 658789Sahrens 6592082Seschrock if (altroot != NULL && altroot[0] != '/') 6603237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6612082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6622082Seschrock altroot)); 663789Sahrens 664789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 665789Sahrens 666789Sahrens if (altroot != NULL) 6672676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 668789Sahrens else 6692676Seschrock zc.zc_value[0] = '\0'; 670789Sahrens 671789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6721544Seschrock &zc.zc_guid) == 0); 673789Sahrens 6742676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6752082Seschrock return (-1); 676789Sahrens 677789Sahrens ret = 0; 6782082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 679789Sahrens char desc[1024]; 680789Sahrens if (newname == NULL) 681789Sahrens (void) snprintf(desc, sizeof (desc), 682789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 683789Sahrens thename); 684789Sahrens else 685789Sahrens (void) snprintf(desc, sizeof (desc), 686789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 687789Sahrens origname, thename); 688789Sahrens 689789Sahrens switch (errno) { 6901544Seschrock case ENOTSUP: 6911544Seschrock /* 6921544Seschrock * Unsupported version. 6931544Seschrock */ 6942082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6951544Seschrock break; 6961544Seschrock 6972174Seschrock case EINVAL: 6982174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6992174Seschrock break; 7002174Seschrock 701789Sahrens default: 7022082Seschrock (void) zpool_standard_error(hdl, errno, desc); 703789Sahrens } 704789Sahrens 705789Sahrens ret = -1; 706789Sahrens } else { 707789Sahrens zpool_handle_t *zhp; 708789Sahrens /* 709789Sahrens * This should never fail, but play it safe anyway. 710789Sahrens */ 7112142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7122142Seschrock ret = -1; 7132142Seschrock } else if (zhp != NULL) { 714789Sahrens ret = zpool_create_zvol_links(zhp); 715789Sahrens zpool_close(zhp); 716789Sahrens } 717789Sahrens } 718789Sahrens 7192676Seschrock zcmd_free_nvlists(&zc); 720789Sahrens return (ret); 721789Sahrens } 722789Sahrens 723789Sahrens /* 724789Sahrens * Scrub the pool. 725789Sahrens */ 726789Sahrens int 727789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 728789Sahrens { 729789Sahrens zfs_cmd_t zc = { 0 }; 730789Sahrens char msg[1024]; 7312082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 732789Sahrens 733789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 734789Sahrens zc.zc_cookie = type; 735789Sahrens 7362082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 737789Sahrens return (0); 738789Sahrens 739789Sahrens (void) snprintf(msg, sizeof (msg), 740789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 741789Sahrens 7422082Seschrock if (errno == EBUSY) 7432082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7442082Seschrock else 7452082Seschrock return (zpool_standard_error(hdl, errno, msg)); 746789Sahrens } 747789Sahrens 7482468Sek110237 /* 7492468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7502468Sek110237 * spare; but FALSE if its an INUSE spare. 7512468Sek110237 */ 7522082Seschrock static nvlist_t * 7532082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7542468Sek110237 boolean_t *avail_spare) 7551544Seschrock { 7561544Seschrock uint_t c, children; 7571544Seschrock nvlist_t **child; 7582082Seschrock uint64_t theguid, present; 7591544Seschrock char *path; 7601544Seschrock uint64_t wholedisk = 0; 7612082Seschrock nvlist_t *ret; 7621544Seschrock 7632082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7641544Seschrock 7651544Seschrock if (search == NULL && 7661544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7671544Seschrock /* 7681544Seschrock * If the device has never been present since import, the only 7691544Seschrock * reliable way to match the vdev is by GUID. 7701544Seschrock */ 7712082Seschrock if (theguid == guid) 7722082Seschrock return (nv); 7731544Seschrock } else if (search != NULL && 7741544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7751544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7761544Seschrock &wholedisk); 7771544Seschrock if (wholedisk) { 7781544Seschrock /* 7791544Seschrock * For whole disks, the internal path has 's0', but the 7801544Seschrock * path passed in by the user doesn't. 7811544Seschrock */ 7821544Seschrock if (strlen(search) == strlen(path) - 2 && 7831544Seschrock strncmp(search, path, strlen(search)) == 0) 7842082Seschrock return (nv); 7851544Seschrock } else if (strcmp(search, path) == 0) { 7862082Seschrock return (nv); 7871544Seschrock } 7881544Seschrock } 7891544Seschrock 7901544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7911544Seschrock &child, &children) != 0) 7922082Seschrock return (NULL); 7931544Seschrock 7941544Seschrock for (c = 0; c < children; c++) 7952082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7962468Sek110237 avail_spare)) != NULL) 7971544Seschrock return (ret); 7981544Seschrock 7992082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 8002082Seschrock &child, &children) == 0) { 8012082Seschrock for (c = 0; c < children; c++) { 8022082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 8032468Sek110237 avail_spare)) != NULL) { 8042468Sek110237 *avail_spare = B_TRUE; 8052082Seschrock return (ret); 8062082Seschrock } 8072082Seschrock } 8082082Seschrock } 8092082Seschrock 8102082Seschrock return (NULL); 8111544Seschrock } 8121544Seschrock 8132082Seschrock nvlist_t * 8142468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8151544Seschrock { 8161544Seschrock char buf[MAXPATHLEN]; 8171544Seschrock const char *search; 8181544Seschrock char *end; 8191544Seschrock nvlist_t *nvroot; 8201544Seschrock uint64_t guid; 8211544Seschrock 8221613Seschrock guid = strtoull(path, &end, 10); 8231544Seschrock if (guid != 0 && *end == '\0') { 8241544Seschrock search = NULL; 8251544Seschrock } else if (path[0] != '/') { 8261544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8271544Seschrock search = buf; 8281544Seschrock } else { 8291544Seschrock search = path; 8301544Seschrock } 8311544Seschrock 8321544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8331544Seschrock &nvroot) == 0); 8341544Seschrock 8352468Sek110237 *avail_spare = B_FALSE; 8362468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8372468Sek110237 } 8382468Sek110237 8392468Sek110237 /* 8402468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8412468Sek110237 */ 8422468Sek110237 static boolean_t 8432468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8442468Sek110237 { 8452468Sek110237 uint64_t spare_guid; 8462468Sek110237 nvlist_t *nvroot; 8472468Sek110237 nvlist_t **spares; 8482468Sek110237 uint_t nspares; 8492468Sek110237 int i; 8502468Sek110237 8512468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8522468Sek110237 &nvroot) == 0); 8532468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8542468Sek110237 &spares, &nspares) == 0) { 8552468Sek110237 for (i = 0; i < nspares; i++) { 8562468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8572468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8582468Sek110237 if (guid == spare_guid) 8592468Sek110237 return (B_TRUE); 8602468Sek110237 } 8612468Sek110237 } 8622468Sek110237 8632468Sek110237 return (B_FALSE); 8641544Seschrock } 8651544Seschrock 866789Sahrens /* 8674451Seschrock * Bring the specified vdev online. The 'flags' parameter is a set of the 8684451Seschrock * ZFS_ONLINE_* flags. 869789Sahrens */ 870789Sahrens int 8714451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 8724451Seschrock vdev_state_t *newstate) 873789Sahrens { 874789Sahrens zfs_cmd_t zc = { 0 }; 875789Sahrens char msg[1024]; 8762082Seschrock nvlist_t *tgt; 8772468Sek110237 boolean_t avail_spare; 8782082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 879789Sahrens 8801544Seschrock (void) snprintf(msg, sizeof (msg), 8811544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 882789Sahrens 8831544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8842468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8852082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 886789Sahrens 8872468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8882468Sek110237 8892468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8902082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8912082Seschrock 8924451Seschrock zc.zc_cookie = VDEV_STATE_ONLINE; 8934451Seschrock zc.zc_obj = flags; 8944451Seschrock 895789Sahrens 8964451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) 8974451Seschrock return (zpool_standard_error(hdl, errno, msg)); 8984451Seschrock 8994451Seschrock *newstate = zc.zc_cookie; 9004451Seschrock return (0); 901789Sahrens } 902789Sahrens 903789Sahrens /* 904789Sahrens * Take the specified vdev offline 905789Sahrens */ 906789Sahrens int 9074451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 908789Sahrens { 909789Sahrens zfs_cmd_t zc = { 0 }; 910789Sahrens char msg[1024]; 9112082Seschrock nvlist_t *tgt; 9122468Sek110237 boolean_t avail_spare; 9132082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 914789Sahrens 9151544Seschrock (void) snprintf(msg, sizeof (msg), 9161544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9171544Seschrock 918789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9192468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9202082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9212082Seschrock 9222468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9232468Sek110237 9242468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9252082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9262082Seschrock 9274451Seschrock zc.zc_cookie = VDEV_STATE_OFFLINE; 9284451Seschrock zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 9291485Slling 9304451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 931789Sahrens return (0); 932789Sahrens 933789Sahrens switch (errno) { 9342082Seschrock case EBUSY: 935789Sahrens 936789Sahrens /* 937789Sahrens * There are no other replicas of this device. 938789Sahrens */ 9392082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9402082Seschrock 9412082Seschrock default: 9422082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9432082Seschrock } 9442082Seschrock } 945789Sahrens 9462082Seschrock /* 9474451Seschrock * Mark the given vdev faulted. 9484451Seschrock */ 9494451Seschrock int 9504451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid) 9514451Seschrock { 9524451Seschrock zfs_cmd_t zc = { 0 }; 9534451Seschrock char msg[1024]; 9544451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 9554451Seschrock 9564451Seschrock (void) snprintf(msg, sizeof (msg), 9574451Seschrock dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 9584451Seschrock 9594451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9604451Seschrock zc.zc_guid = guid; 9614451Seschrock zc.zc_cookie = VDEV_STATE_FAULTED; 9624451Seschrock 9634451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 9644451Seschrock return (0); 9654451Seschrock 9664451Seschrock switch (errno) { 9674451Seschrock case EBUSY: 9684451Seschrock 9694451Seschrock /* 9704451Seschrock * There are no other replicas of this device. 9714451Seschrock */ 9724451Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9734451Seschrock 9744451Seschrock default: 9754451Seschrock return (zpool_standard_error(hdl, errno, msg)); 9764451Seschrock } 9774451Seschrock 9784451Seschrock } 9794451Seschrock 9804451Seschrock /* 9814451Seschrock * Mark the given vdev degraded. 9824451Seschrock */ 9834451Seschrock int 9844451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid) 9854451Seschrock { 9864451Seschrock zfs_cmd_t zc = { 0 }; 9874451Seschrock char msg[1024]; 9884451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 9894451Seschrock 9904451Seschrock (void) snprintf(msg, sizeof (msg), 9914451Seschrock dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 9924451Seschrock 9934451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9944451Seschrock zc.zc_guid = guid; 9954451Seschrock zc.zc_cookie = VDEV_STATE_DEGRADED; 9964451Seschrock 9974451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 9984451Seschrock return (0); 9994451Seschrock 10004451Seschrock return (zpool_standard_error(hdl, errno, msg)); 10014451Seschrock } 10024451Seschrock 10034451Seschrock /* 10042082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 10052082Seschrock * a hot spare. 10062082Seschrock */ 10072082Seschrock static boolean_t 10082082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 10092082Seschrock { 10102082Seschrock nvlist_t **child; 10112082Seschrock uint_t c, children; 10122082Seschrock char *type; 10132082Seschrock 10142082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 10152082Seschrock &children) == 0) { 10162082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 10172082Seschrock &type) == 0); 10182082Seschrock 10192082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 10202082Seschrock children == 2 && child[which] == tgt) 10212082Seschrock return (B_TRUE); 10222082Seschrock 10232082Seschrock for (c = 0; c < children; c++) 10242082Seschrock if (is_replacing_spare(child[c], tgt, which)) 10252082Seschrock return (B_TRUE); 1026789Sahrens } 10272082Seschrock 10282082Seschrock return (B_FALSE); 1029789Sahrens } 1030789Sahrens 1031789Sahrens /* 1032789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 1033*4527Sperrin * If 'replacing' is specified, the new disk will replace the old one. 1034789Sahrens */ 1035789Sahrens int 1036789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 1037789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 1038789Sahrens { 1039789Sahrens zfs_cmd_t zc = { 0 }; 1040789Sahrens char msg[1024]; 1041789Sahrens int ret; 10422082Seschrock nvlist_t *tgt; 10432468Sek110237 boolean_t avail_spare; 1044*4527Sperrin uint64_t val, is_log; 10452082Seschrock char *path; 10462082Seschrock nvlist_t **child; 10472082Seschrock uint_t children; 10482082Seschrock nvlist_t *config_root; 10492082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1050789Sahrens 10511544Seschrock if (replacing) 10521544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10531544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 10541544Seschrock else 10551544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10561544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 10571544Seschrock 1058789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 10592468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 10602082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 10612082Seschrock 10622468Sek110237 if (avail_spare) 10632082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 10642082Seschrock 10652082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 10662082Seschrock zc.zc_cookie = replacing; 10672082Seschrock 10682082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10692082Seschrock &child, &children) != 0 || children != 1) { 10702082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10712082Seschrock "new device must be a single disk")); 10722082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10731544Seschrock } 10742082Seschrock 10752082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10762082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10772082Seschrock 10782082Seschrock /* 10792082Seschrock * If the target is a hot spare that has been swapped in, we can only 10802082Seschrock * replace it with another hot spare. 10812082Seschrock */ 10822082Seschrock if (replacing && 10832082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10842082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10852468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10862468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10872082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10882082Seschrock "can only be replaced by another hot spare")); 10892082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10902082Seschrock } 10912082Seschrock 10922082Seschrock /* 10932082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10942082Seschrock * already spared device. 10952082Seschrock */ 10962082Seschrock if (replacing && 10972082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10982468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10992082Seschrock is_replacing_spare(config_root, tgt, 0)) { 11002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11012082Seschrock "device has already been replaced with a spare")); 11022082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 11032082Seschrock } 1104789Sahrens 11052676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 11062082Seschrock return (-1); 1107789Sahrens 11082082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1109789Sahrens 11102676Seschrock zcmd_free_nvlists(&zc); 1111789Sahrens 1112789Sahrens if (ret == 0) 1113789Sahrens return (0); 1114789Sahrens 1115789Sahrens switch (errno) { 11161544Seschrock case ENOTSUP: 1117789Sahrens /* 1118789Sahrens * Can't attach to or replace this type of vdev. 1119789Sahrens */ 1120*4527Sperrin if (replacing) { 1121*4527Sperrin is_log = B_FALSE; 1122*4527Sperrin (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_LOG, 1123*4527Sperrin &is_log); 1124*4527Sperrin if (is_log) 1125*4527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1126*4527Sperrin "cannot replace a log with a spare")); 1127*4527Sperrin else 1128*4527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1129*4527Sperrin "cannot replace a replacing device")); 1130*4527Sperrin } else { 11312082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11322082Seschrock "can only attach to mirrors and top-level " 11332082Seschrock "disks")); 1134*4527Sperrin } 11352082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1136789Sahrens break; 1137789Sahrens 11381544Seschrock case EINVAL: 1139789Sahrens /* 1140789Sahrens * The new device must be a single disk. 1141789Sahrens */ 11422082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11432082Seschrock "new device must be a single disk")); 11442082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1145789Sahrens break; 1146789Sahrens 11471544Seschrock case EBUSY: 11482082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 11492082Seschrock new_disk); 11502082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1151789Sahrens break; 1152789Sahrens 11531544Seschrock case EOVERFLOW: 1154789Sahrens /* 1155789Sahrens * The new device is too small. 1156789Sahrens */ 11572082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11582082Seschrock "device is too small")); 11592082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1160789Sahrens break; 1161789Sahrens 11621544Seschrock case EDOM: 1163789Sahrens /* 1164789Sahrens * The new device has a different alignment requirement. 1165789Sahrens */ 11662082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11672082Seschrock "devices have different sector alignment")); 11682082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1169789Sahrens break; 1170789Sahrens 11711544Seschrock case ENAMETOOLONG: 1172789Sahrens /* 1173789Sahrens * The resulting top-level vdev spec won't fit in the label. 1174789Sahrens */ 11752082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1176789Sahrens break; 1177789Sahrens 11781544Seschrock default: 11792082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1180789Sahrens } 1181789Sahrens 11822082Seschrock return (-1); 1183789Sahrens } 1184789Sahrens 1185789Sahrens /* 1186789Sahrens * Detach the specified device. 1187789Sahrens */ 1188789Sahrens int 1189789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1190789Sahrens { 1191789Sahrens zfs_cmd_t zc = { 0 }; 1192789Sahrens char msg[1024]; 11932082Seschrock nvlist_t *tgt; 11942468Sek110237 boolean_t avail_spare; 11952082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1196789Sahrens 11971544Seschrock (void) snprintf(msg, sizeof (msg), 11981544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11991544Seschrock 1200789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12012468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12022082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1203789Sahrens 12042468Sek110237 if (avail_spare) 12052082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12062082Seschrock 12072082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 12082082Seschrock 12092082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1210789Sahrens return (0); 1211789Sahrens 1212789Sahrens switch (errno) { 1213789Sahrens 12141544Seschrock case ENOTSUP: 1215789Sahrens /* 1216789Sahrens * Can't detach from this type of vdev. 1217789Sahrens */ 12182082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 12192082Seschrock "applicable to mirror and replacing vdevs")); 12202082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1221789Sahrens break; 1222789Sahrens 12231544Seschrock case EBUSY: 1224789Sahrens /* 1225789Sahrens * There are no other replicas of this device. 1226789Sahrens */ 12272082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1228789Sahrens break; 1229789Sahrens 12301544Seschrock default: 12312082Seschrock (void) zpool_standard_error(hdl, errno, msg); 12321544Seschrock } 12331544Seschrock 12342082Seschrock return (-1); 12352082Seschrock } 12362082Seschrock 12372082Seschrock /* 12382082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 12392082Seschrock */ 12402082Seschrock int 12412082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 12422082Seschrock { 12432082Seschrock zfs_cmd_t zc = { 0 }; 12442082Seschrock char msg[1024]; 12452082Seschrock nvlist_t *tgt; 12462468Sek110237 boolean_t avail_spare; 12472082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12482082Seschrock 12492082Seschrock (void) snprintf(msg, sizeof (msg), 12502082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 12512082Seschrock 12522082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12532468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12542082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12552082Seschrock 12562468Sek110237 if (!avail_spare) { 12572082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12583377Seschrock "only inactive hot spares can be removed")); 12592082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12602082Seschrock } 12612082Seschrock 12622082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 12632082Seschrock 12642082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 12652082Seschrock return (0); 12662082Seschrock 12672082Seschrock return (zpool_standard_error(hdl, errno, msg)); 12681544Seschrock } 12691544Seschrock 12701544Seschrock /* 12711544Seschrock * Clear the errors for the pool, or the particular device if specified. 12721544Seschrock */ 12731544Seschrock int 12741544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 12751544Seschrock { 12761544Seschrock zfs_cmd_t zc = { 0 }; 12771544Seschrock char msg[1024]; 12782082Seschrock nvlist_t *tgt; 12792468Sek110237 boolean_t avail_spare; 12802082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12811544Seschrock 12821544Seschrock if (path) 12831544Seschrock (void) snprintf(msg, sizeof (msg), 12841544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12852676Seschrock path); 12861544Seschrock else 12871544Seschrock (void) snprintf(msg, sizeof (msg), 12881544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12891544Seschrock zhp->zpool_name); 12901544Seschrock 12911544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12922082Seschrock if (path) { 12932468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12942082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12952082Seschrock 12962468Sek110237 if (avail_spare) 12972082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12982082Seschrock 12992082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 13002082Seschrock &zc.zc_guid) == 0); 13011544Seschrock } 13021544Seschrock 13032082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 13041544Seschrock return (0); 13051544Seschrock 13062082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1307789Sahrens } 1308789Sahrens 13093126Sahl /* 13104451Seschrock * Similar to zpool_clear(), but takes a GUID (used by fmd). 13114451Seschrock */ 13124451Seschrock int 13134451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) 13144451Seschrock { 13154451Seschrock zfs_cmd_t zc = { 0 }; 13164451Seschrock char msg[1024]; 13174451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 13184451Seschrock 13194451Seschrock (void) snprintf(msg, sizeof (msg), 13204451Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), 13214451Seschrock guid); 13224451Seschrock 13234451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13244451Seschrock zc.zc_guid = guid; 13254451Seschrock 13264451Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 13274451Seschrock return (0); 13284451Seschrock 13294451Seschrock return (zpool_standard_error(hdl, errno, msg)); 13304451Seschrock } 13314451Seschrock 13324451Seschrock /* 13333126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 13343126Sahl * hierarchy. 13353126Sahl */ 13363126Sahl int 13373126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 13383126Sahl void *data) 1339789Sahrens { 13403126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 13413126Sahl char (*paths)[MAXPATHLEN]; 13423126Sahl size_t size = 4; 13433126Sahl int curr, fd, base, ret = 0; 13443126Sahl DIR *dirp; 13453126Sahl struct dirent *dp; 13463126Sahl struct stat st; 13473126Sahl 13483126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 13493126Sahl return (errno == ENOENT ? 0 : -1); 13503126Sahl 13513126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 13523126Sahl int err = errno; 13533126Sahl (void) close(base); 13543126Sahl return (err == ENOENT ? 0 : -1); 13553126Sahl } 1356789Sahrens 1357789Sahrens /* 13583126Sahl * Oddly this wasn't a directory -- ignore that failure since we 13593126Sahl * know there are no links lower in the (non-existant) hierarchy. 1360789Sahrens */ 13613126Sahl if (!S_ISDIR(st.st_mode)) { 13623126Sahl (void) close(base); 13633126Sahl return (0); 13643126Sahl } 13653126Sahl 13663126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 13673126Sahl (void) close(base); 13683126Sahl return (-1); 1369789Sahrens } 1370789Sahrens 13713126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 13723126Sahl curr = 0; 13733126Sahl 13743126Sahl while (curr >= 0) { 13753126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 13763126Sahl goto err; 13773126Sahl 13783126Sahl if (S_ISDIR(st.st_mode)) { 13793126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 13803126Sahl goto err; 13813126Sahl 13823126Sahl if ((dirp = fdopendir(fd)) == NULL) { 13833126Sahl (void) close(fd); 13843126Sahl goto err; 13853126Sahl } 13863126Sahl 13873126Sahl while ((dp = readdir(dirp)) != NULL) { 13883126Sahl if (dp->d_name[0] == '.') 13893126Sahl continue; 13903126Sahl 13913126Sahl if (curr + 1 == size) { 13923126Sahl paths = zfs_realloc(hdl, paths, 13933126Sahl size * sizeof (paths[0]), 13943126Sahl size * 2 * sizeof (paths[0])); 13953126Sahl if (paths == NULL) { 13963126Sahl (void) closedir(dirp); 13973126Sahl (void) close(fd); 13983126Sahl goto err; 13993126Sahl } 14003126Sahl 14013126Sahl size *= 2; 14023126Sahl } 14033126Sahl 14043126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 14053126Sahl sizeof (paths[curr + 1])); 14063126Sahl (void) strlcat(paths[curr], "/", 14073126Sahl sizeof (paths[curr])); 14083126Sahl (void) strlcat(paths[curr], dp->d_name, 14093126Sahl sizeof (paths[curr])); 14103126Sahl curr++; 14113126Sahl } 14123126Sahl 14133126Sahl (void) closedir(dirp); 14143126Sahl 14153126Sahl } else { 14163126Sahl if ((ret = cb(paths[curr], data)) != 0) 14173126Sahl break; 14183126Sahl } 14193126Sahl 14203126Sahl curr--; 14213126Sahl } 14223126Sahl 14233126Sahl free(paths); 14243126Sahl (void) close(base); 14253126Sahl 14263126Sahl return (ret); 14273126Sahl 14283126Sahl err: 14293126Sahl free(paths); 14303126Sahl (void) close(base); 14313126Sahl return (-1); 14323126Sahl } 14333126Sahl 14343126Sahl typedef struct zvol_cb { 14353126Sahl zpool_handle_t *zcb_pool; 14363126Sahl boolean_t zcb_create; 14373126Sahl } zvol_cb_t; 14383126Sahl 14393126Sahl /*ARGSUSED*/ 14403126Sahl static int 14413126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 14423126Sahl { 14433126Sahl int ret; 14443126Sahl 14453126Sahl if (ZFS_IS_VOLUME(zhp)) 14463126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 14473126Sahl 14483126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1449789Sahrens 1450789Sahrens zfs_close(zhp); 14513126Sahl 1452789Sahrens return (ret); 1453789Sahrens } 1454789Sahrens 1455789Sahrens /* 1456789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1457789Sahrens */ 1458789Sahrens int 1459789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1460789Sahrens { 1461789Sahrens zfs_handle_t *zfp; 1462789Sahrens int ret; 1463789Sahrens 1464789Sahrens /* 1465789Sahrens * If the pool is unavailable, just return success. 1466789Sahrens */ 14672082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 14682082Seschrock zhp->zpool_name)) == NULL) 1469789Sahrens return (0); 1470789Sahrens 14713126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1472789Sahrens 1473789Sahrens zfs_close(zfp); 1474789Sahrens return (ret); 1475789Sahrens } 1476789Sahrens 14773126Sahl static int 14783126Sahl do_zvol_remove(const char *dataset, void *data) 14793126Sahl { 14803126Sahl zpool_handle_t *zhp = data; 14813126Sahl 14823126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 14833126Sahl } 14843126Sahl 1485789Sahrens /* 14863126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 14873126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 14883126Sahl * operation. 1489789Sahrens */ 1490789Sahrens int 1491789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1492789Sahrens { 14933126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1494789Sahrens } 14951354Seschrock 14961354Seschrock /* 14971354Seschrock * Convert from a devid string to a path. 14981354Seschrock */ 14991354Seschrock static char * 15001354Seschrock devid_to_path(char *devid_str) 15011354Seschrock { 15021354Seschrock ddi_devid_t devid; 15031354Seschrock char *minor; 15041354Seschrock char *path; 15051354Seschrock devid_nmlist_t *list = NULL; 15061354Seschrock int ret; 15071354Seschrock 15081354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 15091354Seschrock return (NULL); 15101354Seschrock 15111354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 15121354Seschrock 15131354Seschrock devid_str_free(minor); 15141354Seschrock devid_free(devid); 15151354Seschrock 15161354Seschrock if (ret != 0) 15171354Seschrock return (NULL); 15181354Seschrock 15192082Seschrock if ((path = strdup(list[0].devname)) == NULL) 15202082Seschrock return (NULL); 15212082Seschrock 15221354Seschrock devid_free_nmlist(list); 15231354Seschrock 15241354Seschrock return (path); 15251354Seschrock } 15261354Seschrock 15271354Seschrock /* 15281354Seschrock * Convert from a path to a devid string. 15291354Seschrock */ 15301354Seschrock static char * 15311354Seschrock path_to_devid(const char *path) 15321354Seschrock { 15331354Seschrock int fd; 15341354Seschrock ddi_devid_t devid; 15351354Seschrock char *minor, *ret; 15361354Seschrock 15371354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 15381354Seschrock return (NULL); 15391354Seschrock 15401354Seschrock minor = NULL; 15411354Seschrock ret = NULL; 15421354Seschrock if (devid_get(fd, &devid) == 0) { 15431354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 15441354Seschrock ret = devid_str_encode(devid, minor); 15451354Seschrock if (minor != NULL) 15461354Seschrock devid_str_free(minor); 15471354Seschrock devid_free(devid); 15481354Seschrock } 15491354Seschrock (void) close(fd); 15501354Seschrock 15511354Seschrock return (ret); 15521354Seschrock } 15531354Seschrock 15541354Seschrock /* 15551354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 15561354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 15571354Seschrock * type 'zpool status', and we'll display the correct information anyway. 15581354Seschrock */ 15591354Seschrock static void 15601354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 15611354Seschrock { 15621354Seschrock zfs_cmd_t zc = { 0 }; 15631354Seschrock 15641354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 15652676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 15661354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 15671544Seschrock &zc.zc_guid) == 0); 15681354Seschrock 15692082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 15701354Seschrock } 15711354Seschrock 15721354Seschrock /* 15731354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 15741354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 15751354Seschrock * We also check if this is a whole disk, in which case we strip off the 15761354Seschrock * trailing 's0' slice name. 15771354Seschrock * 15781354Seschrock * This routine is also responsible for identifying when disks have been 15791354Seschrock * reconfigured in a new location. The kernel will have opened the device by 15801354Seschrock * devid, but the path will still refer to the old location. To catch this, we 15811354Seschrock * first do a path -> devid translation (which is fast for the common case). If 15821354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 15831354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 15841354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 15851354Seschrock * of these checks. 15861354Seschrock */ 15871354Seschrock char * 15882082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 15891354Seschrock { 15901354Seschrock char *path, *devid; 15911544Seschrock uint64_t value; 15921544Seschrock char buf[64]; 15934451Seschrock vdev_stat_t *vs; 15944451Seschrock uint_t vsc; 15951354Seschrock 15961544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 15971544Seschrock &value) == 0) { 15981544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 15991544Seschrock &value) == 0); 16002856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 16012856Snd150628 (u_longlong_t)value); 16021544Seschrock path = buf; 16031544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 16041354Seschrock 16054451Seschrock /* 16064451Seschrock * If the device is dead (faulted, offline, etc) then don't 16074451Seschrock * bother opening it. Otherwise we may be forcing the user to 16084451Seschrock * open a misbehaving device, which can have undesirable 16094451Seschrock * effects. 16104451Seschrock */ 16114451Seschrock if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 16124451Seschrock (uint64_t **)&vs, &vsc) != 0 || 16134451Seschrock vs->vs_state >= VDEV_STATE_DEGRADED) && 16144451Seschrock zhp != NULL && 16151354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 16161354Seschrock /* 16171354Seschrock * Determine if the current path is correct. 16181354Seschrock */ 16191354Seschrock char *newdevid = path_to_devid(path); 16201354Seschrock 16211354Seschrock if (newdevid == NULL || 16221354Seschrock strcmp(devid, newdevid) != 0) { 16231354Seschrock char *newpath; 16241354Seschrock 16251354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 16261354Seschrock /* 16271354Seschrock * Update the path appropriately. 16281354Seschrock */ 16291354Seschrock set_path(zhp, nv, newpath); 16302082Seschrock if (nvlist_add_string(nv, 16312082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 16322082Seschrock verify(nvlist_lookup_string(nv, 16332082Seschrock ZPOOL_CONFIG_PATH, 16342082Seschrock &path) == 0); 16351354Seschrock free(newpath); 16361354Seschrock } 16371354Seschrock } 16381354Seschrock 16392082Seschrock if (newdevid) 16402082Seschrock devid_str_free(newdevid); 16411354Seschrock } 16421354Seschrock 16431354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 16441354Seschrock path += 9; 16451354Seschrock 16461354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 16471544Seschrock &value) == 0 && value) { 16482082Seschrock char *tmp = zfs_strdup(hdl, path); 16492082Seschrock if (tmp == NULL) 16502082Seschrock return (NULL); 16511354Seschrock tmp[strlen(path) - 2] = '\0'; 16521354Seschrock return (tmp); 16531354Seschrock } 16541354Seschrock } else { 16551354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 16562082Seschrock 16572082Seschrock /* 16582082Seschrock * If it's a raidz device, we need to stick in the parity level. 16592082Seschrock */ 16602082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 16612082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 16622082Seschrock &value) == 0); 16632082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 16642856Snd150628 (u_longlong_t)value); 16652082Seschrock path = buf; 16662082Seschrock } 16671354Seschrock } 16681354Seschrock 16692082Seschrock return (zfs_strdup(hdl, path)); 16701354Seschrock } 16711544Seschrock 16721544Seschrock static int 16731544Seschrock zbookmark_compare(const void *a, const void *b) 16741544Seschrock { 16751544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 16761544Seschrock } 16771544Seschrock 16781544Seschrock /* 16791544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 16801544Seschrock * caller. 16811544Seschrock */ 16821544Seschrock int 16833444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 16841544Seschrock { 16851544Seschrock zfs_cmd_t zc = { 0 }; 16861544Seschrock uint64_t count; 16872676Seschrock zbookmark_t *zb = NULL; 16883444Sek110237 int i; 16891544Seschrock 16901544Seschrock /* 16911544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 16921544Seschrock * has increased, allocate more space and continue until we get the 16931544Seschrock * entire list. 16941544Seschrock */ 16951544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 16961544Seschrock &count) == 0); 16972676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 16982856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 16992082Seschrock return (-1); 17002676Seschrock zc.zc_nvlist_dst_size = count; 17011544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 17021544Seschrock for (;;) { 17032082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 17042082Seschrock &zc) != 0) { 17052676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 17061544Seschrock if (errno == ENOMEM) { 17073823Svb160487 count = zc.zc_nvlist_dst_size; 17082676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 17093823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 17103823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 17112082Seschrock return (-1); 17121544Seschrock } else { 17131544Seschrock return (-1); 17141544Seschrock } 17151544Seschrock } else { 17161544Seschrock break; 17171544Seschrock } 17181544Seschrock } 17191544Seschrock 17201544Seschrock /* 17211544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 17221544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 17232676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 17241544Seschrock * _not_ copied as part of the process. So we point the start of our 17251544Seschrock * array appropriate and decrement the total number of elements. 17261544Seschrock */ 17272676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 17282676Seschrock zc.zc_nvlist_dst_size; 17292676Seschrock count -= zc.zc_nvlist_dst_size; 17301544Seschrock 17311544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 17321544Seschrock 17333444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 17341544Seschrock 17351544Seschrock /* 17363444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 17371544Seschrock */ 17381544Seschrock for (i = 0; i < count; i++) { 17391544Seschrock nvlist_t *nv; 17401544Seschrock 17413700Sek110237 /* ignoring zb_blkid and zb_level for now */ 17423700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 17433700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 17441544Seschrock continue; 17451544Seschrock 17463444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 17473444Sek110237 goto nomem; 17483444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 17493444Sek110237 zb[i].zb_objset) != 0) { 17503444Sek110237 nvlist_free(nv); 17512082Seschrock goto nomem; 17523444Sek110237 } 17533444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 17543444Sek110237 zb[i].zb_object) != 0) { 17553444Sek110237 nvlist_free(nv); 17563444Sek110237 goto nomem; 17571544Seschrock } 17583444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 17593444Sek110237 nvlist_free(nv); 17603444Sek110237 goto nomem; 17613444Sek110237 } 17623444Sek110237 nvlist_free(nv); 17631544Seschrock } 17641544Seschrock 17653265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 17661544Seschrock return (0); 17672082Seschrock 17682082Seschrock nomem: 17692676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 17702082Seschrock return (no_memory(zhp->zpool_hdl)); 17711544Seschrock } 17721760Seschrock 17731760Seschrock /* 17741760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 17751760Seschrock */ 17761760Seschrock int 17771760Seschrock zpool_upgrade(zpool_handle_t *zhp) 17781760Seschrock { 17791760Seschrock zfs_cmd_t zc = { 0 }; 17802082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 17811760Seschrock 17821760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 17832082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 17843237Slling return (zpool_standard_error_fmt(hdl, errno, 17852082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 17862082Seschrock zhp->zpool_name)); 17871760Seschrock 17881760Seschrock return (0); 17891760Seschrock } 17902926Sek110237 17912926Sek110237 /* 17922926Sek110237 * Log command history. 17932926Sek110237 * 17942926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 17952926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 17964451Seschrock * of the pool; B_FALSE otherwise. 'path' is the pathname containing the 17972926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 17982926Sek110237 */ 17992926Sek110237 void 18002926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 18013912Slling boolean_t pool, boolean_t pool_create) 18022926Sek110237 { 18032926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 18042926Sek110237 char *dspath; 18052926Sek110237 zfs_cmd_t zc = { 0 }; 18062926Sek110237 int i; 18072926Sek110237 18082926Sek110237 /* construct the command string */ 18092926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 18102926Sek110237 for (i = 0; i < argc; i++) { 18112926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 18122926Sek110237 break; 18132926Sek110237 (void) strcat(cmd_buf, " "); 18142926Sek110237 (void) strcat(cmd_buf, argv[i]); 18152926Sek110237 } 18162926Sek110237 18172926Sek110237 /* figure out the poolname */ 18182926Sek110237 dspath = strpbrk(path, "/@"); 18192926Sek110237 if (dspath == NULL) { 18202926Sek110237 (void) strcpy(zc.zc_name, path); 18212926Sek110237 } else { 18222926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 18232926Sek110237 zc.zc_name[dspath-path] = '\0'; 18242926Sek110237 } 18252926Sek110237 18262926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 18272926Sek110237 zc.zc_history_len = strlen(cmd_buf); 18282926Sek110237 18292926Sek110237 /* overloading zc_history_offset */ 18302926Sek110237 zc.zc_history_offset = pool_create; 18312926Sek110237 18322926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 18332926Sek110237 } 18342926Sek110237 18352926Sek110237 /* 18362926Sek110237 * Perform ioctl to get some command history of a pool. 18372926Sek110237 * 18382926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 18392926Sek110237 * logical offset of the history buffer to start reading from. 18402926Sek110237 * 18412926Sek110237 * Upon return, 'off' is the next logical offset to read from and 18422926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 18432926Sek110237 */ 18442926Sek110237 static int 18452926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 18462926Sek110237 { 18472926Sek110237 zfs_cmd_t zc = { 0 }; 18482926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 18492926Sek110237 18502926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18512926Sek110237 18522926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 18532926Sek110237 zc.zc_history_len = *len; 18542926Sek110237 zc.zc_history_offset = *off; 18552926Sek110237 18562926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 18572926Sek110237 switch (errno) { 18582926Sek110237 case EPERM: 18593237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 18603237Slling dgettext(TEXT_DOMAIN, 18612926Sek110237 "cannot show history for pool '%s'"), 18622926Sek110237 zhp->zpool_name)); 18632926Sek110237 case ENOENT: 18643237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 18652926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 18662926Sek110237 "'%s'"), zhp->zpool_name)); 18673863Sek110237 case ENOTSUP: 18683863Sek110237 return (zfs_error_fmt(hdl, EZFS_BADVERSION, 18693863Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 18703863Sek110237 "'%s', pool must be upgraded"), zhp->zpool_name)); 18712926Sek110237 default: 18723237Slling return (zpool_standard_error_fmt(hdl, errno, 18732926Sek110237 dgettext(TEXT_DOMAIN, 18742926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 18752926Sek110237 } 18762926Sek110237 } 18772926Sek110237 18782926Sek110237 *len = zc.zc_history_len; 18792926Sek110237 *off = zc.zc_history_offset; 18802926Sek110237 18812926Sek110237 return (0); 18822926Sek110237 } 18832926Sek110237 18842926Sek110237 /* 18852926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 18862926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 18872926Sek110237 * processed as there wasn't a complete record. 18882926Sek110237 */ 18892926Sek110237 static int 18902926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 18912926Sek110237 nvlist_t ***records, uint_t *numrecords) 18922926Sek110237 { 18932926Sek110237 uint64_t reclen; 18942926Sek110237 nvlist_t *nv; 18952926Sek110237 int i; 18962926Sek110237 18972926Sek110237 while (bytes_read > sizeof (reclen)) { 18982926Sek110237 18992926Sek110237 /* get length of packed record (stored as little endian) */ 19002926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 19012926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 19022926Sek110237 19032926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 19042926Sek110237 break; 19052926Sek110237 19062926Sek110237 /* unpack record */ 19072926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 19082926Sek110237 return (ENOMEM); 19092926Sek110237 bytes_read -= sizeof (reclen) + reclen; 19102926Sek110237 buf += sizeof (reclen) + reclen; 19112926Sek110237 19122926Sek110237 /* add record to nvlist array */ 19132926Sek110237 (*numrecords)++; 19142926Sek110237 if (ISP2(*numrecords + 1)) { 19152926Sek110237 *records = realloc(*records, 19162926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 19172926Sek110237 } 19182926Sek110237 (*records)[*numrecords - 1] = nv; 19192926Sek110237 } 19202926Sek110237 19212926Sek110237 *leftover = bytes_read; 19222926Sek110237 return (0); 19232926Sek110237 } 19242926Sek110237 19252926Sek110237 #define HIS_BUF_LEN (128*1024) 19262926Sek110237 19272926Sek110237 /* 19282926Sek110237 * Retrieve the command history of a pool. 19292926Sek110237 */ 19302926Sek110237 int 19312926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 19322926Sek110237 { 19332926Sek110237 char buf[HIS_BUF_LEN]; 19342926Sek110237 uint64_t off = 0; 19352926Sek110237 nvlist_t **records = NULL; 19362926Sek110237 uint_t numrecords = 0; 19372926Sek110237 int err, i; 19382926Sek110237 19392926Sek110237 do { 19402926Sek110237 uint64_t bytes_read = sizeof (buf); 19412926Sek110237 uint64_t leftover; 19422926Sek110237 19432926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 19442926Sek110237 break; 19452926Sek110237 19462926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 19472926Sek110237 if (!bytes_read) 19482926Sek110237 break; 19492926Sek110237 19502926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 19512926Sek110237 &leftover, &records, &numrecords)) != 0) 19522926Sek110237 break; 19532926Sek110237 off -= leftover; 19542926Sek110237 19552926Sek110237 /* CONSTCOND */ 19562926Sek110237 } while (1); 19572926Sek110237 19582926Sek110237 if (!err) { 19592926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 19602926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 19612926Sek110237 records, numrecords) == 0); 19622926Sek110237 } 19632926Sek110237 for (i = 0; i < numrecords; i++) 19642926Sek110237 nvlist_free(records[i]); 19652926Sek110237 free(records); 19662926Sek110237 19672926Sek110237 return (err); 19682926Sek110237 } 19693444Sek110237 19703444Sek110237 void 19713444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 19723444Sek110237 char *pathname, size_t len) 19733444Sek110237 { 19743444Sek110237 zfs_cmd_t zc = { 0 }; 19753444Sek110237 boolean_t mounted = B_FALSE; 19763444Sek110237 char *mntpnt = NULL; 19773444Sek110237 char dsname[MAXNAMELEN]; 19783444Sek110237 19793444Sek110237 if (dsobj == 0) { 19803444Sek110237 /* special case for the MOS */ 19813444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 19823444Sek110237 return; 19833444Sek110237 } 19843444Sek110237 19853444Sek110237 /* get the dataset's name */ 19863444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 19873444Sek110237 zc.zc_obj = dsobj; 19883444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 19893444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 19903444Sek110237 /* just write out a path of two object numbers */ 19913444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 19923444Sek110237 dsobj, obj); 19933444Sek110237 return; 19943444Sek110237 } 19953444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 19963444Sek110237 19973444Sek110237 /* find out if the dataset is mounted */ 19983444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 19993444Sek110237 20003444Sek110237 /* get the corrupted object's path */ 20013444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 20023444Sek110237 zc.zc_obj = obj; 20033444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 20043444Sek110237 &zc) == 0) { 20053444Sek110237 if (mounted) { 20063444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 20073444Sek110237 zc.zc_value); 20083444Sek110237 } else { 20093444Sek110237 (void) snprintf(pathname, len, "%s:%s", 20103444Sek110237 dsname, zc.zc_value); 20113444Sek110237 } 20123444Sek110237 } else { 20133444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 20143444Sek110237 } 20153444Sek110237 free(mntpnt); 20163444Sek110237 } 20173912Slling 20184276Staylor #define RDISK_ROOT "/dev/rdsk" 20194276Staylor #define BACKUP_SLICE "s2" 20204276Staylor /* 20214276Staylor * Don't start the slice at the default block of 34; many storage 20224276Staylor * devices will use a stripe width of 128k, so start there instead. 20234276Staylor */ 20244276Staylor #define NEW_START_BLOCK 256 20254276Staylor 20264276Staylor /* 20274276Staylor * determine where a partition starts on a disk in the current 20284276Staylor * configuration 20294276Staylor */ 20304276Staylor static diskaddr_t 20314276Staylor find_start_block(nvlist_t *config) 20324276Staylor { 20334276Staylor nvlist_t **child; 20344276Staylor uint_t c, children; 20354276Staylor char *path; 20364276Staylor diskaddr_t sb = MAXOFFSET_T; 20374276Staylor int fd; 20384276Staylor char diskname[MAXPATHLEN]; 20394276Staylor uint64_t wholedisk; 20404276Staylor 20414276Staylor if (nvlist_lookup_nvlist_array(config, 20424276Staylor ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 20434276Staylor if (nvlist_lookup_uint64(config, 20444276Staylor ZPOOL_CONFIG_WHOLE_DISK, 20454276Staylor &wholedisk) != 0 || !wholedisk) { 20464276Staylor return (MAXOFFSET_T); 20474276Staylor } 20484276Staylor if (nvlist_lookup_string(config, 20494276Staylor ZPOOL_CONFIG_PATH, &path) != 0) { 20504276Staylor return (MAXOFFSET_T); 20514276Staylor } 20524276Staylor 20534276Staylor (void) snprintf(diskname, sizeof (diskname), "%s%s", 20544276Staylor RDISK_ROOT, strrchr(path, '/')); 20554276Staylor if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 20564276Staylor struct dk_gpt *vtoc; 20574276Staylor if (efi_alloc_and_read(fd, &vtoc) >= 0) { 20584276Staylor sb = vtoc->efi_parts[0].p_start; 20594276Staylor efi_free(vtoc); 20604276Staylor } 20614276Staylor (void) close(fd); 20624276Staylor } 20634276Staylor return (sb); 20644276Staylor } 20654276Staylor 20664276Staylor for (c = 0; c < children; c++) { 20674276Staylor sb = find_start_block(child[c]); 20684276Staylor if (sb != MAXOFFSET_T) { 20694276Staylor return (sb); 20704276Staylor } 20714276Staylor } 20724276Staylor return (MAXOFFSET_T); 20734276Staylor } 20744276Staylor 20754276Staylor /* 20764276Staylor * Label an individual disk. The name provided is the short name, 20774276Staylor * stripped of any leading /dev path. 20784276Staylor */ 20794276Staylor int 20804276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name) 20814276Staylor { 20824276Staylor char path[MAXPATHLEN]; 20834276Staylor struct dk_gpt *vtoc; 20844276Staylor int fd; 20854276Staylor size_t resv = EFI_MIN_RESV_SIZE; 20864276Staylor uint64_t slice_size; 20874276Staylor diskaddr_t start_block; 20884276Staylor char errbuf[1024]; 20894276Staylor 20904276Staylor if (zhp) { 20914276Staylor nvlist_t *nvroot; 20924276Staylor 20934276Staylor verify(nvlist_lookup_nvlist(zhp->zpool_config, 20944276Staylor ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 20954276Staylor 20964276Staylor if (zhp->zpool_start_block == 0) 20974276Staylor start_block = find_start_block(nvroot); 20984276Staylor else 20994276Staylor start_block = zhp->zpool_start_block; 21004276Staylor zhp->zpool_start_block = start_block; 21014276Staylor } else { 21024276Staylor /* new pool */ 21034276Staylor start_block = NEW_START_BLOCK; 21044276Staylor } 21054276Staylor 21064276Staylor (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name, 21074276Staylor BACKUP_SLICE); 21084276Staylor 21094276Staylor if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 21104276Staylor /* 21114276Staylor * This shouldn't happen. We've long since verified that this 21124276Staylor * is a valid device. 21134276Staylor */ 21144276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 21154276Staylor "label '%s': unable to open device"), name); 21164276Staylor return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 21174276Staylor } 21184276Staylor 21194276Staylor if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 21204276Staylor /* 21214276Staylor * The only way this can fail is if we run out of memory, or we 21224276Staylor * were unable to read the disk's capacity 21234276Staylor */ 21244276Staylor if (errno == ENOMEM) 21254276Staylor (void) no_memory(hdl); 21264276Staylor 21274276Staylor (void) close(fd); 21284276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 21294276Staylor "label '%s': unable to read disk capacity"), name); 21304276Staylor 21314276Staylor return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 21324276Staylor } 21334276Staylor 21344276Staylor slice_size = vtoc->efi_last_u_lba + 1; 21354276Staylor slice_size -= EFI_MIN_RESV_SIZE; 21364276Staylor if (start_block == MAXOFFSET_T) 21374276Staylor start_block = NEW_START_BLOCK; 21384276Staylor slice_size -= start_block; 21394276Staylor 21404276Staylor vtoc->efi_parts[0].p_start = start_block; 21414276Staylor vtoc->efi_parts[0].p_size = slice_size; 21424276Staylor 21434276Staylor /* 21444276Staylor * Why we use V_USR: V_BACKUP confuses users, and is considered 21454276Staylor * disposable by some EFI utilities (since EFI doesn't have a backup 21464276Staylor * slice). V_UNASSIGNED is supposed to be used only for zero size 21474276Staylor * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 21484276Staylor * etc. were all pretty specific. V_USR is as close to reality as we 21494276Staylor * can get, in the absence of V_OTHER. 21504276Staylor */ 21514276Staylor vtoc->efi_parts[0].p_tag = V_USR; 21524276Staylor (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 21534276Staylor 21544276Staylor vtoc->efi_parts[8].p_start = slice_size + start_block; 21554276Staylor vtoc->efi_parts[8].p_size = resv; 21564276Staylor vtoc->efi_parts[8].p_tag = V_RESERVED; 21574276Staylor 21584276Staylor if (efi_write(fd, vtoc) != 0) { 21594276Staylor /* 21604276Staylor * Some block drivers (like pcata) may not support EFI 21614276Staylor * GPT labels. Print out a helpful error message dir- 21624276Staylor * ecting the user to manually label the disk and give 21634276Staylor * a specific slice. 21644276Staylor */ 21654276Staylor (void) close(fd); 21664276Staylor efi_free(vtoc); 21674276Staylor 21684276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21694276Staylor "cannot label '%s': try using fdisk(1M) and then " 21704276Staylor "provide a specific slice"), name); 21714276Staylor return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 21724276Staylor } 21734276Staylor 21744276Staylor (void) close(fd); 21754276Staylor efi_free(vtoc); 21764276Staylor return (0); 21774276Staylor } 21784276Staylor 21793912Slling int 21803912Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 21813912Slling { 21823912Slling zfs_cmd_t zc = { 0 }; 21833912Slling int ret = -1; 21843912Slling char errbuf[1024]; 21853912Slling nvlist_t *nvl = NULL; 21863912Slling nvlist_t *realprops; 21873912Slling 21883912Slling (void) snprintf(errbuf, sizeof (errbuf), 21893912Slling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 21903912Slling zhp->zpool_name); 21913912Slling 21923912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 21933912Slling zfs_error_aux(zhp->zpool_hdl, 21943912Slling dgettext(TEXT_DOMAIN, "pool must be " 21953912Slling "upgraded to support pool properties")); 21963912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, errbuf)); 21973912Slling } 21983912Slling 21993912Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 22003912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); 22013912Slling 22023912Slling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 22033912Slling nvlist_add_string(nvl, propname, propval) != 0) { 22043912Slling return (no_memory(zhp->zpool_hdl)); 22053912Slling } 22063912Slling 22073912Slling if ((realprops = zfs_validate_properties(zhp->zpool_hdl, ZFS_TYPE_POOL, 22083912Slling zhp->zpool_name, nvl, 0, NULL, errbuf)) == NULL) { 22093912Slling nvlist_free(nvl); 22103912Slling return (-1); 22113912Slling } 22123912Slling 22133912Slling nvlist_free(nvl); 22143912Slling nvl = realprops; 22153912Slling 22163912Slling /* 22173912Slling * Execute the corresponding ioctl() to set this property. 22183912Slling */ 22193912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 22203912Slling 22213912Slling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl, NULL) != 0) 22223912Slling return (-1); 22233912Slling 22243912Slling ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SET_PROPS, &zc); 22253912Slling zcmd_free_nvlists(&zc); 22263912Slling 22273912Slling if (ret) 22283912Slling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 22293912Slling 22303912Slling return (ret); 22313912Slling } 22323912Slling 22334451Seschrock uint64_t 22344451Seschrock zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop) 22354451Seschrock { 22364451Seschrock uint64_t value; 22374451Seschrock nvlist_t *nvp; 22384451Seschrock 22394451Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) 22404451Seschrock return (0); 22414451Seschrock 22424451Seschrock if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 22434451Seschrock return (zpool_prop_default_numeric(prop)); 22444451Seschrock 22454451Seschrock switch (prop) { 22464451Seschrock case ZPOOL_PROP_AUTOREPLACE: 22474451Seschrock if (nvlist_lookup_nvlist(zhp->zpool_props, 22484451Seschrock zpool_prop_to_name(prop), &nvp) != 0) { 22494451Seschrock value = zpool_prop_default_numeric(prop); 22504451Seschrock } else { 22514451Seschrock VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, 22524451Seschrock &value) == 0); 22534451Seschrock } 22544451Seschrock return (value); 22554451Seschrock break; 22564451Seschrock 22574451Seschrock default: 22584451Seschrock assert(0); 22594451Seschrock } 22604451Seschrock 22614451Seschrock return (0); 22624451Seschrock } 22634451Seschrock 22643912Slling int 22653912Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, 22663912Slling size_t proplen, zfs_source_t *srctype) 22673912Slling { 22683912Slling uint64_t value; 22693912Slling char msg[1024], *strvalue; 22703912Slling nvlist_t *nvp; 22713912Slling zfs_source_t src = ZFS_SRC_NONE; 22723912Slling 22733912Slling (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 22743912Slling "cannot get property '%s'"), zpool_prop_to_name(prop)); 22753912Slling 22763912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 22773912Slling zfs_error_aux(zhp->zpool_hdl, 22783912Slling dgettext(TEXT_DOMAIN, "pool must be " 22793912Slling "upgraded to support pool properties")); 22803912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); 22813912Slling } 22823912Slling 22834451Seschrock if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 22844451Seschrock prop != ZPOOL_PROP_NAME) 22853912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); 22863912Slling 22873912Slling switch (prop) { 22884451Seschrock case ZPOOL_PROP_NAME: 22893912Slling (void) strlcpy(propbuf, zhp->zpool_name, proplen); 22903912Slling break; 22913912Slling 22924451Seschrock case ZPOOL_PROP_BOOTFS: 22933912Slling if (nvlist_lookup_nvlist(zhp->zpool_props, 22943912Slling zpool_prop_to_name(prop), &nvp) != 0) { 22953912Slling strvalue = (char *)zfs_prop_default_string(prop); 22963912Slling if (strvalue == NULL) 22973912Slling strvalue = "-"; 22983912Slling src = ZFS_SRC_DEFAULT; 22993912Slling } else { 23003912Slling VERIFY(nvlist_lookup_uint64(nvp, 23013912Slling ZFS_PROP_SOURCE, &value) == 0); 23023912Slling src = value; 23033912Slling VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE, 23043912Slling &strvalue) == 0); 23053912Slling if (strlen(strvalue) >= proplen) 23063912Slling return (-1); 23073912Slling } 23084451Seschrock (void) strlcpy(propbuf, strvalue, proplen); 23094451Seschrock break; 23104451Seschrock 23114451Seschrock case ZPOOL_PROP_AUTOREPLACE: 23124451Seschrock if (nvlist_lookup_nvlist(zhp->zpool_props, 23134451Seschrock zpool_prop_to_name(prop), &nvp) != 0) { 23144451Seschrock value = zpool_prop_default_numeric(prop); 23154451Seschrock src = ZFS_SRC_DEFAULT; 23164451Seschrock } else { 23174451Seschrock VERIFY(nvlist_lookup_uint64(nvp, 23184451Seschrock ZFS_PROP_SOURCE, &value) == 0); 23194451Seschrock src = value; 23204451Seschrock VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, 23214451Seschrock &value) == 0); 23224451Seschrock } 23234451Seschrock (void) strlcpy(propbuf, value ? "on" : "off", proplen); 23243912Slling break; 23253912Slling 23263912Slling default: 23273912Slling return (-1); 23283912Slling } 23293912Slling if (srctype) 23303912Slling *srctype = src; 23313912Slling return (0); 23323912Slling } 23333912Slling 23343912Slling int 23353912Slling zpool_get_proplist(libzfs_handle_t *hdl, char *fields, zpool_proplist_t **listp) 23363912Slling { 23373912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_POOL)); 23383912Slling } 23393912Slling 23403912Slling 23413912Slling int 23423912Slling zpool_expand_proplist(zpool_handle_t *zhp, zpool_proplist_t **plp) 23433912Slling { 23443912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 23453912Slling zpool_proplist_t *entry; 23463912Slling char buf[ZFS_MAXPROPLEN]; 23473912Slling 23483912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_POOL) != 0) 23493912Slling return (-1); 23503912Slling 23513912Slling for (entry = *plp; entry != NULL; entry = entry->pl_next) { 23523912Slling 23533912Slling if (entry->pl_fixed) 23543912Slling continue; 23553912Slling 23563912Slling if (entry->pl_prop != ZFS_PROP_INVAL && 23573912Slling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 23583912Slling NULL) == 0) { 23593912Slling if (strlen(buf) > entry->pl_width) 23603912Slling entry->pl_width = strlen(buf); 23613912Slling } 23623912Slling } 23633912Slling 23643912Slling return (0); 23653912Slling } 2366