diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/zdb/zdb.c | 24 | ||||
-rw-r--r-- | cmd/zpool/zpool_main.c | 151 | ||||
-rw-r--r-- | cmd/zpool/zpool_vdev.c | 33 |
3 files changed, 115 insertions, 93 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index d5b8a7745..b58b709e7 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -2515,13 +2515,37 @@ dump_label(const char *dev) bzero(labels, sizeof (labels)); + /* + * Check if we were given absolute path and use it as is. + * Otherwise if the provided vdev name doesn't point to a file, + * try prepending expected disk paths and partition numbers. + */ (void) strlcpy(path, dev, sizeof (path)); + if (dev[0] != '/' && stat64(path, &statbuf) != 0) { + int error; + + error = zfs_resolve_shortname(dev, path, MAXPATHLEN); + if (error == 0 && zfs_dev_is_whole_disk(path)) { + if (zfs_append_partition(path, MAXPATHLEN) == -1) + error = ENOENT; + } + + if (error || (stat64(path, &statbuf) != 0)) { + (void) printf("failed to find device %s, try " + "specifying absolute path instead\n", dev); + return (1); + } + } if ((fd = open64(path, O_RDONLY)) < 0) { (void) printf("cannot open '%s': %s\n", path, strerror(errno)); exit(1); } + if (ioctl(fd, BLKFLSBUF) != 0) + (void) printf("failed to invalidate cache '%s' : %s\n", path, + strerror(errno)); + if (fstat64_blk(fd, &statbuf) != 0) { (void) printf("failed to stat '%s': %s\n", path, strerror(errno)); diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index b984f5583..ebadccf19 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -790,7 +790,10 @@ zpool_do_remove(int argc, char **argv) } /* - * zpool labelclear <vdev> + * zpool labelclear [-f] <vdev> + * + * -f Force clearing the label for the vdevs which are members of + * the exported or foreign pools. * * Verifies that the vdev is not active and zeros out the label information * on the device. @@ -798,8 +801,11 @@ zpool_do_remove(int argc, char **argv) int zpool_do_labelclear(int argc, char **argv) { - char *vdev, *name; + char vdev[MAXPATHLEN]; + char *name = NULL; + struct stat st; int c, fd = -1, ret = 0; + nvlist_t *config; pool_state_t state; boolean_t inuse = B_FALSE; boolean_t force = B_FALSE; @@ -822,90 +828,107 @@ zpool_do_labelclear(int argc, char **argv) /* get vdev name */ if (argc < 1) { - (void) fprintf(stderr, gettext("missing vdev device name\n")); + (void) fprintf(stderr, gettext("missing vdev name\n")); usage(B_FALSE); } - - vdev = argv[0]; - if ((fd = open(vdev, O_RDWR)) < 0) { - (void) fprintf(stderr, gettext("Unable to open %s\n"), vdev); - return (B_FALSE); + if (argc > 1) { + (void) fprintf(stderr, gettext("too many arguments\n")); + usage(B_FALSE); } - name = NULL; - if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) { - if (force) - goto wipe_label; + /* + * Check if we were given absolute path and use it as is. + * Otherwise if the provided vdev name doesn't point to a file, + * try prepending expected disk paths and partition numbers. + */ + (void) strlcpy(vdev, argv[0], sizeof (vdev)); + if (vdev[0] != '/' && stat(vdev, &st) != 0) { + int error; + + error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN); + if (error == 0 && zfs_dev_is_whole_disk(vdev)) { + if (zfs_append_partition(vdev, MAXPATHLEN) == -1) + error = ENOENT; + } - (void) fprintf(stderr, - gettext("Unable to determine pool state for %s\n" - "Use -f to force the clearing any label data\n"), vdev); + if (error || (stat(vdev, &st) != 0)) { + (void) fprintf(stderr, gettext( + "failed to find device %s, try specifying absolute " + "path instead\n"), argv[0]); + return (1); + } + } + if ((fd = open(vdev, O_RDWR)) < 0) { + (void) fprintf(stderr, gettext("failed to open %s: %s\n"), + vdev, strerror(errno)); return (1); } - if (inuse) { - switch (state) { - default: - case POOL_STATE_ACTIVE: - case POOL_STATE_SPARE: - case POOL_STATE_L2CACHE: - (void) fprintf(stderr, - gettext("labelclear operation failed.\n" - "\tVdev %s is a member (%s), of pool \"%s\".\n" - "\tTo remove label information from this device, " - "export or destroy\n\tthe pool, or remove %s from " - "the configuration of this pool\n\tand retry the " - "labelclear operation.\n"), - vdev, zpool_pool_state_to_name(state), name, vdev); - ret = 1; - goto errout; + if (zpool_read_label(fd, &config, NULL) != 0 || config == NULL) { + (void) fprintf(stderr, + gettext("failed to check state for %s\n"), vdev); + return (1); + } + nvlist_free(config); - case POOL_STATE_EXPORTED: - if (force) - break; + ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); + if (ret != 0) { + (void) fprintf(stderr, + gettext("failed to check state for %s\n"), vdev); + return (1); + } - (void) fprintf(stderr, - gettext("labelclear operation failed.\n\tVdev " - "%s is a member of the exported pool \"%s\".\n" - "\tUse \"zpool labelclear -f %s\" to force the " - "removal of label\n\tinformation.\n"), - vdev, name, vdev); - ret = 1; - goto errout; + if (!inuse) + goto wipe_label; - case POOL_STATE_POTENTIALLY_ACTIVE: - if (force) - break; + switch (state) { + default: + case POOL_STATE_ACTIVE: + case POOL_STATE_SPARE: + case POOL_STATE_L2CACHE: + (void) fprintf(stderr, gettext( + "%s is a member (%s) of pool \"%s\"\n"), + vdev, zpool_pool_state_to_name(state), name); + ret = 1; + goto errout; - (void) fprintf(stderr, - gettext("labelclear operation failed.\n" - "\tVdev %s is a member of the pool \"%s\".\n" - "\tThis pool is unknown to this system, but may " - "be active on\n\tanother system. Use " - "\'zpool labelclear -f %s\' to force the\n" - "\tremoval of label information.\n"), - vdev, name, vdev); - ret = 1; - goto errout; + case POOL_STATE_EXPORTED: + if (force) + break; + (void) fprintf(stderr, gettext( + "use '-f' to override the following error:\n" + "%s is a member of exported pool \"%s\"\n"), + vdev, name); + ret = 1; + goto errout; - case POOL_STATE_DESTROYED: - /* inuse should never be set for a destroyed pool... */ + case POOL_STATE_POTENTIALLY_ACTIVE: + if (force) break; - } + (void) fprintf(stderr, gettext( + "use '-f' to override the following error:\n" + "%s is a member of potentially active pool \"%s\"\n"), + vdev, name); + ret = 1; + goto errout; + + case POOL_STATE_DESTROYED: + /* inuse should never be set for a destroyed pool */ + assert(0); + break; } wipe_label: - if (zpool_clear_label(fd) != 0) { + ret = zpool_clear_label(fd); + if (ret != 0) { (void) fprintf(stderr, - gettext("Label clear failed on vdev %s\n"), vdev); - ret = 1; + gettext("failed to clear label for %s\n"), vdev); } errout: - close(fd); - if (name != NULL) - free(name); + free(name); + (void) close(fd); return (ret); } diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index f1b27cb51..c96157eff 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -507,31 +507,6 @@ check_device(const char *path, boolean_t force, } /* - * By "whole disk" we mean an entire physical disk (something we can - * label, toggle the write cache on, etc.) as opposed to the full - * capacity of a pseudo-device such as lofi or did. We act as if we - * are labeling the disk, which should be a pretty good test of whether - * it's a viable device or not. Returns B_TRUE if it is and B_FALSE if - * it isn't. - */ -static boolean_t -is_whole_disk(const char *path) -{ - struct dk_gpt *label; - int fd; - - if ((fd = open(path, O_RDONLY|O_DIRECT)) < 0) - return (B_FALSE); - if (efi_alloc_and_init(fd, EFI_NUMPAR, &label) != 0) { - (void) close(fd); - return (B_FALSE); - } - efi_free(label); - (void) close(fd); - return (B_TRUE); -} - -/* * This may be a shorthand device path or it could be total gibberish. * Check to see if it is a known device available in zfs_vdev_paths. * As part of this check, see if we've been given an entire disk @@ -545,7 +520,7 @@ is_shorthand_path(const char *arg, char *path, size_t path_size, error = zfs_resolve_shortname(arg, path, path_size); if (error == 0) { - *wholedisk = is_whole_disk(path); + *wholedisk = zfs_dev_is_whole_disk(path); if (*wholedisk || (stat64(path, statbuf) == 0)) return (0); } @@ -640,7 +615,7 @@ make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log) /* * Complete device or file path. Exact type is determined by * examining the file descriptor afterwards. Symbolic links - * are resolved to their real paths for the is_whole_disk() + * are resolved to their real paths to determine whole disk * and S_ISBLK/S_ISREG type checks. However, we are careful * to store the given path as ZPOOL_CONFIG_PATH to ensure we * can leverage udev's persistent device labels. @@ -651,7 +626,7 @@ make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log) return (NULL); } - wholedisk = is_whole_disk(path); + wholedisk = zfs_dev_is_whole_disk(path); if (!wholedisk && (stat64(path, &statbuf) != 0)) { (void) fprintf(stderr, gettext("cannot open '%s': %s\n"), @@ -659,7 +634,7 @@ make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log) return (NULL); } - /* After is_whole_disk() check restore original passed path */ + /* After whole disk check restore original passed path */ strlcpy(path, arg, sizeof (path)); } else { err = is_shorthand_path(arg, path, sizeof (path), |