aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorGeorge Wilson <[email protected]>2024-03-29 15:15:56 -0400
committerTony Hutter <[email protected]>2024-04-29 13:50:05 -0700
commit6f323353d280d5e1e318500d05522acd4ae6f894 (patch)
treed0f21ddbd0f124e2584f5c96d6ed36130f09baad /cmd
parentb3b37b84e8336b47c4cbbeae2d4f21ba5c266144 (diff)
Add ashift validation when adding devices to a pool
Currently, zpool add allows users to add top-level vdevs that have different ashifts but doing so prevents users from being able to perform a top-level vdev removal. Often times consumers may not realize that they have mismatched ashifts until the top-level removal fails. This feature adds ashift validation to the zpool add command and will fail the operation if the sector size of the specified vdev does not match the existing pool. This behavior can be disabled by using the -f flag. In addition, new flags have been added to provide fine-grained control to disable specific checks. These flags are: --allow-in-use --allow-ashift-mismatch --allow-replicaton-mismatch The force flag will disable all of these checks. Reviewed by: Brian Behlendorf <[email protected]> Reviewed by: Alexander Motin <[email protected]> Reviewed-by: Mark Maybee <[email protected]> Signed-off-by: George Wilson <[email protected]> Closes #15509
Diffstat (limited to 'cmd')
-rw-r--r--cmd/zpool/zpool_main.c76
-rw-r--r--cmd/ztest.c8
2 files changed, 63 insertions, 21 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index 1e577e712..20b1c8506 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
* Copyright (c) 2012 by Cyril Plisko. All rights reserved.
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
@@ -131,6 +131,13 @@ static int zpool_do_help(int argc, char **argv);
static zpool_compat_status_t zpool_do_load_compat(
const char *, boolean_t *);
+enum zpool_options {
+ ZPOOL_OPTION_POWER = 1024,
+ ZPOOL_OPTION_ALLOW_INUSE,
+ ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH,
+ ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH
+};
+
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
@@ -347,7 +354,7 @@ get_usage(zpool_help_t idx)
{
switch (idx) {
case HELP_ADD:
- return (gettext("\tadd [-fgLnP] [-o property=value] "
+ return (gettext("\tadd [-afgLnP] [-o property=value] "
"<pool> <vdev> ...\n"));
case HELP_ATTACH:
return (gettext("\tattach [-fsw] [-o property=value] "
@@ -1009,8 +1016,9 @@ add_prop_list_default(const char *propname, const char *propval,
}
/*
- * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
+ * zpool add [-afgLnP] [-o property=value] <pool> <vdev> ...
*
+ * -a Disable the ashift validation checks
* -f Force addition of devices, even if they appear in use
* -g Display guid for individual vdev name.
* -L Follow links when resolving vdev path name.
@@ -1026,8 +1034,11 @@ add_prop_list_default(const char *propname, const char *propval,
int
zpool_do_add(int argc, char **argv)
{
- boolean_t force = B_FALSE;
+ boolean_t check_replication = B_TRUE;
+ boolean_t check_inuse = B_TRUE;
boolean_t dryrun = B_FALSE;
+ boolean_t check_ashift = B_TRUE;
+ boolean_t force = B_FALSE;
int name_flags = 0;
int c;
nvlist_t *nvroot;
@@ -1038,8 +1049,18 @@ zpool_do_add(int argc, char **argv)
nvlist_t *props = NULL;
char *propval;
+ struct option long_options[] = {
+ {"allow-in-use", no_argument, NULL, ZPOOL_OPTION_ALLOW_INUSE},
+ {"allow-replication-mismatch", no_argument, NULL,
+ ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH},
+ {"allow-ashift-mismatch", no_argument, NULL,
+ ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH},
+ {0, 0, 0, 0}
+ };
+
/* check options */
- while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
+ while ((c = getopt_long(argc, argv, "fgLno:P", long_options, NULL))
+ != -1) {
switch (c) {
case 'f':
force = B_TRUE;
@@ -1069,6 +1090,15 @@ zpool_do_add(int argc, char **argv)
case 'P':
name_flags |= VDEV_NAME_PATH;
break;
+ case ZPOOL_OPTION_ALLOW_INUSE:
+ check_inuse = B_FALSE;
+ break;
+ case ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH:
+ check_replication = B_FALSE;
+ break;
+ case ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH:
+ check_ashift = B_FALSE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -1089,6 +1119,19 @@ zpool_do_add(int argc, char **argv)
usage(B_FALSE);
}
+ if (force) {
+ if (!check_inuse || !check_replication || !check_ashift) {
+ (void) fprintf(stderr, gettext("'-f' option is not "
+ "allowed with '--allow-replication-mismatch', "
+ "'--allow-ashift-mismatch', or "
+ "'--allow-in-use'\n"));
+ usage(B_FALSE);
+ }
+ check_inuse = B_FALSE;
+ check_replication = B_FALSE;
+ check_ashift = B_FALSE;
+ }
+
poolname = argv[0];
argc--;
@@ -1119,8 +1162,8 @@ zpool_do_add(int argc, char **argv)
}
/* pass off to make_root_vdev for processing */
- nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
- argc, argv);
+ nvroot = make_root_vdev(zhp, props, !check_inuse,
+ check_replication, B_FALSE, dryrun, argc, argv);
if (nvroot == NULL) {
zpool_close(zhp);
return (1);
@@ -1224,7 +1267,7 @@ zpool_do_add(int argc, char **argv)
ret = 0;
} else {
- ret = (zpool_add(zhp, nvroot) != 0);
+ ret = (zpool_add(zhp, nvroot, check_ashift) != 0);
}
nvlist_free(props);
@@ -7068,7 +7111,6 @@ zpool_do_split(int argc, char **argv)
return (ret);
}
-#define POWER_OPT 1024
/*
* zpool online [--power] <pool> <device> ...
@@ -7086,7 +7128,7 @@ zpool_do_online(int argc, char **argv)
int flags = 0;
boolean_t is_power_on = B_FALSE;
struct option long_options[] = {
- {"power", no_argument, NULL, POWER_OPT},
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
{0, 0, 0, 0}
};
@@ -7096,7 +7138,7 @@ zpool_do_online(int argc, char **argv)
case 'e':
flags |= ZFS_ONLINE_EXPAND;
break;
- case POWER_OPT:
+ case ZPOOL_OPTION_POWER:
is_power_on = B_TRUE;
break;
case '?':
@@ -7209,7 +7251,7 @@ zpool_do_offline(int argc, char **argv)
boolean_t is_power_off = B_FALSE;
struct option long_options[] = {
- {"power", no_argument, NULL, POWER_OPT},
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
{0, 0, 0, 0}
};
@@ -7222,7 +7264,7 @@ zpool_do_offline(int argc, char **argv)
case 't':
istmp = B_TRUE;
break;
- case POWER_OPT:
+ case ZPOOL_OPTION_POWER:
is_power_off = B_TRUE;
break;
case '?':
@@ -7322,7 +7364,7 @@ zpool_do_clear(int argc, char **argv)
char *pool, *device;
struct option long_options[] = {
- {"power", no_argument, NULL, POWER_OPT},
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
{0, 0, 0, 0}
};
@@ -7339,7 +7381,7 @@ zpool_do_clear(int argc, char **argv)
case 'X':
xtreme_rewind = B_TRUE;
break;
- case POWER_OPT:
+ case ZPOOL_OPTION_POWER:
is_power_on = B_TRUE;
break;
case '?':
@@ -9099,7 +9141,7 @@ zpool_do_status(int argc, char **argv)
char *cmd = NULL;
struct option long_options[] = {
- {"power", no_argument, NULL, POWER_OPT},
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
{0, 0, 0, 0}
};
@@ -9167,7 +9209,7 @@ zpool_do_status(int argc, char **argv)
case 'x':
cb.cb_explain = B_TRUE;
break;
- case POWER_OPT:
+ case ZPOOL_OPTION_POWER:
cb.cb_print_power = B_TRUE;
break;
case '?':
diff --git a/cmd/ztest.c b/cmd/ztest.c
index 8cfbdfe1c..34744d12b 100644
--- a/cmd/ztest.c
+++ b/cmd/ztest.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -3270,7 +3270,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
"log" : NULL, ztest_opts.zo_raid_children, zs->zs_mirrors,
1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
fnvlist_free(nvroot);
switch (error) {
@@ -3332,7 +3332,7 @@ ztest_vdev_class_add(ztest_ds_t *zd, uint64_t id)
nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0,
class, ztest_opts.zo_raid_children, zs->zs_mirrors, 1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
fnvlist_free(nvroot);
if (error == ENOSPC)
@@ -3439,7 +3439,7 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
*/
nvlist_t *nvroot = make_vdev_root(NULL, aux, NULL,
(ztest_opts.zo_vdev_size * 5) / 4, 0, NULL, 0, 0, 1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
switch (error) {
case 0: