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 */ 21789Sahrens /* 221354Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <assert.h> 29789Sahrens #include <ctype.h> 30789Sahrens #include <errno.h> 31789Sahrens #include <devid.h> 32789Sahrens #include <fcntl.h> 33789Sahrens #include <libintl.h> 34789Sahrens #include <stdio.h> 35789Sahrens #include <stdlib.h> 36789Sahrens #include <string.h> 37789Sahrens #include <unistd.h> 38789Sahrens #include <sys/zfs_ioctl.h> 391544Seschrock #include <sys/zio.h> 40789Sahrens 41789Sahrens #include "zfs_namecheck.h" 42789Sahrens #include "libzfs_impl.h" 43789Sahrens 44789Sahrens /* 45789Sahrens * Validate the given pool name, optionally putting an extended error message in 46789Sahrens * 'buf'. 47789Sahrens */ 48789Sahrens static int 49*1773Seschrock zpool_name_valid(const char *pool, boolean_t isopen, char *buf, size_t buflen) 50789Sahrens { 51789Sahrens namecheck_err_t why; 52789Sahrens char what; 53*1773Seschrock int ret; 54789Sahrens 55*1773Seschrock ret = pool_namecheck(pool, &why, &what); 56*1773Seschrock 57*1773Seschrock /* 58*1773Seschrock * The rules for reserved pool names were extended at a later point. 59*1773Seschrock * But we need to support users with existing pools that may now be 60*1773Seschrock * invalid. So we only check for this expanded set of names during a 61*1773Seschrock * create (or import), and only in userland. 62*1773Seschrock */ 63*1773Seschrock if (ret == 0 && !isopen && 64*1773Seschrock (strncmp(pool, "mirror", 6) == 0 || 65*1773Seschrock strncmp(pool, "raidz", 5) == 0 || 66*1773Seschrock strncmp(pool, "spare", 5) == 0)) { 67*1773Seschrock ret = -1; 68*1773Seschrock why = NAME_ERR_RESERVED; 69*1773Seschrock } 70*1773Seschrock 71*1773Seschrock 72*1773Seschrock if (ret != 0) { 73789Sahrens if (buf != NULL) { 74789Sahrens switch (why) { 751003Slling case NAME_ERR_TOOLONG: 761003Slling (void) snprintf(buf, buflen, 771003Slling dgettext(TEXT_DOMAIN, "name is too long")); 781003Slling break; 791003Slling 80789Sahrens case NAME_ERR_INVALCHAR: 81789Sahrens (void) snprintf(buf, buflen, 82789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 83789Sahrens "'%c' in pool name"), what); 84789Sahrens break; 85789Sahrens 86789Sahrens case NAME_ERR_NOLETTER: 87789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 88789Sahrens "name must begin with a letter"), buflen); 89789Sahrens break; 90789Sahrens 91789Sahrens case NAME_ERR_RESERVED: 92789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 93789Sahrens "name is reserved\n" 94789Sahrens "pool name may have been omitted"), buflen); 95789Sahrens break; 96789Sahrens 97789Sahrens case NAME_ERR_DISKLIKE: 98789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 99789Sahrens "pool name is reserved\n" 100789Sahrens "pool name may have been omitted"), buflen); 101789Sahrens break; 102789Sahrens } 103789Sahrens } 104789Sahrens return (FALSE); 105789Sahrens } 106789Sahrens 107789Sahrens return (TRUE); 108789Sahrens } 109789Sahrens 110789Sahrens /* 111789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 112789Sahrens */ 113789Sahrens void 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: 143789Sahrens zfs_baderror(vs->vs_state); 144789Sahrens } 145789Sahrens 146789Sahrens verify(nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, 147789Sahrens health) == 0); 148789Sahrens } 149789Sahrens 150789Sahrens /* 151789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 152789Sahrens * state. 153789Sahrens */ 154789Sahrens zpool_handle_t * 155789Sahrens zpool_open_canfail(const char *pool) 156789Sahrens { 157789Sahrens zpool_handle_t *zhp; 158789Sahrens int error; 159789Sahrens 160789Sahrens /* 161789Sahrens * Make sure the pool name is valid. 162789Sahrens */ 163*1773Seschrock if (!zpool_name_valid(pool, B_TRUE, NULL, 0)) { 164789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': invalid " 165789Sahrens "pool name"), pool); 166789Sahrens return (NULL); 167789Sahrens } 168789Sahrens 169789Sahrens zhp = zfs_malloc(sizeof (zpool_handle_t)); 170789Sahrens 171789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 172789Sahrens 173952Seschrock if ((error = zpool_refresh_stats(zhp)) != 0) { 174789Sahrens if (error == ENOENT || error == EINVAL) { 175789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': no " 176789Sahrens "such pool"), pool); 177789Sahrens free(zhp); 178789Sahrens return (NULL); 179789Sahrens } else { 180789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 181789Sahrens } 182789Sahrens } else { 183789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 184789Sahrens } 185789Sahrens 186789Sahrens return (zhp); 187789Sahrens } 188789Sahrens 189789Sahrens /* 190789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 191789Sahrens * the configuration cache may be out of date). 192789Sahrens */ 193789Sahrens zpool_handle_t * 194789Sahrens zpool_open_silent(const char *pool) 195789Sahrens { 196789Sahrens zpool_handle_t *zhp; 197789Sahrens int error; 198789Sahrens 199789Sahrens zhp = zfs_malloc(sizeof (zpool_handle_t)); 200789Sahrens 201789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 202789Sahrens 203952Seschrock if ((error = zpool_refresh_stats(zhp)) != 0) { 204789Sahrens if (error == ENOENT || error == EINVAL) { 205789Sahrens free(zhp); 206789Sahrens return (NULL); 207789Sahrens } else { 208789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 209789Sahrens } 210789Sahrens } else { 211789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 212789Sahrens } 213789Sahrens 214789Sahrens return (zhp); 215789Sahrens } 216789Sahrens 217789Sahrens /* 218789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 219789Sahrens * state. 220789Sahrens */ 221789Sahrens zpool_handle_t * 222789Sahrens zpool_open(const char *pool) 223789Sahrens { 224789Sahrens zpool_handle_t *zhp; 225789Sahrens 226789Sahrens if ((zhp = zpool_open_canfail(pool)) == NULL) 227789Sahrens return (NULL); 228789Sahrens 229789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 2301544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': pool is " 2311544Seschrock "currently unavailable"), zhp->zpool_name); 2321544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "run 'zpool status %s' for " 2331544Seschrock "detailed information"), zhp->zpool_name); 234789Sahrens zpool_close(zhp); 235789Sahrens return (NULL); 236789Sahrens } 237789Sahrens 238789Sahrens return (zhp); 239789Sahrens } 240789Sahrens 241789Sahrens /* 242789Sahrens * Close the handle. Simply frees the memory associated with the handle. 243789Sahrens */ 244789Sahrens void 245789Sahrens zpool_close(zpool_handle_t *zhp) 246789Sahrens { 247789Sahrens if (zhp->zpool_config) 248789Sahrens nvlist_free(zhp->zpool_config); 249952Seschrock if (zhp->zpool_old_config) 250952Seschrock nvlist_free(zhp->zpool_old_config); 2511544Seschrock if (zhp->zpool_error_log) { 2521544Seschrock int i; 2531544Seschrock for (i = 0; i < zhp->zpool_error_count; i++) 2541544Seschrock free(zhp->zpool_error_log[i]); 2551544Seschrock free(zhp->zpool_error_log); 2561544Seschrock } 257789Sahrens free(zhp); 258789Sahrens } 259789Sahrens 260789Sahrens /* 261789Sahrens * Return the name of the pool. 262789Sahrens */ 263789Sahrens const char * 264789Sahrens zpool_get_name(zpool_handle_t *zhp) 265789Sahrens { 266789Sahrens return (zhp->zpool_name); 267789Sahrens } 268789Sahrens 269789Sahrens /* 270789Sahrens * Return the GUID of the pool. 271789Sahrens */ 272789Sahrens uint64_t 273789Sahrens zpool_get_guid(zpool_handle_t *zhp) 274789Sahrens { 275789Sahrens uint64_t guid; 276789Sahrens 277789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 278789Sahrens &guid) == 0); 279789Sahrens return (guid); 280789Sahrens } 281789Sahrens 282789Sahrens /* 283789Sahrens * Return the amount of space currently consumed by the pool. 284789Sahrens */ 285789Sahrens uint64_t 286789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 287789Sahrens { 288789Sahrens nvlist_t *nvroot; 289789Sahrens vdev_stat_t *vs; 290789Sahrens uint_t vsc; 291789Sahrens 292789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 293789Sahrens &nvroot) == 0); 294789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 295789Sahrens (uint64_t **)&vs, &vsc) == 0); 296789Sahrens 297789Sahrens return (vs->vs_alloc); 298789Sahrens } 299789Sahrens 300789Sahrens /* 301789Sahrens * Return the total space in the pool. 302789Sahrens */ 303789Sahrens uint64_t 304789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 305789Sahrens { 306789Sahrens nvlist_t *nvroot; 307789Sahrens vdev_stat_t *vs; 308789Sahrens uint_t vsc; 309789Sahrens 310789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 311789Sahrens &nvroot) == 0); 312789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 313789Sahrens (uint64_t **)&vs, &vsc) == 0); 314789Sahrens 315789Sahrens return (vs->vs_space); 316789Sahrens } 317789Sahrens 318789Sahrens /* 319789Sahrens * Return the alternate root for this pool, if any. 320789Sahrens */ 321789Sahrens int 322789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 323789Sahrens { 324789Sahrens zfs_cmd_t zc = { 0 }; 325789Sahrens 326789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3271544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) != 0 || 3281544Seschrock zc.zc_root[0] == '\0') 329789Sahrens return (-1); 330789Sahrens 3311544Seschrock (void) strlcpy(buf, zc.zc_root, buflen); 332789Sahrens 333789Sahrens return (0); 334789Sahrens } 335789Sahrens 336789Sahrens /* 337789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 338789Sahrens */ 339789Sahrens int 340789Sahrens zpool_get_state(zpool_handle_t *zhp) 341789Sahrens { 342789Sahrens return (zhp->zpool_state); 343789Sahrens } 344789Sahrens 345789Sahrens /* 346789Sahrens * Create the named pool, using the provided vdev list. It is assumed 347789Sahrens * that the consumer has already validated the contents of the nvlist, so we 348789Sahrens * don't have to worry about error semantics. 349789Sahrens */ 350789Sahrens int 351789Sahrens zpool_create(const char *pool, nvlist_t *nvroot, const char *altroot) 352789Sahrens { 353789Sahrens zfs_cmd_t zc = { 0 }; 354789Sahrens char *packed; 355789Sahrens size_t len; 356789Sahrens int err; 357789Sahrens char reason[64]; 358789Sahrens 359*1773Seschrock if (!zpool_name_valid(pool, B_FALSE, reason, sizeof (reason))) { 360789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': %s"), 361789Sahrens pool, reason); 362789Sahrens return (-1); 363789Sahrens } 364789Sahrens 365789Sahrens if (altroot != NULL && altroot[0] != '/') { 366789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': alternate " 367789Sahrens "root '%s' must be a complete path"), pool, altroot); 368789Sahrens return (-1); 369789Sahrens } 370789Sahrens 371789Sahrens if ((err = nvlist_size(nvroot, &len, NV_ENCODE_NATIVE)) != 0) 372789Sahrens zfs_baderror(err); 373789Sahrens 374789Sahrens packed = zfs_malloc(len); 375789Sahrens 376789Sahrens if ((err = nvlist_pack(nvroot, &packed, &len, 377789Sahrens NV_ENCODE_NATIVE, 0)) != 0) 378789Sahrens zfs_baderror(err); 379789Sahrens 380789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 381789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 382789Sahrens zc.zc_config_src_size = len; 383789Sahrens 384789Sahrens if (altroot != NULL) 385789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 386789Sahrens 3871544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_CREATE, &zc) != 0) { 388789Sahrens switch (errno) { 389789Sahrens case EEXIST: 390789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 391789Sahrens "pool exists"), pool); 392789Sahrens break; 393789Sahrens 394789Sahrens case EPERM: 395789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 396789Sahrens "permission denied"), pool); 397789Sahrens break; 398789Sahrens 399789Sahrens case EBUSY: 400789Sahrens /* 401789Sahrens * This can happen if the user has specified the same 402789Sahrens * device multiple times. We can't reliably detect this 403789Sahrens * until we try to add it and see we already have a 404789Sahrens * label. 405789Sahrens */ 406789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 407789Sahrens "one or more vdevs refer to the same device"), 408789Sahrens pool); 409789Sahrens break; 410789Sahrens 411789Sahrens case EOVERFLOW: 412789Sahrens /* 413789Sahrens * This occurrs when one of the devices is below 414789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 415789Sahrens * device was the problem device since there's no 416789Sahrens * reliable way to determine device size from userland. 417789Sahrens */ 418789Sahrens { 419789Sahrens char buf[64]; 420789Sahrens 421789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 422789Sahrens 423789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 424789Sahrens "create '%s': one or more devices is less " 425789Sahrens "than the minimum size (%s)"), pool, 426789Sahrens buf); 427789Sahrens } 428789Sahrens break; 429789Sahrens 430789Sahrens case ENAMETOOLONG: 431789Sahrens /* 432789Sahrens * One of the vdevs has exceeded VDEV_SPEC_MAX length in 433789Sahrens * its plaintext representation. 434789Sahrens */ 435789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 436789Sahrens "too many devices in a single vdev"), pool); 437789Sahrens break; 438789Sahrens 439789Sahrens case EIO: 440789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 441789Sahrens "I/O error on one or more devices"), pool); 442789Sahrens break; 443789Sahrens 444789Sahrens case ENXIO: 445789Sahrens /* 446789Sahrens * This is unlikely to happen since we've verified that 447789Sahrens * all the devices can be opened from userland, but it's 448789Sahrens * still possible in some circumstances. 449789Sahrens */ 450789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 451789Sahrens "one or more devices is unavailable"), pool); 452789Sahrens break; 453789Sahrens 454789Sahrens case ENOSPC: 455789Sahrens /* 456789Sahrens * This can occur if we were incapable of writing to a 457789Sahrens * file vdev because the underlying filesystem is out of 458789Sahrens * space. This is very similar to EOVERFLOW, but we'll 459789Sahrens * produce a slightly different message. 460789Sahrens */ 461789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 462789Sahrens "one or more devices is out of space"), pool); 463789Sahrens break; 464789Sahrens 465789Sahrens default: 466789Sahrens zfs_baderror(errno); 467789Sahrens } 468789Sahrens 469789Sahrens return (-1); 470789Sahrens } 471789Sahrens 472789Sahrens free(packed); 473789Sahrens 474789Sahrens /* 475789Sahrens * If this is an alternate root pool, then we automatically set the 476789Sahrens * moutnpoint of the root dataset to be '/'. 477789Sahrens */ 478789Sahrens if (altroot != NULL) { 479789Sahrens zfs_handle_t *zhp; 480789Sahrens 481789Sahrens verify((zhp = zfs_open(pool, ZFS_TYPE_ANY)) != NULL); 482789Sahrens verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0); 483789Sahrens 484789Sahrens zfs_close(zhp); 485789Sahrens } 486789Sahrens 487789Sahrens return (0); 488789Sahrens } 489789Sahrens 490789Sahrens /* 491789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 492789Sahrens * datasets left in the pool. 493789Sahrens */ 494789Sahrens int 495789Sahrens zpool_destroy(zpool_handle_t *zhp) 496789Sahrens { 497789Sahrens zfs_cmd_t zc = { 0 }; 498789Sahrens zfs_handle_t *zfp = NULL; 499789Sahrens 500789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 501789Sahrens (zfp = zfs_open(zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL) 502789Sahrens return (-1); 503789Sahrens 504789Sahrens if (zpool_remove_zvol_links(zhp) != NULL) 505789Sahrens return (-1); 506789Sahrens 507789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 508789Sahrens 5091544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_DESTROY, &zc) != 0) { 510789Sahrens switch (errno) { 511789Sahrens case EPERM: 512789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 513789Sahrens "cannot destroy '%s': permission denied"), 514789Sahrens zhp->zpool_name); 515789Sahrens break; 516789Sahrens 517789Sahrens case EBUSY: 518789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 519789Sahrens "cannot destroy '%s': pool busy"), 520789Sahrens zhp->zpool_name); 521789Sahrens break; 522789Sahrens 523789Sahrens case ENOENT: 524789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 525789Sahrens "cannot destroy '%s': no such pool"), 526789Sahrens zhp->zpool_name); 527789Sahrens break; 528789Sahrens 529789Sahrens case EROFS: 530789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 531789Sahrens "cannot destroy '%s': one or more devices is " 532789Sahrens "read only, or '/' is mounted read only"), 533789Sahrens zhp->zpool_name); 534789Sahrens break; 535789Sahrens 536789Sahrens default: 537789Sahrens zfs_baderror(errno); 538789Sahrens } 539789Sahrens 540789Sahrens if (zfp) 541789Sahrens zfs_close(zfp); 542789Sahrens return (-1); 543789Sahrens } 544789Sahrens 545789Sahrens if (zfp) { 546789Sahrens remove_mountpoint(zfp); 547789Sahrens zfs_close(zfp); 548789Sahrens } 549789Sahrens 550789Sahrens return (0); 551789Sahrens } 552789Sahrens 553789Sahrens /* 554789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 555789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 556789Sahrens */ 557789Sahrens int 558789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 559789Sahrens { 560789Sahrens char *packed; 561789Sahrens size_t len; 562789Sahrens zfs_cmd_t zc; 563789Sahrens 564789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 565789Sahrens 566789Sahrens packed = zfs_malloc(len); 567789Sahrens 568789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 569789Sahrens 570789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 571789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 572789Sahrens zc.zc_config_src_size = len; 573789Sahrens 5741544Seschrock if (zfs_ioctl(ZFS_IOC_VDEV_ADD, &zc) != 0) { 575789Sahrens switch (errno) { 576789Sahrens case EPERM: 577789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 578789Sahrens "permission denied"), zhp->zpool_name); 579789Sahrens break; 580789Sahrens 581789Sahrens case EBUSY: 582789Sahrens /* 583789Sahrens * This can happen if the user has specified the same 584789Sahrens * device multiple times. We can't reliably detect this 585789Sahrens * until we try to add it and see we already have a 586789Sahrens * label. 587789Sahrens */ 588789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 589789Sahrens "one or more vdevs refer to the same device"), 590789Sahrens zhp->zpool_name); 591789Sahrens break; 592789Sahrens 593789Sahrens case ENAMETOOLONG: 594789Sahrens /* 595789Sahrens * One of the vdevs has exceeded VDEV_SPEC_MAX length in 596789Sahrens * its plaintext representation. 597789Sahrens */ 598789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 599789Sahrens "too many devices in a single vdev"), 600789Sahrens zhp->zpool_name); 601789Sahrens break; 602789Sahrens 603789Sahrens case ENXIO: 604789Sahrens /* 605789Sahrens * This is unlikely to happen since we've verified that 606789Sahrens * all the devices can be opened from userland, but it's 607789Sahrens * still possible in some circumstances. 608789Sahrens */ 609789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 610789Sahrens "one or more devices is unavailable"), 611789Sahrens zhp->zpool_name); 612789Sahrens break; 613789Sahrens 614789Sahrens case EOVERFLOW: 615789Sahrens /* 616789Sahrens * This occurrs when one of the devices is below 617789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 618789Sahrens * device was the problem device since there's no 619789Sahrens * reliable way to determine device size from userland. 620789Sahrens */ 621789Sahrens { 622789Sahrens char buf[64]; 623789Sahrens 624789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 625789Sahrens 626789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 627789Sahrens "add to '%s': one or more devices is less " 628789Sahrens "than the minimum size (%s)"), 629789Sahrens zhp->zpool_name, buf); 630789Sahrens } 631789Sahrens break; 632789Sahrens 633789Sahrens default: 634789Sahrens zfs_baderror(errno); 635789Sahrens } 636789Sahrens 637789Sahrens return (-1); 638789Sahrens } 639789Sahrens 640789Sahrens free(packed); 641789Sahrens 642789Sahrens return (0); 643789Sahrens } 644789Sahrens 645789Sahrens /* 646789Sahrens * Exports the pool from the system. The caller must ensure that there are no 647789Sahrens * mounted datasets in the pool. 648789Sahrens */ 649789Sahrens int 650789Sahrens zpool_export(zpool_handle_t *zhp) 651789Sahrens { 652789Sahrens zfs_cmd_t zc = { 0 }; 653789Sahrens 654789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 655789Sahrens return (-1); 656789Sahrens 657789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 658789Sahrens 6591544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_EXPORT, &zc) != 0) { 660789Sahrens switch (errno) { 661789Sahrens case EPERM: 662789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 663789Sahrens "cannot export '%s': permission denied"), 664789Sahrens zhp->zpool_name); 665789Sahrens break; 666789Sahrens 667789Sahrens case EBUSY: 668789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 669789Sahrens "cannot export '%s': pool is in use"), 670789Sahrens zhp->zpool_name); 671789Sahrens break; 672789Sahrens 673789Sahrens case ENOENT: 674789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 675789Sahrens "cannot export '%s': no such pool"), 676789Sahrens zhp->zpool_name); 677789Sahrens break; 678789Sahrens 679789Sahrens default: 680789Sahrens zfs_baderror(errno); 681789Sahrens } 682789Sahrens 683789Sahrens return (-1); 684789Sahrens } 685789Sahrens 686789Sahrens return (0); 687789Sahrens } 688789Sahrens 689789Sahrens /* 690789Sahrens * Import the given pool using the known configuration. The configuration 691789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 692789Sahrens * parameters control whether the pool is imported with a different name or with 693789Sahrens * an alternate root, respectively. 694789Sahrens */ 695789Sahrens int 696789Sahrens zpool_import(nvlist_t *config, const char *newname, const char *altroot) 697789Sahrens { 698789Sahrens zfs_cmd_t zc; 699789Sahrens char *packed; 700789Sahrens size_t len; 701789Sahrens char *thename; 702789Sahrens char *origname; 703789Sahrens int ret; 704789Sahrens 705789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 706789Sahrens &origname) == 0); 707789Sahrens 708789Sahrens if (newname != NULL) { 709*1773Seschrock if (!zpool_name_valid(newname, B_FALSE, NULL, 0)) { 710789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': " 711789Sahrens "invalid pool name"), newname); 712789Sahrens return (-1); 713789Sahrens } 714789Sahrens thename = (char *)newname; 715789Sahrens } else { 716789Sahrens thename = origname; 717789Sahrens } 718789Sahrens 719789Sahrens if (altroot != NULL && altroot[0] != '/') { 720789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': alternate " 721789Sahrens "root '%s' must be a complete path"), thename, 722789Sahrens altroot); 723789Sahrens return (-1); 724789Sahrens } 725789Sahrens 726789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 727789Sahrens 728789Sahrens if (altroot != NULL) 729789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 730789Sahrens else 731789Sahrens zc.zc_root[0] = '\0'; 732789Sahrens 733789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 7341544Seschrock &zc.zc_guid) == 0); 735789Sahrens 736789Sahrens verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0); 737789Sahrens 738789Sahrens packed = zfs_malloc(len); 739789Sahrens 740789Sahrens verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 741789Sahrens 742789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 743789Sahrens zc.zc_config_src_size = len; 744789Sahrens 745789Sahrens ret = 0; 7461544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_IMPORT, &zc) != 0) { 747789Sahrens char desc[1024]; 748789Sahrens if (newname == NULL) 749789Sahrens (void) snprintf(desc, sizeof (desc), 750789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 751789Sahrens thename); 752789Sahrens else 753789Sahrens (void) snprintf(desc, sizeof (desc), 754789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 755789Sahrens origname, thename); 756789Sahrens 757789Sahrens switch (errno) { 758789Sahrens case EEXIST: 759789Sahrens /* 760789Sahrens * A pool with that name already exists. 761789Sahrens */ 762789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: pool exists"), 763789Sahrens desc); 764789Sahrens break; 765789Sahrens 766789Sahrens case EPERM: 767789Sahrens /* 768789Sahrens * The user doesn't have permission to create pools. 769789Sahrens */ 770789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission " 771789Sahrens "denied"), desc); 772789Sahrens break; 773789Sahrens 774789Sahrens case ENXIO: 775789Sahrens case EDOM: 776789Sahrens /* 777789Sahrens * Device is unavailable, or vdev sum didn't match. 778789Sahrens */ 779789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: one or more " 780789Sahrens "devices is unavailable"), 781789Sahrens desc); 782789Sahrens break; 783789Sahrens 7841544Seschrock case ENOTSUP: 7851544Seschrock /* 7861544Seschrock * Unsupported version. 7871544Seschrock */ 7881544Seschrock zfs_error(dgettext(TEXT_DOMAIN, 7891544Seschrock "%s: unsupported version"), desc); 7901544Seschrock break; 7911544Seschrock 792789Sahrens default: 793789Sahrens zfs_baderror(errno); 794789Sahrens } 795789Sahrens 796789Sahrens ret = -1; 797789Sahrens } else { 798789Sahrens zpool_handle_t *zhp; 799789Sahrens /* 800789Sahrens * This should never fail, but play it safe anyway. 801789Sahrens */ 802789Sahrens if ((zhp = zpool_open_silent(thename)) != NULL) { 803789Sahrens ret = zpool_create_zvol_links(zhp); 804789Sahrens zpool_close(zhp); 805789Sahrens } 806789Sahrens } 807789Sahrens 808789Sahrens free(packed); 809789Sahrens return (ret); 810789Sahrens } 811789Sahrens 812789Sahrens /* 813789Sahrens * Scrub the pool. 814789Sahrens */ 815789Sahrens int 816789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 817789Sahrens { 818789Sahrens zfs_cmd_t zc = { 0 }; 819789Sahrens char msg[1024]; 820789Sahrens 821789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 822789Sahrens zc.zc_cookie = type; 823789Sahrens 8241544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_SCRUB, &zc) == 0) 825789Sahrens return (0); 826789Sahrens 827789Sahrens (void) snprintf(msg, sizeof (msg), 828789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 829789Sahrens 830789Sahrens switch (errno) { 831789Sahrens case EPERM: 832789Sahrens /* 833789Sahrens * No permission to scrub this pool. 834789Sahrens */ 835789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 836789Sahrens break; 837789Sahrens 838789Sahrens case EBUSY: 839789Sahrens /* 840789Sahrens * Resilver in progress. 841789Sahrens */ 842789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: currently resilvering"), 843789Sahrens msg); 844789Sahrens break; 845789Sahrens 846789Sahrens default: 847789Sahrens zfs_baderror(errno); 848789Sahrens } 849789Sahrens return (-1); 850789Sahrens } 851789Sahrens 8521544Seschrock static uint64_t 8531544Seschrock vdev_to_guid(nvlist_t *nv, const char *search, uint64_t guid) 8541544Seschrock { 8551544Seschrock uint_t c, children; 8561544Seschrock nvlist_t **child; 8571544Seschrock uint64_t ret, present; 8581544Seschrock char *path; 8591544Seschrock uint64_t wholedisk = 0; 8601544Seschrock 8611544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &ret) == 0); 8621544Seschrock 8631544Seschrock if (search == NULL && 8641544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 8651544Seschrock /* 8661544Seschrock * If the device has never been present since import, the only 8671544Seschrock * reliable way to match the vdev is by GUID. 8681544Seschrock */ 8691544Seschrock if (ret == guid) 8701544Seschrock return (ret); 8711544Seschrock } else if (search != NULL && 8721544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 8731544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 8741544Seschrock &wholedisk); 8751544Seschrock if (wholedisk) { 8761544Seschrock /* 8771544Seschrock * For whole disks, the internal path has 's0', but the 8781544Seschrock * path passed in by the user doesn't. 8791544Seschrock */ 8801544Seschrock if (strlen(search) == strlen(path) - 2 && 8811544Seschrock strncmp(search, path, strlen(search)) == 0) 8821544Seschrock return (ret); 8831544Seschrock } else if (strcmp(search, path) == 0) { 8841544Seschrock return (ret); 8851544Seschrock } 8861544Seschrock } 8871544Seschrock 8881544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 8891544Seschrock &child, &children) != 0) 8901544Seschrock return (0); 8911544Seschrock 8921544Seschrock for (c = 0; c < children; c++) 8931544Seschrock if ((ret = vdev_to_guid(child[c], search, guid)) != 0) 8941544Seschrock return (ret); 8951544Seschrock 8961544Seschrock return (0); 8971544Seschrock } 8981544Seschrock 8991544Seschrock /* 9001544Seschrock * Given a string describing a vdev, returns the matching GUID, or 0 if none. 9011544Seschrock */ 9021544Seschrock uint64_t 9031544Seschrock zpool_vdev_to_guid(zpool_handle_t *zhp, const char *path) 9041544Seschrock { 9051544Seschrock char buf[MAXPATHLEN]; 9061544Seschrock const char *search; 9071544Seschrock char *end; 9081544Seschrock nvlist_t *nvroot; 9091544Seschrock uint64_t guid; 9101544Seschrock 9111613Seschrock guid = strtoull(path, &end, 10); 9121544Seschrock if (guid != 0 && *end == '\0') { 9131544Seschrock search = NULL; 9141544Seschrock } else if (path[0] != '/') { 9151544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 9161544Seschrock search = buf; 9171544Seschrock } else { 9181544Seschrock search = path; 9191544Seschrock } 9201544Seschrock 9211544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 9221544Seschrock &nvroot) == 0); 9231544Seschrock 9241544Seschrock return (vdev_to_guid(nvroot, search, guid)); 9251544Seschrock } 9261544Seschrock 927789Sahrens /* 928789Sahrens * Bring the specified vdev online 929789Sahrens */ 930789Sahrens int 931789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 932789Sahrens { 933789Sahrens zfs_cmd_t zc = { 0 }; 934789Sahrens char msg[1024]; 935789Sahrens 9361544Seschrock (void) snprintf(msg, sizeof (msg), 9371544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 938789Sahrens 9391544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9401544Seschrock if ((zc.zc_guid = zpool_vdev_to_guid(zhp, path)) == 0) { 9411544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: no such device in pool"), 9421544Seschrock msg); 9431544Seschrock return (-1); 9441544Seschrock } 945789Sahrens 9461544Seschrock if (zfs_ioctl(ZFS_IOC_VDEV_ONLINE, &zc) == 0) 9471544Seschrock return (0); 948789Sahrens 949789Sahrens switch (errno) { 950789Sahrens case ENODEV: 951789Sahrens /* 952789Sahrens * Device doesn't exist 953789Sahrens */ 954789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 955789Sahrens break; 956789Sahrens 957789Sahrens case EPERM: 958789Sahrens /* 959789Sahrens * No permission to bring this vdev online. 960789Sahrens */ 961789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 962789Sahrens break; 963789Sahrens 964789Sahrens default: 965789Sahrens zfs_baderror(errno); 966789Sahrens } 967789Sahrens return (-1); 968789Sahrens } 969789Sahrens 970789Sahrens /* 971789Sahrens * Take the specified vdev offline 972789Sahrens */ 973789Sahrens int 9741485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) 975789Sahrens { 976789Sahrens zfs_cmd_t zc = { 0 }; 977789Sahrens char msg[1024]; 978789Sahrens 9791544Seschrock (void) snprintf(msg, sizeof (msg), 9801544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 9811544Seschrock 982789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 9831544Seschrock if ((zc.zc_guid = zpool_vdev_to_guid(zhp, path)) == 0) { 9841544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: no such device in pool"), 9851544Seschrock msg); 9861544Seschrock return (-1); 9871544Seschrock } 988789Sahrens 9891485Slling zc.zc_cookie = istmp; 9901485Slling 9911544Seschrock if (zfs_ioctl(ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 992789Sahrens return (0); 993789Sahrens 994789Sahrens switch (errno) { 995789Sahrens case ENODEV: 996789Sahrens /* 997789Sahrens * Device doesn't exist 998789Sahrens */ 999789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 1000789Sahrens break; 1001789Sahrens 1002789Sahrens case EPERM: 1003789Sahrens /* 1004789Sahrens * No permission to take this vdev offline. 1005789Sahrens */ 1006789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 1007789Sahrens break; 1008789Sahrens 1009789Sahrens case EBUSY: 1010789Sahrens /* 1011789Sahrens * There are no other replicas of this device. 1012789Sahrens */ 1013789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg); 1014789Sahrens break; 1015789Sahrens 1016789Sahrens default: 1017789Sahrens zfs_baderror(errno); 1018789Sahrens } 1019789Sahrens return (-1); 1020789Sahrens } 1021789Sahrens 1022789Sahrens /* 1023789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 1024789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 1025789Sahrens */ 1026789Sahrens int 1027789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 1028789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 1029789Sahrens { 1030789Sahrens zfs_cmd_t zc = { 0 }; 1031789Sahrens char msg[1024]; 1032789Sahrens char *packed; 1033789Sahrens int ret; 1034789Sahrens size_t len; 1035789Sahrens 10361544Seschrock if (replacing) 10371544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10381544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 10391544Seschrock else 10401544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 10411544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 10421544Seschrock 1043789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 10441544Seschrock if ((zc.zc_guid = zpool_vdev_to_guid(zhp, old_disk)) == 0) { 10451544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: no such device in pool"), 10461544Seschrock msg); 10471544Seschrock return (-1); 10481544Seschrock } 1049789Sahrens zc.zc_cookie = replacing; 1050789Sahrens 1051789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 1052789Sahrens 1053789Sahrens packed = zfs_malloc(len); 1054789Sahrens 1055789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 1056789Sahrens 1057789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 1058789Sahrens zc.zc_config_src_size = len; 1059789Sahrens 10601544Seschrock ret = zfs_ioctl(ZFS_IOC_VDEV_ATTACH, &zc); 1061789Sahrens 1062789Sahrens free(packed); 1063789Sahrens 1064789Sahrens if (ret == 0) 1065789Sahrens return (0); 1066789Sahrens 1067789Sahrens switch (errno) { 10681544Seschrock case EPERM: 1069789Sahrens /* 1070789Sahrens * No permission to mess with the config. 1071789Sahrens */ 1072789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 1073789Sahrens break; 1074789Sahrens 10751544Seschrock case ENODEV: 1076789Sahrens /* 1077789Sahrens * Device doesn't exist. 1078789Sahrens */ 1079789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s not in pool"), 1080789Sahrens msg, old_disk); 1081789Sahrens break; 1082789Sahrens 10831544Seschrock case ENOTSUP: 1084789Sahrens /* 1085789Sahrens * Can't attach to or replace this type of vdev. 1086789Sahrens */ 1087789Sahrens if (replacing) 1088789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1089789Sahrens "%s: cannot replace a replacing device"), msg); 1090789Sahrens else 1091789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1092789Sahrens "%s: attach is only applicable to mirrors"), msg); 1093789Sahrens break; 1094789Sahrens 10951544Seschrock case EINVAL: 1096789Sahrens /* 1097789Sahrens * The new device must be a single disk. 1098789Sahrens */ 1099789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1100789Sahrens "%s: <new_device> must be a single disk"), msg); 1101789Sahrens break; 1102789Sahrens 11031544Seschrock case ENXIO: 1104789Sahrens /* 1105789Sahrens * This is unlikely to happen since we've verified that 1106789Sahrens * all the devices can be opened from userland, but it's 1107789Sahrens * still possible in some circumstances. 1108789Sahrens */ 1109789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is unavailable"), 1110789Sahrens msg, new_disk); 1111789Sahrens break; 1112789Sahrens 11131544Seschrock case EBUSY: 1114789Sahrens /* 1115789Sahrens * The new device is is use. 1116789Sahrens */ 1117789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s busy"), msg, new_disk); 1118789Sahrens break; 1119789Sahrens 11201544Seschrock case EOVERFLOW: 1121789Sahrens /* 1122789Sahrens * The new device is too small. 1123789Sahrens */ 1124789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is too small"), 1125789Sahrens msg, new_disk); 1126789Sahrens break; 1127789Sahrens 11281544Seschrock case EDOM: 1129789Sahrens /* 1130789Sahrens * The new device has a different alignment requirement. 1131789Sahrens */ 1132789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1133789Sahrens "%s: devices have different sector alignment"), msg); 1134789Sahrens break; 1135789Sahrens 11361544Seschrock case ENAMETOOLONG: 1137789Sahrens /* 1138789Sahrens * The resulting top-level vdev spec won't fit in the label. 1139789Sahrens */ 1140789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1141789Sahrens "%s: too many devices in a single vdev"), msg); 1142789Sahrens break; 1143789Sahrens 11441544Seschrock default: 1145789Sahrens zfs_baderror(errno); 1146789Sahrens } 1147789Sahrens 1148789Sahrens return (1); 1149789Sahrens } 1150789Sahrens 1151789Sahrens /* 1152789Sahrens * Detach the specified device. 1153789Sahrens */ 1154789Sahrens int 1155789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1156789Sahrens { 1157789Sahrens zfs_cmd_t zc = { 0 }; 1158789Sahrens char msg[1024]; 1159789Sahrens 11601544Seschrock (void) snprintf(msg, sizeof (msg), 11611544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 11621544Seschrock 1163789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 11641544Seschrock if ((zc.zc_guid = zpool_vdev_to_guid(zhp, path)) == 0) { 11651635Sbonwick zfs_error(dgettext(TEXT_DOMAIN, "%s: no such device in pool"), 11661635Sbonwick msg); 11671544Seschrock return (-1); 11681544Seschrock } 1169789Sahrens 11701544Seschrock if (zfs_ioctl(ZFS_IOC_VDEV_DETACH, &zc) == 0) 1171789Sahrens return (0); 1172789Sahrens 1173789Sahrens switch (errno) { 11741544Seschrock case EPERM: 1175789Sahrens /* 1176789Sahrens * No permission to mess with the config. 1177789Sahrens */ 1178789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 1179789Sahrens break; 1180789Sahrens 11811544Seschrock case ENODEV: 1182789Sahrens /* 1183789Sahrens * Device doesn't exist. 1184789Sahrens */ 1185789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 1186789Sahrens break; 1187789Sahrens 11881544Seschrock case ENOTSUP: 1189789Sahrens /* 1190789Sahrens * Can't detach from this type of vdev. 1191789Sahrens */ 1192789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1193789Sahrens "%s: only applicable to mirror and replacing vdevs"), msg); 1194789Sahrens break; 1195789Sahrens 11961544Seschrock case EBUSY: 1197789Sahrens /* 1198789Sahrens * There are no other replicas of this device. 1199789Sahrens */ 1200789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg); 1201789Sahrens break; 1202789Sahrens 12031544Seschrock default: 12041544Seschrock zfs_baderror(errno); 12051544Seschrock } 12061544Seschrock 12071544Seschrock return (1); 12081544Seschrock } 12091544Seschrock 12101544Seschrock /* 12111544Seschrock * Clear the errors for the pool, or the particular device if specified. 12121544Seschrock */ 12131544Seschrock int 12141544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 12151544Seschrock { 12161544Seschrock zfs_cmd_t zc = { 0 }; 12171544Seschrock char msg[1024]; 12181544Seschrock 12191544Seschrock if (path) 12201544Seschrock (void) snprintf(msg, sizeof (msg), 12211544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12221544Seschrock zc.zc_prop_value); 12231544Seschrock else 12241544Seschrock (void) snprintf(msg, sizeof (msg), 12251544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 12261544Seschrock zhp->zpool_name); 12271544Seschrock 12281544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12291544Seschrock if (path && (zc.zc_guid = zpool_vdev_to_guid(zhp, path)) == 0) { 12301544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: no such device in pool"), 12311544Seschrock msg); 12321544Seschrock return (-1); 12331544Seschrock } 12341544Seschrock 12351544Seschrock if (zfs_ioctl(ZFS_IOC_CLEAR, &zc) == 0) 12361544Seschrock return (0); 12371544Seschrock 12381544Seschrock switch (errno) { 12391544Seschrock case EPERM: 12401544Seschrock /* 12411544Seschrock * No permission to mess with the config. 12421544Seschrock */ 12431544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 12441544Seschrock break; 12451544Seschrock 12461544Seschrock case ENODEV: 12471544Seschrock /* 12481544Seschrock * Device doesn't exist. 12491544Seschrock */ 12501544Seschrock zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 12511544Seschrock break; 12521544Seschrock 12531544Seschrock default: 1254789Sahrens zfs_baderror(errno); 1255789Sahrens } 1256789Sahrens 1257789Sahrens return (1); 1258789Sahrens } 1259789Sahrens 1260789Sahrens static int 1261789Sahrens do_zvol(zfs_handle_t *zhp, void *data) 1262789Sahrens { 1263789Sahrens int linktype = (int)(uintptr_t)data; 1264789Sahrens int ret; 1265789Sahrens 1266789Sahrens /* 1267789Sahrens * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we 1268789Sahrens * correctly handle snapshots of volumes. 1269789Sahrens */ 1270789Sahrens if (zhp->zfs_volblocksize != 0) { 1271789Sahrens if (linktype) 1272789Sahrens ret = zvol_create_link(zhp->zfs_name); 1273789Sahrens else 1274789Sahrens ret = zvol_remove_link(zhp->zfs_name); 1275789Sahrens } 1276789Sahrens 1277789Sahrens ret = zfs_iter_children(zhp, do_zvol, data); 1278789Sahrens 1279789Sahrens zfs_close(zhp); 1280789Sahrens return (ret); 1281789Sahrens } 1282789Sahrens 1283789Sahrens /* 1284789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1285789Sahrens */ 1286789Sahrens int 1287789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1288789Sahrens { 1289789Sahrens zfs_handle_t *zfp; 1290789Sahrens int ret; 1291789Sahrens 1292789Sahrens /* 1293789Sahrens * If the pool is unavailable, just return success. 1294789Sahrens */ 1295789Sahrens if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL) 1296789Sahrens return (0); 1297789Sahrens 1298789Sahrens ret = zfs_iter_children(zfp, do_zvol, (void *)TRUE); 1299789Sahrens 1300789Sahrens zfs_close(zfp); 1301789Sahrens return (ret); 1302789Sahrens } 1303789Sahrens 1304789Sahrens /* 1305789Sahrens * Iterate over all zvols in the poool and remove any minor nodes. 1306789Sahrens */ 1307789Sahrens int 1308789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1309789Sahrens { 1310789Sahrens zfs_handle_t *zfp; 1311789Sahrens int ret; 1312789Sahrens 1313789Sahrens /* 1314789Sahrens * If the pool is unavailable, just return success. 1315789Sahrens */ 1316789Sahrens if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL) 1317789Sahrens return (0); 1318789Sahrens 1319789Sahrens ret = zfs_iter_children(zfp, do_zvol, (void *)FALSE); 1320789Sahrens 1321789Sahrens zfs_close(zfp); 1322789Sahrens return (ret); 1323789Sahrens } 13241354Seschrock 13251354Seschrock /* 13261354Seschrock * Convert from a devid string to a path. 13271354Seschrock */ 13281354Seschrock static char * 13291354Seschrock devid_to_path(char *devid_str) 13301354Seschrock { 13311354Seschrock ddi_devid_t devid; 13321354Seschrock char *minor; 13331354Seschrock char *path; 13341354Seschrock devid_nmlist_t *list = NULL; 13351354Seschrock int ret; 13361354Seschrock 13371354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 13381354Seschrock return (NULL); 13391354Seschrock 13401354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 13411354Seschrock 13421354Seschrock devid_str_free(minor); 13431354Seschrock devid_free(devid); 13441354Seschrock 13451354Seschrock if (ret != 0) 13461354Seschrock return (NULL); 13471354Seschrock 13481354Seschrock path = zfs_strdup(list[0].devname); 13491354Seschrock devid_free_nmlist(list); 13501354Seschrock 13511354Seschrock return (path); 13521354Seschrock } 13531354Seschrock 13541354Seschrock /* 13551354Seschrock * Convert from a path to a devid string. 13561354Seschrock */ 13571354Seschrock static char * 13581354Seschrock path_to_devid(const char *path) 13591354Seschrock { 13601354Seschrock int fd; 13611354Seschrock ddi_devid_t devid; 13621354Seschrock char *minor, *ret; 13631354Seschrock 13641354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 13651354Seschrock return (NULL); 13661354Seschrock 13671354Seschrock minor = NULL; 13681354Seschrock ret = NULL; 13691354Seschrock if (devid_get(fd, &devid) == 0) { 13701354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 13711354Seschrock ret = devid_str_encode(devid, minor); 13721354Seschrock if (minor != NULL) 13731354Seschrock devid_str_free(minor); 13741354Seschrock devid_free(devid); 13751354Seschrock } 13761354Seschrock (void) close(fd); 13771354Seschrock 13781354Seschrock return (ret); 13791354Seschrock } 13801354Seschrock 13811354Seschrock /* 13821354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 13831354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 13841354Seschrock * type 'zpool status', and we'll display the correct information anyway. 13851354Seschrock */ 13861354Seschrock static void 13871354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 13881354Seschrock { 13891354Seschrock zfs_cmd_t zc = { 0 }; 13901354Seschrock 13911354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13921354Seschrock (void) strncpy(zc.zc_prop_value, path, sizeof (zc.zc_prop_value)); 13931354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 13941544Seschrock &zc.zc_guid) == 0); 13951354Seschrock 13961544Seschrock (void) zfs_ioctl(ZFS_IOC_VDEV_SETPATH, &zc); 13971354Seschrock } 13981354Seschrock 13991354Seschrock /* 14001354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 14011354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 14021354Seschrock * We also check if this is a whole disk, in which case we strip off the 14031354Seschrock * trailing 's0' slice name. 14041354Seschrock * 14051354Seschrock * This routine is also responsible for identifying when disks have been 14061354Seschrock * reconfigured in a new location. The kernel will have opened the device by 14071354Seschrock * devid, but the path will still refer to the old location. To catch this, we 14081354Seschrock * first do a path -> devid translation (which is fast for the common case). If 14091354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 14101354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 14111354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 14121354Seschrock * of these checks. 14131354Seschrock */ 14141354Seschrock char * 14151354Seschrock zpool_vdev_name(zpool_handle_t *zhp, nvlist_t *nv) 14161354Seschrock { 14171354Seschrock char *path, *devid; 14181544Seschrock uint64_t value; 14191544Seschrock char buf[64]; 14201354Seschrock 14211544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 14221544Seschrock &value) == 0) { 14231544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 14241544Seschrock &value) == 0); 14251613Seschrock (void) snprintf(buf, sizeof (buf), "%llu", value); 14261544Seschrock path = buf; 14271544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 14281354Seschrock 14291354Seschrock if (zhp != NULL && 14301354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 14311354Seschrock /* 14321354Seschrock * Determine if the current path is correct. 14331354Seschrock */ 14341354Seschrock char *newdevid = path_to_devid(path); 14351354Seschrock 14361354Seschrock if (newdevid == NULL || 14371354Seschrock strcmp(devid, newdevid) != 0) { 14381354Seschrock char *newpath; 14391354Seschrock 14401354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 14411354Seschrock /* 14421354Seschrock * Update the path appropriately. 14431354Seschrock */ 14441354Seschrock set_path(zhp, nv, newpath); 14451354Seschrock verify(nvlist_add_string(nv, 14461354Seschrock ZPOOL_CONFIG_PATH, newpath) == 0); 14471354Seschrock free(newpath); 14481354Seschrock verify(nvlist_lookup_string(nv, 14491354Seschrock ZPOOL_CONFIG_PATH, &path) == 0); 14501354Seschrock } 14511354Seschrock 14521354Seschrock if (newdevid) 14531354Seschrock devid_str_free(newdevid); 14541354Seschrock } 14551354Seschrock 14561354Seschrock } 14571354Seschrock 14581354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 14591354Seschrock path += 9; 14601354Seschrock 14611354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 14621544Seschrock &value) == 0 && value) { 14631354Seschrock char *tmp = zfs_strdup(path); 14641354Seschrock tmp[strlen(path) - 2] = '\0'; 14651354Seschrock return (tmp); 14661354Seschrock } 14671354Seschrock } else { 14681354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 14691354Seschrock } 14701354Seschrock 14711354Seschrock return (zfs_strdup(path)); 14721354Seschrock } 14731544Seschrock 14741544Seschrock static int 14751544Seschrock zbookmark_compare(const void *a, const void *b) 14761544Seschrock { 14771544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 14781544Seschrock } 14791544Seschrock 14801544Seschrock /* 14811544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 14821544Seschrock * caller. 14831544Seschrock */ 14841544Seschrock int 14851544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem) 14861544Seschrock { 14871544Seschrock zfs_cmd_t zc = { 0 }; 14881544Seschrock uint64_t count; 14891544Seschrock zbookmark_t *zb; 14901544Seschrock int i, j; 14911544Seschrock 14921544Seschrock if (zhp->zpool_error_log != NULL) { 14931544Seschrock *list = zhp->zpool_error_log; 14941544Seschrock *nelem = zhp->zpool_error_count; 14951544Seschrock return (0); 14961544Seschrock } 14971544Seschrock 14981544Seschrock /* 14991544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 15001544Seschrock * has increased, allocate more space and continue until we get the 15011544Seschrock * entire list. 15021544Seschrock */ 15031544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 15041544Seschrock &count) == 0); 15051544Seschrock zc.zc_config_dst = (uintptr_t)zfs_malloc(count * sizeof (zbookmark_t)); 15061544Seschrock zc.zc_config_dst_size = count; 15071544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 15081544Seschrock for (;;) { 15091544Seschrock if (zfs_ioctl(ZFS_IOC_ERROR_LOG, &zc) != 0) { 15101544Seschrock if (errno == ENOMEM) { 15111544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 15121544Seschrock zc.zc_config_dst = (uintptr_t) 15131544Seschrock zfs_malloc(zc.zc_config_dst_size); 15141544Seschrock } else { 15151544Seschrock return (-1); 15161544Seschrock } 15171544Seschrock } else { 15181544Seschrock break; 15191544Seschrock } 15201544Seschrock } 15211544Seschrock 15221544Seschrock /* 15231544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 15241544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 15251544Seschrock * to first, and 'zc_config_dst_size' indicates the number of boomarks 15261544Seschrock * _not_ copied as part of the process. So we point the start of our 15271544Seschrock * array appropriate and decrement the total number of elements. 15281544Seschrock */ 15291544Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_config_dst) + 15301544Seschrock zc.zc_config_dst_size; 15311544Seschrock count -= zc.zc_config_dst_size; 15321544Seschrock 15331544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 15341544Seschrock 15351544Seschrock /* 15361544Seschrock * Count the number of unique elements 15371544Seschrock */ 15381544Seschrock j = 0; 15391544Seschrock for (i = 0; i < count; i++) { 15401544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15411544Seschrock sizeof (zbookmark_t)) == 0) 15421544Seschrock continue; 15431544Seschrock j++; 15441544Seschrock } 15451544Seschrock 15461544Seschrock /* 15471544Seschrock * If the user has only requested the number of items, return it now 15481544Seschrock * without bothering with the extra work. 15491544Seschrock */ 15501544Seschrock if (list == NULL) { 15511544Seschrock *nelem = j; 15521544Seschrock return (0); 15531544Seschrock } 15541544Seschrock 15551544Seschrock zhp->zpool_error_count = j; 15561544Seschrock 15571544Seschrock /* 15581544Seschrock * Allocate an array of nvlists to hold the results 15591544Seschrock */ 15601544Seschrock zhp->zpool_error_log = zfs_malloc(j * sizeof (nvlist_t *)); 15611544Seschrock 15621544Seschrock /* 15631544Seschrock * Fill in the results with names from the kernel. 15641544Seschrock */ 15651544Seschrock j = 0; 15661544Seschrock for (i = 0; i < count; i++) { 15671544Seschrock char buf[64]; 15681544Seschrock nvlist_t *nv; 15691544Seschrock 15701544Seschrock if (i > 0 && memcmp(&zb[i - 1], &zb[i], 15711544Seschrock sizeof (zbookmark_t)) == 0) 15721544Seschrock continue; 15731544Seschrock 15741544Seschrock verify(nvlist_alloc(&nv, NV_UNIQUE_NAME, 15751544Seschrock 0) == 0); 15761544Seschrock zhp->zpool_error_log[j] = nv; 15771544Seschrock 15781544Seschrock zc.zc_bookmark = zb[i]; 15791544Seschrock if (zfs_ioctl(ZFS_IOC_BOOKMARK_NAME, &zc) == 0) { 15801544Seschrock verify(nvlist_add_string(nv, ZPOOL_ERR_DATASET, 15811544Seschrock zc.zc_prop_name) == 0); 15821544Seschrock verify(nvlist_add_string(nv, ZPOOL_ERR_OBJECT, 15831544Seschrock zc.zc_prop_value) == 0); 15841544Seschrock verify(nvlist_add_string(nv, ZPOOL_ERR_RANGE, 15851544Seschrock zc.zc_filename) == 0); 15861544Seschrock } else { 15871544Seschrock (void) snprintf(buf, sizeof (buf), "%llx", 15881544Seschrock zb[i].zb_objset); 15891544Seschrock verify(nvlist_add_string(nv, 15901544Seschrock ZPOOL_ERR_DATASET, buf) == 0); 15911544Seschrock (void) snprintf(buf, sizeof (buf), "%llx", 15921544Seschrock zb[i].zb_object); 15931544Seschrock verify(nvlist_add_string(nv, ZPOOL_ERR_OBJECT, 15941544Seschrock buf) == 0); 15951544Seschrock (void) snprintf(buf, sizeof (buf), "lvl=%u blkid=%llu", 15961544Seschrock (int)zb[i].zb_level, (long long)zb[i].zb_blkid); 15971544Seschrock verify(nvlist_add_string(nv, ZPOOL_ERR_RANGE, 15981544Seschrock buf) == 0); 15991544Seschrock } 16001544Seschrock 16011544Seschrock j++; 16021544Seschrock } 16031544Seschrock 16041544Seschrock *list = zhp->zpool_error_log; 16051544Seschrock *nelem = zhp->zpool_error_count; 16061544Seschrock 16071544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 16081544Seschrock 16091544Seschrock return (0); 16101544Seschrock } 16111760Seschrock 16121760Seschrock /* 16131760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 16141760Seschrock */ 16151760Seschrock int 16161760Seschrock zpool_upgrade(zpool_handle_t *zhp) 16171760Seschrock { 16181760Seschrock zfs_cmd_t zc = { 0 }; 16191760Seschrock 16201760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 16211760Seschrock if (zfs_ioctl(ZFS_IOC_POOL_UPGRADE, &zc) != 0) { 16221760Seschrock switch (errno) { 16231760Seschrock case EPERM: 16241760Seschrock zfs_error(dgettext(TEXT_DOMAIN, "cannot upgrade '%s': " 16251760Seschrock "permission denied"), zhp->zpool_name); 16261760Seschrock break; 16271760Seschrock default: 16281760Seschrock zfs_baderror(errno); 16291760Seschrock } 16301760Seschrock 16311760Seschrock return (-1); 16321760Seschrock } 16331760Seschrock 16341760Seschrock return (0); 16351760Seschrock } 1636