diff options
author | George Wilson <[email protected]> | 2024-03-29 15:15:56 -0400 |
---|---|---|
committer | Tony Hutter <[email protected]> | 2024-04-29 13:50:05 -0700 |
commit | 6f323353d280d5e1e318500d05522acd4ae6f894 (patch) | |
tree | d0f21ddbd0f124e2584f5c96d6ed36130f09baad /cmd | |
parent | b3b37b84e8336b47c4cbbeae2d4f21ba5c266144 (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.c | 76 | ||||
-rw-r--r-- | cmd/ztest.c | 8 |
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: |