Skip to content

Commit

Permalink
Add FreeBSD 'zpool labelclear' command
Browse files Browse the repository at this point in the history
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-src@119a041

Ported-by: Dmitry Khasanov <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #1126
  • Loading branch information
pik4ez authored and behlendorf committed Jul 9, 2013
1 parent 51a3ae7 commit 131cc95
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 2 deletions.
127 changes: 127 additions & 0 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 **);
Expand Down Expand Up @@ -123,6 +124,7 @@ typedef enum {
HELP_HISTORY,
HELP_IMPORT,
HELP_IOSTAT,
HELP_LABELCLEAR,
HELP_LIST,
HELP_OFFLINE,
HELP_ONLINE,
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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"));
Expand Down Expand Up @@ -641,6 +647,127 @@ zpool_do_remove(int argc, char **argv)
return (ret);
}

/*
* 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] ...
Expand Down
1 change: 1 addition & 0 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ extern void zpool_close(zpool_handle_t *);
extern const char *zpool_get_name(zpool_handle_t *);
extern int zpool_get_state(zpool_handle_t *);
extern char *zpool_state_to_name(vdev_state_t, vdev_aux_t);
extern const char *zpool_pool_state_to_name(pool_state_t);
extern void zpool_free_handles(libzfs_handle_t *);

/*
Expand Down
4 changes: 2 additions & 2 deletions lib/libzfs/libzfs_import.c
Original file line number Diff line number Diff line change
Expand Up @@ -902,8 +902,8 @@ zpool_read_label(int fd, nvlist_t **config)

/*
* Given a file descriptor, clear (zero) the label information. This function
* is currently only used in the appliance stack as part of the ZFS sysevent
* module.
* is used in the appliance stack as part of the ZFS sysevent module and
* to implement the "zpool labelclear" command.
*/
int
zpool_clear_label(int fd)
Expand Down
30 changes: 30 additions & 0 deletions lib/libzfs/libzfs_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,36 @@ zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
return (gettext("UNKNOWN"));
}

/*
* Map POOL STATE to printed strings.
*/
const char *
zpool_pool_state_to_name(pool_state_t state)
{
switch (state) {
default:
break;
case POOL_STATE_ACTIVE:
return (gettext("ACTIVE"));
case POOL_STATE_EXPORTED:
return (gettext("EXPORTED"));
case POOL_STATE_DESTROYED:
return (gettext("DESTROYED"));
case POOL_STATE_SPARE:
return (gettext("SPARE"));
case POOL_STATE_L2CACHE:
return (gettext("L2CACHE"));
case POOL_STATE_UNINITIALIZED:
return (gettext("UNINITIALIZED"));
case POOL_STATE_UNAVAIL:
return (gettext("UNAVAIL"));
case POOL_STATE_POTENTIALLY_ACTIVE:
return (gettext("POTENTIALLY_ACTIVE"));
}

return (gettext("UNKNOWN"));
}

/*
* Get a zpool property value for 'prop' and return the value in
* a pre-allocated buffer.
Expand Down
27 changes: 27 additions & 0 deletions man/man8/zpool.8
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ zpool \- configures ZFS storage pools
\fBzpool iostat\fR [\fB-T\fR u | d ] [\fB-v\fR] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]
.fi

.LP
.nf
\fBzpool labelclear\fR [\fB-f\fR] \fIdevice\fR
.fi

.LP
.nf
\fBzpool list\fR [\fB-Hv\fR] [\fB-o\fR \fIproperty\fR[,...]] [\fIpool\fR] ...
Expand Down Expand Up @@ -1426,6 +1431,28 @@ Verbose statistics. Reports usage statistics for individual \fIvdevs\fR within t

.RE

.sp
.ne 2
.mk
.na
\fB\fBzpool labelclear\fR [\fB-f\fR] \fIdevice\fR
.ad
.sp .6
.RS 4n
Removes ZFS label information from the specified device. The device must not be part of an active pool configuration.
.sp
.ne 2
.mk
.na
\fB\fB-f\fR\fR
.ad
.RS 12n
.rt
Treat exported or foreign devices as inactive.
.RE

.RE

.sp
.ne 2
.mk
Expand Down

0 comments on commit 131cc95

Please sign in to comment.