1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5789Sahrens * Common Development and Distribution License, Version 1.0 only 6789Sahrens * (the "License"). You may not use this file except in compliance 7789Sahrens * with the License. 8789Sahrens * 9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10789Sahrens * or http://www.opensolaris.org/os/licensing. 11789Sahrens * See the License for the specific language governing permissions 12789Sahrens * and limitations under the License. 13789Sahrens * 14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19789Sahrens * 20789Sahrens * CDDL HEADER END 21789Sahrens */ 22789Sahrens /* 23789Sahrens * Copyright 2005 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> 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 49789Sahrens zpool_name_valid(const char *pool, char *buf, size_t buflen) 50789Sahrens { 51789Sahrens namecheck_err_t why; 52789Sahrens char what; 53789Sahrens 54789Sahrens if (strlen(pool) >= ZPOOL_MAXNAMELEN) { 55789Sahrens if (buf) 56789Sahrens (void) snprintf(buf, buflen, 57789Sahrens dgettext(TEXT_DOMAIN, "name is too long")); 58789Sahrens return (FALSE); 59789Sahrens } 60789Sahrens 61789Sahrens if (pool_namecheck(pool, &why, &what) != 0) { 62789Sahrens if (buf != NULL) { 63789Sahrens switch (why) { 64789Sahrens case NAME_ERR_INVALCHAR: 65789Sahrens (void) snprintf(buf, buflen, 66789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 67789Sahrens "'%c' in pool name"), what); 68789Sahrens break; 69789Sahrens 70789Sahrens case NAME_ERR_NOLETTER: 71789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 72789Sahrens "name must begin with a letter"), buflen); 73789Sahrens break; 74789Sahrens 75789Sahrens case NAME_ERR_RESERVED: 76789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 77789Sahrens "name is reserved\n" 78789Sahrens "pool name may have been omitted"), buflen); 79789Sahrens break; 80789Sahrens 81789Sahrens case NAME_ERR_DISKLIKE: 82789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 83789Sahrens "pool name is reserved\n" 84789Sahrens "pool name may have been omitted"), buflen); 85789Sahrens break; 86789Sahrens } 87789Sahrens } 88789Sahrens return (FALSE); 89789Sahrens } 90789Sahrens 91789Sahrens return (TRUE); 92789Sahrens } 93789Sahrens 94789Sahrens /* 95789Sahrens * Set the pool-wide health based on the vdev state of the root vdev. 96789Sahrens */ 97789Sahrens void 98789Sahrens set_pool_health(nvlist_t *config) 99789Sahrens { 100789Sahrens nvlist_t *nvroot; 101789Sahrens vdev_stat_t *vs; 102789Sahrens uint_t vsc; 103789Sahrens char *health; 104789Sahrens 105789Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 106789Sahrens &nvroot) == 0); 107789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 108789Sahrens (uint64_t **)&vs, &vsc) == 0); 109789Sahrens 110789Sahrens switch (vs->vs_state) { 111789Sahrens 112789Sahrens case VDEV_STATE_CLOSED: 113789Sahrens case VDEV_STATE_CANT_OPEN: 114789Sahrens case VDEV_STATE_OFFLINE: 115789Sahrens health = dgettext(TEXT_DOMAIN, "FAULTED"); 116789Sahrens break; 117789Sahrens 118789Sahrens case VDEV_STATE_DEGRADED: 119789Sahrens health = dgettext(TEXT_DOMAIN, "DEGRADED"); 120789Sahrens break; 121789Sahrens 122789Sahrens case VDEV_STATE_HEALTHY: 123789Sahrens health = dgettext(TEXT_DOMAIN, "ONLINE"); 124789Sahrens break; 125789Sahrens 126789Sahrens default: 127789Sahrens zfs_baderror(vs->vs_state); 128789Sahrens } 129789Sahrens 130789Sahrens verify(nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, 131789Sahrens health) == 0); 132789Sahrens } 133789Sahrens 134789Sahrens /* 135789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 136789Sahrens * state. 137789Sahrens */ 138789Sahrens zpool_handle_t * 139789Sahrens zpool_open_canfail(const char *pool) 140789Sahrens { 141789Sahrens zpool_handle_t *zhp; 142789Sahrens int error; 143789Sahrens 144789Sahrens /* 145789Sahrens * Make sure the pool name is valid. 146789Sahrens */ 147789Sahrens if (!zpool_name_valid(pool, NULL, 0)) { 148789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': invalid " 149789Sahrens "pool name"), pool); 150789Sahrens return (NULL); 151789Sahrens } 152789Sahrens 153789Sahrens zhp = zfs_malloc(sizeof (zpool_handle_t)); 154789Sahrens 155789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 156789Sahrens 157*952Seschrock if ((error = zpool_refresh_stats(zhp)) != 0) { 158789Sahrens if (error == ENOENT || error == EINVAL) { 159789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': no " 160789Sahrens "such pool"), pool); 161789Sahrens free(zhp); 162789Sahrens return (NULL); 163789Sahrens } else { 164789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 165789Sahrens } 166789Sahrens } else { 167789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 168789Sahrens } 169789Sahrens 170789Sahrens return (zhp); 171789Sahrens } 172789Sahrens 173789Sahrens /* 174789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 175789Sahrens * the configuration cache may be out of date). 176789Sahrens */ 177789Sahrens zpool_handle_t * 178789Sahrens zpool_open_silent(const char *pool) 179789Sahrens { 180789Sahrens zpool_handle_t *zhp; 181789Sahrens int error; 182789Sahrens 183789Sahrens zhp = zfs_malloc(sizeof (zpool_handle_t)); 184789Sahrens 185789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 186789Sahrens 187*952Seschrock if ((error = zpool_refresh_stats(zhp)) != 0) { 188789Sahrens if (error == ENOENT || error == EINVAL) { 189789Sahrens free(zhp); 190789Sahrens return (NULL); 191789Sahrens } else { 192789Sahrens zhp->zpool_state = POOL_STATE_UNAVAIL; 193789Sahrens } 194789Sahrens } else { 195789Sahrens zhp->zpool_state = POOL_STATE_ACTIVE; 196789Sahrens } 197789Sahrens 198789Sahrens return (zhp); 199789Sahrens } 200789Sahrens 201789Sahrens /* 202789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 203789Sahrens * state. 204789Sahrens */ 205789Sahrens zpool_handle_t * 206789Sahrens zpool_open(const char *pool) 207789Sahrens { 208789Sahrens zpool_handle_t *zhp; 209789Sahrens 210789Sahrens if ((zhp = zpool_open_canfail(pool)) == NULL) 211789Sahrens return (NULL); 212789Sahrens 213789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 214789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open ' %s': pool is " 215789Sahrens "currently unavailable\n"), zhp->zpool_name); 216789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "run 'zpool status -v %s' for " 217789Sahrens "detailed information\n"), zhp->zpool_name); 218789Sahrens zpool_close(zhp); 219789Sahrens return (NULL); 220789Sahrens } 221789Sahrens 222789Sahrens return (zhp); 223789Sahrens } 224789Sahrens 225789Sahrens /* 226789Sahrens * Close the handle. Simply frees the memory associated with the handle. 227789Sahrens */ 228789Sahrens void 229789Sahrens zpool_close(zpool_handle_t *zhp) 230789Sahrens { 231789Sahrens if (zhp->zpool_config) 232789Sahrens nvlist_free(zhp->zpool_config); 233*952Seschrock if (zhp->zpool_old_config) 234*952Seschrock nvlist_free(zhp->zpool_old_config); 235789Sahrens free(zhp); 236789Sahrens } 237789Sahrens 238789Sahrens /* 239789Sahrens * Return the name of the pool. 240789Sahrens */ 241789Sahrens const char * 242789Sahrens zpool_get_name(zpool_handle_t *zhp) 243789Sahrens { 244789Sahrens return (zhp->zpool_name); 245789Sahrens } 246789Sahrens 247789Sahrens /* 248789Sahrens * Return the GUID of the pool. 249789Sahrens */ 250789Sahrens uint64_t 251789Sahrens zpool_get_guid(zpool_handle_t *zhp) 252789Sahrens { 253789Sahrens uint64_t guid; 254789Sahrens 255789Sahrens verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 256789Sahrens &guid) == 0); 257789Sahrens return (guid); 258789Sahrens } 259789Sahrens 260789Sahrens /* 261789Sahrens * Return the amount of space currently consumed by the pool. 262789Sahrens */ 263789Sahrens uint64_t 264789Sahrens zpool_get_space_used(zpool_handle_t *zhp) 265789Sahrens { 266789Sahrens nvlist_t *nvroot; 267789Sahrens vdev_stat_t *vs; 268789Sahrens uint_t vsc; 269789Sahrens 270789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 271789Sahrens &nvroot) == 0); 272789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 273789Sahrens (uint64_t **)&vs, &vsc) == 0); 274789Sahrens 275789Sahrens return (vs->vs_alloc); 276789Sahrens } 277789Sahrens 278789Sahrens /* 279789Sahrens * Return the total space in the pool. 280789Sahrens */ 281789Sahrens uint64_t 282789Sahrens zpool_get_space_total(zpool_handle_t *zhp) 283789Sahrens { 284789Sahrens nvlist_t *nvroot; 285789Sahrens vdev_stat_t *vs; 286789Sahrens uint_t vsc; 287789Sahrens 288789Sahrens verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 289789Sahrens &nvroot) == 0); 290789Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 291789Sahrens (uint64_t **)&vs, &vsc) == 0); 292789Sahrens 293789Sahrens return (vs->vs_space); 294789Sahrens } 295789Sahrens 296789Sahrens /* 297789Sahrens * Return the alternate root for this pool, if any. 298789Sahrens */ 299789Sahrens int 300789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen) 301789Sahrens { 302789Sahrens zfs_cmd_t zc = { 0 }; 303789Sahrens 304789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 305789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 || 306789Sahrens zc.zc_objset_stats.dds_altroot[0] == '\0') 307789Sahrens return (-1); 308789Sahrens 309789Sahrens (void) strlcpy(buf, zc.zc_objset_stats.dds_altroot, buflen); 310789Sahrens 311789Sahrens return (0); 312789Sahrens } 313789Sahrens 314789Sahrens /* 315789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 316789Sahrens */ 317789Sahrens int 318789Sahrens zpool_get_state(zpool_handle_t *zhp) 319789Sahrens { 320789Sahrens return (zhp->zpool_state); 321789Sahrens } 322789Sahrens 323789Sahrens /* 324789Sahrens * Create the named pool, using the provided vdev list. It is assumed 325789Sahrens * that the consumer has already validated the contents of the nvlist, so we 326789Sahrens * don't have to worry about error semantics. 327789Sahrens */ 328789Sahrens int 329789Sahrens zpool_create(const char *pool, nvlist_t *nvroot, const char *altroot) 330789Sahrens { 331789Sahrens zfs_cmd_t zc = { 0 }; 332789Sahrens char *packed; 333789Sahrens size_t len; 334789Sahrens int err; 335789Sahrens char reason[64]; 336789Sahrens 337789Sahrens if (!zpool_name_valid(pool, reason, sizeof (reason))) { 338789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': %s"), 339789Sahrens pool, reason); 340789Sahrens return (-1); 341789Sahrens } 342789Sahrens 343789Sahrens if (altroot != NULL && altroot[0] != '/') { 344789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': alternate " 345789Sahrens "root '%s' must be a complete path"), pool, altroot); 346789Sahrens return (-1); 347789Sahrens } 348789Sahrens 349789Sahrens if ((err = nvlist_size(nvroot, &len, NV_ENCODE_NATIVE)) != 0) 350789Sahrens zfs_baderror(err); 351789Sahrens 352789Sahrens packed = zfs_malloc(len); 353789Sahrens 354789Sahrens if ((err = nvlist_pack(nvroot, &packed, &len, 355789Sahrens NV_ENCODE_NATIVE, 0)) != 0) 356789Sahrens zfs_baderror(err); 357789Sahrens 358789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 359789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 360789Sahrens zc.zc_config_src_size = len; 361789Sahrens 362789Sahrens if (altroot != NULL) 363789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 364789Sahrens 365789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { 366789Sahrens switch (errno) { 367789Sahrens case EEXIST: 368789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 369789Sahrens "pool exists"), pool); 370789Sahrens break; 371789Sahrens 372789Sahrens case EPERM: 373789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 374789Sahrens "permission denied"), pool); 375789Sahrens break; 376789Sahrens 377789Sahrens case EBUSY: 378789Sahrens /* 379789Sahrens * This can happen if the user has specified the same 380789Sahrens * device multiple times. We can't reliably detect this 381789Sahrens * until we try to add it and see we already have a 382789Sahrens * label. 383789Sahrens */ 384789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 385789Sahrens "one or more vdevs refer to the same device"), 386789Sahrens pool); 387789Sahrens break; 388789Sahrens 389789Sahrens case EOVERFLOW: 390789Sahrens /* 391789Sahrens * This occurrs when one of the devices is below 392789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 393789Sahrens * device was the problem device since there's no 394789Sahrens * reliable way to determine device size from userland. 395789Sahrens */ 396789Sahrens { 397789Sahrens char buf[64]; 398789Sahrens 399789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 400789Sahrens 401789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 402789Sahrens "create '%s': one or more devices is less " 403789Sahrens "than the minimum size (%s)"), pool, 404789Sahrens buf); 405789Sahrens } 406789Sahrens break; 407789Sahrens 408789Sahrens case ENAMETOOLONG: 409789Sahrens /* 410789Sahrens * One of the vdevs has exceeded VDEV_SPEC_MAX length in 411789Sahrens * its plaintext representation. 412789Sahrens */ 413789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 414789Sahrens "too many devices in a single vdev"), pool); 415789Sahrens break; 416789Sahrens 417789Sahrens case EIO: 418789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 419789Sahrens "I/O error on one or more devices"), pool); 420789Sahrens break; 421789Sahrens 422789Sahrens case ENXIO: 423789Sahrens /* 424789Sahrens * This is unlikely to happen since we've verified that 425789Sahrens * all the devices can be opened from userland, but it's 426789Sahrens * still possible in some circumstances. 427789Sahrens */ 428789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 429789Sahrens "one or more devices is unavailable"), pool); 430789Sahrens break; 431789Sahrens 432789Sahrens case ENOSPC: 433789Sahrens /* 434789Sahrens * This can occur if we were incapable of writing to a 435789Sahrens * file vdev because the underlying filesystem is out of 436789Sahrens * space. This is very similar to EOVERFLOW, but we'll 437789Sahrens * produce a slightly different message. 438789Sahrens */ 439789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 440789Sahrens "one or more devices is out of space"), pool); 441789Sahrens break; 442789Sahrens 443789Sahrens default: 444789Sahrens zfs_baderror(errno); 445789Sahrens } 446789Sahrens 447789Sahrens return (-1); 448789Sahrens } 449789Sahrens 450789Sahrens free(packed); 451789Sahrens 452789Sahrens /* 453789Sahrens * If this is an alternate root pool, then we automatically set the 454789Sahrens * moutnpoint of the root dataset to be '/'. 455789Sahrens */ 456789Sahrens if (altroot != NULL) { 457789Sahrens zfs_handle_t *zhp; 458789Sahrens 459789Sahrens verify((zhp = zfs_open(pool, ZFS_TYPE_ANY)) != NULL); 460789Sahrens verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0); 461789Sahrens 462789Sahrens zfs_close(zhp); 463789Sahrens } 464789Sahrens 465789Sahrens return (0); 466789Sahrens } 467789Sahrens 468789Sahrens /* 469789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 470789Sahrens * datasets left in the pool. 471789Sahrens */ 472789Sahrens int 473789Sahrens zpool_destroy(zpool_handle_t *zhp) 474789Sahrens { 475789Sahrens zfs_cmd_t zc = { 0 }; 476789Sahrens zfs_handle_t *zfp = NULL; 477789Sahrens 478789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 479789Sahrens (zfp = zfs_open(zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL) 480789Sahrens return (-1); 481789Sahrens 482789Sahrens if (zpool_remove_zvol_links(zhp) != NULL) 483789Sahrens return (-1); 484789Sahrens 485789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 486789Sahrens 487789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 488789Sahrens switch (errno) { 489789Sahrens case EPERM: 490789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 491789Sahrens "cannot destroy '%s': permission denied"), 492789Sahrens zhp->zpool_name); 493789Sahrens break; 494789Sahrens 495789Sahrens case EBUSY: 496789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 497789Sahrens "cannot destroy '%s': pool busy"), 498789Sahrens zhp->zpool_name); 499789Sahrens break; 500789Sahrens 501789Sahrens case ENOENT: 502789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 503789Sahrens "cannot destroy '%s': no such pool"), 504789Sahrens zhp->zpool_name); 505789Sahrens break; 506789Sahrens 507789Sahrens case EROFS: 508789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 509789Sahrens "cannot destroy '%s': one or more devices is " 510789Sahrens "read only, or '/' is mounted read only"), 511789Sahrens zhp->zpool_name); 512789Sahrens break; 513789Sahrens 514789Sahrens default: 515789Sahrens zfs_baderror(errno); 516789Sahrens } 517789Sahrens 518789Sahrens if (zfp) 519789Sahrens zfs_close(zfp); 520789Sahrens return (-1); 521789Sahrens } 522789Sahrens 523789Sahrens if (zfp) { 524789Sahrens remove_mountpoint(zfp); 525789Sahrens zfs_close(zfp); 526789Sahrens } 527789Sahrens 528789Sahrens return (0); 529789Sahrens } 530789Sahrens 531789Sahrens /* 532789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 533789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 534789Sahrens */ 535789Sahrens int 536789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 537789Sahrens { 538789Sahrens char *packed; 539789Sahrens size_t len; 540789Sahrens zfs_cmd_t zc; 541789Sahrens 542789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 543789Sahrens 544789Sahrens packed = zfs_malloc(len); 545789Sahrens 546789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 547789Sahrens 548789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 549789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 550789Sahrens zc.zc_config_src_size = len; 551789Sahrens 552789Sahrens if (ioctl(zfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { 553789Sahrens switch (errno) { 554789Sahrens case EPERM: 555789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 556789Sahrens "permission denied"), zhp->zpool_name); 557789Sahrens break; 558789Sahrens 559789Sahrens case EBUSY: 560789Sahrens /* 561789Sahrens * This can happen if the user has specified the same 562789Sahrens * device multiple times. We can't reliably detect this 563789Sahrens * until we try to add it and see we already have a 564789Sahrens * label. 565789Sahrens */ 566789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 567789Sahrens "one or more vdevs refer to the same device"), 568789Sahrens zhp->zpool_name); 569789Sahrens break; 570789Sahrens 571789Sahrens case ENAMETOOLONG: 572789Sahrens /* 573789Sahrens * One of the vdevs has exceeded VDEV_SPEC_MAX length in 574789Sahrens * its plaintext representation. 575789Sahrens */ 576789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 577789Sahrens "too many devices in a single vdev"), 578789Sahrens zhp->zpool_name); 579789Sahrens break; 580789Sahrens 581789Sahrens case ENXIO: 582789Sahrens /* 583789Sahrens * This is unlikely to happen since we've verified that 584789Sahrens * all the devices can be opened from userland, but it's 585789Sahrens * still possible in some circumstances. 586789Sahrens */ 587789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': " 588789Sahrens "one or more devices is unavailable"), 589789Sahrens zhp->zpool_name); 590789Sahrens break; 591789Sahrens 592789Sahrens case EOVERFLOW: 593789Sahrens /* 594789Sahrens * This occurrs when one of the devices is below 595789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 596789Sahrens * device was the problem device since there's no 597789Sahrens * reliable way to determine device size from userland. 598789Sahrens */ 599789Sahrens { 600789Sahrens char buf[64]; 601789Sahrens 602789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 603789Sahrens 604789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 605789Sahrens "add to '%s': one or more devices is less " 606789Sahrens "than the minimum size (%s)"), 607789Sahrens zhp->zpool_name, buf); 608789Sahrens } 609789Sahrens break; 610789Sahrens 611789Sahrens default: 612789Sahrens zfs_baderror(errno); 613789Sahrens } 614789Sahrens 615789Sahrens return (-1); 616789Sahrens } 617789Sahrens 618789Sahrens free(packed); 619789Sahrens 620789Sahrens return (0); 621789Sahrens } 622789Sahrens 623789Sahrens /* 624789Sahrens * Exports the pool from the system. The caller must ensure that there are no 625789Sahrens * mounted datasets in the pool. 626789Sahrens */ 627789Sahrens int 628789Sahrens zpool_export(zpool_handle_t *zhp) 629789Sahrens { 630789Sahrens zfs_cmd_t zc = { 0 }; 631789Sahrens 632789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 633789Sahrens return (-1); 634789Sahrens 635789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 636789Sahrens 637789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) { 638789Sahrens switch (errno) { 639789Sahrens case EPERM: 640789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 641789Sahrens "cannot export '%s': permission denied"), 642789Sahrens zhp->zpool_name); 643789Sahrens break; 644789Sahrens 645789Sahrens case EBUSY: 646789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 647789Sahrens "cannot export '%s': pool is in use"), 648789Sahrens zhp->zpool_name); 649789Sahrens break; 650789Sahrens 651789Sahrens case ENOENT: 652789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 653789Sahrens "cannot export '%s': no such pool"), 654789Sahrens zhp->zpool_name); 655789Sahrens break; 656789Sahrens 657789Sahrens default: 658789Sahrens zfs_baderror(errno); 659789Sahrens } 660789Sahrens 661789Sahrens return (-1); 662789Sahrens } 663789Sahrens 664789Sahrens return (0); 665789Sahrens } 666789Sahrens 667789Sahrens /* 668789Sahrens * Import the given pool using the known configuration. The configuration 669789Sahrens * should have come from zpool_find_import(). The 'newname' and 'altroot' 670789Sahrens * parameters control whether the pool is imported with a different name or with 671789Sahrens * an alternate root, respectively. 672789Sahrens */ 673789Sahrens int 674789Sahrens zpool_import(nvlist_t *config, const char *newname, const char *altroot) 675789Sahrens { 676789Sahrens zfs_cmd_t zc; 677789Sahrens char *packed; 678789Sahrens size_t len; 679789Sahrens char *thename; 680789Sahrens char *origname; 681789Sahrens int ret; 682789Sahrens 683789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 684789Sahrens &origname) == 0); 685789Sahrens 686789Sahrens if (newname != NULL) { 687789Sahrens if (!zpool_name_valid(newname, NULL, 0)) { 688789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': " 689789Sahrens "invalid pool name"), newname); 690789Sahrens return (-1); 691789Sahrens } 692789Sahrens thename = (char *)newname; 693789Sahrens } else { 694789Sahrens thename = origname; 695789Sahrens } 696789Sahrens 697789Sahrens if (altroot != NULL && altroot[0] != '/') { 698789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': alternate " 699789Sahrens "root '%s' must be a complete path"), thename, 700789Sahrens altroot); 701789Sahrens return (-1); 702789Sahrens } 703789Sahrens 704789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 705789Sahrens 706789Sahrens if (altroot != NULL) 707789Sahrens (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); 708789Sahrens else 709789Sahrens zc.zc_root[0] = '\0'; 710789Sahrens 711789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 712789Sahrens &zc.zc_pool_guid) == 0); 713789Sahrens 714789Sahrens verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0); 715789Sahrens 716789Sahrens packed = zfs_malloc(len); 717789Sahrens 718789Sahrens verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 719789Sahrens 720789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 721789Sahrens zc.zc_config_src_size = len; 722789Sahrens 723789Sahrens ret = 0; 724789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 725789Sahrens char desc[1024]; 726789Sahrens if (newname == NULL) 727789Sahrens (void) snprintf(desc, sizeof (desc), 728789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 729789Sahrens thename); 730789Sahrens else 731789Sahrens (void) snprintf(desc, sizeof (desc), 732789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 733789Sahrens origname, thename); 734789Sahrens 735789Sahrens switch (errno) { 736789Sahrens case EEXIST: 737789Sahrens /* 738789Sahrens * A pool with that name already exists. 739789Sahrens */ 740789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: pool exists"), 741789Sahrens desc); 742789Sahrens break; 743789Sahrens 744789Sahrens case EPERM: 745789Sahrens /* 746789Sahrens * The user doesn't have permission to create pools. 747789Sahrens */ 748789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission " 749789Sahrens "denied"), desc); 750789Sahrens break; 751789Sahrens 752789Sahrens case ENXIO: 753789Sahrens case EDOM: 754789Sahrens /* 755789Sahrens * Device is unavailable, or vdev sum didn't match. 756789Sahrens */ 757789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: one or more " 758789Sahrens "devices is unavailable"), 759789Sahrens desc); 760789Sahrens break; 761789Sahrens 762789Sahrens default: 763789Sahrens zfs_baderror(errno); 764789Sahrens } 765789Sahrens 766789Sahrens ret = -1; 767789Sahrens } else { 768789Sahrens zpool_handle_t *zhp; 769789Sahrens /* 770789Sahrens * This should never fail, but play it safe anyway. 771789Sahrens */ 772789Sahrens if ((zhp = zpool_open_silent(thename)) != NULL) { 773789Sahrens ret = zpool_create_zvol_links(zhp); 774789Sahrens zpool_close(zhp); 775789Sahrens } 776789Sahrens } 777789Sahrens 778789Sahrens free(packed); 779789Sahrens return (ret); 780789Sahrens } 781789Sahrens 782789Sahrens /* 783789Sahrens * Scrub the pool. 784789Sahrens */ 785789Sahrens int 786789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 787789Sahrens { 788789Sahrens zfs_cmd_t zc = { 0 }; 789789Sahrens char msg[1024]; 790789Sahrens 791789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 792789Sahrens zc.zc_cookie = type; 793789Sahrens 794789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0) 795789Sahrens return (0); 796789Sahrens 797789Sahrens (void) snprintf(msg, sizeof (msg), 798789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 799789Sahrens 800789Sahrens switch (errno) { 801789Sahrens case EPERM: 802789Sahrens /* 803789Sahrens * No permission to scrub this pool. 804789Sahrens */ 805789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 806789Sahrens break; 807789Sahrens 808789Sahrens case EBUSY: 809789Sahrens /* 810789Sahrens * Resilver in progress. 811789Sahrens */ 812789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: currently resilvering"), 813789Sahrens msg); 814789Sahrens break; 815789Sahrens 816789Sahrens default: 817789Sahrens zfs_baderror(errno); 818789Sahrens } 819789Sahrens return (-1); 820789Sahrens } 821789Sahrens 822789Sahrens /* 823789Sahrens * Bring the specified vdev online 824789Sahrens */ 825789Sahrens int 826789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path) 827789Sahrens { 828789Sahrens zfs_cmd_t zc = { 0 }; 829789Sahrens char msg[1024]; 830789Sahrens 831789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 832789Sahrens (void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value), 833789Sahrens "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path); 834789Sahrens 835789Sahrens if (ioctl(zfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) 836789Sahrens return (0); 837789Sahrens 838789Sahrens (void) snprintf(msg, sizeof (msg), 839789Sahrens dgettext(TEXT_DOMAIN, "cannot online %s"), zc.zc_prop_value); 840789Sahrens 841789Sahrens switch (errno) { 842789Sahrens case ENODEV: 843789Sahrens /* 844789Sahrens * Device doesn't exist 845789Sahrens */ 846789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 847789Sahrens break; 848789Sahrens 849789Sahrens case EPERM: 850789Sahrens /* 851789Sahrens * No permission to bring this vdev online. 852789Sahrens */ 853789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 854789Sahrens break; 855789Sahrens 856789Sahrens default: 857789Sahrens zfs_baderror(errno); 858789Sahrens } 859789Sahrens return (-1); 860789Sahrens } 861789Sahrens 862789Sahrens /* 863789Sahrens * Take the specified vdev offline 864789Sahrens */ 865789Sahrens int 866789Sahrens zpool_vdev_offline(zpool_handle_t *zhp, const char *path) 867789Sahrens { 868789Sahrens zfs_cmd_t zc = { 0 }; 869789Sahrens char msg[1024]; 870789Sahrens 871789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 872789Sahrens (void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value), 873789Sahrens "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path); 874789Sahrens 875789Sahrens if (ioctl(zfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) 876789Sahrens return (0); 877789Sahrens 878789Sahrens (void) snprintf(msg, sizeof (msg), 879789Sahrens dgettext(TEXT_DOMAIN, "cannot offline %s"), zc.zc_prop_value); 880789Sahrens 881789Sahrens switch (errno) { 882789Sahrens case ENODEV: 883789Sahrens /* 884789Sahrens * Device doesn't exist 885789Sahrens */ 886789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 887789Sahrens break; 888789Sahrens 889789Sahrens case EPERM: 890789Sahrens /* 891789Sahrens * No permission to take this vdev offline. 892789Sahrens */ 893789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 894789Sahrens break; 895789Sahrens 896789Sahrens case EBUSY: 897789Sahrens /* 898789Sahrens * There are no other replicas of this device. 899789Sahrens */ 900789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg); 901789Sahrens break; 902789Sahrens 903789Sahrens default: 904789Sahrens zfs_baderror(errno); 905789Sahrens } 906789Sahrens return (-1); 907789Sahrens } 908789Sahrens 909789Sahrens /* 910789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 911789Sahrens * If 'replacing' is specified, tne new disk will replace the old one. 912789Sahrens */ 913789Sahrens int 914789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 915789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 916789Sahrens { 917789Sahrens zfs_cmd_t zc = { 0 }; 918789Sahrens char msg[1024]; 919789Sahrens char *packed; 920789Sahrens int ret; 921789Sahrens size_t len; 922789Sahrens 923789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 924789Sahrens (void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value), 925789Sahrens "%s%s", old_disk[0] == '/' ? "" : "/dev/dsk/", old_disk); 926789Sahrens zc.zc_cookie = replacing; 927789Sahrens 928789Sahrens verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); 929789Sahrens 930789Sahrens packed = zfs_malloc(len); 931789Sahrens 932789Sahrens verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 933789Sahrens 934789Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 935789Sahrens zc.zc_config_src_size = len; 936789Sahrens 937789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); 938789Sahrens 939789Sahrens free(packed); 940789Sahrens 941789Sahrens if (ret == 0) 942789Sahrens return (0); 943789Sahrens 944789Sahrens if (replacing) 945789Sahrens (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 946789Sahrens "cannot replace %s with %s"), old_disk, new_disk); 947789Sahrens else 948789Sahrens (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 949789Sahrens "cannot attach %s to %s"), new_disk, old_disk); 950789Sahrens 951789Sahrens switch (errno) { 952789Sahrens case EPERM: 953789Sahrens /* 954789Sahrens * No permission to mess with the config. 955789Sahrens */ 956789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 957789Sahrens break; 958789Sahrens 959789Sahrens case ENODEV: 960789Sahrens /* 961789Sahrens * Device doesn't exist. 962789Sahrens */ 963789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s not in pool"), 964789Sahrens msg, old_disk); 965789Sahrens break; 966789Sahrens 967789Sahrens case ENOTSUP: 968789Sahrens /* 969789Sahrens * Can't attach to or replace this type of vdev. 970789Sahrens */ 971789Sahrens if (replacing) 972789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 973789Sahrens "%s: cannot replace a replacing device"), msg); 974789Sahrens else 975789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 976789Sahrens "%s: attach is only applicable to mirrors"), msg); 977789Sahrens break; 978789Sahrens 979789Sahrens case EINVAL: 980789Sahrens /* 981789Sahrens * The new device must be a single disk. 982789Sahrens */ 983789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 984789Sahrens "%s: <new_device> must be a single disk"), msg); 985789Sahrens break; 986789Sahrens 987789Sahrens case ENXIO: 988789Sahrens /* 989789Sahrens * This is unlikely to happen since we've verified that 990789Sahrens * all the devices can be opened from userland, but it's 991789Sahrens * still possible in some circumstances. 992789Sahrens */ 993789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is unavailable"), 994789Sahrens msg, new_disk); 995789Sahrens break; 996789Sahrens 997789Sahrens case EBUSY: 998789Sahrens /* 999789Sahrens * The new device is is use. 1000789Sahrens */ 1001789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s busy"), msg, new_disk); 1002789Sahrens break; 1003789Sahrens 1004789Sahrens case EOVERFLOW: 1005789Sahrens /* 1006789Sahrens * The new device is too small. 1007789Sahrens */ 1008789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is too small"), 1009789Sahrens msg, new_disk); 1010789Sahrens break; 1011789Sahrens 1012789Sahrens case EDOM: 1013789Sahrens /* 1014789Sahrens * The new device has a different alignment requirement. 1015789Sahrens */ 1016789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1017789Sahrens "%s: devices have different sector alignment"), msg); 1018789Sahrens break; 1019789Sahrens 1020789Sahrens case ENAMETOOLONG: 1021789Sahrens /* 1022789Sahrens * The resulting top-level vdev spec won't fit in the label. 1023789Sahrens */ 1024789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1025789Sahrens "%s: too many devices in a single vdev"), msg); 1026789Sahrens break; 1027789Sahrens 1028789Sahrens default: 1029789Sahrens zfs_baderror(errno); 1030789Sahrens } 1031789Sahrens 1032789Sahrens return (1); 1033789Sahrens } 1034789Sahrens 1035789Sahrens /* 1036789Sahrens * Detach the specified device. 1037789Sahrens */ 1038789Sahrens int 1039789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1040789Sahrens { 1041789Sahrens zfs_cmd_t zc = { 0 }; 1042789Sahrens char msg[1024]; 1043789Sahrens 1044789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1045789Sahrens (void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value), 1046789Sahrens "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path); 1047789Sahrens 1048789Sahrens if (ioctl(zfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1049789Sahrens return (0); 1050789Sahrens 1051789Sahrens (void) snprintf(msg, sizeof (msg), 1052789Sahrens dgettext(TEXT_DOMAIN, "cannot detach %s"), zc.zc_prop_value); 1053789Sahrens 1054789Sahrens switch (errno) { 1055789Sahrens case EPERM: 1056789Sahrens /* 1057789Sahrens * No permission to mess with the config. 1058789Sahrens */ 1059789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg); 1060789Sahrens break; 1061789Sahrens 1062789Sahrens case ENODEV: 1063789Sahrens /* 1064789Sahrens * Device doesn't exist. 1065789Sahrens */ 1066789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg); 1067789Sahrens break; 1068789Sahrens 1069789Sahrens case ENOTSUP: 1070789Sahrens /* 1071789Sahrens * Can't detach from this type of vdev. 1072789Sahrens */ 1073789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1074789Sahrens "%s: only applicable to mirror and replacing vdevs"), msg); 1075789Sahrens break; 1076789Sahrens 1077789Sahrens case EBUSY: 1078789Sahrens /* 1079789Sahrens * There are no other replicas of this device. 1080789Sahrens */ 1081789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg); 1082789Sahrens break; 1083789Sahrens 1084789Sahrens default: 1085789Sahrens zfs_baderror(errno); 1086789Sahrens } 1087789Sahrens 1088789Sahrens return (1); 1089789Sahrens } 1090789Sahrens 1091789Sahrens static int 1092789Sahrens do_zvol(zfs_handle_t *zhp, void *data) 1093789Sahrens { 1094789Sahrens int linktype = (int)(uintptr_t)data; 1095789Sahrens int ret; 1096789Sahrens 1097789Sahrens /* 1098789Sahrens * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we 1099789Sahrens * correctly handle snapshots of volumes. 1100789Sahrens */ 1101789Sahrens if (zhp->zfs_volblocksize != 0) { 1102789Sahrens if (linktype) 1103789Sahrens ret = zvol_create_link(zhp->zfs_name); 1104789Sahrens else 1105789Sahrens ret = zvol_remove_link(zhp->zfs_name); 1106789Sahrens } 1107789Sahrens 1108789Sahrens ret = zfs_iter_children(zhp, do_zvol, data); 1109789Sahrens 1110789Sahrens zfs_close(zhp); 1111789Sahrens return (ret); 1112789Sahrens } 1113789Sahrens 1114789Sahrens /* 1115789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1116789Sahrens */ 1117789Sahrens int 1118789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1119789Sahrens { 1120789Sahrens zfs_handle_t *zfp; 1121789Sahrens int ret; 1122789Sahrens 1123789Sahrens /* 1124789Sahrens * If the pool is unavailable, just return success. 1125789Sahrens */ 1126789Sahrens if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL) 1127789Sahrens return (0); 1128789Sahrens 1129789Sahrens ret = zfs_iter_children(zfp, do_zvol, (void *)TRUE); 1130789Sahrens 1131789Sahrens zfs_close(zfp); 1132789Sahrens return (ret); 1133789Sahrens } 1134789Sahrens 1135789Sahrens /* 1136789Sahrens * Iterate over all zvols in the poool and remove any minor nodes. 1137789Sahrens */ 1138789Sahrens int 1139789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1140789Sahrens { 1141789Sahrens zfs_handle_t *zfp; 1142789Sahrens int ret; 1143789Sahrens 1144789Sahrens /* 1145789Sahrens * If the pool is unavailable, just return success. 1146789Sahrens */ 1147789Sahrens if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL) 1148789Sahrens return (0); 1149789Sahrens 1150789Sahrens ret = zfs_iter_children(zfp, do_zvol, (void *)FALSE); 1151789Sahrens 1152789Sahrens zfs_close(zfp); 1153789Sahrens return (ret); 1154789Sahrens } 1155