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 */ 21*2082Seschrock 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 */ 49*2082Seschrock static boolean_t 50*2082Seschrock 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)) { 68*2082Seschrock zfs_error_aux(hdl, 69*2082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 70*2082Seschrock return (B_FALSE); 711773Seschrock } 721773Seschrock 731773Seschrock 741773Seschrock if (ret != 0) { 75*2082Seschrock if (hdl != NULL) { 76789Sahrens switch (why) { 771003Slling case NAME_ERR_TOOLONG: 78*2082Seschrock zfs_error_aux(hdl, 791003Slling dgettext(TEXT_DOMAIN, "name is too long")); 801003Slling break; 811003Slling 82789Sahrens case NAME_ERR_INVALCHAR: 83*2082Seschrock zfs_error_aux(hdl, 84789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 85789Sahrens "'%c' in pool name"), what); 86789Sahrens break; 87789Sahrens 88789Sahrens case NAME_ERR_NOLETTER: 89*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 90*2082Seschrock "name must begin with a letter")); 91789Sahrens break; 92789Sahrens 93789Sahrens case NAME_ERR_RESERVED: 94*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 95*2082Seschrock "name is reserved")); 96789Sahrens break; 97789Sahrens 98789Sahrens case NAME_ERR_DISKLIKE: 99*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 100*2082Seschrock "pool name is reserved")); 101789Sahrens break; 102789Sahrens } 103789Sahrens } 104*2082Seschrock return (B_FALSE); 105789Sahrens } 106789Sahrens 107*2082Seschrock return (B_TRUE); 108789Sahrens } 109789Sahrens 110789Sahrens /* 111789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 112789Sahrens */ 113*2082Seschrock int 114789Sahrens set_pool_health(nvlist_t *config) 115789Sahrens { 116789Sahrens nvlist_t *nvroot; 117789Sahrens vdev_stat_t *vs; 118789Sahrens uint_t vsc; 119789Sahrens char *health; 120789Sahrens 121789Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 122789Sahrens &nvroot) == 0); 123789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 124789Sahrens (uint64_t **)&vs, &vsc) == 0); 125789Sahrens 126789Sahrens switch (vs->vs_state) { 127789Sahrens 128789Sahrens case VDEV_STATE_CLOSED: 129789Sahrens case VDEV_STATE_CANT_OPEN: 130789Sahrens case VDEV_STATE_OFFLINE: 131789Sahrens health = dgettext(TEXT_DOMAIN, "FAULTED"); 132789Sahrens break; 133789Sahrens 134789Sahrens case VDEV_STATE_DEGRADED: 135789Sahrens health = dgettext(TEXT_DOMAIN, "DEGRADED"); 136789Sahrens break; 137789Sahrens 138789Sahrens case VDEV_STATE_HEALTHY: 139789Sahrens health = dgettext(TEXT_DOMAIN, "ONLINE"); 140789Sahrens break; 141789Sahrens 142789Sahrens default: 143*2082Seschrock abort(); 144789Sahrens } 145789Sahrens 146*2082Seschrock return (nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, health)); 147789Sahrens } 148789Sahrens 149789Sahrens /* 150789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 151789Sahrens * state. 152789Sahrens */ 153789Sahrens zpool_handle_t * 154*2082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 155789Sahrens { 156789Sahrens zpool_handle_t *zhp; 157789Sahrens 158789Sahrens /* 159789Sahrens * Make sure the pool name is valid. 160789Sahrens */ 161*2082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 162*2082Seschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, 163*2082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 164*2082Seschrock pool); 165789Sahrens return (NULL); 166789Sahrens } 167789Sahrens 168*2082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 169*2082Seschrock return (NULL); 170789Sahrens 171*2082Seschrock zhp->zpool_hdl = hdl; 172789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 173789Sahrens 174*2082Seschrock if (zpool_refresh_stats(zhp) != 0) { 175*2082Seschrock if (errno == ENOENT || errno == EINVAL) { 176*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 177*2082Seschrock "no such pool")); 178*2082Seschrock (void) zfs_error(hdl, EZFS_NOENT, 179*2082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 180*2082Seschrock pool); 181789Sahrens free(zhp); 182789Sahrens return (NULL); 183789Sahrens } else { 184789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 185789Sahrens } 186789Sahrens } else { 187789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 188789Sahrens } 189789Sahrens 190789Sahrens return (zhp); 191789Sahrens } 192789Sahrens 193789Sahrens /* 194789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 195789Sahrens * the configuration cache may be out of date). 196789Sahrens */ 197789Sahrens zpool_handle_t * 198*2082Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool) 199789Sahrens { 200789Sahrens zpool_handle_t *zhp; 201789Sahrens 202*2082Seschrock if ((zhp = calloc(sizeof (zpool_handle_t), 1)) == NULL) 203*2082Seschrock return (NULL); 204789Sahrens 205*2082Seschrock zhp->zpool_hdl = hdl; 206789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 207789Sahrens 208*2082Seschrock if (zpool_refresh_stats(zhp) != 0) { 209*2082Seschrock if (errno == ENOENT || errno == EINVAL) { 210789Sahrens free(zhp); 211789Sahrens return (NULL); 212789Sahrens } else { 213789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 214789Sahrens } 215789Sahrens } else { 216789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 217789Sahrens } 218789Sahrens 219789Sahrens return (zhp); 220789Sahrens } 221789Sahrens 222789Sahrens /* 223789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 224789Sahrens * state. 225789Sahrens */ 226789Sahrens zpool_handle_t * 227*2082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 228789Sahrens { 229789Sahrens zpool_handle_t *zhp; 230789Sahrens 231*2082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 232789Sahrens return (NULL); 233789Sahrens 234789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 235*2082Seschrock (void) zfs_error(hdl, EZFS_POOLUNAVAIL, 236*2082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 237789Sahrens zpool_close(zhp); 238789Sahrens return (NULL); 239789Sahrens } 240789Sahrens 241789Sahrens return (zhp); 242789Sahrens } 243789Sahrens 244789Sahrens /* 245789Sahrens * Close the handle. Simply frees the memory associated with the handle. 246789Sahrens */ 247789Sahrens void 248789Sahrens zpool_close(zpool_handle_t *zhp) 249789Sahrens { 250789Sahrens if (zhp->zpool_config) 251789Sahrens nvlist_free(zhp->zpool_config); 252952Seschrock if (zhp->zpool_old_config) 253952Seschrock nvlist_free(zhp->zpool_old_config); 2541544Seschrock if (zhp->zpool_error_log) { 2551544Seschrock int i; 2561544Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 257*2082Seschrock nvlist_free(zhp->zpool_error_log[i]); 2581544Seschrock free(zhp->zpool_error_log); 2591544Seschrock } 260789Sahrens free(zhp); 261789Sahrens } 262789Sahrens 263789Sahrens /* 264789Sahrens * Return the name of the pool. 265789Sahrens */ 266789Sahrens const char * 267789Sahrens zpool_get_name(zpool_handle_t *zhp) 268789Sahrens { 269789Sahrens return (zhp->zpool_name); 270789Sahrens } 271789Sahrens 272789Sahrens /* 273789Sahrens * Return the GUID of the pool. 274789Sahrens */ 275789Sahrens uint64_t 276789Sahrens zpool_get_guid(zpool_handle_t *zhp) 277789Sahrens { 278789Sahrens uint64_t guid; 279789Sahrens 280789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 281789Sahrens &guid) == 0); 282789Sahrens return (guid); 283789Sahrens } 284789Sahrens 285789Sahrens /* 286*2082Seschrock * Return the version of the pool. 287*2082Seschrock */ 288*2082Seschrock uint64_t 289*2082Seschrock zpool_get_version(zpool_handle_t *zhp) 290*2082Seschrock { 291*2082Seschrock uint64_t version; 292*2082Seschrock 293*2082Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION, 294*2082Seschrock &version) == 0); 295*2082Seschrock 296*2082Seschrock return (version); 297*2082Seschrock } 298*2082Seschrock 299*2082Seschrock /* 300789Sahrens * Return the amount of space currently consumed by the pool. 301789Sahrens */ 302789Sahrens uint64_t 303789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 304789Sahrens { 305789Sahrens nvlist_t *nvroot; 306789Sahrens vdev_stat_t *vs; 307789Sahrens uint_t vsc; 308789Sahrens 309789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 310789Sahrens &nvroot) == 0); 311789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 312789Sahrens (uint64_t **)&vs, &vsc) == 0); 313789Sahrens 314789Sahrens return (vs->vs_alloc); 315789Sahrens } 316789Sahrens 317789Sahrens /* 318789Sahrens * Return the total space in the pool. 319789Sahrens */ 320789Sahrens uint64_t 321789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 322789Sahrens { 323789Sahrens nvlist_t *nvroot; 324789Sahrens vdev_stat_t *vs; 325789Sahrens uint_t vsc; 326789Sahrens 327789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 328789Sahrens &nvroot) == 0); 329789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 330789Sahrens (uint64_t **)&vs, &vsc) == 0); 331789Sahrens 332789Sahrens return (vs->vs_space); 333789Sahrens } 334789Sahrens 335789Sahrens /* 336789Sahrens * Return the alternate root for this pool, if any. 337789Sahrens */ 338789Sahrens int 339789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 340789Sahrens { 341789Sahrens zfs_cmd_t zc = { 0 }; 342789Sahrens 343789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 344*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3451544Seschrock zc.zc_root[0] == '\0') 346789Sahrens return (-1); 347789Sahrens 3481544Seschrock (void) strlcpy(buf, zc.zc_root, buflen); 349789Sahrens 350789Sahrens return (0); 351789Sahrens } 352789Sahrens 353789Sahrens /* 354789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 355789Sahrens */ 356789Sahrens int 357789Sahrens zpool_get_state(zpool_handle_t *zhp) 358789Sahrens { 359789Sahrens return (zhp->zpool_state); 360789Sahrens } 361789Sahrens 362789Sahrens /* 363789Sahrens * Create the named pool, using the provided vdev list. It is assumed 364789Sahrens * that the consumer has already validated the contents of the nvlist, so we 365789Sahrens * don't have to worry about error semantics. 366789Sahrens */ 367789Sahrens int 368*2082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 369*2082Seschrock const char *altroot) 370789Sahrens { 371789Sahrens zfs_cmd_t zc = { 0 }; 372789Sahrens char *packed; 373789Sahrens size_t len; 374*2082Seschrock char msg[1024]; 375*2082Seschrock 376*2082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 377*2082Seschrock "cannot create '%s'"), pool); 378789Sahrens 379*2082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 380*2082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 381*2082Seschrock 382*2082Seschrock if (altroot != NULL && altroot[0] != '/') 383*2082Seschrock return (zfs_error(hdl, EZFS_BADPATH, 384*2082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); 385789Sahrens 386*2082Seschrock if (nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) != 0) 387*2082Seschrock return (no_memory(hdl)); 388*2082Seschrock 389*2082Seschrock if ((packed = zfs_alloc(hdl, len)) == NULL) 390789Sahrens return (-1); 391789Sahrens 392*2082Seschrock if (nvlist_pack(nvroot, &packed, &len, 393*2082Seschrock NV_ENCODE_NATIVE, 0) != 0) { 394*2082Seschrock free(packed); 395*2082Seschrock return (no_memory(hdl)); 396*2082Seschrock } 397789Sahrens 398789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 399789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 400789Sahrens zc.zc_config_src_size = len; 401789Sahrens 402789Sahrens if (altroot != NULL) 403789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 404789Sahrens 405*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 406*2082Seschrock free(packed); 407*2082Seschrock 408789Sahrens switch (errno) { 409789Sahrens case EBUSY: 410789Sahrens /* 411789Sahrens * This can happen if the user has specified the same 412789Sahrens * device multiple times. We can't reliably detect this 413789Sahrens * until we try to add it and see we already have a 414789Sahrens * label. 415789Sahrens */ 416*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 417*2082Seschrock "one or more vdevs refer to the same device")); 418*2082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 419789Sahrens 420789Sahrens case EOVERFLOW: 421789Sahrens /* 422*2082Seschrock * This occurs when one of the devices is below 423789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 424789Sahrens * device was the problem device since there's no 425789Sahrens * reliable way to determine device size from userland. 426789Sahrens */ 427789Sahrens { 428789Sahrens char buf[64]; 429789Sahrens 430789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 431789Sahrens 432*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 433*2082Seschrock "one or more devices is less than the " 434*2082Seschrock "minimum size (%s)"), buf); 435789Sahrens } 436*2082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 437789Sahrens 438789Sahrens case ENOSPC: 439*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 440*2082Seschrock "one or more devices is out of space")); 441*2082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 442789Sahrens 443789Sahrens default: 444*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 445789Sahrens } 446789Sahrens } 447789Sahrens 448789Sahrens free(packed); 449789Sahrens 450789Sahrens /* 451789Sahrens * If this is an alternate root pool, then we automatically set the 452789Sahrens * moutnpoint of the root dataset to be '/'. 453789Sahrens */ 454789Sahrens if (altroot != NULL) { 455789Sahrens zfs_handle_t *zhp; 456789Sahrens 457*2082Seschrock verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); 458789Sahrens verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0); 459789Sahrens 460789Sahrens zfs_close(zhp); 461789Sahrens } 462789Sahrens 463789Sahrens return (0); 464789Sahrens } 465789Sahrens 466789Sahrens /* 467789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 468789Sahrens * datasets left in the pool. 469789Sahrens */ 470789Sahrens int 471789Sahrens zpool_destroy(zpool_handle_t *zhp) 472789Sahrens { 473789Sahrens zfs_cmd_t zc = { 0 }; 474789Sahrens zfs_handle_t *zfp = NULL; 475*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 476*2082Seschrock char msg[1024]; 477789Sahrens 478789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 479*2082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 480*2082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 481789Sahrens return (-1); 482789Sahrens 483789Sahrens if (zpool_remove_zvol_links(zhp) != NULL) 484789Sahrens return (-1); 485789Sahrens 486789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 487789Sahrens 488*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 489*2082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 490*2082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 491789Sahrens 492*2082Seschrock if (errno == EROFS) { 493*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 494*2082Seschrock "one or more devices is read only")); 495*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 496*2082Seschrock } else { 497*2082Seschrock (void) zpool_standard_error(hdl, errno, msg); 498789Sahrens } 499789Sahrens 500789Sahrens if (zfp) 501789Sahrens zfs_close(zfp); 502789Sahrens return (-1); 503789Sahrens } 504789Sahrens 505789Sahrens if (zfp) { 506789Sahrens remove_mountpoint(zfp); 507789Sahrens zfs_close(zfp); 508789Sahrens } 509789Sahrens 510789Sahrens return (0); 511789Sahrens } 512789Sahrens 513789Sahrens /* 514789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 515789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 516789Sahrens */ 517789Sahrens int 518789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 519789Sahrens { 520789Sahrens char *packed; 521789Sahrens size_t len; 522789Sahrens zfs_cmd_t zc; 523*2082Seschrock int ret; 524*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 525*2082Seschrock char msg[1024]; 526*2082Seschrock nvlist_t **spares; 527*2082Seschrock uint_t nspares; 528*2082Seschrock 529*2082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 530*2082Seschrock "cannot add to '%s'"), zhp->zpool_name); 531*2082Seschrock 532*2082Seschrock if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && 533*2082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 534*2082Seschrock &spares, &nspares) == 0) { 535*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 536*2082Seschrock "upgraded to add hot spares")); 537*2082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 538*2082Seschrock } 539789Sahrens 540789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 541789Sahrens 542*2082Seschrock if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL) 543*2082Seschrock return (-1); 544789Sahrens 545789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 546789Sahrens 547789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 548789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 549789Sahrens zc.zc_config_src_size = len; 550789Sahrens 551*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 552789Sahrens switch (errno) { 553789Sahrens case EBUSY: 554789Sahrens /* 555789Sahrens * This can happen if the user has specified the same 556789Sahrens * device multiple times. We can't reliably detect this 557789Sahrens * until we try to add it and see we already have a 558789Sahrens * label. 559789Sahrens */ 560*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 561*2082Seschrock "one or more vdevs refer to the same device")); 562*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 563789Sahrens break; 564789Sahrens 565789Sahrens case EOVERFLOW: 566789Sahrens /* 567789Sahrens * This occurrs when one of the devices is below 568789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 569789Sahrens * device was the problem device since there's no 570789Sahrens * reliable way to determine device size from userland. 571789Sahrens */ 572789Sahrens { 573789Sahrens char buf[64]; 574789Sahrens 575789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 576789Sahrens 577*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 578*2082Seschrock "device is less than the minimum " 579*2082Seschrock "size (%s)"), buf); 580789Sahrens } 581*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 582*2082Seschrock break; 583*2082Seschrock 584*2082Seschrock case ENOTSUP: 585*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 586*2082Seschrock "pool must be upgraded to add raidz2 vdevs")); 587*2082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 588789Sahrens break; 589789Sahrens 590789Sahrens default: 591*2082Seschrock (void) zpool_standard_error(hdl, errno, msg); 592789Sahrens } 593789Sahrens 594*2082Seschrock ret = -1; 595*2082Seschrock } else { 596*2082Seschrock ret = 0; 597789Sahrens } 598789Sahrens 599789Sahrens free(packed); 600789Sahrens 601*2082Seschrock return (ret); 602789Sahrens } 603789Sahrens 604789Sahrens /* 605789Sahrens * Exports the pool from the system. The caller must ensure that there are no 606789Sahrens * mounted datasets in the pool. 607789Sahrens */ 608789Sahrens int 609789Sahrens zpool_export(zpool_handle_t *zhp) 610789Sahrens { 611789Sahrens zfs_cmd_t zc = { 0 }; 612789Sahrens 613789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 614789Sahrens return (-1); 615789Sahrens 616789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 617789Sahrens 618*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) 619*2082Seschrock return (zpool_standard_error(zhp->zpool_hdl, errno, 620*2082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 621*2082Seschrock zhp->zpool_name)); 622789Sahrens 623789Sahrens return (0); 624789Sahrens } 625789Sahrens 626789Sahrens /* 627789Sahrens * Import the given pool using the known configuration. The configuration 628789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 629789Sahrens * parameters control whether the pool is imported with a different name or with 630789Sahrens * an alternate root, respectively. 631789Sahrens */ 632789Sahrens int 633*2082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 634*2082Seschrock const char *altroot) 635789Sahrens { 636789Sahrens zfs_cmd_t zc; 637789Sahrens char *packed; 638789Sahrens size_t len; 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) { 647*2082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 648*2082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, 649*2082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 650*2082Seschrock newname)); 651789Sahrens thename = (char *)newname; 652789Sahrens } else { 653789Sahrens thename = origname; 654789Sahrens } 655789Sahrens 656*2082Seschrock if (altroot != NULL && altroot[0] != '/') 657*2082Seschrock return (zfs_error(hdl, EZFS_BADPATH, 658*2082Seschrock dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), 659*2082Seschrock altroot)); 660789Sahrens 661789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 662789Sahrens 663789Sahrens if (altroot != NULL) 664789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 665789Sahrens else 666789Sahrens zc.zc_root[0] = '\0'; 667789Sahrens 668789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 6691544Seschrock &zc.zc_guid) == 0); 670789Sahrens 671789Sahrens verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0); 672789Sahrens 673*2082Seschrock if ((packed = zfs_alloc(hdl, len)) == NULL) 674*2082Seschrock return (-1); 675789Sahrens 676789Sahrens verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 677789Sahrens 678789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 679789Sahrens zc.zc_config_src_size = len; 680789Sahrens 681789Sahrens ret = 0; 682*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 683789Sahrens char desc[1024]; 684789Sahrens if (newname == NULL) 685789Sahrens (void) snprintf(desc, sizeof (desc), 686789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 687789Sahrens thename); 688789Sahrens else 689789Sahrens (void) snprintf(desc, sizeof (desc), 690789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 691789Sahrens origname, thename); 692789Sahrens 693789Sahrens switch (errno) { 6941544Seschrock case ENOTSUP: 6951544Seschrock /* 6961544Seschrock * Unsupported version. 6971544Seschrock */ 698*2082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 6991544Seschrock break; 7001544Seschrock 701789Sahrens default: 702*2082Seschrock (void) zpool_standard_error(hdl, errno, desc); 703789Sahrens } 704789Sahrens 705789Sahrens ret = -1; 706789Sahrens } else { 707789Sahrens zpool_handle_t *zhp; 708789Sahrens /* 709789Sahrens * This should never fail, but play it safe anyway. 710789Sahrens */ 711*2082Seschrock if ((zhp = zpool_open_silent(hdl, thename)) != NULL) { 712789Sahrens ret = zpool_create_zvol_links(zhp); 713789Sahrens zpool_close(zhp); 714789Sahrens } 715789Sahrens } 716789Sahrens 717789Sahrens free(packed); 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]; 729*2082Seschrock 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 734*2082Seschrock 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 740*2082Seschrock if (errno == EBUSY) 741*2082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 742*2082Seschrock else 743*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 744789Sahrens } 745789Sahrens 746*2082Seschrock static nvlist_t * 747*2082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 748*2082Seschrock boolean_t *isspare) 7491544Seschrock { 7501544Seschrock uint_t c, children; 7511544Seschrock nvlist_t **child; 752*2082Seschrock uint64_t theguid, present; 7531544Seschrock char *path; 7541544Seschrock uint64_t wholedisk = 0; 755*2082Seschrock nvlist_t *ret; 7561544Seschrock 757*2082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 7581544Seschrock 7591544Seschrock if (search == NULL && 7601544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 7611544Seschrock /* 7621544Seschrock * If the device has never been present since import, the only 7631544Seschrock * reliable way to match the vdev is by GUID. 7641544Seschrock */ 765*2082Seschrock if (theguid == guid) 766*2082Seschrock return (nv); 7671544Seschrock } else if (search != NULL && 7681544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 7691544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 7701544Seschrock &wholedisk); 7711544Seschrock if (wholedisk) { 7721544Seschrock /* 7731544Seschrock * For whole disks, the internal path has 's0', but the 7741544Seschrock * path passed in by the user doesn't. 7751544Seschrock */ 7761544Seschrock if (strlen(search) == strlen(path) - 2 && 7771544Seschrock strncmp(search, path, strlen(search)) == 0) 778*2082Seschrock return (nv); 7791544Seschrock } else if (strcmp(search, path) == 0) { 780*2082Seschrock return (nv); 7811544Seschrock } 7821544Seschrock } 7831544Seschrock 7841544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 7851544Seschrock &child, &children) != 0) 786*2082Seschrock return (NULL); 7871544Seschrock 7881544Seschrock for (c = 0; c < children; c++) 789*2082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 790*2082Seschrock isspare)) != NULL) 7911544Seschrock return (ret); 7921544Seschrock 793*2082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 794*2082Seschrock &child, &children) == 0) { 795*2082Seschrock for (c = 0; c < children; c++) { 796*2082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 797*2082Seschrock isspare)) != NULL) { 798*2082Seschrock *isspare = B_TRUE; 799*2082Seschrock return (ret); 800*2082Seschrock } 801*2082Seschrock } 802*2082Seschrock } 803*2082Seschrock 804*2082Seschrock return (NULL); 8051544Seschrock } 8061544Seschrock 807*2082Seschrock nvlist_t * 808*2082Seschrock zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *isspare) 8091544Seschrock { 8101544Seschrock char buf[MAXPATHLEN]; 8111544Seschrock const char *search; 8121544Seschrock char *end; 8131544Seschrock nvlist_t *nvroot; 8141544Seschrock uint64_t guid; 8151544Seschrock 8161613Seschrock guid = strtoull(path, &end, 10); 8171544Seschrock if (guid != 0 && *end == '\0') { 8181544Seschrock search = NULL; 8191544Seschrock } else if (path[0] != '/') { 8201544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 8211544Seschrock search = buf; 8221544Seschrock } else { 8231544Seschrock search = path; 8241544Seschrock } 8251544Seschrock 8261544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 8271544Seschrock &nvroot) == 0); 8281544Seschrock 829*2082Seschrock *isspare = B_FALSE; 830*2082Seschrock return (vdev_to_nvlist_iter(nvroot, search, guid, isspare)); 8311544Seschrock } 8321544Seschrock 833789Sahrens /* 834789Sahrens * Bring the specified vdev online 835789Sahrens */ 836789Sahrens int 837789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 838789Sahrens { 839789Sahrens zfs_cmd_t zc = { 0 }; 840789Sahrens char msg[1024]; 841*2082Seschrock nvlist_t *tgt; 842*2082Seschrock boolean_t isspare; 843*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 844789Sahrens 8451544Seschrock (void) snprintf(msg, sizeof (msg), 8461544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 847789Sahrens 8481544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 849*2082Seschrock if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == NULL) 850*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 851789Sahrens 852*2082Seschrock if (isspare) 853*2082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 854*2082Seschrock 855*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 856*2082Seschrock 857*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 8581544Seschrock return (0); 859789Sahrens 860*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 861789Sahrens } 862789Sahrens 863789Sahrens /* 864789Sahrens * Take the specified vdev offline 865789Sahrens */ 866789Sahrens int 8671485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 868789Sahrens { 869789Sahrens zfs_cmd_t zc = { 0 }; 870789Sahrens char msg[1024]; 871*2082Seschrock nvlist_t *tgt; 872*2082Seschrock boolean_t isspare; 873*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 874789Sahrens 8751544Seschrock (void) snprintf(msg, sizeof (msg), 8761544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 8771544Seschrock 878789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 879*2082Seschrock if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == NULL) 880*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 881*2082Seschrock 882*2082Seschrock if (isspare) 883*2082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 884*2082Seschrock 885*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 886789Sahrens 8871485Slling zc.zc_cookie = istmp; 8881485Slling 889*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 890789Sahrens return (0); 891789Sahrens 892789Sahrens switch (errno) { 893*2082Seschrock case EBUSY: 894789Sahrens 895789Sahrens /* 896789Sahrens * There are no other replicas of this device. 897789Sahrens */ 898*2082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 899*2082Seschrock 900*2082Seschrock default: 901*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 902*2082Seschrock } 903*2082Seschrock } 904789Sahrens 905*2082Seschrock /* 906*2082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 907*2082Seschrock * a hot spare. 908*2082Seschrock */ 909*2082Seschrock static boolean_t 910*2082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 911*2082Seschrock { 912*2082Seschrock nvlist_t **child; 913*2082Seschrock uint_t c, children; 914*2082Seschrock char *type; 915*2082Seschrock 916*2082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 917*2082Seschrock &children) == 0) { 918*2082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 919*2082Seschrock &type) == 0); 920*2082Seschrock 921*2082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 922*2082Seschrock children == 2 && child[which] == tgt) 923*2082Seschrock return (B_TRUE); 924*2082Seschrock 925*2082Seschrock for (c = 0; c < children; c++) 926*2082Seschrock if (is_replacing_spare(child[c], tgt, which)) 927*2082Seschrock return (B_TRUE); 928789Sahrens } 929*2082Seschrock 930*2082Seschrock return (B_FALSE); 931789Sahrens } 932789Sahrens 933789Sahrens /* 934789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 935789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 936789Sahrens */ 937789Sahrens int 938789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 939789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 940789Sahrens { 941789Sahrens zfs_cmd_t zc = { 0 }; 942789Sahrens char msg[1024]; 943789Sahrens char *packed; 944789Sahrens int ret; 945789Sahrens size_t len; 946*2082Seschrock nvlist_t *tgt; 947*2082Seschrock boolean_t isspare; 948*2082Seschrock uint64_t val; 949*2082Seschrock char *path; 950*2082Seschrock nvlist_t **child; 951*2082Seschrock uint_t children; 952*2082Seschrock nvlist_t *config_root; 953*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 954789Sahrens 9551544Seschrock if (replacing) 9561544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9571544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 9581544Seschrock else 9591544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9601544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 9611544Seschrock 962789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 963*2082Seschrock if ((tgt = zpool_find_vdev(zhp, old_disk, &isspare)) == 0) 964*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 965*2082Seschrock 966*2082Seschrock if (isspare) 967*2082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 968*2082Seschrock 969*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 970*2082Seschrock zc.zc_cookie = replacing; 971*2082Seschrock 972*2082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 973*2082Seschrock &child, &children) != 0 || children != 1) { 974*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 975*2082Seschrock "new device must be a single disk")); 976*2082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 9771544Seschrock } 978*2082Seschrock 979*2082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 980*2082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 981*2082Seschrock 982*2082Seschrock /* 983*2082Seschrock * If the target is a hot spare that has been swapped in, we can only 984*2082Seschrock * replace it with another hot spare. 985*2082Seschrock */ 986*2082Seschrock if (replacing && 987*2082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 988*2082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 989*2082Seschrock (zpool_find_vdev(zhp, path, &isspare) == NULL || !isspare) && 990*2082Seschrock is_replacing_spare(config_root, tgt, 1)) { 991*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 992*2082Seschrock "can only be replaced by another hot spare")); 993*2082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 994*2082Seschrock } 995*2082Seschrock 996*2082Seschrock /* 997*2082Seschrock * If we are attempting to replace a spare, it canot be applied to an 998*2082Seschrock * already spared device. 999*2082Seschrock */ 1000*2082Seschrock if (replacing && 1001*2082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 1002*2082Seschrock zpool_find_vdev(zhp, path, &isspare) != NULL && isspare && 1003*2082Seschrock is_replacing_spare(config_root, tgt, 0)) { 1004*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1005*2082Seschrock "device has already been replaced with a spare")); 1006*2082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 1007*2082Seschrock } 1008789Sahrens 1009789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 1010789Sahrens 1011*2082Seschrock if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL) 1012*2082Seschrock return (-1); 1013789Sahrens 1014789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 1015789Sahrens 1016789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 1017789Sahrens zc.zc_config_src_size = len; 1018789Sahrens 1019*2082Seschrock ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 1020789Sahrens 1021789Sahrens free(packed); 1022789Sahrens 1023789Sahrens if (ret == 0) 1024789Sahrens return (0); 1025789Sahrens 1026789Sahrens switch (errno) { 10271544Seschrock case ENOTSUP: 1028789Sahrens /* 1029789Sahrens * Can't attach to or replace this type of vdev. 1030789Sahrens */ 1031789Sahrens if (replacing) 1032*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1033*2082Seschrock "cannot replace a replacing device")); 1034789Sahrens else 1035*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1036*2082Seschrock "can only attach to mirrors and top-level " 1037*2082Seschrock "disks")); 1038*2082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1039789Sahrens break; 1040789Sahrens 10411544Seschrock case EINVAL: 1042789Sahrens /* 1043789Sahrens * The new device must be a single disk. 1044789Sahrens */ 1045*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1046*2082Seschrock "new device must be a single disk")); 1047*2082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1048789Sahrens break; 1049789Sahrens 10501544Seschrock case EBUSY: 1051*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 1052*2082Seschrock new_disk); 1053*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1054789Sahrens break; 1055789Sahrens 10561544Seschrock case EOVERFLOW: 1057789Sahrens /* 1058789Sahrens * The new device is too small. 1059789Sahrens */ 1060*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1061*2082Seschrock "device is too small")); 1062*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1063789Sahrens break; 1064789Sahrens 10651544Seschrock case EDOM: 1066789Sahrens /* 1067789Sahrens * The new device has a different alignment requirement. 1068789Sahrens */ 1069*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1070*2082Seschrock "devices have different sector alignment")); 1071*2082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1072789Sahrens break; 1073789Sahrens 10741544Seschrock case ENAMETOOLONG: 1075789Sahrens /* 1076789Sahrens * The resulting top-level vdev spec won't fit in the label. 1077789Sahrens */ 1078*2082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1079789Sahrens break; 1080789Sahrens 10811544Seschrock default: 1082*2082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1083789Sahrens } 1084789Sahrens 1085*2082Seschrock return (-1); 1086789Sahrens } 1087789Sahrens 1088789Sahrens /* 1089789Sahrens * Detach the specified device. 1090789Sahrens */ 1091789Sahrens int 1092789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1093789Sahrens { 1094789Sahrens zfs_cmd_t zc = { 0 }; 1095789Sahrens char msg[1024]; 1096*2082Seschrock nvlist_t *tgt; 1097*2082Seschrock boolean_t isspare; 1098*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1099789Sahrens 11001544Seschrock (void) snprintf(msg, sizeof (msg), 11011544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11021544Seschrock 1103789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1104*2082Seschrock if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0) 1105*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1106789Sahrens 1107*2082Seschrock if (isspare) 1108*2082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 1109*2082Seschrock 1110*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 1111*2082Seschrock 1112*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1113789Sahrens return (0); 1114789Sahrens 1115789Sahrens switch (errno) { 1116789Sahrens 11171544Seschrock case ENOTSUP: 1118789Sahrens /* 1119789Sahrens * Can't detach from this type of vdev. 1120789Sahrens */ 1121*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 1122*2082Seschrock "applicable to mirror and replacing vdevs")); 1123*2082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1124789Sahrens break; 1125789Sahrens 11261544Seschrock case EBUSY: 1127789Sahrens /* 1128789Sahrens * There are no other replicas of this device. 1129789Sahrens */ 1130*2082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1131789Sahrens break; 1132789Sahrens 11331544Seschrock default: 1134*2082Seschrock (void) zpool_standard_error(hdl, errno, msg); 11351544Seschrock } 11361544Seschrock 1137*2082Seschrock return (-1); 1138*2082Seschrock } 1139*2082Seschrock 1140*2082Seschrock /* 1141*2082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 1142*2082Seschrock */ 1143*2082Seschrock int 1144*2082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 1145*2082Seschrock { 1146*2082Seschrock zfs_cmd_t zc = { 0 }; 1147*2082Seschrock char msg[1024]; 1148*2082Seschrock nvlist_t *tgt; 1149*2082Seschrock boolean_t isspare; 1150*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1151*2082Seschrock 1152*2082Seschrock (void) snprintf(msg, sizeof (msg), 1153*2082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 1154*2082Seschrock 1155*2082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1156*2082Seschrock if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0) 1157*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1158*2082Seschrock 1159*2082Seschrock if (!isspare) { 1160*2082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1161*2082Seschrock "only hot spares can be removed")); 1162*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1163*2082Seschrock } 1164*2082Seschrock 1165*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 1166*2082Seschrock 1167*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 1168*2082Seschrock return (0); 1169*2082Seschrock 1170*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 11711544Seschrock } 11721544Seschrock 11731544Seschrock /* 11741544Seschrock * Clear the errors for the pool, or the particular device if specified. 11751544Seschrock */ 11761544Seschrock int 11771544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 11781544Seschrock { 11791544Seschrock zfs_cmd_t zc = { 0 }; 11801544Seschrock char msg[1024]; 1181*2082Seschrock nvlist_t *tgt; 1182*2082Seschrock boolean_t isspare; 1183*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 11841544Seschrock 11851544Seschrock if (path) 11861544Seschrock (void) snprintf(msg, sizeof (msg), 11871544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 11881544Seschrock zc.zc_prop_value); 11891544Seschrock else 11901544Seschrock (void) snprintf(msg, sizeof (msg), 11911544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 11921544Seschrock zhp->zpool_name); 11931544Seschrock 11941544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1195*2082Seschrock if (path) { 1196*2082Seschrock if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0) 1197*2082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1198*2082Seschrock 1199*2082Seschrock if (isspare) 1200*2082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 1201*2082Seschrock 1202*2082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 1203*2082Seschrock &zc.zc_guid) == 0); 12041544Seschrock } 12051544Seschrock 1206*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 12071544Seschrock return (0); 12081544Seschrock 1209*2082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1210789Sahrens } 1211789Sahrens 1212789Sahrens static int 1213789Sahrens do_zvol(zfs_handle_t *zhp, void *data) 1214789Sahrens { 1215789Sahrens int linktype = (int)(uintptr_t)data; 1216789Sahrens int ret; 1217789Sahrens 1218789Sahrens /* 1219789Sahrens * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we 1220789Sahrens * correctly handle snapshots of volumes. 1221789Sahrens */ 1222789Sahrens if (zhp->zfs_volblocksize != 0) { 1223789Sahrens if (linktype) 1224*2082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 1225789Sahrens else 1226*2082Seschrock ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 1227789Sahrens } 1228789Sahrens 1229789Sahrens ret = zfs_iter_children(zhp, do_zvol, data); 1230789Sahrens 1231789Sahrens zfs_close(zhp); 1232789Sahrens return (ret); 1233789Sahrens } 1234789Sahrens 1235789Sahrens /* 1236789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1237789Sahrens */ 1238789Sahrens int 1239789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1240789Sahrens { 1241789Sahrens zfs_handle_t *zfp; 1242789Sahrens int ret; 1243789Sahrens 1244789Sahrens /* 1245789Sahrens * If the pool is unavailable, just return success. 1246789Sahrens */ 1247*2082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 1248*2082Seschrock zhp->zpool_name)) == NULL) 1249789Sahrens return (0); 1250789Sahrens 1251*2082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE); 1252789Sahrens 1253789Sahrens zfs_close(zfp); 1254789Sahrens return (ret); 1255789Sahrens } 1256789Sahrens 1257789Sahrens /* 1258789Sahrens * Iterate over all zvols in the poool and remove any minor nodes. 1259789Sahrens */ 1260789Sahrens int 1261789Sahrens zpool_remove_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 */ 1269*2082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 1270*2082Seschrock zhp->zpool_name)) == NULL) 1271789Sahrens return (0); 1272789Sahrens 1273*2082Seschrock ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE); 1274789Sahrens 1275789Sahrens zfs_close(zfp); 1276789Sahrens return (ret); 1277789Sahrens } 12781354Seschrock 12791354Seschrock /* 12801354Seschrock * Convert from a devid string to a path. 12811354Seschrock */ 12821354Seschrock static char * 12831354Seschrock devid_to_path(char *devid_str) 12841354Seschrock { 12851354Seschrock ddi_devid_t devid; 12861354Seschrock char *minor; 12871354Seschrock char *path; 12881354Seschrock devid_nmlist_t *list = NULL; 12891354Seschrock int ret; 12901354Seschrock 12911354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 12921354Seschrock return (NULL); 12931354Seschrock 12941354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 12951354Seschrock 12961354Seschrock devid_str_free(minor); 12971354Seschrock devid_free(devid); 12981354Seschrock 12991354Seschrock if (ret != 0) 13001354Seschrock return (NULL); 13011354Seschrock 1302*2082Seschrock if ((path = strdup(list[0].devname)) == NULL) 1303*2082Seschrock return (NULL); 1304*2082Seschrock 13051354Seschrock devid_free_nmlist(list); 13061354Seschrock 13071354Seschrock return (path); 13081354Seschrock } 13091354Seschrock 13101354Seschrock /* 13111354Seschrock * Convert from a path to a devid string. 13121354Seschrock */ 13131354Seschrock static char * 13141354Seschrock path_to_devid(const char *path) 13151354Seschrock { 13161354Seschrock int fd; 13171354Seschrock ddi_devid_t devid; 13181354Seschrock char *minor, *ret; 13191354Seschrock 13201354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 13211354Seschrock return (NULL); 13221354Seschrock 13231354Seschrock minor = NULL; 13241354Seschrock ret = NULL; 13251354Seschrock if (devid_get(fd, &devid) == 0) { 13261354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 13271354Seschrock ret = devid_str_encode(devid, minor); 13281354Seschrock if (minor != NULL) 13291354Seschrock devid_str_free(minor); 13301354Seschrock devid_free(devid); 13311354Seschrock } 13321354Seschrock (void) close(fd); 13331354Seschrock 13341354Seschrock return (ret); 13351354Seschrock } 13361354Seschrock 13371354Seschrock /* 13381354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 13391354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 13401354Seschrock * type 'zpool status', and we'll display the correct information anyway. 13411354Seschrock */ 13421354Seschrock static void 13431354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 13441354Seschrock { 13451354Seschrock zfs_cmd_t zc = { 0 }; 13461354Seschrock 13471354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13481354Seschrock (void) strncpy(zc.zc_prop_value, path, sizeof (zc.zc_prop_value)); 13491354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 13501544Seschrock &zc.zc_guid) == 0); 13511354Seschrock 1352*2082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 13531354Seschrock } 13541354Seschrock 13551354Seschrock /* 13561354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 13571354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 13581354Seschrock * We also check if this is a whole disk, in which case we strip off the 13591354Seschrock * trailing 's0' slice name. 13601354Seschrock * 13611354Seschrock * This routine is also responsible for identifying when disks have been 13621354Seschrock * reconfigured in a new location. The kernel will have opened the device by 13631354Seschrock * devid, but the path will still refer to the old location. To catch this, we 13641354Seschrock * first do a path -> devid translation (which is fast for the common case). If 13651354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 13661354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 13671354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 13681354Seschrock * of these checks. 13691354Seschrock */ 13701354Seschrock char * 1371*2082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 13721354Seschrock { 13731354Seschrock char *path, *devid; 13741544Seschrock uint64_t value; 13751544Seschrock char buf[64]; 13761354Seschrock 13771544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 13781544Seschrock &value) == 0) { 13791544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 13801544Seschrock &value) == 0); 13811613Seschrock (void) snprintf(buf, sizeof (buf), "%llu", value); 13821544Seschrock path = buf; 13831544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 13841354Seschrock 13851354Seschrock if (zhp != NULL && 13861354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 13871354Seschrock /* 13881354Seschrock * Determine if the current path is correct. 13891354Seschrock */ 13901354Seschrock char *newdevid = path_to_devid(path); 13911354Seschrock 13921354Seschrock if (newdevid == NULL || 13931354Seschrock strcmp(devid, newdevid) != 0) { 13941354Seschrock char *newpath; 13951354Seschrock 13961354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 13971354Seschrock /* 13981354Seschrock * Update the path appropriately. 13991354Seschrock */ 14001354Seschrock set_path(zhp, nv, newpath); 1401*2082Seschrock if (nvlist_add_string(nv, 1402*2082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 1403*2082Seschrock verify(nvlist_lookup_string(nv, 1404*2082Seschrock ZPOOL_CONFIG_PATH, 1405*2082Seschrock &path) == 0); 14061354Seschrock free(newpath); 14071354Seschrock } 14081354Seschrock } 14091354Seschrock 1410*2082Seschrock if (newdevid) 1411*2082Seschrock devid_str_free(newdevid); 14121354Seschrock } 14131354Seschrock 14141354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 14151354Seschrock path += 9; 14161354Seschrock 14171354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 14181544Seschrock &value) == 0 && value) { 1419*2082Seschrock char *tmp = zfs_strdup(hdl, path); 1420*2082Seschrock if (tmp == NULL) 1421*2082Seschrock return (NULL); 14221354Seschrock tmp[strlen(path) - 2] = '\0'; 14231354Seschrock return (tmp); 14241354Seschrock } 14251354Seschrock } else { 14261354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 1427*2082Seschrock 1428*2082Seschrock /* 1429*2082Seschrock * If it's a raidz device, we need to stick in the parity level. 1430*2082Seschrock */ 1431*2082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 1432*2082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 1433*2082Seschrock &value) == 0); 1434*2082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 1435*2082Seschrock value); 1436*2082Seschrock path = buf; 1437*2082Seschrock } 14381354Seschrock } 14391354Seschrock 1440*2082Seschrock return (zfs_strdup(hdl, path)); 14411354Seschrock } 14421544Seschrock 14431544Seschrock static int 14441544Seschrock zbookmark_compare(const void *a, const void *b) 14451544Seschrock { 14461544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 14471544Seschrock } 14481544Seschrock 14491544Seschrock /* 14501544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 14511544Seschrock * caller. 14521544Seschrock */ 14531544Seschrock int 14541544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem) 14551544Seschrock { 14561544Seschrock zfs_cmd_t zc = { 0 }; 14571544Seschrock uint64_t count; 14581544Seschrock zbookmark_t *zb; 14591544Seschrock int i, j; 14601544Seschrock 14611544Seschrock if (zhp->zpool_error_log != NULL) { 14621544Seschrock *list = zhp->zpool_error_log; 14631544Seschrock *nelem = zhp->zpool_error_count; 14641544Seschrock return (0); 14651544Seschrock } 14661544Seschrock 14671544Seschrock /* 14681544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 14691544Seschrock * has increased, allocate more space and continue until we get the 14701544Seschrock * entire list. 14711544Seschrock */ 14721544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 14731544Seschrock &count) == 0); 1474*2082Seschrock if ((zc.zc_config_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 1475*2082Seschrock count * sizeof (zbookmark_t))) == NULL) 1476*2082Seschrock return (-1); 14771544Seschrock zc.zc_config_dst_size = count; 14781544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 14791544Seschrock for (;;) { 1480*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 1481*2082Seschrock &zc) != 0) { 1482*2082Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 14831544Seschrock if (errno == ENOMEM) { 1484*2082Seschrock if ((zc.zc_config_dst = (uintptr_t) 1485*2082Seschrock zfs_alloc(zhp->zpool_hdl, 1486*2082Seschrock zc.zc_config_dst_size)) == NULL) 1487*2082Seschrock return (-1); 14881544Seschrock } else { 14891544Seschrock return (-1); 14901544Seschrock } 14911544Seschrock } else { 14921544Seschrock break; 14931544Seschrock } 14941544Seschrock } 14951544Seschrock 14961544Seschrock /* 14971544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 14981544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 14991544Seschrock * to first, and 'zc_config_dst_size' indicates the number of boomarks 15001544Seschrock * _not_ copied as part of the process. So we point the start of our 15011544Seschrock * array appropriate and decrement the total number of elements. 15021544Seschrock */ 15031544Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_config_dst) + 15041544Seschrock zc.zc_config_dst_size; 15051544Seschrock count -= zc.zc_config_dst_size; 15061544Seschrock 15071544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 15081544Seschrock 15091544Seschrock /* 15101544Seschrock * Count the number of unique elements 15111544Seschrock */ 15121544Seschrock j = 0; 15131544Seschrock for (i = 0; i < count; i++) { 15141544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15151544Seschrock sizeof (zbookmark_t)) == 0) 15161544Seschrock continue; 15171544Seschrock j++; 15181544Seschrock } 15191544Seschrock 15201544Seschrock /* 15211544Seschrock * If the user has only requested the number of items, return it now 15221544Seschrock * without bothering with the extra work. 15231544Seschrock */ 15241544Seschrock if (list == NULL) { 15251544Seschrock *nelem = j; 1526*2082Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 15271544Seschrock return (0); 15281544Seschrock } 15291544Seschrock 15301544Seschrock zhp->zpool_error_count = j; 15311544Seschrock 15321544Seschrock /* 15331544Seschrock * Allocate an array of nvlists to hold the results 15341544Seschrock */ 1535*2082Seschrock if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, 1536*2082Seschrock j * sizeof (nvlist_t *))) == NULL) { 1537*2082Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 1538*2082Seschrock return (-1); 1539*2082Seschrock } 15401544Seschrock 15411544Seschrock /* 15421544Seschrock * Fill in the results with names from the kernel. 15431544Seschrock */ 15441544Seschrock j = 0; 15451544Seschrock for (i = 0; i < count; i++) { 15461544Seschrock char buf[64]; 15471544Seschrock nvlist_t *nv; 15481544Seschrock 15491544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15501544Seschrock sizeof (zbookmark_t)) == 0) 15511544Seschrock continue; 15521544Seschrock 1553*2082Seschrock if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 1554*2082Seschrock 0) != 0) 1555*2082Seschrock goto nomem; 15561544Seschrock zhp->zpool_error_log[j] = nv; 15571544Seschrock 15581544Seschrock zc.zc_bookmark = zb[i]; 1559*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_BOOKMARK_NAME, 1560*2082Seschrock &zc) == 0) { 1561*2082Seschrock if (nvlist_add_string(nv, ZPOOL_ERR_DATASET, 1562*2082Seschrock zc.zc_prop_name) != 0 || 1563*2082Seschrock nvlist_add_string(nv, ZPOOL_ERR_OBJECT, 1564*2082Seschrock zc.zc_prop_value) != 0 || 1565*2082Seschrock nvlist_add_string(nv, ZPOOL_ERR_RANGE, 1566*2082Seschrock zc.zc_filename) != 0) 1567*2082Seschrock goto nomem; 15681544Seschrock } else { 15691544Seschrock (void) snprintf(buf, sizeof (buf), "%llx", 15701544Seschrock zb[i].zb_objset); 1571*2082Seschrock if (nvlist_add_string(nv, 1572*2082Seschrock ZPOOL_ERR_DATASET, buf) != 0) 1573*2082Seschrock goto nomem; 15741544Seschrock (void) snprintf(buf, sizeof (buf), "%llx", 15751544Seschrock zb[i].zb_object); 1576*2082Seschrock if (nvlist_add_string(nv, ZPOOL_ERR_OBJECT, 1577*2082Seschrock buf) != 0) 1578*2082Seschrock goto nomem; 15791544Seschrock (void) snprintf(buf, sizeof (buf), "lvl=%u blkid=%llu", 15801544Seschrock (int)zb[i].zb_level, (long long)zb[i].zb_blkid); 1581*2082Seschrock if (nvlist_add_string(nv, ZPOOL_ERR_RANGE, 1582*2082Seschrock buf) != 0) 1583*2082Seschrock goto nomem; 15841544Seschrock } 15851544Seschrock 15861544Seschrock j++; 15871544Seschrock } 15881544Seschrock 15891544Seschrock *list = zhp->zpool_error_log; 15901544Seschrock *nelem = zhp->zpool_error_count; 15911544Seschrock 15921544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 15931544Seschrock 15941544Seschrock return (0); 1595*2082Seschrock 1596*2082Seschrock nomem: 1597*2082Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 1598*2082Seschrock for (i = 0; i < zhp->zpool_error_count; i++) { 1599*2082Seschrock if (zhp->zpool_error_log[i]) 1600*2082Seschrock free(zhp->zpool_error_log[i]); 1601*2082Seschrock } 1602*2082Seschrock free(zhp->zpool_error_log); 1603*2082Seschrock zhp->zpool_error_log = NULL; 1604*2082Seschrock return (no_memory(zhp->zpool_hdl)); 16051544Seschrock } 16061760Seschrock 16071760Seschrock /* 16081760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16091760Seschrock */ 16101760Seschrock int 16111760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16121760Seschrock { 16131760Seschrock zfs_cmd_t zc = { 0 }; 1614*2082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16151760Seschrock 16161760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 1617*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 1618*2082Seschrock return (zpool_standard_error(hdl, errno, 1619*2082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 1620*2082Seschrock zhp->zpool_name)); 16211760Seschrock 16221760Seschrock return (0); 16231760Seschrock } 1624