diff options
author | Dmitry Khasanov <[email protected]> | 2013-07-05 18:01:44 +0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-07-09 15:58:05 -0700 |
commit | 131cc95ca78b8552c13555d2cded791808008ff3 (patch) | |
tree | 90018a1dc98bcc07bcf98f1cb15bc5672409ee15 /cmd/zpool | |
parent | 51a3ae72d23d89d35a4a67059b39e870d66a2495 (diff) |
Add FreeBSD 'zpool labelclear' command
The FreeBSD implementation of zfs adds the 'zpool labelclear'
command. Since this functionality is helpful and straight
forward to add it is being included in ZoL.
References:
freebsd/freebsd@119a041dc9230275239a8de68c534c0754181e7e
Ported-by: Dmitry Khasanov <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #1126
Diffstat (limited to 'cmd/zpool')
-rw-r--r-- | cmd/zpool/zpool_main.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 19f1f28a9..da9f3e1a3 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -63,6 +63,7 @@ static int zpool_do_destroy(int, char **); static int zpool_do_add(int, char **); static int zpool_do_remove(int, char **); +static int zpool_do_labelclear(int, char **); static int zpool_do_list(int, char **); static int zpool_do_iostat(int, char **); @@ -123,6 +124,7 @@ typedef enum { HELP_HISTORY, HELP_IMPORT, HELP_IOSTAT, + HELP_LABELCLEAR, HELP_LIST, HELP_OFFLINE, HELP_ONLINE, @@ -162,6 +164,8 @@ static zpool_command_t command_table[] = { { "add", zpool_do_add, HELP_ADD }, { "remove", zpool_do_remove, HELP_REMOVE }, { NULL }, + { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, + { NULL }, { "list", zpool_do_list, HELP_LIST }, { "iostat", zpool_do_iostat, HELP_IOSTAT }, { "status", zpool_do_status, HELP_STATUS }, @@ -233,6 +237,8 @@ get_usage(zpool_help_t idx) { case HELP_IOSTAT: return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " "[count]]\n")); + case HELP_LABELCLEAR: + return (gettext("\tlabelclear [-f] <vdev>\n")); case HELP_LIST: return (gettext("\tlist [-H] [-o property[,...]] " "[-T d|u] [pool] ... [interval [count]]\n")); @@ -642,6 +648,127 @@ zpool_do_remove(int argc, char **argv) } /* + * zpool labelclear <vdev> + * + * Verifies that the vdev is not active and zeros out the label information + * on the device. + */ +int +zpool_do_labelclear(int argc, char **argv) +{ + char *vdev, *name; + int c, fd = -1, ret = 0; + pool_state_t state; + boolean_t inuse = B_FALSE; + boolean_t force = B_FALSE; + + /* check options */ + while ((c = getopt(argc, argv, "f")) != -1) { + switch (c) { + case 'f': + force = B_TRUE; + break; + default: + (void) fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + usage(B_FALSE); + } + } + + argc -= optind; + argv += optind; + + /* get vdev name */ + if (argc < 1) { + (void) fprintf(stderr, gettext("missing vdev device 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); + } + + name = NULL; + if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) { + if (force) + goto wipe_label; + + (void) fprintf(stderr, + gettext("Unable to determine pool state for %s\n" + "Use -f to force the clearing any label data\n"), vdev); + + 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; + + case POOL_STATE_EXPORTED: + if (force) + break; + + (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; + + case POOL_STATE_POTENTIALLY_ACTIVE: + if (force) + break; + + (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_DESTROYED: + /* inuse should never be set for a destroyed pool... */ + break; + } + } + +wipe_label: + if (zpool_clear_label(fd) != 0) { + (void) fprintf(stderr, + gettext("Label clear failed on vdev %s\n"), vdev); + ret = 1; + } + +errout: + close(fd); + if (name != NULL) + free(name); + + return (ret); +} + +/* * zpool create [-fnd] [-o property=value] ... * [-O file-system-property=value] ... * [-R root] [-m mountpoint] <pool> <dev> ... |