mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 04:07:45 +03:00
OpenZFS 6865 - want zfs-tests cases for zpool labelclear command
Authored by: Yuri Pankov <yuri.pankov@nexenta.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: John Kennedy <john.kennedy@delphix.com> Approved by: Robert Mustacchi <rm@joyent.com> Reviewed-by: loli10K <ezomori.nozomu@gmail.com> Ported-by: Brian Behlendorf <behlendorf1@llnl.gov> Porting Notes: - Updated 'zpool labelclear' and 'zdb -l' such that they attempt to find a vdev given solely its short name. This behavior is consistent with the upstream OpenZFS code and the test cases depend on it. The actual implementation differs slightly due to device naming conventions on Linux. - auto_online_001_pos, auto_replace_001_pos and add-o_ashift test cases updated to expect failure when no label exists. - read_efi_label() and zpool_label_disk_check() are read-only operations and should use O_RDONLY at open time to enforce this. - zpool_label_disk() and zpool_relabel_disk() write the partition information using O_DIRECT an fsync() and page cache invalidation to ensure a consistent view of the device. - dump_label() in zdb should invalidate the page cache in order to get the authoritative label from disk. OpenZFS-issue: https://www.illumos.org/issues/6865 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/c95076c Closes #5981
This commit is contained in:
committed by
Brian Behlendorf
parent
047187c1bd
commit
dbb38f6605
+96
-73
@@ -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);
|
||||
}
|
||||
if (argc > 1) {
|
||||
(void) fprintf(stderr, gettext("too many arguments\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);
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
name = NULL;
|
||||
if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) {
|
||||
if (force)
|
||||
goto wipe_label;
|
||||
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);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
wipe_label:
|
||||
if (zpool_clear_label(fd) != 0) {
|
||||
if ((fd = open(vdev, O_RDWR)) < 0) {
|
||||
(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
|
||||
vdev, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (zpool_read_label(fd, &config, NULL) != 0 || config == NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("Label clear failed on vdev %s\n"), vdev);
|
||||
gettext("failed to check state for %s\n"), vdev);
|
||||
return (1);
|
||||
}
|
||||
nvlist_free(config);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!inuse)
|
||||
goto wipe_label;
|
||||
|
||||
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;
|
||||
|
||||
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_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:
|
||||
ret = zpool_clear_label(fd);
|
||||
if (ret != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to clear label for %s\n"), vdev);
|
||||
}
|
||||
|
||||
errout:
|
||||
close(fd);
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(name);
|
||||
(void) close(fd);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user