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