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 || 731773Seschrock strncmp(pool, "spare", 5) == 0)) { 742082Seschrock zfs_error_aux(hdl, 752082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 762082Seschrock return (B_FALSE); 771773Seschrock } 781773Seschrock 791773Seschrock 801773Seschrock if (ret != 0) { 812082Seschrock if (hdl != NULL) { 82789Sahrens switch (why) { 831003Slling case NAME_ERR_TOOLONG: 842082Seschrock zfs_error_aux(hdl, 851003Slling dgettext(TEXT_DOMAIN, "name is too long")); 861003Slling break; 871003Slling 88789Sahrens case NAME_ERR_INVALCHAR: 892082Seschrock zfs_error_aux(hdl, 90789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 91789Sahrens "'%c' in pool name"), what); 92789Sahrens break; 93789Sahrens 94789Sahrens case NAME_ERR_NOLETTER: 952082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 962082Seschrock "name must begin with a letter")); 97789Sahrens break; 98789Sahrens 99789Sahrens case NAME_ERR_RESERVED: 1002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1012082Seschrock "name is reserved")); 102789Sahrens break; 103789Sahrens 104789Sahrens case NAME_ERR_DISKLIKE: 1052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1062082Seschrock "pool name is reserved")); 107789Sahrens break; 1082856Snd150628 1092856Snd150628 case NAME_ERR_LEADING_SLASH: 1102856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1112856Snd150628 "leading slash in name")); 1122856Snd150628 break; 1132856Snd150628 1142856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 1152856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1162856Snd150628 "empty component in name")); 1172856Snd150628 break; 1182856Snd150628 1192856Snd150628 case NAME_ERR_TRAILING_SLASH: 1202856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1212856Snd150628 "trailing slash in name")); 1222856Snd150628 break; 1232856Snd150628 1242856Snd150628 case NAME_ERR_MULTIPLE_AT: 1252856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1262856Snd150628 "multiple '@' delimiters in name")); 1272856Snd150628 break; 1282856Snd150628 129789Sahrens } 130789Sahrens } 1312082Seschrock return (B_FALSE); 132789Sahrens } 133789Sahrens 1342082Seschrock return (B_TRUE); 135789Sahrens } 136789Sahrens 1373912Slling static int 1383912Slling zpool_get_all_props(zpool_handle_t *zhp) 1393912Slling { 1403912Slling zfs_cmd_t zc = { 0 }; 1413912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 1423912Slling 1433912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1443912Slling 1453912Slling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 1463912Slling return (-1); 1473912Slling 1483912Slling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 1493912Slling if (errno == ENOMEM) { 1503912Slling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 1513912Slling zcmd_free_nvlists(&zc); 1523912Slling return (-1); 1533912Slling } 1543912Slling } else { 1553912Slling zcmd_free_nvlists(&zc); 1563912Slling return (-1); 1573912Slling } 1583912Slling } 1593912Slling 1603912Slling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 1613912Slling zcmd_free_nvlists(&zc); 1623912Slling return (-1); 1633912Slling } 1643912Slling 1653912Slling zcmd_free_nvlists(&zc); 1663912Slling 1673912Slling return (0); 1683912Slling } 1693912Slling 170789Sahrens /* 171789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 172789Sahrens * state. 173789Sahrens */ 174789Sahrens zpool_handle_t * 1752082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 176789Sahrens { 177789Sahrens zpool_handle_t *zhp; 1782142Seschrock boolean_t missing; 179789Sahrens 180789Sahrens /* 181789Sahrens * Make sure the pool name is valid. 182789Sahrens */ 1832082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 1843237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1852082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1862082Seschrock pool); 187789Sahrens return (NULL); 188789Sahrens } 189789Sahrens 1902082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1912082Seschrock return (NULL); 192789Sahrens 1932082Seschrock zhp->zpool_hdl = hdl; 194789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 195789Sahrens 1962142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1972142Seschrock zpool_close(zhp); 1982142Seschrock return (NULL); 1992142Seschrock } 2002142Seschrock 2012142Seschrock if (missing) { 2022142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2032142Seschrock "no such pool")); 2043237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 2052142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 2062142Seschrock pool); 2072142Seschrock zpool_close(zhp); 2082142Seschrock return (NULL); 209789Sahrens } 210789Sahrens 211789Sahrens return (zhp); 212789Sahrens } 213789Sahrens 214789Sahrens /* 215789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 216789Sahrens * the configuration cache may be out of date). 217789Sahrens */ 2182142Seschrock int 2192142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 220789Sahrens { 221789Sahrens zpool_handle_t *zhp; 2222142Seschrock boolean_t missing; 223789Sahrens 2242142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 2252142Seschrock return (-1); 226789Sahrens 2272082Seschrock zhp->zpool_hdl = hdl; 228789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 229789Sahrens 2302142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2312142Seschrock zpool_close(zhp); 2322142Seschrock return (-1); 233789Sahrens } 234789Sahrens 2352142Seschrock if (missing) { 2362142Seschrock zpool_close(zhp); 2372142Seschrock *ret = NULL; 2382142Seschrock return (0); 2392142Seschrock } 2402142Seschrock 2412142Seschrock *ret = zhp; 2422142Seschrock return (0); 243789Sahrens } 244789Sahrens 245789Sahrens /* 246789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 247789Sahrens * state. 248789Sahrens */ 249789Sahrens zpool_handle_t * 2502082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 251789Sahrens { 252789Sahrens zpool_handle_t *zhp; 253789Sahrens 2542082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 255789Sahrens return (NULL); 256789Sahrens 257789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2583237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 2592082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 260789Sahrens zpool_close(zhp); 261789Sahrens return (NULL); 262789Sahrens } 263789Sahrens 264789Sahrens return (zhp); 265789Sahrens } 266789Sahrens 267789Sahrens /* 268789Sahrens * Close the handle. Simply frees the memory associated with the handle. 269789Sahrens */ 270789Sahrens void 271789Sahrens zpool_close(zpool_handle_t *zhp) 272789Sahrens { 273789Sahrens if (zhp->zpool_config) 274789Sahrens nvlist_free(zhp->zpool_config); 275952Seschrock if (zhp->zpool_old_config) 276952Seschrock nvlist_free(zhp->zpool_old_config); 2773912Slling if (zhp->zpool_props) 2783912Slling nvlist_free(zhp->zpool_props); 279789Sahrens free(zhp); 280789Sahrens } 281789Sahrens 282789Sahrens /* 283789Sahrens * Return the name of the pool. 284789Sahrens */ 285789Sahrens const char * 286789Sahrens zpool_get_name(zpool_handle_t *zhp) 287789Sahrens { 288789Sahrens return (zhp->zpool_name); 289789Sahrens } 290789Sahrens 291789Sahrens /* 292789Sahrens * Return the GUID of the pool. 293789Sahrens */ 294789Sahrens uint64_t 295789Sahrens zpool_get_guid(zpool_handle_t *zhp) 296789Sahrens { 297789Sahrens uint64_t guid; 298789Sahrens 299789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 300789Sahrens &guid) == 0); 301789Sahrens return (guid); 302789Sahrens } 303789Sahrens 304789Sahrens /* 3052082Seschrock * Return the version of the pool. 3062082Seschrock */ 3072082Seschrock uint64_t 3082082Seschrock zpool_get_version(zpool_handle_t *zhp) 3092082Seschrock { 3102082Seschrock uint64_t version; 3112082Seschrock 3122082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3132082Seschrock &version) == 0); 3142082Seschrock 3152082Seschrock return (version); 3162082Seschrock } 3172082Seschrock 3182082Seschrock /* 319789Sahrens * Return the amount of space currently consumed by the pool. 320789Sahrens */ 321789Sahrens uint64_t 322789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 323789Sahrens { 324789Sahrens nvlist_t *nvroot; 325789Sahrens vdev_stat_t *vs; 326789Sahrens uint_t vsc; 327789Sahrens 328789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 329789Sahrens &nvroot) == 0); 330789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 331789Sahrens (uint64_t **)&vs, &vsc) == 0); 332789Sahrens 333789Sahrens return (vs->vs_alloc); 334789Sahrens } 335789Sahrens 336789Sahrens /* 337789Sahrens * Return the total space in the pool. 338789Sahrens */ 339789Sahrens uint64_t 340789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 341789Sahrens { 342789Sahrens nvlist_t *nvroot; 343789Sahrens vdev_stat_t *vs; 344789Sahrens uint_t vsc; 345789Sahrens 346789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 347789Sahrens &nvroot) == 0); 348789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 349789Sahrens (uint64_t **)&vs, &vsc) == 0); 350789Sahrens 351789Sahrens return (vs->vs_space); 352789Sahrens } 353789Sahrens 354789Sahrens /* 355789Sahrens * Return the alternate root for this pool, if any. 356789Sahrens */ 357789Sahrens int 358789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 359789Sahrens { 360789Sahrens zfs_cmd_t zc = { 0 }; 361789Sahrens 362789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3632082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3642676Seschrock zc.zc_value[0] == '\0') 365789Sahrens return (-1); 366789Sahrens 3672676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 368789Sahrens 369789Sahrens return (0); 370789Sahrens } 371789Sahrens 372789Sahrens /* 373789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 374789Sahrens */ 375789Sahrens int 376789Sahrens zpool_get_state(zpool_handle_t *zhp) 377789Sahrens { 378789Sahrens return (zhp->zpool_state); 379789Sahrens } 380789Sahrens 381789Sahrens /* 382789Sahrens * Create the named pool, using the provided vdev list. It is assumed 383789Sahrens * that the consumer has already validated the contents of the nvlist, so we 384789Sahrens * don't have to worry about error semantics. 385789Sahrens */ 386789Sahrens int 3872082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3882082Seschrock const char *altroot) 389789Sahrens { 390789Sahrens zfs_cmd_t zc = { 0 }; 3912082Seschrock char msg[1024]; 3922082Seschrock 3932082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3942082Seschrock "cannot create '%s'"), pool); 395789Sahrens 3962082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 3972082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 3982082Seschrock 3992082Seschrock if (altroot != NULL && altroot[0] != '/') 4003237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 4012082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 402789Sahrens 4032676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 404789Sahrens return (-1); 405789Sahrens 406789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 407789Sahrens 408789Sahrens if (altroot != NULL) 4092676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 410789Sahrens 4112082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4122676Seschrock zcmd_free_nvlists(&zc); 4132082Seschrock 414789Sahrens switch (errno) { 415789Sahrens case EBUSY: 416789Sahrens /* 417789Sahrens * This can happen if the user has specified the same 418789Sahrens * device multiple times. We can't reliably detect this 419789Sahrens * until we try to add it and see we already have a 420789Sahrens * label. 421789Sahrens */ 4222082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4232082Seschrock "one or more vdevs refer to the same device")); 4242082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 425789Sahrens 426789Sahrens case EOVERFLOW: 427789Sahrens /* 4282082Seschrock * This occurs when one of the devices is below 429789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 430789Sahrens * device was the problem device since there's no 431789Sahrens * reliable way to determine device size from userland. 432789Sahrens */ 433789Sahrens { 434789Sahrens char buf[64]; 435789Sahrens 436789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 437789Sahrens 4382082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4392082Seschrock "one or more devices is less than the " 4402082Seschrock "minimum size (%s)"), buf); 441789Sahrens } 4422082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 443789Sahrens 444789Sahrens case ENOSPC: 4452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4462082Seschrock "one or more devices is out of space")); 4472082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 448789Sahrens 449789Sahrens default: 4502082Seschrock return (zpool_standard_error(hdl, errno, msg)); 451789Sahrens } 452789Sahrens } 453789Sahrens 4542676Seschrock zcmd_free_nvlists(&zc); 455789Sahrens 456789Sahrens /* 457789Sahrens * If this is an alternate root pool, then we automatically set the 4582676Seschrock * mountpoint of the root dataset to be '/'. 459789Sahrens */ 460789Sahrens if (altroot != NULL) { 461789Sahrens zfs_handle_t *zhp; 462789Sahrens 4632082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4642676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4652676Seschrock "/") == 0); 466789Sahrens 467789Sahrens zfs_close(zhp); 468789Sahrens } 469789Sahrens 470789Sahrens return (0); 471789Sahrens } 472789Sahrens 473789Sahrens /* 474789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 475789Sahrens * datasets left in the pool. 476789Sahrens */ 477789Sahrens int 478789Sahrens zpool_destroy(zpool_handle_t *zhp) 479789Sahrens { 480789Sahrens zfs_cmd_t zc = { 0 }; 481789Sahrens zfs_handle_t *zfp = NULL; 4822082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4832082Seschrock char msg[1024]; 484789Sahrens 485789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4862082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4872082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 488789Sahrens return (-1); 489789Sahrens 4902856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 491789Sahrens return (-1); 492789Sahrens 493789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 494789Sahrens 4952082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 4962082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 4972082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 498789Sahrens 4992082Seschrock if (errno == EROFS) { 5002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5012082Seschrock "one or more devices is read only")); 5022082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5032082Seschrock } else { 5042082Seschrock (void) zpool_standard_error(hdl, errno, msg); 505789Sahrens } 506789Sahrens 507789Sahrens if (zfp) 508789Sahrens zfs_close(zfp); 509789Sahrens return (-1); 510789Sahrens } 511789Sahrens 512789Sahrens if (zfp) { 513789Sahrens remove_mountpoint(zfp); 514789Sahrens zfs_close(zfp); 515789Sahrens } 516789Sahrens 517789Sahrens return (0); 518789Sahrens } 519789Sahrens 520789Sahrens /* 521789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 522789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 523789Sahrens */ 524789Sahrens int 525789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 526789Sahrens { 5272676Seschrock zfs_cmd_t zc = { 0 }; 5282082Seschrock int ret; 5292082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5302082Seschrock char msg[1024]; 5312082Seschrock nvlist_t **spares; 5322082Seschrock uint_t nspares; 5332082Seschrock 5342082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5352082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5362082Seschrock 5372082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5382082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5392082Seschrock &spares, &nspares) == 0) { 5402082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5412082Seschrock "upgraded to add hot spares")); 5422082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5432082Seschrock } 544789Sahrens 5452676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5462082Seschrock return (-1); 547789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 548789Sahrens 5492082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 550789Sahrens switch (errno) { 551789Sahrens case EBUSY: 552789Sahrens /* 553789Sahrens * This can happen if the user has specified the same 554789Sahrens * device multiple times. We can't reliably detect this 555789Sahrens * until we try to add it and see we already have a 556789Sahrens * label. 557789Sahrens */ 5582082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5592082Seschrock "one or more vdevs refer to the same device")); 5602082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 561789Sahrens break; 562789Sahrens 563789Sahrens case EOVERFLOW: 564789Sahrens /* 565789Sahrens * This occurrs when one of the devices is below 566789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 567789Sahrens * device was the problem device since there's no 568789Sahrens * reliable way to determine device size from userland. 569789Sahrens */ 570789Sahrens { 571789Sahrens char buf[64]; 572789Sahrens 573789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 574789Sahrens 5752082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5762082Seschrock "device is less than the minimum " 5772082Seschrock "size (%s)"), buf); 578789Sahrens } 5792082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5802082Seschrock break; 5812082Seschrock 5822082Seschrock case ENOTSUP: 5832082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5842082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5852082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 586789Sahrens break; 587789Sahrens 5883912Slling case EDOM: 5893912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5904295Slling "root pool can not have multiple vdevs")); 5913912Slling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 5923912Slling break; 5933912Slling 594789Sahrens default: 5952082Seschrock (void) zpool_standard_error(hdl, errno, msg); 596789Sahrens } 597789Sahrens 5982082Seschrock ret = -1; 5992082Seschrock } else { 6002082Seschrock ret = 0; 601789Sahrens } 602789Sahrens 6032676Seschrock zcmd_free_nvlists(&zc); 604789Sahrens 6052082Seschrock return (ret); 606789Sahrens } 607789Sahrens 608789Sahrens /* 609789Sahrens * Exports the pool from the system. The caller must ensure that there are no 610789Sahrens * mounted datasets in the pool. 611789Sahrens */ 612789Sahrens int 613789Sahrens zpool_export(zpool_handle_t *zhp) 614789Sahrens { 615789Sahrens zfs_cmd_t zc = { 0 }; 616789Sahrens 617789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 618789Sahrens return (-1); 619789Sahrens 620789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 621789Sahrens 6222082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6233237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 6242082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6252082Seschrock zhp->zpool_name)); 626789Sahrens return (0); 627789Sahrens } 628789Sahrens 629789Sahrens /* 630789Sahrens * Import the given pool using the known configuration. The configuration 631789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 632789Sahrens * parameters control whether the pool is imported with a different name or with 633789Sahrens * an alternate root, respectively. 634789Sahrens */ 635789Sahrens int 6362082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6372082Seschrock const char *altroot) 638789Sahrens { 6392676Seschrock zfs_cmd_t zc = { 0 }; 640789Sahrens char *thename; 641789Sahrens char *origname; 642789Sahrens int ret; 643789Sahrens 644789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 645789Sahrens &origname) == 0); 646789Sahrens 647789Sahrens if (newname != NULL) { 6482082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6493237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6502082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6512082Seschrock newname)); 652789Sahrens thename = (char *)newname; 653789Sahrens } else { 654789Sahrens thename = origname; 655789Sahrens } 656789Sahrens 6572082Seschrock if (altroot != NULL && altroot[0] != '/') 6583237Slling return (zfs_error_fmt(hdl, EZFS_BADPATH, 6592082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6602082Seschrock altroot)); 661789Sahrens 662789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 663789Sahrens 664789Sahrens if (altroot != NULL) 6652676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 666789Sahrens else 6672676Seschrock zc.zc_value[0] = '\0'; 668789Sahrens 669789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6701544Seschrock &zc.zc_guid) == 0); 671789Sahrens 6722676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6732082Seschrock return (-1); 674789Sahrens 675789Sahrens ret = 0; 6762082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 677789Sahrens char desc[1024]; 678789Sahrens if (newname == NULL) 679789Sahrens (void) snprintf(desc, sizeof (desc), 680789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 681789Sahrens thename); 682789Sahrens else 683789Sahrens (void) snprintf(desc, sizeof (desc), 684789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 685789Sahrens origname, thename); 686789Sahrens 687789Sahrens switch (errno) { 6881544Seschrock case ENOTSUP: 6891544Seschrock /* 6901544Seschrock * Unsupported version. 6911544Seschrock */ 6922082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6931544Seschrock break; 6941544Seschrock 6952174Seschrock case EINVAL: 6962174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6972174Seschrock break; 6982174Seschrock 699789Sahrens default: 7002082Seschrock (void) zpool_standard_error(hdl, errno, desc); 701789Sahrens } 702789Sahrens 703789Sahrens ret = -1; 704789Sahrens } else { 705789Sahrens zpool_handle_t *zhp; 706789Sahrens /* 707789Sahrens * This should never fail, but play it safe anyway. 708789Sahrens */ 7092142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7102142Seschrock ret = -1; 7112142Seschrock } else if (zhp != NULL) { 712789Sahrens ret = zpool_create_zvol_links(zhp); 713789Sahrens zpool_close(zhp); 714789Sahrens } 715789Sahrens } 716789Sahrens 7172676Seschrock zcmd_free_nvlists(&zc); 718789Sahrens return (ret); 719789Sahrens } 720789Sahrens 721789Sahrens /* 722789Sahrens * Scrub the pool. 723789Sahrens */ 724789Sahrens int 725789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 726789Sahrens { 727789Sahrens zfs_cmd_t zc = { 0 }; 728789Sahrens char msg[1024]; 7292082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 730789Sahrens 731789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 732789Sahrens zc.zc_cookie = type; 733789Sahrens 7342082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 735789Sahrens return (0); 736789Sahrens 737789Sahrens (void) snprintf(msg, sizeof (msg), 738789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 739789Sahrens 7402082Seschrock if (errno == EBUSY) 7412082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7422082Seschrock else 7432082Seschrock return (zpool_standard_error(hdl, errno, msg)); 744789Sahrens } 745789Sahrens 7462468Sek110237 /* 7472468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7482468Sek110237 * spare; but FALSE if its an INUSE spare. 7492468Sek110237 */ 7502082Seschrock static nvlist_t * 7512082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7522468Sek110237 boolean_t *avail_spare) 7531544Seschrock { 7541544Seschrock uint_t c, children; 7551544Seschrock nvlist_t **child; 7562082Seschrock uint64_t theguid, present; 7571544Seschrock char *path; 7581544Seschrock uint64_t wholedisk = 0; 7592082Seschrock nvlist_t *ret; 7601544Seschrock 7612082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7621544Seschrock 7631544Seschrock if (search == NULL && 7641544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7651544Seschrock /* 7661544Seschrock * If the device has never been present since import, the only 7671544Seschrock * reliable way to match the vdev is by GUID. 7681544Seschrock */ 7692082Seschrock if (theguid == guid) 7702082Seschrock return (nv); 7711544Seschrock } else if (search != NULL && 7721544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7731544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7741544Seschrock &wholedisk); 7751544Seschrock if (wholedisk) { 7761544Seschrock /* 7771544Seschrock * For whole disks, the internal path has 's0', but the 7781544Seschrock * path passed in by the user doesn't. 7791544Seschrock */ 7801544Seschrock if (strlen(search) == strlen(path) - 2 && 7811544Seschrock strncmp(search, path, strlen(search)) == 0) 7822082Seschrock return (nv); 7831544Seschrock } else if (strcmp(search, path) == 0) { 7842082Seschrock return (nv); 7851544Seschrock } 7861544Seschrock } 7871544Seschrock 7881544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7891544Seschrock &child, &children) != 0) 7902082Seschrock return (NULL); 7911544Seschrock 7921544Seschrock for (c = 0; c < children; c++) 7932082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7942468Sek110237 avail_spare)) != NULL) 7951544Seschrock return (ret); 7961544Seschrock 7972082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 7982082Seschrock &child, &children) == 0) { 7992082Seschrock for (c = 0; c < children; c++) { 8002082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 8012468Sek110237 avail_spare)) != NULL) { 8022468Sek110237 *avail_spare = B_TRUE; 8032082Seschrock return (ret); 8042082Seschrock } 8052082Seschrock } 8062082Seschrock } 8072082Seschrock 8082082Seschrock return (NULL); 8091544Seschrock } 8101544Seschrock 8112082Seschrock nvlist_t * 8122468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8131544Seschrock { 8141544Seschrock char buf[MAXPATHLEN]; 8151544Seschrock const char *search; 8161544Seschrock char *end; 8171544Seschrock nvlist_t *nvroot; 8181544Seschrock uint64_t guid; 8191544Seschrock 8201613Seschrock guid = strtoull(path, &end, 10); 8211544Seschrock if (guid != 0 && *end == '\0') { 8221544Seschrock search = NULL; 8231544Seschrock } else if (path[0] != '/') { 8241544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8251544Seschrock search = buf; 8261544Seschrock } else { 8271544Seschrock search = path; 8281544Seschrock } 8291544Seschrock 8301544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8311544Seschrock &nvroot) == 0); 8321544Seschrock 8332468Sek110237 *avail_spare = B_FALSE; 8342468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8352468Sek110237 } 8362468Sek110237 8372468Sek110237 /* 8382468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8392468Sek110237 */ 8402468Sek110237 static boolean_t 8412468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8422468Sek110237 { 8432468Sek110237 uint64_t spare_guid; 8442468Sek110237 nvlist_t *nvroot; 8452468Sek110237 nvlist_t **spares; 8462468Sek110237 uint_t nspares; 8472468Sek110237 int i; 8482468Sek110237 8492468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8502468Sek110237 &nvroot) == 0); 8512468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8522468Sek110237 &spares, &nspares) == 0) { 8532468Sek110237 for (i = 0; i < nspares; i++) { 8542468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8552468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8562468Sek110237 if (guid == spare_guid) 8572468Sek110237 return (B_TRUE); 8582468Sek110237 } 8592468Sek110237 } 8602468Sek110237 8612468Sek110237 return (B_FALSE); 8621544Seschrock } 8631544Seschrock 864789Sahrens /* 865*4451Seschrock * Bring the specified vdev online. The 'flags' parameter is a set of the 866*4451Seschrock * ZFS_ONLINE_* flags. 867789Sahrens */ 868789Sahrens int 869*4451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 870*4451Seschrock vdev_state_t *newstate) 871789Sahrens { 872789Sahrens zfs_cmd_t zc = { 0 }; 873789Sahrens char msg[1024]; 8742082Seschrock nvlist_t *tgt; 8752468Sek110237 boolean_t avail_spare; 8762082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 877789Sahrens 8781544Seschrock (void) snprintf(msg, sizeof (msg), 8791544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 880789Sahrens 8811544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8822468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8832082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 884789Sahrens 8852468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8862468Sek110237 8872468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8882082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8892082Seschrock 890*4451Seschrock zc.zc_cookie = VDEV_STATE_ONLINE; 891*4451Seschrock zc.zc_obj = flags; 892*4451Seschrock 893789Sahrens 894*4451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) 895*4451Seschrock return (zpool_standard_error(hdl, errno, msg)); 896*4451Seschrock 897*4451Seschrock *newstate = zc.zc_cookie; 898*4451Seschrock return (0); 899789Sahrens } 900789Sahrens 901789Sahrens /* 902789Sahrens * Take the specified vdev offline 903789Sahrens */ 904789Sahrens int 905*4451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 906789Sahrens { 907789Sahrens zfs_cmd_t zc = { 0 }; 908789Sahrens char msg[1024]; 9092082Seschrock nvlist_t *tgt; 9102468Sek110237 boolean_t avail_spare; 9112082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 912789Sahrens 9131544Seschrock (void) snprintf(msg, sizeof (msg), 9141544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9151544Seschrock 916789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9172468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9182082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9192082Seschrock 9202468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9212468Sek110237 9222468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9232082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9242082Seschrock 925*4451Seschrock zc.zc_cookie = VDEV_STATE_OFFLINE; 926*4451Seschrock zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 9271485Slling 928*4451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 929789Sahrens return (0); 930789Sahrens 931789Sahrens switch (errno) { 9322082Seschrock case EBUSY: 933789Sahrens 934789Sahrens /* 935789Sahrens * There are no other replicas of this device. 936789Sahrens */ 9372082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9382082Seschrock 9392082Seschrock default: 9402082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9412082Seschrock } 9422082Seschrock } 943789Sahrens 9442082Seschrock /* 945*4451Seschrock * Mark the given vdev faulted. 946*4451Seschrock */ 947*4451Seschrock int 948*4451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid) 949*4451Seschrock { 950*4451Seschrock zfs_cmd_t zc = { 0 }; 951*4451Seschrock char msg[1024]; 952*4451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 953*4451Seschrock 954*4451Seschrock (void) snprintf(msg, sizeof (msg), 955*4451Seschrock dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 956*4451Seschrock 957*4451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 958*4451Seschrock zc.zc_guid = guid; 959*4451Seschrock zc.zc_cookie = VDEV_STATE_FAULTED; 960*4451Seschrock 961*4451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 962*4451Seschrock return (0); 963*4451Seschrock 964*4451Seschrock switch (errno) { 965*4451Seschrock case EBUSY: 966*4451Seschrock 967*4451Seschrock /* 968*4451Seschrock * There are no other replicas of this device. 969*4451Seschrock */ 970*4451Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 971*4451Seschrock 972*4451Seschrock default: 973*4451Seschrock return (zpool_standard_error(hdl, errno, msg)); 974*4451Seschrock } 975*4451Seschrock 976*4451Seschrock } 977*4451Seschrock 978*4451Seschrock /* 979*4451Seschrock * Mark the given vdev degraded. 980*4451Seschrock */ 981*4451Seschrock int 982*4451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid) 983*4451Seschrock { 984*4451Seschrock zfs_cmd_t zc = { 0 }; 985*4451Seschrock char msg[1024]; 986*4451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 987*4451Seschrock 988*4451Seschrock (void) snprintf(msg, sizeof (msg), 989*4451Seschrock dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 990*4451Seschrock 991*4451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 992*4451Seschrock zc.zc_guid = guid; 993*4451Seschrock zc.zc_cookie = VDEV_STATE_DEGRADED; 994*4451Seschrock 995*4451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 996*4451Seschrock return (0); 997*4451Seschrock 998*4451Seschrock return (zpool_standard_error(hdl, errno, msg)); 999*4451Seschrock } 1000*4451Seschrock 1001*4451Seschrock /* 10022082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 10032082Seschrock * a hot spare. 10042082Seschrock */ 10052082Seschrock static boolean_t 10062082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 10072082Seschrock { 10082082Seschrock nvlist_t **child; 10092082Seschrock uint_t c, children; 10102082Seschrock char *type; 10112082Seschrock 10122082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 10132082Seschrock &children) == 0) { 10142082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 10152082Seschrock &type) == 0); 10162082Seschrock 10172082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 10182082Seschrock children == 2 && child[which] == tgt) 10192082Seschrock return (B_TRUE); 10202082Seschrock 10212082Seschrock for (c = 0; c < children; c++) 10222082Seschrock if (is_replacing_spare(child[c], tgt, which)) 10232082Seschrock return (B_TRUE); 1024789Sahrens } 10252082Seschrock 10262082Seschrock return (B_FALSE); 1027789Sahrens } 1028789Sahrens 1029789Sahrens /* 1030789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 1031789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 1032789Sahrens */ 1033789Sahrens int 1034789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 1035789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 1036789Sahrens { 1037789Sahrens zfs_cmd_t zc = { 0 }; 1038789Sahrens char msg[1024]; 1039789Sahrens int ret; 10402082Seschrock nvlist_t *tgt; 10412468Sek110237 boolean_t avail_spare; 10422082Seschrock uint64_t val; 10432082Seschrock char *path; 10442082Seschrock nvlist_t **child; 10452082Seschrock uint_t children; 10462082Seschrock nvlist_t *config_root; 10472082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1048789Sahrens 10491544Seschrock if (replacing) 10501544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10511544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 10521544Seschrock else 10531544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10541544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 10551544Seschrock 1056789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 10572468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 10582082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 10592082Seschrock 10602468Sek110237 if (avail_spare) 10612082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 10622082Seschrock 10632082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 10642082Seschrock zc.zc_cookie = replacing; 10652082Seschrock 10662082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10672082Seschrock &child, &children) != 0 || children != 1) { 10682082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10692082Seschrock "new device must be a single disk")); 10702082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10711544Seschrock } 10722082Seschrock 10732082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10742082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10752082Seschrock 10762082Seschrock /* 10772082Seschrock * If the target is a hot spare that has been swapped in, we can only 10782082Seschrock * replace it with another hot spare. 10792082Seschrock */ 10802082Seschrock if (replacing && 10812082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10822082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10832468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10842468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10852082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10862082Seschrock "can only be replaced by another hot spare")); 10872082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10882082Seschrock } 10892082Seschrock 10902082Seschrock /* 10912082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10922082Seschrock * already spared device. 10932082Seschrock */ 10942082Seschrock if (replacing && 10952082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10962468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10972082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10992082Seschrock "device has already been replaced with a spare")); 11002082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 11012082Seschrock } 1102789Sahrens 11032676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 11042082Seschrock return (-1); 1105789Sahrens 11062082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1107789Sahrens 11082676Seschrock zcmd_free_nvlists(&zc); 1109789Sahrens 1110789Sahrens if (ret == 0) 1111789Sahrens return (0); 1112789Sahrens 1113789Sahrens switch (errno) { 11141544Seschrock case ENOTSUP: 1115789Sahrens /* 1116789Sahrens * Can't attach to or replace this type of vdev. 1117789Sahrens */ 1118789Sahrens if (replacing) 11192082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11202082Seschrock "cannot replace a replacing device")); 1121789Sahrens else 11222082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11232082Seschrock "can only attach to mirrors and top-level " 11242082Seschrock "disks")); 11252082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1126789Sahrens break; 1127789Sahrens 11281544Seschrock case EINVAL: 1129789Sahrens /* 1130789Sahrens * The new device must be a single disk. 1131789Sahrens */ 11322082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11332082Seschrock "new device must be a single disk")); 11342082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1135789Sahrens break; 1136789Sahrens 11371544Seschrock case EBUSY: 11382082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 11392082Seschrock new_disk); 11402082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1141789Sahrens break; 1142789Sahrens 11431544Seschrock case EOVERFLOW: 1144789Sahrens /* 1145789Sahrens * The new device is too small. 1146789Sahrens */ 11472082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11482082Seschrock "device is too small")); 11492082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1150789Sahrens break; 1151789Sahrens 11521544Seschrock case EDOM: 1153789Sahrens /* 1154789Sahrens * The new device has a different alignment requirement. 1155789Sahrens */ 11562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11572082Seschrock "devices have different sector alignment")); 11582082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1159789Sahrens break; 1160789Sahrens 11611544Seschrock case ENAMETOOLONG: 1162789Sahrens /* 1163789Sahrens * The resulting top-level vdev spec won't fit in the label. 1164789Sahrens */ 11652082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1166789Sahrens break; 1167789Sahrens 11681544Seschrock default: 11692082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1170789Sahrens } 1171789Sahrens 11722082Seschrock return (-1); 1173789Sahrens } 1174789Sahrens 1175789Sahrens /* 1176789Sahrens * Detach the specified device. 1177789Sahrens */ 1178789Sahrens int 1179789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1180789Sahrens { 1181789Sahrens zfs_cmd_t zc = { 0 }; 1182789Sahrens char msg[1024]; 11832082Seschrock nvlist_t *tgt; 11842468Sek110237 boolean_t avail_spare; 11852082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1186789Sahrens 11871544Seschrock (void) snprintf(msg, sizeof (msg), 11881544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11891544Seschrock 1190789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11912468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11922082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1193789Sahrens 11942468Sek110237 if (avail_spare) 11952082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11962082Seschrock 11972082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11982082Seschrock 11992082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1200789Sahrens return (0); 1201789Sahrens 1202789Sahrens switch (errno) { 1203789Sahrens 12041544Seschrock case ENOTSUP: 1205789Sahrens /* 1206789Sahrens * Can't detach from this type of vdev. 1207789Sahrens */ 12082082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 12092082Seschrock "applicable to mirror and replacing vdevs")); 12102082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1211789Sahrens break; 1212789Sahrens 12131544Seschrock case EBUSY: 1214789Sahrens /* 1215789Sahrens * There are no other replicas of this device. 1216789Sahrens */ 12172082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1218789Sahrens break; 1219789Sahrens 12201544Seschrock default: 12212082Seschrock (void) zpool_standard_error(hdl, errno, msg); 12221544Seschrock } 12231544Seschrock 12242082Seschrock return (-1); 12252082Seschrock } 12262082Seschrock 12272082Seschrock /* 12282082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 12292082Seschrock */ 12302082Seschrock int 12312082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 12322082Seschrock { 12332082Seschrock zfs_cmd_t zc = { 0 }; 12342082Seschrock char msg[1024]; 12352082Seschrock nvlist_t *tgt; 12362468Sek110237 boolean_t avail_spare; 12372082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12382082Seschrock 12392082Seschrock (void) snprintf(msg, sizeof (msg), 12402082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 12412082Seschrock 12422082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12432468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12442082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12452082Seschrock 12462468Sek110237 if (!avail_spare) { 12472082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12483377Seschrock "only inactive hot spares can be removed")); 12492082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12502082Seschrock } 12512082Seschrock 12522082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 12532082Seschrock 12542082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 12552082Seschrock return (0); 12562082Seschrock 12572082Seschrock return (zpool_standard_error(hdl, errno, msg)); 12581544Seschrock } 12591544Seschrock 12601544Seschrock /* 12611544Seschrock * Clear the errors for the pool, or the particular device if specified. 12621544Seschrock */ 12631544Seschrock int 12641544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 12651544Seschrock { 12661544Seschrock zfs_cmd_t zc = { 0 }; 12671544Seschrock char msg[1024]; 12682082Seschrock nvlist_t *tgt; 12692468Sek110237 boolean_t avail_spare; 12702082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12711544Seschrock 12721544Seschrock if (path) 12731544Seschrock (void) snprintf(msg, sizeof (msg), 12741544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12752676Seschrock path); 12761544Seschrock else 12771544Seschrock (void) snprintf(msg, sizeof (msg), 12781544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12791544Seschrock zhp->zpool_name); 12801544Seschrock 12811544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12822082Seschrock if (path) { 12832468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12842082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12852082Seschrock 12862468Sek110237 if (avail_spare) 12872082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12882082Seschrock 12892082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12902082Seschrock &zc.zc_guid) == 0); 12911544Seschrock } 12921544Seschrock 12932082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12941544Seschrock return (0); 12951544Seschrock 12962082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1297789Sahrens } 1298789Sahrens 12993126Sahl /* 1300*4451Seschrock * Similar to zpool_clear(), but takes a GUID (used by fmd). 1301*4451Seschrock */ 1302*4451Seschrock int 1303*4451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) 1304*4451Seschrock { 1305*4451Seschrock zfs_cmd_t zc = { 0 }; 1306*4451Seschrock char msg[1024]; 1307*4451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1308*4451Seschrock 1309*4451Seschrock (void) snprintf(msg, sizeof (msg), 1310*4451Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), 1311*4451Seschrock guid); 1312*4451Seschrock 1313*4451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1314*4451Seschrock zc.zc_guid = guid; 1315*4451Seschrock 1316*4451Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 1317*4451Seschrock return (0); 1318*4451Seschrock 1319*4451Seschrock return (zpool_standard_error(hdl, errno, msg)); 1320*4451Seschrock } 1321*4451Seschrock 1322*4451Seschrock /* 13233126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 13243126Sahl * hierarchy. 13253126Sahl */ 13263126Sahl int 13273126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 13283126Sahl void *data) 1329789Sahrens { 13303126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 13313126Sahl char (*paths)[MAXPATHLEN]; 13323126Sahl size_t size = 4; 13333126Sahl int curr, fd, base, ret = 0; 13343126Sahl DIR *dirp; 13353126Sahl struct dirent *dp; 13363126Sahl struct stat st; 13373126Sahl 13383126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 13393126Sahl return (errno == ENOENT ? 0 : -1); 13403126Sahl 13413126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 13423126Sahl int err = errno; 13433126Sahl (void) close(base); 13443126Sahl return (err == ENOENT ? 0 : -1); 13453126Sahl } 1346789Sahrens 1347789Sahrens /* 13483126Sahl * Oddly this wasn't a directory -- ignore that failure since we 13493126Sahl * know there are no links lower in the (non-existant) hierarchy. 1350789Sahrens */ 13513126Sahl if (!S_ISDIR(st.st_mode)) { 13523126Sahl (void) close(base); 13533126Sahl return (0); 13543126Sahl } 13553126Sahl 13563126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 13573126Sahl (void) close(base); 13583126Sahl return (-1); 1359789Sahrens } 1360789Sahrens 13613126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 13623126Sahl curr = 0; 13633126Sahl 13643126Sahl while (curr >= 0) { 13653126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 13663126Sahl goto err; 13673126Sahl 13683126Sahl if (S_ISDIR(st.st_mode)) { 13693126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 13703126Sahl goto err; 13713126Sahl 13723126Sahl if ((dirp = fdopendir(fd)) == NULL) { 13733126Sahl (void) close(fd); 13743126Sahl goto err; 13753126Sahl } 13763126Sahl 13773126Sahl while ((dp = readdir(dirp)) != NULL) { 13783126Sahl if (dp->d_name[0] == '.') 13793126Sahl continue; 13803126Sahl 13813126Sahl if (curr + 1 == size) { 13823126Sahl paths = zfs_realloc(hdl, paths, 13833126Sahl size * sizeof (paths[0]), 13843126Sahl size * 2 * sizeof (paths[0])); 13853126Sahl if (paths == NULL) { 13863126Sahl (void) closedir(dirp); 13873126Sahl (void) close(fd); 13883126Sahl goto err; 13893126Sahl } 13903126Sahl 13913126Sahl size *= 2; 13923126Sahl } 13933126Sahl 13943126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 13953126Sahl sizeof (paths[curr + 1])); 13963126Sahl (void) strlcat(paths[curr], "/", 13973126Sahl sizeof (paths[curr])); 13983126Sahl (void) strlcat(paths[curr], dp->d_name, 13993126Sahl sizeof (paths[curr])); 14003126Sahl curr++; 14013126Sahl } 14023126Sahl 14033126Sahl (void) closedir(dirp); 14043126Sahl 14053126Sahl } else { 14063126Sahl if ((ret = cb(paths[curr], data)) != 0) 14073126Sahl break; 14083126Sahl } 14093126Sahl 14103126Sahl curr--; 14113126Sahl } 14123126Sahl 14133126Sahl free(paths); 14143126Sahl (void) close(base); 14153126Sahl 14163126Sahl return (ret); 14173126Sahl 14183126Sahl err: 14193126Sahl free(paths); 14203126Sahl (void) close(base); 14213126Sahl return (-1); 14223126Sahl } 14233126Sahl 14243126Sahl typedef struct zvol_cb { 14253126Sahl zpool_handle_t *zcb_pool; 14263126Sahl boolean_t zcb_create; 14273126Sahl } zvol_cb_t; 14283126Sahl 14293126Sahl /*ARGSUSED*/ 14303126Sahl static int 14313126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 14323126Sahl { 14333126Sahl int ret; 14343126Sahl 14353126Sahl if (ZFS_IS_VOLUME(zhp)) 14363126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 14373126Sahl 14383126Sahl ret = zfs_iter_children(zhp, do_zvol_create, NULL); 1439789Sahrens 1440789Sahrens zfs_close(zhp); 14413126Sahl 1442789Sahrens return (ret); 1443789Sahrens } 1444789Sahrens 1445789Sahrens /* 1446789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1447789Sahrens */ 1448789Sahrens int 1449789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1450789Sahrens { 1451789Sahrens zfs_handle_t *zfp; 1452789Sahrens int ret; 1453789Sahrens 1454789Sahrens /* 1455789Sahrens * If the pool is unavailable, just return success. 1456789Sahrens */ 14572082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 14582082Seschrock zhp->zpool_name)) == NULL) 1459789Sahrens return (0); 1460789Sahrens 14613126Sahl ret = zfs_iter_children(zfp, do_zvol_create, NULL); 1462789Sahrens 1463789Sahrens zfs_close(zfp); 1464789Sahrens return (ret); 1465789Sahrens } 1466789Sahrens 14673126Sahl static int 14683126Sahl do_zvol_remove(const char *dataset, void *data) 14693126Sahl { 14703126Sahl zpool_handle_t *zhp = data; 14713126Sahl 14723126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 14733126Sahl } 14743126Sahl 1475789Sahrens /* 14763126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 14773126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 14783126Sahl * operation. 1479789Sahrens */ 1480789Sahrens int 1481789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1482789Sahrens { 14833126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1484789Sahrens } 14851354Seschrock 14861354Seschrock /* 14871354Seschrock * Convert from a devid string to a path. 14881354Seschrock */ 14891354Seschrock static char * 14901354Seschrock devid_to_path(char *devid_str) 14911354Seschrock { 14921354Seschrock ddi_devid_t devid; 14931354Seschrock char *minor; 14941354Seschrock char *path; 14951354Seschrock devid_nmlist_t *list = NULL; 14961354Seschrock int ret; 14971354Seschrock 14981354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 14991354Seschrock return (NULL); 15001354Seschrock 15011354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 15021354Seschrock 15031354Seschrock devid_str_free(minor); 15041354Seschrock devid_free(devid); 15051354Seschrock 15061354Seschrock if (ret != 0) 15071354Seschrock return (NULL); 15081354Seschrock 15092082Seschrock if ((path = strdup(list[0].devname)) == NULL) 15102082Seschrock return (NULL); 15112082Seschrock 15121354Seschrock devid_free_nmlist(list); 15131354Seschrock 15141354Seschrock return (path); 15151354Seschrock } 15161354Seschrock 15171354Seschrock /* 15181354Seschrock * Convert from a path to a devid string. 15191354Seschrock */ 15201354Seschrock static char * 15211354Seschrock path_to_devid(const char *path) 15221354Seschrock { 15231354Seschrock int fd; 15241354Seschrock ddi_devid_t devid; 15251354Seschrock char *minor, *ret; 15261354Seschrock 15271354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 15281354Seschrock return (NULL); 15291354Seschrock 15301354Seschrock minor = NULL; 15311354Seschrock ret = NULL; 15321354Seschrock if (devid_get(fd, &devid) == 0) { 15331354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 15341354Seschrock ret = devid_str_encode(devid, minor); 15351354Seschrock if (minor != NULL) 15361354Seschrock devid_str_free(minor); 15371354Seschrock devid_free(devid); 15381354Seschrock } 15391354Seschrock (void) close(fd); 15401354Seschrock 15411354Seschrock return (ret); 15421354Seschrock } 15431354Seschrock 15441354Seschrock /* 15451354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 15461354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 15471354Seschrock * type 'zpool status', and we'll display the correct information anyway. 15481354Seschrock */ 15491354Seschrock static void 15501354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 15511354Seschrock { 15521354Seschrock zfs_cmd_t zc = { 0 }; 15531354Seschrock 15541354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 15552676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 15561354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 15571544Seschrock &zc.zc_guid) == 0); 15581354Seschrock 15592082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 15601354Seschrock } 15611354Seschrock 15621354Seschrock /* 15631354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 15641354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 15651354Seschrock * We also check if this is a whole disk, in which case we strip off the 15661354Seschrock * trailing 's0' slice name. 15671354Seschrock * 15681354Seschrock * This routine is also responsible for identifying when disks have been 15691354Seschrock * reconfigured in a new location. The kernel will have opened the device by 15701354Seschrock * devid, but the path will still refer to the old location. To catch this, we 15711354Seschrock * first do a path -> devid translation (which is fast for the common case). If 15721354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 15731354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 15741354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 15751354Seschrock * of these checks. 15761354Seschrock */ 15771354Seschrock char * 15782082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 15791354Seschrock { 15801354Seschrock char *path, *devid; 15811544Seschrock uint64_t value; 15821544Seschrock char buf[64]; 1583*4451Seschrock vdev_stat_t *vs; 1584*4451Seschrock uint_t vsc; 15851354Seschrock 15861544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 15871544Seschrock &value) == 0) { 15881544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 15891544Seschrock &value) == 0); 15902856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 15912856Snd150628 (u_longlong_t)value); 15921544Seschrock path = buf; 15931544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 15941354Seschrock 1595*4451Seschrock /* 1596*4451Seschrock * If the device is dead (faulted, offline, etc) then don't 1597*4451Seschrock * bother opening it. Otherwise we may be forcing the user to 1598*4451Seschrock * open a misbehaving device, which can have undesirable 1599*4451Seschrock * effects. 1600*4451Seschrock */ 1601*4451Seschrock if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 1602*4451Seschrock (uint64_t **)&vs, &vsc) != 0 || 1603*4451Seschrock vs->vs_state >= VDEV_STATE_DEGRADED) && 1604*4451Seschrock zhp != NULL && 16051354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 16061354Seschrock /* 16071354Seschrock * Determine if the current path is correct. 16081354Seschrock */ 16091354Seschrock char *newdevid = path_to_devid(path); 16101354Seschrock 16111354Seschrock if (newdevid == NULL || 16121354Seschrock strcmp(devid, newdevid) != 0) { 16131354Seschrock char *newpath; 16141354Seschrock 16151354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 16161354Seschrock /* 16171354Seschrock * Update the path appropriately. 16181354Seschrock */ 16191354Seschrock set_path(zhp, nv, newpath); 16202082Seschrock if (nvlist_add_string(nv, 16212082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 16222082Seschrock verify(nvlist_lookup_string(nv, 16232082Seschrock ZPOOL_CONFIG_PATH, 16242082Seschrock &path) == 0); 16251354Seschrock free(newpath); 16261354Seschrock } 16271354Seschrock } 16281354Seschrock 16292082Seschrock if (newdevid) 16302082Seschrock devid_str_free(newdevid); 16311354Seschrock } 16321354Seschrock 16331354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 16341354Seschrock path += 9; 16351354Seschrock 16361354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 16371544Seschrock &value) == 0 && value) { 16382082Seschrock char *tmp = zfs_strdup(hdl, path); 16392082Seschrock if (tmp == NULL) 16402082Seschrock return (NULL); 16411354Seschrock tmp[strlen(path) - 2] = '\0'; 16421354Seschrock return (tmp); 16431354Seschrock } 16441354Seschrock } else { 16451354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 16462082Seschrock 16472082Seschrock /* 16482082Seschrock * If it's a raidz device, we need to stick in the parity level. 16492082Seschrock */ 16502082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 16512082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 16522082Seschrock &value) == 0); 16532082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 16542856Snd150628 (u_longlong_t)value); 16552082Seschrock path = buf; 16562082Seschrock } 16571354Seschrock } 16581354Seschrock 16592082Seschrock return (zfs_strdup(hdl, path)); 16601354Seschrock } 16611544Seschrock 16621544Seschrock static int 16631544Seschrock zbookmark_compare(const void *a, const void *b) 16641544Seschrock { 16651544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 16661544Seschrock } 16671544Seschrock 16681544Seschrock /* 16691544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 16701544Seschrock * caller. 16711544Seschrock */ 16721544Seschrock int 16733444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 16741544Seschrock { 16751544Seschrock zfs_cmd_t zc = { 0 }; 16761544Seschrock uint64_t count; 16772676Seschrock zbookmark_t *zb = NULL; 16783444Sek110237 int i; 16791544Seschrock 16801544Seschrock /* 16811544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 16821544Seschrock * has increased, allocate more space and continue until we get the 16831544Seschrock * entire list. 16841544Seschrock */ 16851544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 16861544Seschrock &count) == 0); 16872676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 16882856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 16892082Seschrock return (-1); 16902676Seschrock zc.zc_nvlist_dst_size = count; 16911544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16921544Seschrock for (;;) { 16932082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 16942082Seschrock &zc) != 0) { 16952676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16961544Seschrock if (errno == ENOMEM) { 16973823Svb160487 count = zc.zc_nvlist_dst_size; 16982676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 16993823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 17003823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 17012082Seschrock return (-1); 17021544Seschrock } else { 17031544Seschrock return (-1); 17041544Seschrock } 17051544Seschrock } else { 17061544Seschrock break; 17071544Seschrock } 17081544Seschrock } 17091544Seschrock 17101544Seschrock /* 17111544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 17121544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 17132676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 17141544Seschrock * _not_ copied as part of the process. So we point the start of our 17151544Seschrock * array appropriate and decrement the total number of elements. 17161544Seschrock */ 17172676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 17182676Seschrock zc.zc_nvlist_dst_size; 17192676Seschrock count -= zc.zc_nvlist_dst_size; 17201544Seschrock 17211544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 17221544Seschrock 17233444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 17241544Seschrock 17251544Seschrock /* 17263444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 17271544Seschrock */ 17281544Seschrock for (i = 0; i < count; i++) { 17291544Seschrock nvlist_t *nv; 17301544Seschrock 17313700Sek110237 /* ignoring zb_blkid and zb_level for now */ 17323700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 17333700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 17341544Seschrock continue; 17351544Seschrock 17363444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 17373444Sek110237 goto nomem; 17383444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 17393444Sek110237 zb[i].zb_objset) != 0) { 17403444Sek110237 nvlist_free(nv); 17412082Seschrock goto nomem; 17423444Sek110237 } 17433444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 17443444Sek110237 zb[i].zb_object) != 0) { 17453444Sek110237 nvlist_free(nv); 17463444Sek110237 goto nomem; 17471544Seschrock } 17483444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 17493444Sek110237 nvlist_free(nv); 17503444Sek110237 goto nomem; 17513444Sek110237 } 17523444Sek110237 nvlist_free(nv); 17531544Seschrock } 17541544Seschrock 17553265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 17561544Seschrock return (0); 17572082Seschrock 17582082Seschrock nomem: 17592676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 17602082Seschrock return (no_memory(zhp->zpool_hdl)); 17611544Seschrock } 17621760Seschrock 17631760Seschrock /* 17641760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 17651760Seschrock */ 17661760Seschrock int 17671760Seschrock zpool_upgrade(zpool_handle_t *zhp) 17681760Seschrock { 17691760Seschrock zfs_cmd_t zc = { 0 }; 17702082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 17711760Seschrock 17721760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 17732082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 17743237Slling return (zpool_standard_error_fmt(hdl, errno, 17752082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 17762082Seschrock zhp->zpool_name)); 17771760Seschrock 17781760Seschrock return (0); 17791760Seschrock } 17802926Sek110237 17812926Sek110237 /* 17822926Sek110237 * Log command history. 17832926Sek110237 * 17842926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 17852926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 1786*4451Seschrock * of the pool; B_FALSE otherwise. 'path' is the pathname containing the 17872926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 17882926Sek110237 */ 17892926Sek110237 void 17902926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 17913912Slling boolean_t pool, boolean_t pool_create) 17922926Sek110237 { 17932926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 17942926Sek110237 char *dspath; 17952926Sek110237 zfs_cmd_t zc = { 0 }; 17962926Sek110237 int i; 17972926Sek110237 17982926Sek110237 /* construct the command string */ 17992926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 18002926Sek110237 for (i = 0; i < argc; i++) { 18012926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 18022926Sek110237 break; 18032926Sek110237 (void) strcat(cmd_buf, " "); 18042926Sek110237 (void) strcat(cmd_buf, argv[i]); 18052926Sek110237 } 18062926Sek110237 18072926Sek110237 /* figure out the poolname */ 18082926Sek110237 dspath = strpbrk(path, "/@"); 18092926Sek110237 if (dspath == NULL) { 18102926Sek110237 (void) strcpy(zc.zc_name, path); 18112926Sek110237 } else { 18122926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 18132926Sek110237 zc.zc_name[dspath-path] = '\0'; 18142926Sek110237 } 18152926Sek110237 18162926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 18172926Sek110237 zc.zc_history_len = strlen(cmd_buf); 18182926Sek110237 18192926Sek110237 /* overloading zc_history_offset */ 18202926Sek110237 zc.zc_history_offset = pool_create; 18212926Sek110237 18222926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 18232926Sek110237 } 18242926Sek110237 18252926Sek110237 /* 18262926Sek110237 * Perform ioctl to get some command history of a pool. 18272926Sek110237 * 18282926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 18292926Sek110237 * logical offset of the history buffer to start reading from. 18302926Sek110237 * 18312926Sek110237 * Upon return, 'off' is the next logical offset to read from and 18322926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 18332926Sek110237 */ 18342926Sek110237 static int 18352926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 18362926Sek110237 { 18372926Sek110237 zfs_cmd_t zc = { 0 }; 18382926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 18392926Sek110237 18402926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18412926Sek110237 18422926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 18432926Sek110237 zc.zc_history_len = *len; 18442926Sek110237 zc.zc_history_offset = *off; 18452926Sek110237 18462926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 18472926Sek110237 switch (errno) { 18482926Sek110237 case EPERM: 18493237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 18503237Slling dgettext(TEXT_DOMAIN, 18512926Sek110237 "cannot show history for pool '%s'"), 18522926Sek110237 zhp->zpool_name)); 18532926Sek110237 case ENOENT: 18543237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 18552926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 18562926Sek110237 "'%s'"), zhp->zpool_name)); 18573863Sek110237 case ENOTSUP: 18583863Sek110237 return (zfs_error_fmt(hdl, EZFS_BADVERSION, 18593863Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 18603863Sek110237 "'%s', pool must be upgraded"), zhp->zpool_name)); 18612926Sek110237 default: 18623237Slling return (zpool_standard_error_fmt(hdl, errno, 18632926Sek110237 dgettext(TEXT_DOMAIN, 18642926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 18652926Sek110237 } 18662926Sek110237 } 18672926Sek110237 18682926Sek110237 *len = zc.zc_history_len; 18692926Sek110237 *off = zc.zc_history_offset; 18702926Sek110237 18712926Sek110237 return (0); 18722926Sek110237 } 18732926Sek110237 18742926Sek110237 /* 18752926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 18762926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 18772926Sek110237 * processed as there wasn't a complete record. 18782926Sek110237 */ 18792926Sek110237 static int 18802926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 18812926Sek110237 nvlist_t ***records, uint_t *numrecords) 18822926Sek110237 { 18832926Sek110237 uint64_t reclen; 18842926Sek110237 nvlist_t *nv; 18852926Sek110237 int i; 18862926Sek110237 18872926Sek110237 while (bytes_read > sizeof (reclen)) { 18882926Sek110237 18892926Sek110237 /* get length of packed record (stored as little endian) */ 18902926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 18912926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 18922926Sek110237 18932926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 18942926Sek110237 break; 18952926Sek110237 18962926Sek110237 /* unpack record */ 18972926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 18982926Sek110237 return (ENOMEM); 18992926Sek110237 bytes_read -= sizeof (reclen) + reclen; 19002926Sek110237 buf += sizeof (reclen) + reclen; 19012926Sek110237 19022926Sek110237 /* add record to nvlist array */ 19032926Sek110237 (*numrecords)++; 19042926Sek110237 if (ISP2(*numrecords + 1)) { 19052926Sek110237 *records = realloc(*records, 19062926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 19072926Sek110237 } 19082926Sek110237 (*records)[*numrecords - 1] = nv; 19092926Sek110237 } 19102926Sek110237 19112926Sek110237 *leftover = bytes_read; 19122926Sek110237 return (0); 19132926Sek110237 } 19142926Sek110237 19152926Sek110237 #define HIS_BUF_LEN (128*1024) 19162926Sek110237 19172926Sek110237 /* 19182926Sek110237 * Retrieve the command history of a pool. 19192926Sek110237 */ 19202926Sek110237 int 19212926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 19222926Sek110237 { 19232926Sek110237 char buf[HIS_BUF_LEN]; 19242926Sek110237 uint64_t off = 0; 19252926Sek110237 nvlist_t **records = NULL; 19262926Sek110237 uint_t numrecords = 0; 19272926Sek110237 int err, i; 19282926Sek110237 19292926Sek110237 do { 19302926Sek110237 uint64_t bytes_read = sizeof (buf); 19312926Sek110237 uint64_t leftover; 19322926Sek110237 19332926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 19342926Sek110237 break; 19352926Sek110237 19362926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 19372926Sek110237 if (!bytes_read) 19382926Sek110237 break; 19392926Sek110237 19402926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 19412926Sek110237 &leftover, &records, &numrecords)) != 0) 19422926Sek110237 break; 19432926Sek110237 off -= leftover; 19442926Sek110237 19452926Sek110237 /* CONSTCOND */ 19462926Sek110237 } while (1); 19472926Sek110237 19482926Sek110237 if (!err) { 19492926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 19502926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 19512926Sek110237 records, numrecords) == 0); 19522926Sek110237 } 19532926Sek110237 for (i = 0; i < numrecords; i++) 19542926Sek110237 nvlist_free(records[i]); 19552926Sek110237 free(records); 19562926Sek110237 19572926Sek110237 return (err); 19582926Sek110237 } 19593444Sek110237 19603444Sek110237 void 19613444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 19623444Sek110237 char *pathname, size_t len) 19633444Sek110237 { 19643444Sek110237 zfs_cmd_t zc = { 0 }; 19653444Sek110237 boolean_t mounted = B_FALSE; 19663444Sek110237 char *mntpnt = NULL; 19673444Sek110237 char dsname[MAXNAMELEN]; 19683444Sek110237 19693444Sek110237 if (dsobj == 0) { 19703444Sek110237 /* special case for the MOS */ 19713444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 19723444Sek110237 return; 19733444Sek110237 } 19743444Sek110237 19753444Sek110237 /* get the dataset's name */ 19763444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 19773444Sek110237 zc.zc_obj = dsobj; 19783444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 19793444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 19803444Sek110237 /* just write out a path of two object numbers */ 19813444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 19823444Sek110237 dsobj, obj); 19833444Sek110237 return; 19843444Sek110237 } 19853444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 19863444Sek110237 19873444Sek110237 /* find out if the dataset is mounted */ 19883444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 19893444Sek110237 19903444Sek110237 /* get the corrupted object's path */ 19913444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 19923444Sek110237 zc.zc_obj = obj; 19933444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 19943444Sek110237 &zc) == 0) { 19953444Sek110237 if (mounted) { 19963444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 19973444Sek110237 zc.zc_value); 19983444Sek110237 } else { 19993444Sek110237 (void) snprintf(pathname, len, "%s:%s", 20003444Sek110237 dsname, zc.zc_value); 20013444Sek110237 } 20023444Sek110237 } else { 20033444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 20043444Sek110237 } 20053444Sek110237 free(mntpnt); 20063444Sek110237 } 20073912Slling 20084276Staylor #define RDISK_ROOT "/dev/rdsk" 20094276Staylor #define BACKUP_SLICE "s2" 20104276Staylor /* 20114276Staylor * Don't start the slice at the default block of 34; many storage 20124276Staylor * devices will use a stripe width of 128k, so start there instead. 20134276Staylor */ 20144276Staylor #define NEW_START_BLOCK 256 20154276Staylor 20164276Staylor /* 20174276Staylor * determine where a partition starts on a disk in the current 20184276Staylor * configuration 20194276Staylor */ 20204276Staylor static diskaddr_t 20214276Staylor find_start_block(nvlist_t *config) 20224276Staylor { 20234276Staylor nvlist_t **child; 20244276Staylor uint_t c, children; 20254276Staylor char *path; 20264276Staylor diskaddr_t sb = MAXOFFSET_T; 20274276Staylor int fd; 20284276Staylor char diskname[MAXPATHLEN]; 20294276Staylor uint64_t wholedisk; 20304276Staylor 20314276Staylor if (nvlist_lookup_nvlist_array(config, 20324276Staylor ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 20334276Staylor if (nvlist_lookup_uint64(config, 20344276Staylor ZPOOL_CONFIG_WHOLE_DISK, 20354276Staylor &wholedisk) != 0 || !wholedisk) { 20364276Staylor return (MAXOFFSET_T); 20374276Staylor } 20384276Staylor if (nvlist_lookup_string(config, 20394276Staylor ZPOOL_CONFIG_PATH, &path) != 0) { 20404276Staylor return (MAXOFFSET_T); 20414276Staylor } 20424276Staylor 20434276Staylor (void) snprintf(diskname, sizeof (diskname), "%s%s", 20444276Staylor RDISK_ROOT, strrchr(path, '/')); 20454276Staylor if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 20464276Staylor struct dk_gpt *vtoc; 20474276Staylor if (efi_alloc_and_read(fd, &vtoc) >= 0) { 20484276Staylor sb = vtoc->efi_parts[0].p_start; 20494276Staylor efi_free(vtoc); 20504276Staylor } 20514276Staylor (void) close(fd); 20524276Staylor } 20534276Staylor return (sb); 20544276Staylor } 20554276Staylor 20564276Staylor for (c = 0; c < children; c++) { 20574276Staylor sb = find_start_block(child[c]); 20584276Staylor if (sb != MAXOFFSET_T) { 20594276Staylor return (sb); 20604276Staylor } 20614276Staylor } 20624276Staylor return (MAXOFFSET_T); 20634276Staylor } 20644276Staylor 20654276Staylor /* 20664276Staylor * Label an individual disk. The name provided is the short name, 20674276Staylor * stripped of any leading /dev path. 20684276Staylor */ 20694276Staylor int 20704276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name) 20714276Staylor { 20724276Staylor char path[MAXPATHLEN]; 20734276Staylor struct dk_gpt *vtoc; 20744276Staylor int fd; 20754276Staylor size_t resv = EFI_MIN_RESV_SIZE; 20764276Staylor uint64_t slice_size; 20774276Staylor diskaddr_t start_block; 20784276Staylor char errbuf[1024]; 20794276Staylor 20804276Staylor if (zhp) { 20814276Staylor nvlist_t *nvroot; 20824276Staylor 20834276Staylor verify(nvlist_lookup_nvlist(zhp->zpool_config, 20844276Staylor ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 20854276Staylor 20864276Staylor if (zhp->zpool_start_block == 0) 20874276Staylor start_block = find_start_block(nvroot); 20884276Staylor else 20894276Staylor start_block = zhp->zpool_start_block; 20904276Staylor zhp->zpool_start_block = start_block; 20914276Staylor } else { 20924276Staylor /* new pool */ 20934276Staylor start_block = NEW_START_BLOCK; 20944276Staylor } 20954276Staylor 20964276Staylor (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name, 20974276Staylor BACKUP_SLICE); 20984276Staylor 20994276Staylor if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 21004276Staylor /* 21014276Staylor * This shouldn't happen. We've long since verified that this 21024276Staylor * is a valid device. 21034276Staylor */ 21044276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 21054276Staylor "label '%s': unable to open device"), name); 21064276Staylor return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 21074276Staylor } 21084276Staylor 21094276Staylor if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 21104276Staylor /* 21114276Staylor * The only way this can fail is if we run out of memory, or we 21124276Staylor * were unable to read the disk's capacity 21134276Staylor */ 21144276Staylor if (errno == ENOMEM) 21154276Staylor (void) no_memory(hdl); 21164276Staylor 21174276Staylor (void) close(fd); 21184276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 21194276Staylor "label '%s': unable to read disk capacity"), name); 21204276Staylor 21214276Staylor return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 21224276Staylor } 21234276Staylor 21244276Staylor slice_size = vtoc->efi_last_u_lba + 1; 21254276Staylor slice_size -= EFI_MIN_RESV_SIZE; 21264276Staylor if (start_block == MAXOFFSET_T) 21274276Staylor start_block = NEW_START_BLOCK; 21284276Staylor slice_size -= start_block; 21294276Staylor 21304276Staylor vtoc->efi_parts[0].p_start = start_block; 21314276Staylor vtoc->efi_parts[0].p_size = slice_size; 21324276Staylor 21334276Staylor /* 21344276Staylor * Why we use V_USR: V_BACKUP confuses users, and is considered 21354276Staylor * disposable by some EFI utilities (since EFI doesn't have a backup 21364276Staylor * slice). V_UNASSIGNED is supposed to be used only for zero size 21374276Staylor * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 21384276Staylor * etc. were all pretty specific. V_USR is as close to reality as we 21394276Staylor * can get, in the absence of V_OTHER. 21404276Staylor */ 21414276Staylor vtoc->efi_parts[0].p_tag = V_USR; 21424276Staylor (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 21434276Staylor 21444276Staylor vtoc->efi_parts[8].p_start = slice_size + start_block; 21454276Staylor vtoc->efi_parts[8].p_size = resv; 21464276Staylor vtoc->efi_parts[8].p_tag = V_RESERVED; 21474276Staylor 21484276Staylor if (efi_write(fd, vtoc) != 0) { 21494276Staylor /* 21504276Staylor * Some block drivers (like pcata) may not support EFI 21514276Staylor * GPT labels. Print out a helpful error message dir- 21524276Staylor * ecting the user to manually label the disk and give 21534276Staylor * a specific slice. 21544276Staylor */ 21554276Staylor (void) close(fd); 21564276Staylor efi_free(vtoc); 21574276Staylor 21584276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21594276Staylor "cannot label '%s': try using fdisk(1M) and then " 21604276Staylor "provide a specific slice"), name); 21614276Staylor return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 21624276Staylor } 21634276Staylor 21644276Staylor (void) close(fd); 21654276Staylor efi_free(vtoc); 21664276Staylor return (0); 21674276Staylor } 21684276Staylor 21693912Slling int 21703912Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 21713912Slling { 21723912Slling zfs_cmd_t zc = { 0 }; 21733912Slling int ret = -1; 21743912Slling char errbuf[1024]; 21753912Slling nvlist_t *nvl = NULL; 21763912Slling nvlist_t *realprops; 21773912Slling 21783912Slling (void) snprintf(errbuf, sizeof (errbuf), 21793912Slling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 21803912Slling zhp->zpool_name); 21813912Slling 21823912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 21833912Slling zfs_error_aux(zhp->zpool_hdl, 21843912Slling dgettext(TEXT_DOMAIN, "pool must be " 21853912Slling "upgraded to support pool properties")); 21863912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, errbuf)); 21873912Slling } 21883912Slling 21893912Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 21903912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); 21913912Slling 21923912Slling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 21933912Slling nvlist_add_string(nvl, propname, propval) != 0) { 21943912Slling return (no_memory(zhp->zpool_hdl)); 21953912Slling } 21963912Slling 21973912Slling if ((realprops = zfs_validate_properties(zhp->zpool_hdl, ZFS_TYPE_POOL, 21983912Slling zhp->zpool_name, nvl, 0, NULL, errbuf)) == NULL) { 21993912Slling nvlist_free(nvl); 22003912Slling return (-1); 22013912Slling } 22023912Slling 22033912Slling nvlist_free(nvl); 22043912Slling nvl = realprops; 22053912Slling 22063912Slling /* 22073912Slling * Execute the corresponding ioctl() to set this property. 22083912Slling */ 22093912Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 22103912Slling 22113912Slling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl, NULL) != 0) 22123912Slling return (-1); 22133912Slling 22143912Slling ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SET_PROPS, &zc); 22153912Slling zcmd_free_nvlists(&zc); 22163912Slling 22173912Slling if (ret) 22183912Slling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 22193912Slling 22203912Slling return (ret); 22213912Slling } 22223912Slling 2223*4451Seschrock uint64_t 2224*4451Seschrock zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop) 2225*4451Seschrock { 2226*4451Seschrock uint64_t value; 2227*4451Seschrock nvlist_t *nvp; 2228*4451Seschrock 2229*4451Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) 2230*4451Seschrock return (0); 2231*4451Seschrock 2232*4451Seschrock if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 2233*4451Seschrock return (zpool_prop_default_numeric(prop)); 2234*4451Seschrock 2235*4451Seschrock switch (prop) { 2236*4451Seschrock case ZPOOL_PROP_AUTOREPLACE: 2237*4451Seschrock if (nvlist_lookup_nvlist(zhp->zpool_props, 2238*4451Seschrock zpool_prop_to_name(prop), &nvp) != 0) { 2239*4451Seschrock value = zpool_prop_default_numeric(prop); 2240*4451Seschrock } else { 2241*4451Seschrock VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, 2242*4451Seschrock &value) == 0); 2243*4451Seschrock } 2244*4451Seschrock return (value); 2245*4451Seschrock break; 2246*4451Seschrock 2247*4451Seschrock default: 2248*4451Seschrock assert(0); 2249*4451Seschrock } 2250*4451Seschrock 2251*4451Seschrock return (0); 2252*4451Seschrock } 2253*4451Seschrock 22543912Slling int 22553912Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, 22563912Slling size_t proplen, zfs_source_t *srctype) 22573912Slling { 22583912Slling uint64_t value; 22593912Slling char msg[1024], *strvalue; 22603912Slling nvlist_t *nvp; 22613912Slling zfs_source_t src = ZFS_SRC_NONE; 22623912Slling 22633912Slling (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 22643912Slling "cannot get property '%s'"), zpool_prop_to_name(prop)); 22653912Slling 22663912Slling if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { 22673912Slling zfs_error_aux(zhp->zpool_hdl, 22683912Slling dgettext(TEXT_DOMAIN, "pool must be " 22693912Slling "upgraded to support pool properties")); 22703912Slling return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); 22713912Slling } 22723912Slling 2273*4451Seschrock if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 2274*4451Seschrock prop != ZPOOL_PROP_NAME) 22753912Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); 22763912Slling 22773912Slling switch (prop) { 2278*4451Seschrock case ZPOOL_PROP_NAME: 22793912Slling (void) strlcpy(propbuf, zhp->zpool_name, proplen); 22803912Slling break; 22813912Slling 2282*4451Seschrock case ZPOOL_PROP_BOOTFS: 22833912Slling if (nvlist_lookup_nvlist(zhp->zpool_props, 22843912Slling zpool_prop_to_name(prop), &nvp) != 0) { 22853912Slling strvalue = (char *)zfs_prop_default_string(prop); 22863912Slling if (strvalue == NULL) 22873912Slling strvalue = "-"; 22883912Slling src = ZFS_SRC_DEFAULT; 22893912Slling } else { 22903912Slling VERIFY(nvlist_lookup_uint64(nvp, 22913912Slling ZFS_PROP_SOURCE, &value) == 0); 22923912Slling src = value; 22933912Slling VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE, 22943912Slling &strvalue) == 0); 22953912Slling if (strlen(strvalue) >= proplen) 22963912Slling return (-1); 22973912Slling } 2298*4451Seschrock (void) strlcpy(propbuf, strvalue, proplen); 2299*4451Seschrock break; 2300*4451Seschrock 2301*4451Seschrock case ZPOOL_PROP_AUTOREPLACE: 2302*4451Seschrock if (nvlist_lookup_nvlist(zhp->zpool_props, 2303*4451Seschrock zpool_prop_to_name(prop), &nvp) != 0) { 2304*4451Seschrock value = zpool_prop_default_numeric(prop); 2305*4451Seschrock src = ZFS_SRC_DEFAULT; 2306*4451Seschrock } else { 2307*4451Seschrock VERIFY(nvlist_lookup_uint64(nvp, 2308*4451Seschrock ZFS_PROP_SOURCE, &value) == 0); 2309*4451Seschrock src = value; 2310*4451Seschrock VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, 2311*4451Seschrock &value) == 0); 2312*4451Seschrock } 2313*4451Seschrock (void) strlcpy(propbuf, value ? "on" : "off", proplen); 23143912Slling break; 23153912Slling 23163912Slling default: 23173912Slling return (-1); 23183912Slling } 23193912Slling if (srctype) 23203912Slling *srctype = src; 23213912Slling return (0); 23223912Slling } 23233912Slling 23243912Slling int 23253912Slling zpool_get_proplist(libzfs_handle_t *hdl, char *fields, zpool_proplist_t **listp) 23263912Slling { 23273912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_POOL)); 23283912Slling } 23293912Slling 23303912Slling 23313912Slling int 23323912Slling zpool_expand_proplist(zpool_handle_t *zhp, zpool_proplist_t **plp) 23333912Slling { 23343912Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 23353912Slling zpool_proplist_t *entry; 23363912Slling char buf[ZFS_MAXPROPLEN]; 23373912Slling 23383912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_POOL) != 0) 23393912Slling return (-1); 23403912Slling 23413912Slling for (entry = *plp; entry != NULL; entry = entry->pl_next) { 23423912Slling 23433912Slling if (entry->pl_fixed) 23443912Slling continue; 23453912Slling 23463912Slling if (entry->pl_prop != ZFS_PROP_INVAL && 23473912Slling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 23483912Slling NULL) == 0) { 23493912Slling if (strlen(buf) > entry->pl_width) 23503912Slling entry->pl_width = strlen(buf); 23513912Slling } 23523912Slling } 23533912Slling 23543912Slling return (0); 23553912Slling } 2356