summaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/zdb/zdb.c24
-rw-r--r--cmd/zpool/zpool_main.c151
-rw-r--r--cmd/zpool/zpool_vdev.c33
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),