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> 41*2926Sek110237 #include <strings.h> 42789Sahrens 43789Sahrens #include "zfs_namecheck.h" 44789Sahrens #include "libzfs_impl.h" 45789Sahrens 46789Sahrens /* 47789Sahrens * Validate the given pool name, optionally putting an extended error message in 48789Sahrens * 'buf'. 49789Sahrens */ 502082Seschrock static boolean_t 512082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 52789Sahrens { 53789Sahrens namecheck_err_t why; 54789Sahrens char what; 551773Seschrock int ret; 56789Sahrens 571773Seschrock ret = pool_namecheck(pool, &why, &what); 581773Seschrock 591773Seschrock /* 601773Seschrock * The rules for reserved pool names were extended at a later point. 611773Seschrock * But we need to support users with existing pools that may now be 621773Seschrock * invalid. So we only check for this expanded set of names during a 631773Seschrock * create (or import), and only in userland. 641773Seschrock */ 651773Seschrock if (ret == 0 && !isopen && 661773Seschrock (strncmp(pool, "mirror", 6) == 0 || 671773Seschrock strncmp(pool, "raidz", 5) == 0 || 681773Seschrock strncmp(pool, "spare", 5) == 0)) { 692082Seschrock zfs_error_aux(hdl, 702082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 712082Seschrock return (B_FALSE); 721773Seschrock } 731773Seschrock 741773Seschrock 751773Seschrock if (ret != 0) { 762082Seschrock if (hdl != NULL) { 77789Sahrens switch (why) { 781003Slling case NAME_ERR_TOOLONG: 792082Seschrock zfs_error_aux(hdl, 801003Slling dgettext(TEXT_DOMAIN, "name is too long")); 811003Slling break; 821003Slling 83789Sahrens case NAME_ERR_INVALCHAR: 842082Seschrock zfs_error_aux(hdl, 85789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 86789Sahrens "'%c' in pool name"), what); 87789Sahrens break; 88789Sahrens 89789Sahrens case NAME_ERR_NOLETTER: 902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 912082Seschrock "name must begin with a letter")); 92789Sahrens break; 93789Sahrens 94789Sahrens case NAME_ERR_RESERVED: 952082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 962082Seschrock "name is reserved")); 97789Sahrens break; 98789Sahrens 99789Sahrens case NAME_ERR_DISKLIKE: 1002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1012082Seschrock "pool name is reserved")); 102789Sahrens break; 1032856Snd150628 1042856Snd150628 case NAME_ERR_LEADING_SLASH: 1052856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1062856Snd150628 "leading slash in name")); 1072856Snd150628 break; 1082856Snd150628 1092856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 1102856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1112856Snd150628 "empty component in name")); 1122856Snd150628 break; 1132856Snd150628 1142856Snd150628 case NAME_ERR_TRAILING_SLASH: 1152856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1162856Snd150628 "trailing slash in name")); 1172856Snd150628 break; 1182856Snd150628 1192856Snd150628 case NAME_ERR_MULTIPLE_AT: 1202856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1212856Snd150628 "multiple '@' delimiters in name")); 1222856Snd150628 break; 1232856Snd150628 124789Sahrens } 125789Sahrens } 1262082Seschrock return (B_FALSE); 127789Sahrens } 128789Sahrens 1292082Seschrock return (B_TRUE); 130789Sahrens } 131789Sahrens 132789Sahrens /* 133789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 134789Sahrens */ 1352082Seschrock int 136789Sahrens set_pool_health(nvlist_t *config) 137789Sahrens { 138789Sahrens nvlist_t *nvroot; 139789Sahrens vdev_stat_t *vs; 140789Sahrens uint_t vsc; 141789Sahrens char *health; 142789Sahrens 143789Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 144789Sahrens &nvroot) == 0); 145789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 146789Sahrens (uint64_t **)&vs, &vsc) == 0); 147789Sahrens 148789Sahrens switch (vs->vs_state) { 149789Sahrens 150789Sahrens case VDEV_STATE_CLOSED: 151789Sahrens case VDEV_STATE_CANT_OPEN: 152789Sahrens case VDEV_STATE_OFFLINE: 153789Sahrens health = dgettext(TEXT_DOMAIN, "FAULTED"); 154789Sahrens break; 155789Sahrens 156789Sahrens case VDEV_STATE_DEGRADED: 157789Sahrens health = dgettext(TEXT_DOMAIN, "DEGRADED"); 158789Sahrens break; 159789Sahrens 160789Sahrens case VDEV_STATE_HEALTHY: 161789Sahrens health = dgettext(TEXT_DOMAIN, "ONLINE"); 162789Sahrens break; 163789Sahrens 164789Sahrens default: 1652082Seschrock abort(); 166789Sahrens } 167789Sahrens 1682082Seschrock return (nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, health)); 169789Sahrens } 170789Sahrens 171789Sahrens /* 172789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 173789Sahrens * state. 174789Sahrens */ 175789Sahrens zpool_handle_t * 1762082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 177789Sahrens { 178789Sahrens zpool_handle_t *zhp; 1792142Seschrock boolean_t missing; 180789Sahrens 181789Sahrens /* 182789Sahrens * Make sure the pool name is valid. 183789Sahrens */ 1842082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 1852082Seschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, 1862082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 1872082Seschrock pool); 188789Sahrens return (NULL); 189789Sahrens } 190789Sahrens 1912082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1922082Seschrock return (NULL); 193789Sahrens 1942082Seschrock zhp->zpool_hdl = hdl; 195789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 196789Sahrens 1972142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 1982142Seschrock zpool_close(zhp); 1992142Seschrock return (NULL); 2002142Seschrock } 2012142Seschrock 2022142Seschrock if (missing) { 2032142Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2042142Seschrock "no such pool")); 2052142Seschrock (void) zfs_error(hdl, EZFS_NOENT, 2062142Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 2072142Seschrock pool); 2082142Seschrock zpool_close(zhp); 2092142Seschrock return (NULL); 210789Sahrens } 211789Sahrens 212789Sahrens return (zhp); 213789Sahrens } 214789Sahrens 215789Sahrens /* 216789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 217789Sahrens * the configuration cache may be out of date). 218789Sahrens */ 2192142Seschrock int 2202142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 221789Sahrens { 222789Sahrens zpool_handle_t *zhp; 2232142Seschrock boolean_t missing; 224789Sahrens 2252142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 2262142Seschrock return (-1); 227789Sahrens 2282082Seschrock zhp->zpool_hdl = hdl; 229789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 230789Sahrens 2312142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 2322142Seschrock zpool_close(zhp); 2332142Seschrock return (-1); 234789Sahrens } 235789Sahrens 2362142Seschrock if (missing) { 2372142Seschrock zpool_close(zhp); 2382142Seschrock *ret = NULL; 2392142Seschrock return (0); 2402142Seschrock } 2412142Seschrock 2422142Seschrock *ret = zhp; 2432142Seschrock return (0); 244789Sahrens } 245789Sahrens 246789Sahrens /* 247789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 248789Sahrens * state. 249789Sahrens */ 250789Sahrens zpool_handle_t * 2512082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 252789Sahrens { 253789Sahrens zpool_handle_t *zhp; 254789Sahrens 2552082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 256789Sahrens return (NULL); 257789Sahrens 258789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2592082Seschrock (void) zfs_error(hdl, EZFS_POOLUNAVAIL, 2602082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 261789Sahrens zpool_close(zhp); 262789Sahrens return (NULL); 263789Sahrens } 264789Sahrens 265789Sahrens return (zhp); 266789Sahrens } 267789Sahrens 268789Sahrens /* 269789Sahrens * Close the handle. Simply frees the memory associated with the handle. 270789Sahrens */ 271789Sahrens void 272789Sahrens zpool_close(zpool_handle_t *zhp) 273789Sahrens { 274789Sahrens if (zhp->zpool_config) 275789Sahrens nvlist_free(zhp->zpool_config); 276952Seschrock if (zhp->zpool_old_config) 277952Seschrock nvlist_free(zhp->zpool_old_config); 2781544Seschrock if (zhp->zpool_error_log) { 2791544Seschrock int i; 2801544Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 2812082Seschrock nvlist_free(zhp->zpool_error_log[i]); 2821544Seschrock free(zhp->zpool_error_log); 2831544Seschrock } 284789Sahrens free(zhp); 285789Sahrens } 286789Sahrens 287789Sahrens /* 288789Sahrens * Return the name of the pool. 289789Sahrens */ 290789Sahrens const char * 291789Sahrens zpool_get_name(zpool_handle_t *zhp) 292789Sahrens { 293789Sahrens return (zhp->zpool_name); 294789Sahrens } 295789Sahrens 296789Sahrens /* 297789Sahrens * Return the GUID of the pool. 298789Sahrens */ 299789Sahrens uint64_t 300789Sahrens zpool_get_guid(zpool_handle_t *zhp) 301789Sahrens { 302789Sahrens uint64_t guid; 303789Sahrens 304789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 305789Sahrens &guid) == 0); 306789Sahrens return (guid); 307789Sahrens } 308789Sahrens 309789Sahrens /* 3102082Seschrock * Return the version of the pool. 3112082Seschrock */ 3122082Seschrock uint64_t 3132082Seschrock zpool_get_version(zpool_handle_t *zhp) 3142082Seschrock { 3152082Seschrock uint64_t version; 3162082Seschrock 3172082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 3182082Seschrock &version) == 0); 3192082Seschrock 3202082Seschrock return (version); 3212082Seschrock } 3222082Seschrock 3232082Seschrock /* 324789Sahrens * Return the amount of space currently consumed by the pool. 325789Sahrens */ 326789Sahrens uint64_t 327789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 328789Sahrens { 329789Sahrens nvlist_t *nvroot; 330789Sahrens vdev_stat_t *vs; 331789Sahrens uint_t vsc; 332789Sahrens 333789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 334789Sahrens &nvroot) == 0); 335789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 336789Sahrens (uint64_t **)&vs, &vsc) == 0); 337789Sahrens 338789Sahrens return (vs->vs_alloc); 339789Sahrens } 340789Sahrens 341789Sahrens /* 342789Sahrens * Return the total space in the pool. 343789Sahrens */ 344789Sahrens uint64_t 345789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 346789Sahrens { 347789Sahrens nvlist_t *nvroot; 348789Sahrens vdev_stat_t *vs; 349789Sahrens uint_t vsc; 350789Sahrens 351789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 352789Sahrens &nvroot) == 0); 353789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 354789Sahrens (uint64_t **)&vs, &vsc) == 0); 355789Sahrens 356789Sahrens return (vs->vs_space); 357789Sahrens } 358789Sahrens 359789Sahrens /* 360789Sahrens * Return the alternate root for this pool, if any. 361789Sahrens */ 362789Sahrens int 363789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 364789Sahrens { 365789Sahrens zfs_cmd_t zc = { 0 }; 366789Sahrens 367789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3682082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3692676Seschrock zc.zc_value[0] == '\0') 370789Sahrens return (-1); 371789Sahrens 3722676Seschrock (void) strlcpy(buf, zc.zc_value, buflen); 373789Sahrens 374789Sahrens return (0); 375789Sahrens } 376789Sahrens 377789Sahrens /* 378789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 379789Sahrens */ 380789Sahrens int 381789Sahrens zpool_get_state(zpool_handle_t *zhp) 382789Sahrens { 383789Sahrens return (zhp->zpool_state); 384789Sahrens } 385789Sahrens 386789Sahrens /* 387789Sahrens * Create the named pool, using the provided vdev list. It is assumed 388789Sahrens * that the consumer has already validated the contents of the nvlist, so we 389789Sahrens * don't have to worry about error semantics. 390789Sahrens */ 391789Sahrens int 3922082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 3932082Seschrock const char *altroot) 394789Sahrens { 395789Sahrens zfs_cmd_t zc = { 0 }; 3962082Seschrock char msg[1024]; 3972082Seschrock 3982082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 3992082Seschrock "cannot create '%s'"), pool); 400789Sahrens 4012082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 4022082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 4032082Seschrock 4042082Seschrock if (altroot != NULL && altroot[0] != '/') 4052082Seschrock return (zfs_error(hdl, EZFS_BADPATH, 4062082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 407789Sahrens 4082676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 409789Sahrens return (-1); 410789Sahrens 411789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 412789Sahrens 413789Sahrens if (altroot != NULL) 4142676Seschrock (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); 415789Sahrens 4162082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 4172676Seschrock zcmd_free_nvlists(&zc); 4182082Seschrock 419789Sahrens switch (errno) { 420789Sahrens case EBUSY: 421789Sahrens /* 422789Sahrens * This can happen if the user has specified the same 423789Sahrens * device multiple times. We can't reliably detect this 424789Sahrens * until we try to add it and see we already have a 425789Sahrens * label. 426789Sahrens */ 4272082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4282082Seschrock "one or more vdevs refer to the same device")); 4292082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 430789Sahrens 431789Sahrens case EOVERFLOW: 432789Sahrens /* 4332082Seschrock * This occurs when one of the devices is below 434789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 435789Sahrens * device was the problem device since there's no 436789Sahrens * reliable way to determine device size from userland. 437789Sahrens */ 438789Sahrens { 439789Sahrens char buf[64]; 440789Sahrens 441789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 442789Sahrens 4432082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4442082Seschrock "one or more devices is less than the " 4452082Seschrock "minimum size (%s)"), buf); 446789Sahrens } 4472082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 448789Sahrens 449789Sahrens case ENOSPC: 4502082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4512082Seschrock "one or more devices is out of space")); 4522082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 453789Sahrens 454789Sahrens default: 4552082Seschrock return (zpool_standard_error(hdl, errno, msg)); 456789Sahrens } 457789Sahrens } 458789Sahrens 4592676Seschrock zcmd_free_nvlists(&zc); 460789Sahrens 461789Sahrens /* 462789Sahrens * If this is an alternate root pool, then we automatically set the 4632676Seschrock * mountpoint of the root dataset to be '/'. 464789Sahrens */ 465789Sahrens if (altroot != NULL) { 466789Sahrens zfs_handle_t *zhp; 467789Sahrens 4682082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 4692676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 4702676Seschrock "/") == 0); 471789Sahrens 472789Sahrens zfs_close(zhp); 473789Sahrens } 474789Sahrens 475789Sahrens return (0); 476789Sahrens } 477789Sahrens 478789Sahrens /* 479789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 480789Sahrens * datasets left in the pool. 481789Sahrens */ 482789Sahrens int 483789Sahrens zpool_destroy(zpool_handle_t *zhp) 484789Sahrens { 485789Sahrens zfs_cmd_t zc = { 0 }; 486789Sahrens zfs_handle_t *zfp = NULL; 4872082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 4882082Seschrock char msg[1024]; 489789Sahrens 490789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 4912082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 4922082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 493789Sahrens return (-1); 494789Sahrens 4952856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 496789Sahrens return (-1); 497789Sahrens 498789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 499789Sahrens 5002082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 5012082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5022082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 503789Sahrens 5042082Seschrock if (errno == EROFS) { 5052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5062082Seschrock "one or more devices is read only")); 5072082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5082082Seschrock } else { 5092082Seschrock (void) zpool_standard_error(hdl, errno, msg); 510789Sahrens } 511789Sahrens 512789Sahrens if (zfp) 513789Sahrens zfs_close(zfp); 514789Sahrens return (-1); 515789Sahrens } 516789Sahrens 517789Sahrens if (zfp) { 518789Sahrens remove_mountpoint(zfp); 519789Sahrens zfs_close(zfp); 520789Sahrens } 521789Sahrens 522789Sahrens return (0); 523789Sahrens } 524789Sahrens 525789Sahrens /* 526789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 527789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 528789Sahrens */ 529789Sahrens int 530789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 531789Sahrens { 5322676Seschrock zfs_cmd_t zc = { 0 }; 5332082Seschrock int ret; 5342082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 5352082Seschrock char msg[1024]; 5362082Seschrock nvlist_t **spares; 5372082Seschrock uint_t nspares; 5382082Seschrock 5392082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 5402082Seschrock "cannot add to '%s'"), zhp->zpool_name); 5412082Seschrock 5422082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 5432082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5442082Seschrock &spares, &nspares) == 0) { 5452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 5462082Seschrock "upgraded to add hot spares")); 5472082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 5482082Seschrock } 549789Sahrens 5502676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 5512082Seschrock return (-1); 552789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 553789Sahrens 5542082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 555789Sahrens switch (errno) { 556789Sahrens case EBUSY: 557789Sahrens /* 558789Sahrens * This can happen if the user has specified the same 559789Sahrens * device multiple times. We can't reliably detect this 560789Sahrens * until we try to add it and see we already have a 561789Sahrens * label. 562789Sahrens */ 5632082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5642082Seschrock "one or more vdevs refer to the same device")); 5652082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 566789Sahrens break; 567789Sahrens 568789Sahrens case EOVERFLOW: 569789Sahrens /* 570789Sahrens * This occurrs when one of the devices is below 571789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 572789Sahrens * device was the problem device since there's no 573789Sahrens * reliable way to determine device size from userland. 574789Sahrens */ 575789Sahrens { 576789Sahrens char buf[64]; 577789Sahrens 578789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 579789Sahrens 5802082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5812082Seschrock "device is less than the minimum " 5822082Seschrock "size (%s)"), buf); 583789Sahrens } 5842082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 5852082Seschrock break; 5862082Seschrock 5872082Seschrock case ENOTSUP: 5882082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5892082Seschrock "pool must be upgraded to add raidz2 vdevs")); 5902082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 591789Sahrens break; 592789Sahrens 593789Sahrens default: 5942082Seschrock (void) zpool_standard_error(hdl, errno, msg); 595789Sahrens } 596789Sahrens 5972082Seschrock ret = -1; 5982082Seschrock } else { 5992082Seschrock ret = 0; 600789Sahrens } 601789Sahrens 6022676Seschrock zcmd_free_nvlists(&zc); 603789Sahrens 6042082Seschrock return (ret); 605789Sahrens } 606789Sahrens 607789Sahrens /* 608789Sahrens * Exports the pool from the system. The caller must ensure that there are no 609789Sahrens * mounted datasets in the pool. 610789Sahrens */ 611789Sahrens int 612789Sahrens zpool_export(zpool_handle_t *zhp) 613789Sahrens { 614789Sahrens zfs_cmd_t zc = { 0 }; 615789Sahrens 616789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 617789Sahrens return (-1); 618789Sahrens 619789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 620789Sahrens 6212082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 6222082Seschrock return (zpool_standard_error(zhp->zpool_hdl, errno, 6232082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 6242082Seschrock zhp->zpool_name)); 625789Sahrens 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)) 6492082Seschrock return (zfs_error(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] != '/') 6582082Seschrock return (zfs_error(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 /* 865789Sahrens * Bring the specified vdev online 866789Sahrens */ 867789Sahrens int 868789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 869789Sahrens { 870789Sahrens zfs_cmd_t zc = { 0 }; 871789Sahrens char msg[1024]; 8722082Seschrock nvlist_t *tgt; 8732468Sek110237 boolean_t avail_spare; 8742082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 875789Sahrens 8761544Seschrock (void) snprintf(msg, sizeof (msg), 8771544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 878789Sahrens 8791544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 8802468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 8812082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 882789Sahrens 8832468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 8842468Sek110237 8852468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 8862082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 8872082Seschrock 8882082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8891544Seschrock return (0); 890789Sahrens 8912082Seschrock return (zpool_standard_error(hdl, errno, msg)); 892789Sahrens } 893789Sahrens 894789Sahrens /* 895789Sahrens * Take the specified vdev offline 896789Sahrens */ 897789Sahrens int 8981485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 899789Sahrens { 900789Sahrens zfs_cmd_t zc = { 0 }; 901789Sahrens char msg[1024]; 9022082Seschrock nvlist_t *tgt; 9032468Sek110237 boolean_t avail_spare; 9042082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 905789Sahrens 9061544Seschrock (void) snprintf(msg, sizeof (msg), 9071544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9081544Seschrock 909789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9102468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 9112082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9122082Seschrock 9132468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9142468Sek110237 9152468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 9162082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9172082Seschrock 9181485Slling zc.zc_cookie = istmp; 9191485Slling 9202082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 921789Sahrens return (0); 922789Sahrens 923789Sahrens switch (errno) { 9242082Seschrock case EBUSY: 925789Sahrens 926789Sahrens /* 927789Sahrens * There are no other replicas of this device. 928789Sahrens */ 9292082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 9302082Seschrock 9312082Seschrock default: 9322082Seschrock return (zpool_standard_error(hdl, errno, msg)); 9332082Seschrock } 9342082Seschrock } 935789Sahrens 9362082Seschrock /* 9372082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 9382082Seschrock * a hot spare. 9392082Seschrock */ 9402082Seschrock static boolean_t 9412082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 9422082Seschrock { 9432082Seschrock nvlist_t **child; 9442082Seschrock uint_t c, children; 9452082Seschrock char *type; 9462082Seschrock 9472082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 9482082Seschrock &children) == 0) { 9492082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 9502082Seschrock &type) == 0); 9512082Seschrock 9522082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 9532082Seschrock children == 2 && child[which] == tgt) 9542082Seschrock return (B_TRUE); 9552082Seschrock 9562082Seschrock for (c = 0; c < children; c++) 9572082Seschrock if (is_replacing_spare(child[c], tgt, which)) 9582082Seschrock return (B_TRUE); 959789Sahrens } 9602082Seschrock 9612082Seschrock return (B_FALSE); 962789Sahrens } 963789Sahrens 964789Sahrens /* 965789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 966789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 967789Sahrens */ 968789Sahrens int 969789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 970789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 971789Sahrens { 972789Sahrens zfs_cmd_t zc = { 0 }; 973789Sahrens char msg[1024]; 974789Sahrens int ret; 9752082Seschrock nvlist_t *tgt; 9762468Sek110237 boolean_t avail_spare; 9772082Seschrock uint64_t val; 9782082Seschrock char *path; 9792082Seschrock nvlist_t **child; 9802082Seschrock uint_t children; 9812082Seschrock nvlist_t *config_root; 9822082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 983789Sahrens 9841544Seschrock if (replacing) 9851544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9861544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9871544Seschrock else 9881544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9891544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9901544Seschrock 991789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9922468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 9932082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 9942082Seschrock 9952468Sek110237 if (avail_spare) 9962082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 9972082Seschrock 9982082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 9992082Seschrock zc.zc_cookie = replacing; 10002082Seschrock 10012082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 10022082Seschrock &child, &children) != 0 || children != 1) { 10032082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10042082Seschrock "new device must be a single disk")); 10052082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 10061544Seschrock } 10072082Seschrock 10082082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 10092082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 10102082Seschrock 10112082Seschrock /* 10122082Seschrock * If the target is a hot spare that has been swapped in, we can only 10132082Seschrock * replace it with another hot spare. 10142082Seschrock */ 10152082Seschrock if (replacing && 10162082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 10172082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10182468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 10192468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 10202082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10212082Seschrock "can only be replaced by another hot spare")); 10222082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10232082Seschrock } 10242082Seschrock 10252082Seschrock /* 10262082Seschrock * If we are attempting to replace a spare, it canot be applied to an 10272082Seschrock * already spared device. 10282082Seschrock */ 10292082Seschrock if (replacing && 10302082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 10312468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 10322082Seschrock is_replacing_spare(config_root, tgt, 0)) { 10332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10342082Seschrock "device has already been replaced with a spare")); 10352082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 10362082Seschrock } 1037789Sahrens 10382676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) 10392082Seschrock return (-1); 1040789Sahrens 10412082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1042789Sahrens 10432676Seschrock zcmd_free_nvlists(&zc); 1044789Sahrens 1045789Sahrens if (ret == 0) 1046789Sahrens return (0); 1047789Sahrens 1048789Sahrens switch (errno) { 10491544Seschrock case ENOTSUP: 1050789Sahrens /* 1051789Sahrens * Can't attach to or replace this type of vdev. 1052789Sahrens */ 1053789Sahrens if (replacing) 10542082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10552082Seschrock "cannot replace a replacing device")); 1056789Sahrens else 10572082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10582082Seschrock "can only attach to mirrors and top-level " 10592082Seschrock "disks")); 10602082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1061789Sahrens break; 1062789Sahrens 10631544Seschrock case EINVAL: 1064789Sahrens /* 1065789Sahrens * The new device must be a single disk. 1066789Sahrens */ 10672082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10682082Seschrock "new device must be a single disk")); 10692082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1070789Sahrens break; 1071789Sahrens 10721544Seschrock case EBUSY: 10732082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 10742082Seschrock new_disk); 10752082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1076789Sahrens break; 1077789Sahrens 10781544Seschrock case EOVERFLOW: 1079789Sahrens /* 1080789Sahrens * The new device is too small. 1081789Sahrens */ 10822082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10832082Seschrock "device is too small")); 10842082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1085789Sahrens break; 1086789Sahrens 10871544Seschrock case EDOM: 1088789Sahrens /* 1089789Sahrens * The new device has a different alignment requirement. 1090789Sahrens */ 10912082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10922082Seschrock "devices have different sector alignment")); 10932082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1094789Sahrens break; 1095789Sahrens 10961544Seschrock case ENAMETOOLONG: 1097789Sahrens /* 1098789Sahrens * The resulting top-level vdev spec won't fit in the label. 1099789Sahrens */ 11002082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1101789Sahrens break; 1102789Sahrens 11031544Seschrock default: 11042082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1105789Sahrens } 1106789Sahrens 11072082Seschrock return (-1); 1108789Sahrens } 1109789Sahrens 1110789Sahrens /* 1111789Sahrens * Detach the specified device. 1112789Sahrens */ 1113789Sahrens int 1114789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1115789Sahrens { 1116789Sahrens zfs_cmd_t zc = { 0 }; 1117789Sahrens char msg[1024]; 11182082Seschrock nvlist_t *tgt; 11192468Sek110237 boolean_t avail_spare; 11202082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1121789Sahrens 11221544Seschrock (void) snprintf(msg, sizeof (msg), 11231544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11241544Seschrock 1125789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11262468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11272082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1128789Sahrens 11292468Sek110237 if (avail_spare) 11302082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 11312082Seschrock 11322082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11332082Seschrock 11342082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1135789Sahrens return (0); 1136789Sahrens 1137789Sahrens switch (errno) { 1138789Sahrens 11391544Seschrock case ENOTSUP: 1140789Sahrens /* 1141789Sahrens * Can't detach from this type of vdev. 1142789Sahrens */ 11432082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 11442082Seschrock "applicable to mirror and replacing vdevs")); 11452082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1146789Sahrens break; 1147789Sahrens 11481544Seschrock case EBUSY: 1149789Sahrens /* 1150789Sahrens * There are no other replicas of this device. 1151789Sahrens */ 11522082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1153789Sahrens break; 1154789Sahrens 11551544Seschrock default: 11562082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11571544Seschrock } 11581544Seschrock 11592082Seschrock return (-1); 11602082Seschrock } 11612082Seschrock 11622082Seschrock /* 11632082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 11642082Seschrock */ 11652082Seschrock int 11662082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 11672082Seschrock { 11682082Seschrock zfs_cmd_t zc = { 0 }; 11692082Seschrock char msg[1024]; 11702082Seschrock nvlist_t *tgt; 11712468Sek110237 boolean_t avail_spare; 11722082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11732082Seschrock 11742082Seschrock (void) snprintf(msg, sizeof (msg), 11752082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 11762082Seschrock 11772082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11782468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 11792082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11802082Seschrock 11812468Sek110237 if (!avail_spare) { 11822082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11832082Seschrock "only hot spares can be removed")); 11842082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 11852082Seschrock } 11862082Seschrock 11872082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 11882082Seschrock 11892082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 11902082Seschrock return (0); 11912082Seschrock 11922082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11931544Seschrock } 11941544Seschrock 11951544Seschrock /* 11961544Seschrock * Clear the errors for the pool, or the particular device if specified. 11971544Seschrock */ 11981544Seschrock int 11991544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 12001544Seschrock { 12011544Seschrock zfs_cmd_t zc = { 0 }; 12021544Seschrock char msg[1024]; 12032082Seschrock nvlist_t *tgt; 12042468Sek110237 boolean_t avail_spare; 12052082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 12061544Seschrock 12071544Seschrock if (path) 12081544Seschrock (void) snprintf(msg, sizeof (msg), 12091544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12102676Seschrock path); 12111544Seschrock else 12121544Seschrock (void) snprintf(msg, sizeof (msg), 12131544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12141544Seschrock zhp->zpool_name); 12151544Seschrock 12161544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12172082Seschrock if (path) { 12182468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 12192082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 12202082Seschrock 12212468Sek110237 if (avail_spare) 12222082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12232082Seschrock 12242082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 12252082Seschrock &zc.zc_guid) == 0); 12261544Seschrock } 12271544Seschrock 12282082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12291544Seschrock return (0); 12301544Seschrock 12312082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1232789Sahrens } 1233789Sahrens 1234789Sahrens static int 1235789Sahrens do_zvol(zfs_handle_t *zhp, void *data) 1236789Sahrens { 1237789Sahrens int linktype = (int)(uintptr_t)data; 1238789Sahrens int ret; 1239789Sahrens 1240789Sahrens /* 1241789Sahrens * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we 1242789Sahrens * correctly handle snapshots of volumes. 1243789Sahrens */ 12442676Seschrock if (ZFS_IS_VOLUME(zhp)) { 1245789Sahrens if (linktype) 12462082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 1247789Sahrens else 12482082Seschrock ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 1249789Sahrens } 1250789Sahrens 1251789Sahrens ret = zfs_iter_children(zhp, do_zvol, data); 1252789Sahrens 1253789Sahrens zfs_close(zhp); 1254789Sahrens return (ret); 1255789Sahrens } 1256789Sahrens 1257789Sahrens /* 1258789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1259789Sahrens */ 1260789Sahrens int 1261789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1262789Sahrens { 1263789Sahrens zfs_handle_t *zfp; 1264789Sahrens int ret; 1265789Sahrens 1266789Sahrens /* 1267789Sahrens * If the pool is unavailable, just return success. 1268789Sahrens */ 12692082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 12702082Seschrock zhp->zpool_name)) == NULL) 1271789Sahrens return (0); 1272789Sahrens 12732082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE); 1274789Sahrens 1275789Sahrens zfs_close(zfp); 1276789Sahrens return (ret); 1277789Sahrens } 1278789Sahrens 1279789Sahrens /* 1280789Sahrens * Iterate over all zvols in the poool and remove any minor nodes. 1281789Sahrens */ 1282789Sahrens int 1283789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1284789Sahrens { 1285789Sahrens zfs_handle_t *zfp; 1286789Sahrens int ret; 1287789Sahrens 1288789Sahrens /* 1289789Sahrens * If the pool is unavailable, just return success. 1290789Sahrens */ 12912082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 12922082Seschrock zhp->zpool_name)) == NULL) 1293789Sahrens return (0); 1294789Sahrens 12952082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE); 1296789Sahrens 1297789Sahrens zfs_close(zfp); 1298789Sahrens return (ret); 1299789Sahrens } 13001354Seschrock 13011354Seschrock /* 13021354Seschrock * Convert from a devid string to a path. 13031354Seschrock */ 13041354Seschrock static char * 13051354Seschrock devid_to_path(char *devid_str) 13061354Seschrock { 13071354Seschrock ddi_devid_t devid; 13081354Seschrock char *minor; 13091354Seschrock char *path; 13101354Seschrock devid_nmlist_t *list = NULL; 13111354Seschrock int ret; 13121354Seschrock 13131354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 13141354Seschrock return (NULL); 13151354Seschrock 13161354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 13171354Seschrock 13181354Seschrock devid_str_free(minor); 13191354Seschrock devid_free(devid); 13201354Seschrock 13211354Seschrock if (ret != 0) 13221354Seschrock return (NULL); 13231354Seschrock 13242082Seschrock if ((path = strdup(list[0].devname)) == NULL) 13252082Seschrock return (NULL); 13262082Seschrock 13271354Seschrock devid_free_nmlist(list); 13281354Seschrock 13291354Seschrock return (path); 13301354Seschrock } 13311354Seschrock 13321354Seschrock /* 13331354Seschrock * Convert from a path to a devid string. 13341354Seschrock */ 13351354Seschrock static char * 13361354Seschrock path_to_devid(const char *path) 13371354Seschrock { 13381354Seschrock int fd; 13391354Seschrock ddi_devid_t devid; 13401354Seschrock char *minor, *ret; 13411354Seschrock 13421354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 13431354Seschrock return (NULL); 13441354Seschrock 13451354Seschrock minor = NULL; 13461354Seschrock ret = NULL; 13471354Seschrock if (devid_get(fd, &devid) == 0) { 13481354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 13491354Seschrock ret = devid_str_encode(devid, minor); 13501354Seschrock if (minor != NULL) 13511354Seschrock devid_str_free(minor); 13521354Seschrock devid_free(devid); 13531354Seschrock } 13541354Seschrock (void) close(fd); 13551354Seschrock 13561354Seschrock return (ret); 13571354Seschrock } 13581354Seschrock 13591354Seschrock /* 13601354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 13611354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 13621354Seschrock * type 'zpool status', and we'll display the correct information anyway. 13631354Seschrock */ 13641354Seschrock static void 13651354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 13661354Seschrock { 13671354Seschrock zfs_cmd_t zc = { 0 }; 13681354Seschrock 13691354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13702676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 13711354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 13721544Seschrock &zc.zc_guid) == 0); 13731354Seschrock 13742082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 13751354Seschrock } 13761354Seschrock 13771354Seschrock /* 13781354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 13791354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 13801354Seschrock * We also check if this is a whole disk, in which case we strip off the 13811354Seschrock * trailing 's0' slice name. 13821354Seschrock * 13831354Seschrock * This routine is also responsible for identifying when disks have been 13841354Seschrock * reconfigured in a new location. The kernel will have opened the device by 13851354Seschrock * devid, but the path will still refer to the old location. To catch this, we 13861354Seschrock * first do a path -> devid translation (which is fast for the common case). If 13871354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 13881354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 13891354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 13901354Seschrock * of these checks. 13911354Seschrock */ 13921354Seschrock char * 13932082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 13941354Seschrock { 13951354Seschrock char *path, *devid; 13961544Seschrock uint64_t value; 13971544Seschrock char buf[64]; 13981354Seschrock 13991544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14001544Seschrock &value) == 0) { 14011544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14021544Seschrock &value) == 0); 14032856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 14042856Snd150628 (u_longlong_t)value); 14051544Seschrock path = buf; 14061544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 14071354Seschrock 14081354Seschrock if (zhp != NULL && 14091354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 14101354Seschrock /* 14111354Seschrock * Determine if the current path is correct. 14121354Seschrock */ 14131354Seschrock char *newdevid = path_to_devid(path); 14141354Seschrock 14151354Seschrock if (newdevid == NULL || 14161354Seschrock strcmp(devid, newdevid) != 0) { 14171354Seschrock char *newpath; 14181354Seschrock 14191354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 14201354Seschrock /* 14211354Seschrock * Update the path appropriately. 14221354Seschrock */ 14231354Seschrock set_path(zhp, nv, newpath); 14242082Seschrock if (nvlist_add_string(nv, 14252082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 14262082Seschrock verify(nvlist_lookup_string(nv, 14272082Seschrock ZPOOL_CONFIG_PATH, 14282082Seschrock &path) == 0); 14291354Seschrock free(newpath); 14301354Seschrock } 14311354Seschrock } 14321354Seschrock 14332082Seschrock if (newdevid) 14342082Seschrock devid_str_free(newdevid); 14351354Seschrock } 14361354Seschrock 14371354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 14381354Seschrock path += 9; 14391354Seschrock 14401354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 14411544Seschrock &value) == 0 && value) { 14422082Seschrock char *tmp = zfs_strdup(hdl, path); 14432082Seschrock if (tmp == NULL) 14442082Seschrock return (NULL); 14451354Seschrock tmp[strlen(path) - 2] = '\0'; 14461354Seschrock return (tmp); 14471354Seschrock } 14481354Seschrock } else { 14491354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 14502082Seschrock 14512082Seschrock /* 14522082Seschrock * If it's a raidz device, we need to stick in the parity level. 14532082Seschrock */ 14542082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 14552082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 14562082Seschrock &value) == 0); 14572082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 14582856Snd150628 (u_longlong_t)value); 14592082Seschrock path = buf; 14602082Seschrock } 14611354Seschrock } 14621354Seschrock 14632082Seschrock return (zfs_strdup(hdl, path)); 14641354Seschrock } 14651544Seschrock 14661544Seschrock static int 14671544Seschrock zbookmark_compare(const void *a, const void *b) 14681544Seschrock { 14691544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 14701544Seschrock } 14711544Seschrock 14721544Seschrock /* 14731544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 14741544Seschrock * caller. 14751544Seschrock */ 14761544Seschrock int 14771544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem) 14781544Seschrock { 14791544Seschrock zfs_cmd_t zc = { 0 }; 14801544Seschrock uint64_t count; 14812676Seschrock zbookmark_t *zb = NULL; 14822676Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 14831544Seschrock int i, j; 14841544Seschrock 14851544Seschrock if (zhp->zpool_error_log != NULL) { 14861544Seschrock *list = zhp->zpool_error_log; 14871544Seschrock *nelem = zhp->zpool_error_count; 14881544Seschrock return (0); 14891544Seschrock } 14901544Seschrock 14911544Seschrock /* 14921544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 14931544Seschrock * has increased, allocate more space and continue until we get the 14941544Seschrock * entire list. 14951544Seschrock */ 14961544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 14971544Seschrock &count) == 0); 14982676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 14992856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 15002082Seschrock return (-1); 15012676Seschrock zc.zc_nvlist_dst_size = count; 15021544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15031544Seschrock for (;;) { 15042082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 15052082Seschrock &zc) != 0) { 15062676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15071544Seschrock if (errno == ENOMEM) { 15082676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 15092082Seschrock zfs_alloc(zhp->zpool_hdl, 15102856Snd150628 zc.zc_nvlist_dst_size)) == (uintptr_t)NULL) 15112082Seschrock return (-1); 15121544Seschrock } else { 15131544Seschrock return (-1); 15141544Seschrock } 15151544Seschrock } else { 15161544Seschrock break; 15171544Seschrock } 15181544Seschrock } 15191544Seschrock 15201544Seschrock /* 15211544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 15221544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 15232676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 15241544Seschrock * _not_ copied as part of the process. So we point the start of our 15251544Seschrock * array appropriate and decrement the total number of elements. 15261544Seschrock */ 15272676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 15282676Seschrock zc.zc_nvlist_dst_size; 15292676Seschrock count -= zc.zc_nvlist_dst_size; 15302676Seschrock zc.zc_nvlist_dst = 0ULL; 15311544Seschrock 15321544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 15331544Seschrock 15341544Seschrock /* 15351544Seschrock * Count the number of unique elements 15361544Seschrock */ 15371544Seschrock j = 0; 15381544Seschrock for (i = 0; i < count; i++) { 15391544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15401544Seschrock sizeof (zbookmark_t)) == 0) 15411544Seschrock continue; 15421544Seschrock j++; 15431544Seschrock } 15441544Seschrock 15451544Seschrock /* 15461544Seschrock * If the user has only requested the number of items, return it now 15471544Seschrock * without bothering with the extra work. 15481544Seschrock */ 15491544Seschrock if (list == NULL) { 15501544Seschrock *nelem = j; 15512676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15521544Seschrock return (0); 15531544Seschrock } 15541544Seschrock 15551544Seschrock zhp->zpool_error_count = j; 15561544Seschrock 15571544Seschrock /* 15581544Seschrock * Allocate an array of nvlists to hold the results 15591544Seschrock */ 15602082Seschrock if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, 15612082Seschrock j * sizeof (nvlist_t *))) == NULL) { 15622676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 15632082Seschrock return (-1); 15642082Seschrock } 15651544Seschrock 15661544Seschrock /* 15671544Seschrock * Fill in the results with names from the kernel. 15681544Seschrock */ 15691544Seschrock j = 0; 15701544Seschrock for (i = 0; i < count; i++) { 15711544Seschrock char buf[64]; 15721544Seschrock nvlist_t *nv; 15731544Seschrock 15741544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15751544Seschrock sizeof (zbookmark_t)) == 0) 15761544Seschrock continue; 15771544Seschrock 15782676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 15792082Seschrock goto nomem; 15801544Seschrock 15811544Seschrock zc.zc_bookmark = zb[i]; 15822676Seschrock for (;;) { 15832676Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, 15842676Seschrock ZFS_IOC_BOOKMARK_NAME, &zc) != 0) { 15852676Seschrock if (errno == ENOMEM) { 15862676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) 15872676Seschrock != 0) { 15882676Seschrock zcmd_free_nvlists(&zc); 15892676Seschrock goto nomem; 15902676Seschrock } 15912676Seschrock 15922676Seschrock continue; 15932676Seschrock } else { 15942676Seschrock if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 15952676Seschrock 0) != 0) 15962676Seschrock goto nomem; 15972676Seschrock 15982676Seschrock zhp->zpool_error_log[j] = nv; 15992676Seschrock (void) snprintf(buf, sizeof (buf), 16002856Snd150628 "%llx", (longlong_t) 16012856Snd150628 zb[i].zb_objset); 16022676Seschrock if (nvlist_add_string(nv, 16032676Seschrock ZPOOL_ERR_DATASET, buf) != 0) 16042676Seschrock goto nomem; 16052676Seschrock (void) snprintf(buf, sizeof (buf), 16062856Snd150628 "%llx", (longlong_t) 16072856Snd150628 zb[i].zb_object); 16082676Seschrock if (nvlist_add_string(nv, 16092676Seschrock ZPOOL_ERR_OBJECT, buf) != 0) 16102676Seschrock goto nomem; 16112676Seschrock (void) snprintf(buf, sizeof (buf), 16122676Seschrock "lvl=%u blkid=%llu", 16132676Seschrock (int)zb[i].zb_level, 16142676Seschrock (long long)zb[i].zb_blkid); 16152676Seschrock if (nvlist_add_string(nv, 16162676Seschrock ZPOOL_ERR_RANGE, buf) != 0) 16172676Seschrock goto nomem; 16182676Seschrock } 16192676Seschrock } else { 16202676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, 16212676Seschrock &zhp->zpool_error_log[j]) != 0) { 16222676Seschrock zcmd_free_nvlists(&zc); 16232676Seschrock goto nomem; 16242676Seschrock } 16252676Seschrock } 16262676Seschrock 16272676Seschrock break; 16281544Seschrock } 16291544Seschrock 16302676Seschrock zcmd_free_nvlists(&zc); 16312676Seschrock 16321544Seschrock j++; 16331544Seschrock } 16341544Seschrock 16351544Seschrock *list = zhp->zpool_error_log; 16361544Seschrock *nelem = zhp->zpool_error_count; 16372676Seschrock free(zb); 16381544Seschrock 16391544Seschrock return (0); 16402082Seschrock 16412082Seschrock nomem: 16422676Seschrock free(zb); 16432676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 16442676Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 16452676Seschrock nvlist_free(zhp->zpool_error_log[i]); 16462082Seschrock free(zhp->zpool_error_log); 16472082Seschrock zhp->zpool_error_log = NULL; 16482082Seschrock return (no_memory(zhp->zpool_hdl)); 16491544Seschrock } 16501760Seschrock 16511760Seschrock /* 16521760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16531760Seschrock */ 16541760Seschrock int 16551760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16561760Seschrock { 16571760Seschrock zfs_cmd_t zc = { 0 }; 16582082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16591760Seschrock 16601760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16612082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 16622082Seschrock return (zpool_standard_error(hdl, errno, 16632082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 16642082Seschrock zhp->zpool_name)); 16651760Seschrock 16661760Seschrock return (0); 16671760Seschrock } 1668*2926Sek110237 1669*2926Sek110237 /* 1670*2926Sek110237 * Log command history. 1671*2926Sek110237 * 1672*2926Sek110237 * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE 1673*2926Sek110237 * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation 1674*2926Sek110237 * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the 1675*2926Sek110237 * poolname. 'argc' and 'argv' are used to construct the command string. 1676*2926Sek110237 */ 1677*2926Sek110237 void 1678*2926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path, 1679*2926Sek110237 boolean_t pool, boolean_t pool_create) 1680*2926Sek110237 { 1681*2926Sek110237 char cmd_buf[HIS_MAX_RECORD_LEN]; 1682*2926Sek110237 char *dspath; 1683*2926Sek110237 zfs_cmd_t zc = { 0 }; 1684*2926Sek110237 int i; 1685*2926Sek110237 1686*2926Sek110237 /* construct the command string */ 1687*2926Sek110237 (void) strcpy(cmd_buf, pool ? "zpool" : "zfs"); 1688*2926Sek110237 for (i = 0; i < argc; i++) { 1689*2926Sek110237 if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN) 1690*2926Sek110237 break; 1691*2926Sek110237 (void) strcat(cmd_buf, " "); 1692*2926Sek110237 (void) strcat(cmd_buf, argv[i]); 1693*2926Sek110237 } 1694*2926Sek110237 1695*2926Sek110237 /* figure out the poolname */ 1696*2926Sek110237 dspath = strpbrk(path, "/@"); 1697*2926Sek110237 if (dspath == NULL) { 1698*2926Sek110237 (void) strcpy(zc.zc_name, path); 1699*2926Sek110237 } else { 1700*2926Sek110237 (void) strncpy(zc.zc_name, path, dspath - path); 1701*2926Sek110237 zc.zc_name[dspath-path] = '\0'; 1702*2926Sek110237 } 1703*2926Sek110237 1704*2926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)cmd_buf; 1705*2926Sek110237 zc.zc_history_len = strlen(cmd_buf); 1706*2926Sek110237 1707*2926Sek110237 /* overloading zc_history_offset */ 1708*2926Sek110237 zc.zc_history_offset = pool_create; 1709*2926Sek110237 1710*2926Sek110237 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc); 1711*2926Sek110237 } 1712*2926Sek110237 1713*2926Sek110237 /* 1714*2926Sek110237 * Perform ioctl to get some command history of a pool. 1715*2926Sek110237 * 1716*2926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 1717*2926Sek110237 * logical offset of the history buffer to start reading from. 1718*2926Sek110237 * 1719*2926Sek110237 * Upon return, 'off' is the next logical offset to read from and 1720*2926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 1721*2926Sek110237 */ 1722*2926Sek110237 static int 1723*2926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 1724*2926Sek110237 { 1725*2926Sek110237 zfs_cmd_t zc = { 0 }; 1726*2926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 1727*2926Sek110237 1728*2926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1729*2926Sek110237 1730*2926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 1731*2926Sek110237 zc.zc_history_len = *len; 1732*2926Sek110237 zc.zc_history_offset = *off; 1733*2926Sek110237 1734*2926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 1735*2926Sek110237 switch (errno) { 1736*2926Sek110237 case EPERM: 1737*2926Sek110237 return (zfs_error(hdl, EZFS_PERM, dgettext(TEXT_DOMAIN, 1738*2926Sek110237 "cannot show history for pool '%s'"), 1739*2926Sek110237 zhp->zpool_name)); 1740*2926Sek110237 case ENOENT: 1741*2926Sek110237 return (zfs_error(hdl, EZFS_NOHISTORY, 1742*2926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 1743*2926Sek110237 "'%s'"), zhp->zpool_name)); 1744*2926Sek110237 default: 1745*2926Sek110237 return (zpool_standard_error(hdl, errno, 1746*2926Sek110237 dgettext(TEXT_DOMAIN, 1747*2926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 1748*2926Sek110237 } 1749*2926Sek110237 } 1750*2926Sek110237 1751*2926Sek110237 *len = zc.zc_history_len; 1752*2926Sek110237 *off = zc.zc_history_offset; 1753*2926Sek110237 1754*2926Sek110237 return (0); 1755*2926Sek110237 } 1756*2926Sek110237 1757*2926Sek110237 /* 1758*2926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 1759*2926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 1760*2926Sek110237 * processed as there wasn't a complete record. 1761*2926Sek110237 */ 1762*2926Sek110237 static int 1763*2926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 1764*2926Sek110237 nvlist_t ***records, uint_t *numrecords) 1765*2926Sek110237 { 1766*2926Sek110237 uint64_t reclen; 1767*2926Sek110237 nvlist_t *nv; 1768*2926Sek110237 int i; 1769*2926Sek110237 1770*2926Sek110237 while (bytes_read > sizeof (reclen)) { 1771*2926Sek110237 1772*2926Sek110237 /* get length of packed record (stored as little endian) */ 1773*2926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 1774*2926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 1775*2926Sek110237 1776*2926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 1777*2926Sek110237 break; 1778*2926Sek110237 1779*2926Sek110237 /* unpack record */ 1780*2926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 1781*2926Sek110237 return (ENOMEM); 1782*2926Sek110237 bytes_read -= sizeof (reclen) + reclen; 1783*2926Sek110237 buf += sizeof (reclen) + reclen; 1784*2926Sek110237 1785*2926Sek110237 /* add record to nvlist array */ 1786*2926Sek110237 (*numrecords)++; 1787*2926Sek110237 if (ISP2(*numrecords + 1)) { 1788*2926Sek110237 *records = realloc(*records, 1789*2926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 1790*2926Sek110237 } 1791*2926Sek110237 (*records)[*numrecords - 1] = nv; 1792*2926Sek110237 } 1793*2926Sek110237 1794*2926Sek110237 *leftover = bytes_read; 1795*2926Sek110237 return (0); 1796*2926Sek110237 } 1797*2926Sek110237 1798*2926Sek110237 #define HIS_BUF_LEN (128*1024) 1799*2926Sek110237 1800*2926Sek110237 /* 1801*2926Sek110237 * Retrieve the command history of a pool. 1802*2926Sek110237 */ 1803*2926Sek110237 int 1804*2926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 1805*2926Sek110237 { 1806*2926Sek110237 char buf[HIS_BUF_LEN]; 1807*2926Sek110237 uint64_t off = 0; 1808*2926Sek110237 nvlist_t **records = NULL; 1809*2926Sek110237 uint_t numrecords = 0; 1810*2926Sek110237 int err, i; 1811*2926Sek110237 1812*2926Sek110237 do { 1813*2926Sek110237 uint64_t bytes_read = sizeof (buf); 1814*2926Sek110237 uint64_t leftover; 1815*2926Sek110237 1816*2926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 1817*2926Sek110237 break; 1818*2926Sek110237 1819*2926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 1820*2926Sek110237 if (!bytes_read) 1821*2926Sek110237 break; 1822*2926Sek110237 1823*2926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 1824*2926Sek110237 &leftover, &records, &numrecords)) != 0) 1825*2926Sek110237 break; 1826*2926Sek110237 off -= leftover; 1827*2926Sek110237 1828*2926Sek110237 /* CONSTCOND */ 1829*2926Sek110237 } while (1); 1830*2926Sek110237 1831*2926Sek110237 if (!err) { 1832*2926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 1833*2926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 1834*2926Sek110237 records, numrecords) == 0); 1835*2926Sek110237 } 1836*2926Sek110237 for (i = 0; i < numrecords; i++) 1837*2926Sek110237 nvlist_free(records[i]); 1838*2926Sek110237 free(records); 1839*2926Sek110237 1840*2926Sek110237 return (err); 1841*2926Sek110237 } 1842