1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 212082Seschrock 22789Sahrens /* 231354Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens #include <assert.h> 30789Sahrens #include <ctype.h> 31789Sahrens #include <errno.h> 32789Sahrens #include <devid.h> 33789Sahrens #include <fcntl.h> 34789Sahrens #include <libintl.h> 35789Sahrens #include <stdio.h> 36789Sahrens #include <stdlib.h> 37789Sahrens #include <string.h> 38789Sahrens #include <unistd.h> 39789Sahrens #include <sys/zfs_ioctl.h> 401544Seschrock #include <sys/zio.h> 41789Sahrens 42789Sahrens #include "zfs_namecheck.h" 43789Sahrens #include "libzfs_impl.h" 44789Sahrens 45789Sahrens /* 46789Sahrens * Validate the given pool name, optionally putting an extended error message in 47789Sahrens * 'buf'. 48789Sahrens */ 492082Seschrock static boolean_t 502082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 51789Sahrens { 52789Sahrens namecheck_err_t why; 53789Sahrens char what; 541773Seschrock int ret; 55789Sahrens 561773Seschrock ret = pool_namecheck(pool, &why, &what); 571773Seschrock 581773Seschrock /* 591773Seschrock * The rules for reserved pool names were extended at a later point. 601773Seschrock * But we need to support users with existing pools that may now be 611773Seschrock * invalid. So we only check for this expanded set of names during a 621773Seschrock * create (or import), and only in userland. 631773Seschrock */ 641773Seschrock if (ret == 0 && !isopen && 651773Seschrock (strncmp(pool, "mirror", 6) == 0 || 661773Seschrock strncmp(pool, "raidz", 5) == 0 || 671773Seschrock strncmp(pool, "spare", 5) == 0)) { 682082Seschrock zfs_error_aux(hdl, 692082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 702082Seschrock return (B_FALSE); 711773Seschrock } 721773Seschrock 731773Seschrock 741773Seschrock if (ret != 0) { 752082Seschrock if (hdl != NULL) { 76789Sahrens switch (why) { 771003Slling case NAME_ERR_TOOLONG: 782082Seschrock zfs_error_aux(hdl, 791003Slling dgettext(TEXT_DOMAIN, "name is too long")); 801003Slling break; 811003Slling 82789Sahrens case NAME_ERR_INVALCHAR: 832082Seschrock zfs_error_aux(hdl, 84789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 85789Sahrens "'%c' in pool name"), what); 86789Sahrens break; 87789Sahrens 88789Sahrens case NAME_ERR_NOLETTER: 892082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 902082Seschrock "name must begin with a letter")); 91789Sahrens break; 92789Sahrens 93789Sahrens case NAME_ERR_RESERVED: 942082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 952082Seschrock "name is reserved")); 96789Sahrens break; 97789Sahrens 98789Sahrens case NAME_ERR_DISKLIKE: 992082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1002082Seschrock "pool name is reserved")); 101789Sahrens break; 102*2856Snd150628 103*2856Snd150628 case NAME_ERR_LEADING_SLASH: 104*2856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 105*2856Snd150628 "leading slash in name")); 106*2856Snd150628 break; 107*2856Snd150628 108*2856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 109*2856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 110*2856Snd150628 "empty component in name")); 111*2856Snd150628 break; 112*2856Snd150628 113*2856Snd150628 case NAME_ERR_TRAILING_SLASH: 114*2856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 115*2856Snd150628 "trailing slash in name")); 116*2856Snd150628 break; 117*2856Snd150628 118*2856Snd150628 case NAME_ERR_MULTIPLE_AT: 119*2856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 120*2856Snd150628 "multiple '@' delimiters in name")); 121*2856Snd150628 break; 122*2856Snd150628 123789Sahrens } 124789Sahrens } 1252082Seschrock return (B_FALSE); 126789Sahrens } 127789Sahrens 1282082Seschrock return (B_TRUE); 129789Sahrens } 130789Sahrens 131789Sahrens /* 132789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 133789Sahrens */ 1342082Seschrock int 135789Sahrens set_pool_health(nvlist_t *config) 136789Sahrens { 137789Sahrens nvlist_t *nvroot; 138789Sahrens vdev_stat_t *vs; 139789Sahrens uint_t vsc; 140789Sahrens char *health; 141789Sahrens 142789Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 143789Sahrens &nvroot) == 0); 144789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 145789Sahrens (uint64_t **)&vs, &vsc) == 0); 146789Sahrens 147789Sahrens switch (vs->vs_state) { 148789Sahrens 149789Sahrens case VDEV_STATE_CLOSED: 150789Sahrens case VDEV_STATE_CANT_OPEN: 151789Sahrens case VDEV_STATE_OFFLINE: 152789Sahrens health = dgettext(TEXT_DOMAIN, "FAULTED"); 153789Sahrens break; 154789Sahrens 155789Sahrens case VDEV_STATE_DEGRADED: 156789Sahrens health = dgettext(TEXT_DOMAIN, "DEGRADED"); 157789Sahrens break; 158789Sahrens 159789Sahrens case VDEV_STATE_HEALTHY: 160789Sahrens health = dgettext(TEXT_DOMAIN, "ONLINE"); 161789Sahrens break; 162789Sahrens 163789Sahrens default: 1642082Seschrock abort(); 165789Sahrens } 166789Sahrens 1672082Seschrock return (nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, health)); 168789Sahrens } 169789Sahrens 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)) { 1842082Seschrock (void) zfs_error(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")); 2042142Seschrock (void) zfs_error(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) { 2582082Seschrock (void) zfs_error(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); 2771544Seschrock if (zhp->zpool_error_log) { 2781544Seschrock int i; 2791544Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 2802082Seschrock nvlist_free(zhp->zpool_error_log[i]); 2811544Seschrock free(zhp->zpool_error_log); 2821544Seschrock } 283789Sahrens free(zhp); 284789Sahrens } 285789Sahrens 286789Sahrens /* 287789Sahrens * Return the name of the pool. 288789Sahrens */ 289789Sahrens const char * 290789Sahrens zpool_get_name(zpool_handle_t *zhp) 291789Sahrens { 292789Sahrens return (zhp->zpool_name); 293789Sahrens } 294789Sahrens 295789Sahrens /* 296789Sahrens * Return the GUID of the pool. 297789Sahrens */ 298789Sahrens uint64_t 299789Sahrens zpool_get_guid(zpool_handle_t *zhp) 300789Sahrens { 301789Sahrens uint64_t guid; 302789Sahrens 303789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 304789Sahrens &guid) == 0); 305789Sahrens return (guid); 306789Sahrens } 307789Sahrens 308789Sahrens /* 3092082Seschrock * Return the version of the pool. 3102082Seschrock */ 3112082Seschrock uint64_t 3122082Seschrock zpool_get_version(zpool_handle_t *zhp) 3132082Seschrock { 3142082Seschrock uint64_t version; 3152082Seschrock 3162082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3172082Seschrock &version) == 0); 3182082Seschrock 3192082Seschrock return (version); 3202082Seschrock } 3212082Seschrock 3222082Seschrock /* 323789Sahrens * Return the amount of space currently consumed by the pool. 324789Sahrens */ 325789Sahrens uint64_t 326789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 327789Sahrens { 328789Sahrens nvlist_t *nvroot; 329789Sahrens vdev_stat_t *vs; 330789Sahrens uint_t vsc; 331789Sahrens 332789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 333789Sahrens &nvroot) == 0); 334789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 335789Sahrens (uint64_t **)&vs, &vsc) == 0); 336789Sahrens 337789Sahrens return (vs->vs_alloc); 338789Sahrens } 339789Sahrens 340789Sahrens /* 341789Sahrens * Return the total space in the pool. 342789Sahrens */ 343789Sahrens uint64_t 344789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 345789Sahrens { 346789Sahrens nvlist_t *nvroot; 347789Sahrens vdev_stat_t *vs; 348789Sahrens uint_t vsc; 349789Sahrens 350789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 351789Sahrens &nvroot) == 0); 352789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 353789Sahrens (uint64_t **)&vs, &vsc) == 0); 354789Sahrens 355789Sahrens return (vs->vs_space); 356789Sahrens } 357789Sahrens 358789Sahrens /* 359789Sahrens * Return the alternate root for this pool, if any. 360789Sahrens */ 361789Sahrens int 362789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 363789Sahrens { 364789Sahrens zfs_cmd_t zc = { 0 }; 365789Sahrens 366789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3672082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3682676Seschrock zc.zc_value[0] == '\0') 369789Sahrens return (-1); 370789Sahrens 3712676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 372789Sahrens 373789Sahrens return (0); 374789Sahrens } 375789Sahrens 376789Sahrens /* 377789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 378789Sahrens */ 379789Sahrens int 380789Sahrens zpool_get_state(zpool_handle_t *zhp) 381789Sahrens { 382789Sahrens return (zhp->zpool_state); 383789Sahrens } 384789Sahrens 385789Sahrens /* 386789Sahrens * Create the named pool, using the provided vdev list. It is assumed 387789Sahrens * that the consumer has already validated the contents of the nvlist, so we 388789Sahrens * don't have to worry about error semantics. 389789Sahrens */ 390789Sahrens int 3912082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3922082Seschrock const char *altroot) 393789Sahrens { 394789Sahrens zfs_cmd_t zc = { 0 }; 3952082Seschrock char msg[1024]; 3962082Seschrock 3972082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3982082Seschrock "cannot create '%s'"), pool); 399789Sahrens 4002082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 4012082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 4022082Seschrock 4032082Seschrock if (altroot != NULL && altroot[0] != '/') 4042082Seschrock return (zfs_error(hdl, EZFS_BADPATH, 4052082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 406789Sahrens 4072676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 408789Sahrens return (-1); 409789Sahrens 410789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 411789Sahrens 412789Sahrens if (altroot != NULL) 4132676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 414789Sahrens 4152082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4162676Seschrock zcmd_free_nvlists(&zc); 4172082Seschrock 418789Sahrens switch (errno) { 419789Sahrens case EBUSY: 420789Sahrens /* 421789Sahrens * This can happen if the user has specified the same 422789Sahrens * device multiple times. We can't reliably detect this 423789Sahrens * until we try to add it and see we already have a 424789Sahrens * label. 425789Sahrens */ 4262082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4272082Seschrock "one or more vdevs refer to the same device")); 4282082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 429789Sahrens 430789Sahrens case EOVERFLOW: 431789Sahrens /* 4322082Seschrock * This occurs when one of the devices is below 433789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 434789Sahrens * device was the problem device since there's no 435789Sahrens * reliable way to determine device size from userland. 436789Sahrens */ 437789Sahrens { 438789Sahrens char buf[64]; 439789Sahrens 440789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 441789Sahrens 4422082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4432082Seschrock "one or more devices is less than the " 4442082Seschrock "minimum size (%s)"), buf); 445789Sahrens } 4462082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 447789Sahrens 448789Sahrens case ENOSPC: 4492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4502082Seschrock "one or more devices is out of space")); 4512082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 452789Sahrens 453789Sahrens default: 4542082Seschrock return (zpool_standard_error(hdl, errno, msg)); 455789Sahrens } 456789Sahrens } 457789Sahrens 4582676Seschrock zcmd_free_nvlists(&zc); 459789Sahrens 460789Sahrens /* 461789Sahrens * If this is an alternate root pool, then we automatically set the 4622676Seschrock * mountpoint of the root dataset to be '/'. 463789Sahrens */ 464789Sahrens if (altroot != NULL) { 465789Sahrens zfs_handle_t *zhp; 466789Sahrens 4672082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4682676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4692676Seschrock "/") == 0); 470789Sahrens 471789Sahrens zfs_close(zhp); 472789Sahrens } 473789Sahrens 474789Sahrens return (0); 475789Sahrens } 476789Sahrens 477789Sahrens /* 478789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 479789Sahrens * datasets left in the pool. 480789Sahrens */ 481789Sahrens int 482789Sahrens zpool_destroy(zpool_handle_t *zhp) 483789Sahrens { 484789Sahrens zfs_cmd_t zc = { 0 }; 485789Sahrens zfs_handle_t *zfp = NULL; 4862082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4872082Seschrock char msg[1024]; 488789Sahrens 489789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4902082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4912082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 492789Sahrens return (-1); 493789Sahrens 494*2856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 495789Sahrens return (-1); 496789Sahrens 497789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 498789Sahrens 4992082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 5002082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5012082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 502789Sahrens 5032082Seschrock if (errno == EROFS) { 5042082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5052082Seschrock "one or more devices is read only")); 5062082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5072082Seschrock } else { 5082082Seschrock (void) zpool_standard_error(hdl, errno, msg); 509789Sahrens } 510789Sahrens 511789Sahrens if (zfp) 512789Sahrens zfs_close(zfp); 513789Sahrens return (-1); 514789Sahrens } 515789Sahrens 516789Sahrens if (zfp) { 517789Sahrens remove_mountpoint(zfp); 518789Sahrens zfs_close(zfp); 519789Sahrens } 520789Sahrens 521789Sahrens return (0); 522789Sahrens } 523789Sahrens 524789Sahrens /* 525789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 526789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 527789Sahrens */ 528789Sahrens int 529789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 530789Sahrens { 5312676Seschrock zfs_cmd_t zc = { 0 }; 5322082Seschrock int ret; 5332082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5342082Seschrock char msg[1024]; 5352082Seschrock nvlist_t **spares; 5362082Seschrock uint_t nspares; 5372082Seschrock 5382082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5392082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5402082Seschrock 5412082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5422082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5432082Seschrock &spares, &nspares) == 0) { 5442082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5452082Seschrock "upgraded to add hot spares")); 5462082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5472082Seschrock } 548789Sahrens 5492676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5502082Seschrock return (-1); 551789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 552789Sahrens 5532082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 554789Sahrens switch (errno) { 555789Sahrens case EBUSY: 556789Sahrens /* 557789Sahrens * This can happen if the user has specified the same 558789Sahrens * device multiple times. We can't reliably detect this 559789Sahrens * until we try to add it and see we already have a 560789Sahrens * label. 561789Sahrens */ 5622082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5632082Seschrock "one or more vdevs refer to the same device")); 5642082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 565789Sahrens break; 566789Sahrens 567789Sahrens case EOVERFLOW: 568789Sahrens /* 569789Sahrens * This occurrs when one of the devices is below 570789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 571789Sahrens * device was the problem device since there's no 572789Sahrens * reliable way to determine device size from userland. 573789Sahrens */ 574789Sahrens { 575789Sahrens char buf[64]; 576789Sahrens 577789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 578789Sahrens 5792082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5802082Seschrock "device is less than the minimum " 5812082Seschrock "size (%s)"), buf); 582789Sahrens } 5832082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5842082Seschrock break; 5852082Seschrock 5862082Seschrock case ENOTSUP: 5872082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5882082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5892082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 590789Sahrens break; 591789Sahrens 592789Sahrens default: 5932082Seschrock (void) zpool_standard_error(hdl, errno, msg); 594789Sahrens } 595789Sahrens 5962082Seschrock ret = -1; 5972082Seschrock } else { 5982082Seschrock ret = 0; 599789Sahrens } 600789Sahrens 6012676Seschrock zcmd_free_nvlists(&zc); 602789Sahrens 6032082Seschrock return (ret); 604789Sahrens } 605789Sahrens 606789Sahrens /* 607789Sahrens * Exports the pool from the system. The caller must ensure that there are no 608789Sahrens * mounted datasets in the pool. 609789Sahrens */ 610789Sahrens int 611789Sahrens zpool_export(zpool_handle_t *zhp) 612789Sahrens { 613789Sahrens zfs_cmd_t zc = { 0 }; 614789Sahrens 615789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 616789Sahrens return (-1); 617789Sahrens 618789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 619789Sahrens 6202082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6212082Seschrock return (zpool_standard_error(zhp->zpool_hdl, errno, 6222082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6232082Seschrock zhp->zpool_name)); 624789Sahrens 625789Sahrens return (0); 626789Sahrens } 627789Sahrens 628789Sahrens /* 629789Sahrens * Import the given pool using the known configuration. The configuration 630789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 631789Sahrens * parameters control whether the pool is imported with a different name or with 632789Sahrens * an alternate root, respectively. 633789Sahrens */ 634789Sahrens int 6352082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 6362082Seschrock const char *altroot) 637789Sahrens { 6382676Seschrock zfs_cmd_t zc = { 0 }; 639789Sahrens char *thename; 640789Sahrens char *origname; 641789Sahrens int ret; 642789Sahrens 643789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 644789Sahrens &origname) == 0); 645789Sahrens 646789Sahrens if (newname != NULL) { 6472082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 6482082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, 6492082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 6502082Seschrock newname)); 651789Sahrens thename = (char *)newname; 652789Sahrens } else { 653789Sahrens thename = origname; 654789Sahrens } 655789Sahrens 6562082Seschrock if (altroot != NULL && altroot[0] != '/') 6572082Seschrock return (zfs_error(hdl, EZFS_BADPATH, 6582082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 6592082Seschrock altroot)); 660789Sahrens 661789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 662789Sahrens 663789Sahrens if (altroot != NULL) 6642676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 665789Sahrens else 6662676Seschrock zc.zc_value[0] = '\0'; 667789Sahrens 668789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6691544Seschrock &zc.zc_guid) == 0); 670789Sahrens 6712676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) 6722082Seschrock return (-1); 673789Sahrens 674789Sahrens ret = 0; 6752082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 676789Sahrens char desc[1024]; 677789Sahrens if (newname == NULL) 678789Sahrens (void) snprintf(desc, sizeof (desc), 679789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 680789Sahrens thename); 681789Sahrens else 682789Sahrens (void) snprintf(desc, sizeof (desc), 683789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 684789Sahrens origname, thename); 685789Sahrens 686789Sahrens switch (errno) { 6871544Seschrock case ENOTSUP: 6881544Seschrock /* 6891544Seschrock * Unsupported version. 6901544Seschrock */ 6912082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6921544Seschrock break; 6931544Seschrock 6942174Seschrock case EINVAL: 6952174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 6962174Seschrock break; 6972174Seschrock 698789Sahrens default: 6992082Seschrock (void) zpool_standard_error(hdl, errno, desc); 700789Sahrens } 701789Sahrens 702789Sahrens ret = -1; 703789Sahrens } else { 704789Sahrens zpool_handle_t *zhp; 705789Sahrens /* 706789Sahrens * This should never fail, but play it safe anyway. 707789Sahrens */ 7082142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 7092142Seschrock ret = -1; 7102142Seschrock } else if (zhp != NULL) { 711789Sahrens ret = zpool_create_zvol_links(zhp); 712789Sahrens zpool_close(zhp); 713789Sahrens } 714789Sahrens } 715789Sahrens 7162676Seschrock zcmd_free_nvlists(&zc); 717789Sahrens return (ret); 718789Sahrens } 719789Sahrens 720789Sahrens /* 721789Sahrens * Scrub the pool. 722789Sahrens */ 723789Sahrens int 724789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 725789Sahrens { 726789Sahrens zfs_cmd_t zc = { 0 }; 727789Sahrens char msg[1024]; 7282082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 729789Sahrens 730789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 731789Sahrens zc.zc_cookie = type; 732789Sahrens 7332082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 734789Sahrens return (0); 735789Sahrens 736789Sahrens (void) snprintf(msg, sizeof (msg), 737789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 738789Sahrens 7392082Seschrock if (errno == EBUSY) 7402082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 7412082Seschrock else 7422082Seschrock return (zpool_standard_error(hdl, errno, msg)); 743789Sahrens } 744789Sahrens 7452468Sek110237 /* 7462468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 7472468Sek110237 * spare; but FALSE if its an INUSE spare. 7482468Sek110237 */ 7492082Seschrock static nvlist_t * 7502082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 7512468Sek110237 boolean_t *avail_spare) 7521544Seschrock { 7531544Seschrock uint_t c, children; 7541544Seschrock nvlist_t **child; 7552082Seschrock uint64_t theguid, present; 7561544Seschrock char *path; 7571544Seschrock uint64_t wholedisk = 0; 7582082Seschrock nvlist_t *ret; 7591544Seschrock 7602082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7611544Seschrock 7621544Seschrock if (search == NULL && 7631544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7641544Seschrock /* 7651544Seschrock * If the device has never been present since import, the only 7661544Seschrock * reliable way to match the vdev is by GUID. 7671544Seschrock */ 7682082Seschrock if (theguid == guid) 7692082Seschrock return (nv); 7701544Seschrock } else if (search != NULL && 7711544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7721544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7731544Seschrock &wholedisk); 7741544Seschrock if (wholedisk) { 7751544Seschrock /* 7761544Seschrock * For whole disks, the internal path has 's0', but the 7771544Seschrock * path passed in by the user doesn't. 7781544Seschrock */ 7791544Seschrock if (strlen(search) == strlen(path) - 2 && 7801544Seschrock strncmp(search, path, strlen(search)) == 0) 7812082Seschrock return (nv); 7821544Seschrock } else if (strcmp(search, path) == 0) { 7832082Seschrock return (nv); 7841544Seschrock } 7851544Seschrock } 7861544Seschrock 7871544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7881544Seschrock &child, &children) != 0) 7892082Seschrock return (NULL); 7901544Seschrock 7911544Seschrock for (c = 0; c < children; c++) 7922082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 7932468Sek110237 avail_spare)) != NULL) 7941544Seschrock return (ret); 7951544Seschrock 7962082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 7972082Seschrock &child, &children) == 0) { 7982082Seschrock for (c = 0; c < children; c++) { 7992082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 8002468Sek110237 avail_spare)) != NULL) { 8012468Sek110237 *avail_spare = B_TRUE; 8022082Seschrock return (ret); 8032082Seschrock } 8042082Seschrock } 8052082Seschrock } 8062082Seschrock 8072082Seschrock return (NULL); 8081544Seschrock } 8091544Seschrock 8102082Seschrock nvlist_t * 8112468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 8121544Seschrock { 8131544Seschrock char buf[MAXPATHLEN]; 8141544Seschrock const char *search; 8151544Seschrock char *end; 8161544Seschrock nvlist_t *nvroot; 8171544Seschrock uint64_t guid; 8181544Seschrock 8191613Seschrock guid = strtoull(path, &end, 10); 8201544Seschrock if (guid != 0 && *end == '\0') { 8211544Seschrock search = NULL; 8221544Seschrock } else if (path[0] != '/') { 8231544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8241544Seschrock search = buf; 8251544Seschrock } else { 8261544Seschrock search = path; 8271544Seschrock } 8281544Seschrock 8291544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8301544Seschrock &nvroot) == 0); 8311544Seschrock 8322468Sek110237 *avail_spare = B_FALSE; 8332468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 8342468Sek110237 } 8352468Sek110237 8362468Sek110237 /* 8372468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 8382468Sek110237 */ 8392468Sek110237 static boolean_t 8402468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 8412468Sek110237 { 8422468Sek110237 uint64_t spare_guid; 8432468Sek110237 nvlist_t *nvroot; 8442468Sek110237 nvlist_t **spares; 8452468Sek110237 uint_t nspares; 8462468Sek110237 int i; 8472468Sek110237 8482468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8492468Sek110237 &nvroot) == 0); 8502468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8512468Sek110237 &spares, &nspares) == 0) { 8522468Sek110237 for (i = 0; i < nspares; i++) { 8532468Sek110237 verify(nvlist_lookup_uint64(spares[i], 8542468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 8552468Sek110237 if (guid == spare_guid) 8562468Sek110237 return (B_TRUE); 8572468Sek110237 } 8582468Sek110237 } 8592468Sek110237 8602468Sek110237 return (B_FALSE); 8611544Seschrock } 8621544Seschrock 863789Sahrens /* 864789Sahrens * Bring the specified vdev online 865789Sahrens */ 866789Sahrens int 867789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 868789Sahrens { 869789Sahrens zfs_cmd_t zc = { 0 }; 870789Sahrens char msg[1024]; 8712082Seschrock nvlist_t *tgt; 8722468Sek110237 boolean_t avail_spare; 8732082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 874789Sahrens 8751544Seschrock (void) snprintf(msg, sizeof (msg), 8761544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 877789Sahrens 8781544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8792468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8802082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 881789Sahrens 8822468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8832468Sek110237 8842468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8852082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8862082Seschrock 8872082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8881544Seschrock return (0); 889789Sahrens 8902082Seschrock return (zpool_standard_error(hdl, errno, msg)); 891789Sahrens } 892789Sahrens 893789Sahrens /* 894789Sahrens * Take the specified vdev offline 895789Sahrens */ 896789Sahrens int 8971485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 898789Sahrens { 899789Sahrens zfs_cmd_t zc = { 0 }; 900789Sahrens char msg[1024]; 9012082Seschrock nvlist_t *tgt; 9022468Sek110237 boolean_t avail_spare; 9032082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 904789Sahrens 9051544Seschrock (void) snprintf(msg, sizeof (msg), 9061544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9071544Seschrock 908789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9092468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9102082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9112082Seschrock 9122468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9132468Sek110237 9142468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9152082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9162082Seschrock 9171485Slling zc.zc_cookie = istmp; 9181485Slling 9192082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 920789Sahrens return (0); 921789Sahrens 922789Sahrens switch (errno) { 9232082Seschrock case EBUSY: 924789Sahrens 925789Sahrens /* 926789Sahrens * There are no other replicas of this device. 927789Sahrens */ 9282082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9292082Seschrock 9302082Seschrock default: 9312082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9322082Seschrock } 9332082Seschrock } 934789Sahrens 9352082Seschrock /* 9362082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 9372082Seschrock * a hot spare. 9382082Seschrock */ 9392082Seschrock static boolean_t 9402082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 9412082Seschrock { 9422082Seschrock nvlist_t **child; 9432082Seschrock uint_t c, children; 9442082Seschrock char *type; 9452082Seschrock 9462082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9472082Seschrock &children) == 0) { 9482082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9492082Seschrock &type) == 0); 9502082Seschrock 9512082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9522082Seschrock children == 2 && child[which] == tgt) 9532082Seschrock return (B_TRUE); 9542082Seschrock 9552082Seschrock for (c = 0; c < children; c++) 9562082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9572082Seschrock return (B_TRUE); 958789Sahrens } 9592082Seschrock 9602082Seschrock return (B_FALSE); 961789Sahrens } 962789Sahrens 963789Sahrens /* 964789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 965789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 966789Sahrens */ 967789Sahrens int 968789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 969789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 970789Sahrens { 971789Sahrens zfs_cmd_t zc = { 0 }; 972789Sahrens char msg[1024]; 973789Sahrens int ret; 9742082Seschrock nvlist_t *tgt; 9752468Sek110237 boolean_t avail_spare; 9762082Seschrock uint64_t val; 9772082Seschrock char *path; 9782082Seschrock nvlist_t **child; 9792082Seschrock uint_t children; 9802082Seschrock nvlist_t *config_root; 9812082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 982789Sahrens 9831544Seschrock if (replacing) 9841544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9851544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9861544Seschrock else 9871544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9881544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9891544Seschrock 990789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9912468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9922082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9932082Seschrock 9942468Sek110237 if (avail_spare) 9952082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9962082Seschrock 9972082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9982082Seschrock zc.zc_cookie = replacing; 9992082Seschrock 10002082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10012082Seschrock &child, &children) != 0 || children != 1) { 10022082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10032082Seschrock "new device must be a single disk")); 10042082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10051544Seschrock } 10062082Seschrock 10072082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10082082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10092082Seschrock 10102082Seschrock /* 10112082Seschrock * If the target is a hot spare that has been swapped in, we can only 10122082Seschrock * replace it with another hot spare. 10132082Seschrock */ 10142082Seschrock if (replacing && 10152082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10162082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10172468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10182468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10192082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10202082Seschrock "can only be replaced by another hot spare")); 10212082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10222082Seschrock } 10232082Seschrock 10242082Seschrock /* 10252082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10262082Seschrock * already spared device. 10272082Seschrock */ 10282082Seschrock if (replacing && 10292082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10302468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10312082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10322082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10332082Seschrock "device has already been replaced with a spare")); 10342082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10352082Seschrock } 1036789Sahrens 10372676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 10382082Seschrock return (-1); 1039789Sahrens 10402082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1041789Sahrens 10422676Seschrock zcmd_free_nvlists(&zc); 1043789Sahrens 1044789Sahrens if (ret == 0) 1045789Sahrens return (0); 1046789Sahrens 1047789Sahrens switch (errno) { 10481544Seschrock case ENOTSUP: 1049789Sahrens /* 1050789Sahrens * Can't attach to or replace this type of vdev. 1051789Sahrens */ 1052789Sahrens if (replacing) 10532082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10542082Seschrock "cannot replace a replacing device")); 1055789Sahrens else 10562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10572082Seschrock "can only attach to mirrors and top-level " 10582082Seschrock "disks")); 10592082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1060789Sahrens break; 1061789Sahrens 10621544Seschrock case EINVAL: 1063789Sahrens /* 1064789Sahrens * The new device must be a single disk. 1065789Sahrens */ 10662082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10672082Seschrock "new device must be a single disk")); 10682082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1069789Sahrens break; 1070789Sahrens 10711544Seschrock case EBUSY: 10722082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10732082Seschrock new_disk); 10742082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1075789Sahrens break; 1076789Sahrens 10771544Seschrock case EOVERFLOW: 1078789Sahrens /* 1079789Sahrens * The new device is too small. 1080789Sahrens */ 10812082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10822082Seschrock "device is too small")); 10832082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1084789Sahrens break; 1085789Sahrens 10861544Seschrock case EDOM: 1087789Sahrens /* 1088789Sahrens * The new device has a different alignment requirement. 1089789Sahrens */ 10902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10912082Seschrock "devices have different sector alignment")); 10922082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1093789Sahrens break; 1094789Sahrens 10951544Seschrock case ENAMETOOLONG: 1096789Sahrens /* 1097789Sahrens * The resulting top-level vdev spec won't fit in the label. 1098789Sahrens */ 10992082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1100789Sahrens break; 1101789Sahrens 11021544Seschrock default: 11032082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1104789Sahrens } 1105789Sahrens 11062082Seschrock return (-1); 1107789Sahrens } 1108789Sahrens 1109789Sahrens /* 1110789Sahrens * Detach the specified device. 1111789Sahrens */ 1112789Sahrens int 1113789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1114789Sahrens { 1115789Sahrens zfs_cmd_t zc = { 0 }; 1116789Sahrens char msg[1024]; 11172082Seschrock nvlist_t *tgt; 11182468Sek110237 boolean_t avail_spare; 11192082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1120789Sahrens 11211544Seschrock (void) snprintf(msg, sizeof (msg), 11221544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11231544Seschrock 1124789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11252468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11262082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1127789Sahrens 11282468Sek110237 if (avail_spare) 11292082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11302082Seschrock 11312082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11322082Seschrock 11332082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1134789Sahrens return (0); 1135789Sahrens 1136789Sahrens switch (errno) { 1137789Sahrens 11381544Seschrock case ENOTSUP: 1139789Sahrens /* 1140789Sahrens * Can't detach from this type of vdev. 1141789Sahrens */ 11422082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11432082Seschrock "applicable to mirror and replacing vdevs")); 11442082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1145789Sahrens break; 1146789Sahrens 11471544Seschrock case EBUSY: 1148789Sahrens /* 1149789Sahrens * There are no other replicas of this device. 1150789Sahrens */ 11512082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1152789Sahrens break; 1153789Sahrens 11541544Seschrock default: 11552082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11561544Seschrock } 11571544Seschrock 11582082Seschrock return (-1); 11592082Seschrock } 11602082Seschrock 11612082Seschrock /* 11622082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11632082Seschrock */ 11642082Seschrock int 11652082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11662082Seschrock { 11672082Seschrock zfs_cmd_t zc = { 0 }; 11682082Seschrock char msg[1024]; 11692082Seschrock nvlist_t *tgt; 11702468Sek110237 boolean_t avail_spare; 11712082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11722082Seschrock 11732082Seschrock (void) snprintf(msg, sizeof (msg), 11742082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11752082Seschrock 11762082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11772468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11782082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11792082Seschrock 11802468Sek110237 if (!avail_spare) { 11812082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11822082Seschrock "only hot spares can be removed")); 11832082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11842082Seschrock } 11852082Seschrock 11862082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11872082Seschrock 11882082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11892082Seschrock return (0); 11902082Seschrock 11912082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11921544Seschrock } 11931544Seschrock 11941544Seschrock /* 11951544Seschrock * Clear the errors for the pool, or the particular device if specified. 11961544Seschrock */ 11971544Seschrock int 11981544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 11991544Seschrock { 12001544Seschrock zfs_cmd_t zc = { 0 }; 12011544Seschrock char msg[1024]; 12022082Seschrock nvlist_t *tgt; 12032468Sek110237 boolean_t avail_spare; 12042082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12051544Seschrock 12061544Seschrock if (path) 12071544Seschrock (void) snprintf(msg, sizeof (msg), 12081544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12092676Seschrock path); 12101544Seschrock else 12111544Seschrock (void) snprintf(msg, sizeof (msg), 12121544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12131544Seschrock zhp->zpool_name); 12141544Seschrock 12151544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12162082Seschrock if (path) { 12172468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12182082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12192082Seschrock 12202468Sek110237 if (avail_spare) 12212082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12222082Seschrock 12232082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12242082Seschrock &zc.zc_guid) == 0); 12251544Seschrock } 12261544Seschrock 12272082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12281544Seschrock return (0); 12291544Seschrock 12302082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1231789Sahrens } 1232789Sahrens 1233789Sahrens static int 1234789Sahrens do_zvol(zfs_handle_t *zhp, void *data) 1235789Sahrens { 1236789Sahrens int linktype = (int)(uintptr_t)data; 1237789Sahrens int ret; 1238789Sahrens 1239789Sahrens /* 1240789Sahrens * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we 1241789Sahrens * correctly handle snapshots of volumes. 1242789Sahrens */ 12432676Seschrock if (ZFS_IS_VOLUME(zhp)) { 1244789Sahrens if (linktype) 12452082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 1246789Sahrens else 12472082Seschrock ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 1248789Sahrens } 1249789Sahrens 1250789Sahrens ret = zfs_iter_children(zhp, do_zvol, data); 1251789Sahrens 1252789Sahrens zfs_close(zhp); 1253789Sahrens return (ret); 1254789Sahrens } 1255789Sahrens 1256789Sahrens /* 1257789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1258789Sahrens */ 1259789Sahrens int 1260789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1261789Sahrens { 1262789Sahrens zfs_handle_t *zfp; 1263789Sahrens int ret; 1264789Sahrens 1265789Sahrens /* 1266789Sahrens * If the pool is unavailable, just return success. 1267789Sahrens */ 12682082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 12692082Seschrock zhp->zpool_name)) == NULL) 1270789Sahrens return (0); 1271789Sahrens 12722082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE); 1273789Sahrens 1274789Sahrens zfs_close(zfp); 1275789Sahrens return (ret); 1276789Sahrens } 1277789Sahrens 1278789Sahrens /* 1279789Sahrens * Iterate over all zvols in the poool and remove any minor nodes. 1280789Sahrens */ 1281789Sahrens int 1282789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1283789Sahrens { 1284789Sahrens zfs_handle_t *zfp; 1285789Sahrens int ret; 1286789Sahrens 1287789Sahrens /* 1288789Sahrens * If the pool is unavailable, just return success. 1289789Sahrens */ 12902082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 12912082Seschrock zhp->zpool_name)) == NULL) 1292789Sahrens return (0); 1293789Sahrens 12942082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE); 1295789Sahrens 1296789Sahrens zfs_close(zfp); 1297789Sahrens return (ret); 1298789Sahrens } 12991354Seschrock 13001354Seschrock /* 13011354Seschrock * Convert from a devid string to a path. 13021354Seschrock */ 13031354Seschrock static char * 13041354Seschrock devid_to_path(char *devid_str) 13051354Seschrock { 13061354Seschrock ddi_devid_t devid; 13071354Seschrock char *minor; 13081354Seschrock char *path; 13091354Seschrock devid_nmlist_t *list = NULL; 13101354Seschrock int ret; 13111354Seschrock 13121354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 13131354Seschrock return (NULL); 13141354Seschrock 13151354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 13161354Seschrock 13171354Seschrock devid_str_free(minor); 13181354Seschrock devid_free(devid); 13191354Seschrock 13201354Seschrock if (ret != 0) 13211354Seschrock return (NULL); 13221354Seschrock 13232082Seschrock if ((path = strdup(list[0].devname)) == NULL) 13242082Seschrock return (NULL); 13252082Seschrock 13261354Seschrock devid_free_nmlist(list); 13271354Seschrock 13281354Seschrock return (path); 13291354Seschrock } 13301354Seschrock 13311354Seschrock /* 13321354Seschrock * Convert from a path to a devid string. 13331354Seschrock */ 13341354Seschrock static char * 13351354Seschrock path_to_devid(const char *path) 13361354Seschrock { 13371354Seschrock int fd; 13381354Seschrock ddi_devid_t devid; 13391354Seschrock char *minor, *ret; 13401354Seschrock 13411354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 13421354Seschrock return (NULL); 13431354Seschrock 13441354Seschrock minor = NULL; 13451354Seschrock ret = NULL; 13461354Seschrock if (devid_get(fd, &devid) == 0) { 13471354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 13481354Seschrock ret = devid_str_encode(devid, minor); 13491354Seschrock if (minor != NULL) 13501354Seschrock devid_str_free(minor); 13511354Seschrock devid_free(devid); 13521354Seschrock } 13531354Seschrock (void) close(fd); 13541354Seschrock 13551354Seschrock return (ret); 13561354Seschrock } 13571354Seschrock 13581354Seschrock /* 13591354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 13601354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 13611354Seschrock * type 'zpool status', and we'll display the correct information anyway. 13621354Seschrock */ 13631354Seschrock static void 13641354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 13651354Seschrock { 13661354Seschrock zfs_cmd_t zc = { 0 }; 13671354Seschrock 13681354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13692676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 13701354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 13711544Seschrock &zc.zc_guid) == 0); 13721354Seschrock 13732082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 13741354Seschrock } 13751354Seschrock 13761354Seschrock /* 13771354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 13781354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 13791354Seschrock * We also check if this is a whole disk, in which case we strip off the 13801354Seschrock * trailing 's0' slice name. 13811354Seschrock * 13821354Seschrock * This routine is also responsible for identifying when disks have been 13831354Seschrock * reconfigured in a new location. The kernel will have opened the device by 13841354Seschrock * devid, but the path will still refer to the old location. To catch this, we 13851354Seschrock * first do a path -> devid translation (which is fast for the common case). If 13861354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 13871354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 13881354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 13891354Seschrock * of these checks. 13901354Seschrock */ 13911354Seschrock char * 13922082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 13931354Seschrock { 13941354Seschrock char *path, *devid; 13951544Seschrock uint64_t value; 13961544Seschrock char buf[64]; 13971354Seschrock 13981544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 13991544Seschrock &value) == 0) { 14001544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14011544Seschrock &value) == 0); 1402*2856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 1403*2856Snd150628 (u_longlong_t)value); 14041544Seschrock path = buf; 14051544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 14061354Seschrock 14071354Seschrock if (zhp != NULL && 14081354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 14091354Seschrock /* 14101354Seschrock * Determine if the current path is correct. 14111354Seschrock */ 14121354Seschrock char *newdevid = path_to_devid(path); 14131354Seschrock 14141354Seschrock if (newdevid == NULL || 14151354Seschrock strcmp(devid, newdevid) != 0) { 14161354Seschrock char *newpath; 14171354Seschrock 14181354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 14191354Seschrock /* 14201354Seschrock * Update the path appropriately. 14211354Seschrock */ 14221354Seschrock set_path(zhp, nv, newpath); 14232082Seschrock if (nvlist_add_string(nv, 14242082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 14252082Seschrock verify(nvlist_lookup_string(nv, 14262082Seschrock ZPOOL_CONFIG_PATH, 14272082Seschrock &path) == 0); 14281354Seschrock free(newpath); 14291354Seschrock } 14301354Seschrock } 14311354Seschrock 14322082Seschrock if (newdevid) 14332082Seschrock devid_str_free(newdevid); 14341354Seschrock } 14351354Seschrock 14361354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 14371354Seschrock path += 9; 14381354Seschrock 14391354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 14401544Seschrock &value) == 0 && value) { 14412082Seschrock char *tmp = zfs_strdup(hdl, path); 14422082Seschrock if (tmp == NULL) 14432082Seschrock return (NULL); 14441354Seschrock tmp[strlen(path) - 2] = '\0'; 14451354Seschrock return (tmp); 14461354Seschrock } 14471354Seschrock } else { 14481354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 14492082Seschrock 14502082Seschrock /* 14512082Seschrock * If it's a raidz device, we need to stick in the parity level. 14522082Seschrock */ 14532082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 14542082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 14552082Seschrock &value) == 0); 14562082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 1457*2856Snd150628 (u_longlong_t)value); 14582082Seschrock path = buf; 14592082Seschrock } 14601354Seschrock } 14611354Seschrock 14622082Seschrock return (zfs_strdup(hdl, path)); 14631354Seschrock } 14641544Seschrock 14651544Seschrock static int 14661544Seschrock zbookmark_compare(const void *a, const void *b) 14671544Seschrock { 14681544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 14691544Seschrock } 14701544Seschrock 14711544Seschrock /* 14721544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 14731544Seschrock * caller. 14741544Seschrock */ 14751544Seschrock int 14761544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem) 14771544Seschrock { 14781544Seschrock zfs_cmd_t zc = { 0 }; 14791544Seschrock uint64_t count; 14802676Seschrock zbookmark_t *zb = NULL; 14812676Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 14821544Seschrock int i, j; 14831544Seschrock 14841544Seschrock if (zhp->zpool_error_log != NULL) { 14851544Seschrock *list = zhp->zpool_error_log; 14861544Seschrock *nelem = zhp->zpool_error_count; 14871544Seschrock return (0); 14881544Seschrock } 14891544Seschrock 14901544Seschrock /* 14911544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 14921544Seschrock * has increased, allocate more space and continue until we get the 14931544Seschrock * entire list. 14941544Seschrock */ 14951544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 14961544Seschrock &count) == 0); 14972676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 1498*2856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 14992082Seschrock return (-1); 15002676Seschrock zc.zc_nvlist_dst_size = count; 15011544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15021544Seschrock for (;;) { 15032082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 15042082Seschrock &zc) != 0) { 15052676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15061544Seschrock if (errno == ENOMEM) { 15072676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 15082082Seschrock zfs_alloc(zhp->zpool_hdl, 1509*2856Snd150628 zc.zc_nvlist_dst_size)) == (uintptr_t)NULL) 15102082Seschrock return (-1); 15111544Seschrock } else { 15121544Seschrock return (-1); 15131544Seschrock } 15141544Seschrock } else { 15151544Seschrock break; 15161544Seschrock } 15171544Seschrock } 15181544Seschrock 15191544Seschrock /* 15201544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 15211544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 15222676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 15231544Seschrock * _not_ copied as part of the process. So we point the start of our 15241544Seschrock * array appropriate and decrement the total number of elements. 15251544Seschrock */ 15262676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 15272676Seschrock zc.zc_nvlist_dst_size; 15282676Seschrock count -= zc.zc_nvlist_dst_size; 15292676Seschrock zc.zc_nvlist_dst = 0ULL; 15301544Seschrock 15311544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 15321544Seschrock 15331544Seschrock /* 15341544Seschrock * Count the number of unique elements 15351544Seschrock */ 15361544Seschrock j = 0; 15371544Seschrock for (i = 0; i < count; i++) { 15381544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15391544Seschrock sizeof (zbookmark_t)) == 0) 15401544Seschrock continue; 15411544Seschrock j++; 15421544Seschrock } 15431544Seschrock 15441544Seschrock /* 15451544Seschrock * If the user has only requested the number of items, return it now 15461544Seschrock * without bothering with the extra work. 15471544Seschrock */ 15481544Seschrock if (list == NULL) { 15491544Seschrock *nelem = j; 15502676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15511544Seschrock return (0); 15521544Seschrock } 15531544Seschrock 15541544Seschrock zhp->zpool_error_count = j; 15551544Seschrock 15561544Seschrock /* 15571544Seschrock * Allocate an array of nvlists to hold the results 15581544Seschrock */ 15592082Seschrock if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, 15602082Seschrock j * sizeof (nvlist_t *))) == NULL) { 15612676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15622082Seschrock return (-1); 15632082Seschrock } 15641544Seschrock 15651544Seschrock /* 15661544Seschrock * Fill in the results with names from the kernel. 15671544Seschrock */ 15681544Seschrock j = 0; 15691544Seschrock for (i = 0; i < count; i++) { 15701544Seschrock char buf[64]; 15711544Seschrock nvlist_t *nv; 15721544Seschrock 15731544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15741544Seschrock sizeof (zbookmark_t)) == 0) 15751544Seschrock continue; 15761544Seschrock 15772676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 15782082Seschrock goto nomem; 15791544Seschrock 15801544Seschrock zc.zc_bookmark = zb[i]; 15812676Seschrock for (;;) { 15822676Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, 15832676Seschrock ZFS_IOC_BOOKMARK_NAME, &zc) != 0) { 15842676Seschrock if (errno == ENOMEM) { 15852676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) 15862676Seschrock != 0) { 15872676Seschrock zcmd_free_nvlists(&zc); 15882676Seschrock goto nomem; 15892676Seschrock } 15902676Seschrock 15912676Seschrock continue; 15922676Seschrock } else { 15932676Seschrock if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 15942676Seschrock 0) != 0) 15952676Seschrock goto nomem; 15962676Seschrock 15972676Seschrock zhp->zpool_error_log[j] = nv; 15982676Seschrock (void) snprintf(buf, sizeof (buf), 1599*2856Snd150628 "%llx", (longlong_t) 1600*2856Snd150628 zb[i].zb_objset); 16012676Seschrock if (nvlist_add_string(nv, 16022676Seschrock ZPOOL_ERR_DATASET, buf) != 0) 16032676Seschrock goto nomem; 16042676Seschrock (void) snprintf(buf, sizeof (buf), 1605*2856Snd150628 "%llx", (longlong_t) 1606*2856Snd150628 zb[i].zb_object); 16072676Seschrock if (nvlist_add_string(nv, 16082676Seschrock ZPOOL_ERR_OBJECT, buf) != 0) 16092676Seschrock goto nomem; 16102676Seschrock (void) snprintf(buf, sizeof (buf), 16112676Seschrock "lvl=%u blkid=%llu", 16122676Seschrock (int)zb[i].zb_level, 16132676Seschrock (long long)zb[i].zb_blkid); 16142676Seschrock if (nvlist_add_string(nv, 16152676Seschrock ZPOOL_ERR_RANGE, buf) != 0) 16162676Seschrock goto nomem; 16172676Seschrock } 16182676Seschrock } else { 16192676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, 16202676Seschrock &zhp->zpool_error_log[j]) != 0) { 16212676Seschrock zcmd_free_nvlists(&zc); 16222676Seschrock goto nomem; 16232676Seschrock } 16242676Seschrock } 16252676Seschrock 16262676Seschrock break; 16271544Seschrock } 16281544Seschrock 16292676Seschrock zcmd_free_nvlists(&zc); 16302676Seschrock 16311544Seschrock j++; 16321544Seschrock } 16331544Seschrock 16341544Seschrock *list = zhp->zpool_error_log; 16351544Seschrock *nelem = zhp->zpool_error_count; 16362676Seschrock free(zb); 16371544Seschrock 16381544Seschrock return (0); 16392082Seschrock 16402082Seschrock nomem: 16412676Seschrock free(zb); 16422676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16432676Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 16442676Seschrock nvlist_free(zhp->zpool_error_log[i]); 16452082Seschrock free(zhp->zpool_error_log); 16462082Seschrock zhp->zpool_error_log = NULL; 16472082Seschrock return (no_memory(zhp->zpool_hdl)); 16481544Seschrock } 16491760Seschrock 16501760Seschrock /* 16511760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16521760Seschrock */ 16531760Seschrock int 16541760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16551760Seschrock { 16561760Seschrock zfs_cmd_t zc = { 0 }; 16572082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16581760Seschrock 16591760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16602082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 16612082Seschrock return (zpool_standard_error(hdl, errno, 16622082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 16632082Seschrock zhp->zpool_name)); 16641760Seschrock 16651760Seschrock return (0); 16661760Seschrock } 1667