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