diff options
21 files changed, 219 insertions, 58 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: diff --git a/include/libzfs.h b/include/libzfs.h index 4f06b5d3c..2823b8845 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2022 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright Joyent, Inc. * Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright (c) 2016, Intel Corporation. @@ -158,6 +158,7 @@ typedef enum zfs_error { EZFS_RESUME_EXISTS, /* Resume on existing dataset without force */ EZFS_SHAREFAILED, /* filesystem share failed */ EZFS_RAIDZ_EXPAND_IN_PROGRESS, /* a raidz is currently expanding */ + EZFS_ASHIFT_MISMATCH, /* can't add vdevs with different ashifts */ EZFS_UNKNOWN } zfs_error_t; @@ -261,7 +262,7 @@ _LIBZFS_H boolean_t zpool_skip_pool(const char *); _LIBZFS_H int zpool_create(libzfs_handle_t *, const char *, nvlist_t *, nvlist_t *, nvlist_t *); _LIBZFS_H int zpool_destroy(zpool_handle_t *, const char *); -_LIBZFS_H int zpool_add(zpool_handle_t *, nvlist_t *); +_LIBZFS_H int zpool_add(zpool_handle_t *, nvlist_t *, boolean_t check_ashift); typedef struct splitflags { /* do not split, but return the config that would be split off */ diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 2683b774e..f84cb7aad 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 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, 2017 Joyent, Inc. All rights reserved. * Copyright (c) 2014 Integros [integros.com] @@ -1573,6 +1573,7 @@ typedef enum { ZFS_ERR_RESUME_EXISTS, ZFS_ERR_CRYPTO_NOTSUP, ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS, + ZFS_ERR_ASHIFT_MISMATCH, } zfs_errno_t; /* diff --git a/include/sys/spa.h b/include/sys/spa.h index 87ddbd90e..31eeefb7f 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2021 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. @@ -784,7 +784,7 @@ extern int bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx); #define SPA_ASYNC_DETACH_SPARE 0x4000 /* device manipulation */ -extern int spa_vdev_add(spa_t *spa, nvlist_t *nvroot); +extern int spa_vdev_add(spa_t *spa, nvlist_t *nvroot, boolean_t ashift_check); extern int spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing, int rebuild); extern int spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 2b904aeca..771c7407e 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -1112,14 +1112,11 @@ <var-decl name='prev' type-id='b03eadb4' visibility='default'/> </data-member> </class-decl> - <class-decl name='list' size-in-bits='256' is-struct='yes' visibility='default' id='e824dae9'> + <class-decl name='list' size-in-bits='192' is-struct='yes' visibility='default' id='e824dae9'> <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='list_size' type-id='b59d7dce' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> <var-decl name='list_offset' type-id='b59d7dce' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='128'> + <data-member access='public' layout-offset-in-bits='64'> <var-decl name='list_head' type-id='b0b5e45e' visibility='default'/> </data-member> </class-decl> @@ -2878,6 +2875,9 @@ </function-type> </abi-instr> <abi-instr address-size='64' path='lib/libzfs/libzfs_crypto.c' language='LANG_C99'> + <array-type-def dimensions='1' type-id='38b51b3c' size-in-bits='832' id='02b72c00'> + <subrange length='13' type-id='7359adad' id='487fded1'/> + </array-type-def> <array-type-def dimensions='1' type-id='fb7c6451' size-in-bits='256' id='64177143'> <subrange length='32' type-id='7359adad' id='ae5bde82'/> </array-type-def> @@ -2890,6 +2890,10 @@ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/> <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/> <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/> + <class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/> + <array-type-def dimensions='1' type-id='80f4b756' size-in-bits='832' id='39e6f84a'> + <subrange length='13' type-id='7359adad' id='487fded1'/> + </array-type-def> <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='896' id='47394ee0'> <subrange length='28' type-id='7359adad' id='3db583d7'/> </array-type-def> @@ -3010,6 +3014,24 @@ <typedef-decl name='__clock_t' type-id='bd54fe1a' id='4d66c6d7'/> <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/> <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/> + <class-decl name='__locale_struct' size-in-bits='1856' is-struct='yes' visibility='default' id='90cc1ce3'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='__locales' type-id='02b72c00' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='832'> + <var-decl name='__ctype_b' type-id='31347b7a' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='896'> + <var-decl name='__ctype_tolower' type-id='6d60f45d' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='960'> + <var-decl name='__ctype_toupper' type-id='6d60f45d' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1024'> + <var-decl name='__names' type-id='39e6f84a' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='__locale_t' type-id='f01e1813' id='b7ac9b5f'/> <class-decl name='__sigset_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='b9c97942' visibility='default' id='2616147f'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='__val' type-id='d2baa450' visibility='default'/> @@ -3025,6 +3047,7 @@ </data-member> </union-decl> <typedef-decl name='__sigval_t' type-id='a094b870' id='eabacd01'/> + <typedef-decl name='locale_t' type-id='b7ac9b5f' id='973a4f8d'/> <class-decl name='siginfo_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='cb681f62' visibility='default' id='d8149419'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='si_signo' type-id='95e97e5e' visibility='default'/> @@ -3260,9 +3283,13 @@ <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/> <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/> <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/> + <pointer-type-def type-id='23de8b96' size-in-bits='64' id='38b51b3c'/> + <pointer-type-def type-id='90cc1ce3' size-in-bits='64' id='f01e1813'/> <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/> <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/> + <qualified-type-def type-id='95e97e5e' const='yes' id='2448a865'/> + <pointer-type-def type-id='2448a865' size-in-bits='64' id='6d60f45d'/> <qualified-type-def type-id='aca3bac8' const='yes' id='2498fd78'/> <pointer-type-def type-id='2498fd78' size-in-bits='64' id='eed6c816'/> <qualified-type-def type-id='eed6c816' restrict='yes' id='a431a9da'/> @@ -3295,6 +3322,7 @@ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/> <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/> <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/> + <class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/> <function-decl name='zpool_get_prop_int' mangled-name='zpool_get_prop_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop_int'> <parameter type-id='4c81de99'/> <parameter type-id='5d0c23fb'/> @@ -3399,6 +3427,10 @@ <function-decl name='dlerror' visibility='default' binding='global' size-in-bits='64'> <return type-id='26a90f95'/> </function-decl> + <function-decl name='uselocale' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='973a4f8d'/> + <return type-id='973a4f8d'/> + </function-decl> <function-decl name='PKCS5_PBKDF2_HMAC_SHA1' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='80f4b756'/> <parameter type-id='95e97e5e'/> @@ -3482,8 +3514,9 @@ <parameter type-id='80f4b756'/> <return type-id='26a90f95'/> </function-decl> - <function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'> + <function-decl name='strerror_l' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='95e97e5e'/> + <parameter type-id='973a4f8d'/> <return type-id='26a90f95'/> </function-decl> <function-decl name='tcgetattr' visibility='default' binding='global' size-in-bits='64'> @@ -3840,12 +3873,18 @@ <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/> <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/> <pointer-type-def type-id='01a1b934' size-in-bits='64' id='566b3f52'/> + <qualified-type-def type-id='566b3f52' restrict='yes' id='c878edd6'/> + <pointer-type-def type-id='566b3f52' size-in-bits='64' id='82d4e9e8'/> + <qualified-type-def type-id='82d4e9e8' restrict='yes' id='aa19c230'/> <pointer-type-def type-id='7e291ce6' size-in-bits='64' id='ca64ff60'/> <pointer-type-def type-id='9da381c4' size-in-bits='64' id='cb785ebf'/> <pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/> <pointer-type-def type-id='8e0af06e' size-in-bits='64' id='053457bd'/> <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/> <pointer-type-def type-id='a63d15a3' size-in-bits='64' id='a195f4a3'/> + <qualified-type-def type-id='a195f4a3' restrict='yes' id='33518961'/> + <pointer-type-def type-id='a195f4a3' size-in-bits='64' id='e80ff3ab'/> + <qualified-type-def type-id='e80ff3ab' restrict='yes' id='8f2c7109'/> <pointer-type-def type-id='eae6431d' size-in-bits='64' id='0d41d328'/> <pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/> <pointer-type-def type-id='dddf6ca2' size-in-bits='64' id='d915a820'/> @@ -4278,9 +4317,13 @@ <parameter type-id='9d424d31'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='getgrnam' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='566b3f52'/> + <function-decl name='getgrnam_r' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='c878edd6'/> + <parameter type-id='266fe297'/> + <parameter type-id='b59d7dce'/> + <parameter type-id='aa19c230'/> + <return type-id='95e97e5e'/> </function-decl> <function-decl name='hasmntopt' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='48bea5ec'/> @@ -4304,9 +4347,13 @@ <parameter type-id='18c91f9e'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='getpwnam' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <return type-id='a195f4a3'/> + <function-decl name='getpwnam_r' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='33518961'/> + <parameter type-id='266fe297'/> + <parameter type-id='b59d7dce'/> + <parameter type-id='8f2c7109'/> + <return type-id='95e97e5e'/> </function-decl> <function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='9d26089a'/> @@ -6245,6 +6292,7 @@ <function-decl name='zpool_add' mangled-name='zpool_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_add'> <parameter type-id='4c81de99' name='zhp'/> <parameter type-id='5ce45b60' name='nvroot'/> + <parameter type-id='c19b74c3' name='ashift_check'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zpool_export' mangled-name='zpool_export' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_export'> @@ -6696,7 +6744,7 @@ <enumerator name='LZC_SEND_FLAG_RAW' value='8'/> <enumerator name='LZC_SEND_FLAG_SAVED' value='16'/> </enum-decl> - <class-decl name='ddt_key' size-in-bits='320' is-struct='yes' visibility='default' id='e0a4a1cb'> + <class-decl name='ddt_key_t' size-in-bits='320' is-struct='yes' naming-typedef-id='67f6d2cf' visibility='default' id='5fae1718'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='ddk_cksum' type-id='39730d0b' visibility='default'/> </data-member> @@ -6704,7 +6752,7 @@ <var-decl name='ddk_prop' type-id='9c313c2d' visibility='default'/> </data-member> </class-decl> - <typedef-decl name='ddt_key_t' type-id='e0a4a1cb' id='67f6d2cf'/> + <typedef-decl name='ddt_key_t' type-id='5fae1718' id='67f6d2cf'/> <enum-decl name='dmu_object_type' id='04b3b0b9'> <underlying-type type-id='9cac1fee'/> <enumerator name='DMU_OT_NONE' value='0'/> diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 6d5ac9d59..e95b361da 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -22,7 +22,7 @@ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov <[email protected]> * Copyright (c) 2018 Datto Inc. * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. @@ -1724,7 +1724,7 @@ zpool_discard_checkpoint(zpool_handle_t *zhp) * necessary verification to ensure that the vdev specification is well-formed. */ int -zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) +zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot, boolean_t check_ashift) { zfs_cmd_t zc = {"\0"}; int ret; @@ -1756,6 +1756,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) zcmd_write_conf_nvlist(hdl, &zc, nvroot); (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + zc.zc_flags = check_ashift; if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { switch (errno) { diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 463cec085..60e9262f6 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2020 Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov <[email protected]> * Copyright (c) 2017 Datto Inc. * Copyright (c) 2020 The FreeBSD Foundation @@ -317,6 +317,9 @@ libzfs_error_description(libzfs_handle_t *hdl) case EZFS_RESUME_EXISTS: return (dgettext(TEXT_DOMAIN, "Resuming recv on existing " "dataset without force")); + case EZFS_ASHIFT_MISMATCH: + return (dgettext(TEXT_DOMAIN, "adding devices with " + "different physical sector sizes is not allowed")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: @@ -763,6 +766,9 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ZFS_ERR_IOC_ARG_BADTYPE: zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); break; + case ZFS_ERR_ASHIFT_MISMATCH: + zfs_verror(hdl, EZFS_ASHIFT_MISMATCH, fmt, ap); + break; default: zfs_error_aux(hdl, "%s", strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); diff --git a/man/man8/zpool-add.8 b/man/man8/zpool-add.8 index 8ccdcccc7..60b35f1a5 100644 --- a/man/man8/zpool-add.8 +++ b/man/man8/zpool-add.8 @@ -24,8 +24,9 @@ .\" Copyright (c) 2018 George Melikov. All Rights Reserved. .\" Copyright 2017 Nexenta Systems, Inc. .\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved. +.\" Copyright (c) 2024 by Delphix. All Rights Reserved. .\" -.Dd March 16, 2022 +.Dd March 8, 2024 .Dt ZPOOL-ADD 8 .Os . @@ -36,6 +37,7 @@ .Nm zpool .Cm add .Op Fl fgLnP +.Op Fl -allow-in-use -allow-replication-mismatch -allow-ashift-mismatch .Oo Fl o Ar property Ns = Ns Ar value Oc .Ar pool vdev Ns … . @@ -56,7 +58,8 @@ subcommand. .It Fl f Forces use of .Ar vdev Ns s , -even if they appear in use or specify a conflicting replication level. +even if they appear in use, have conflicting ashift values, or specify +a conflicting replication level. Not all devices can be overridden in this manner. .It Fl g Display @@ -91,6 +94,17 @@ See the manual page for a list of valid properties that can be set. The only property supported at the moment is .Sy ashift . +.It Fl -allow-ashift-mismatch +Disable the ashift validation which allows mismatched ashift values in the +pool. +Adding top-level +.Ar vdev Ns s +with different sector sizes will prohibit future device removal operations, see +.Xr zpool-remove 8 . +.It Fl -allow-in-use +Allow vdevs to be added even if they might be in use in another pool. +.It Fl -allow-replication-mismatch +Allow vdevs with conflicting replication levels to be added to the pool. .El . .Sh EXAMPLES diff --git a/module/zfs/spa.c b/module/zfs/spa.c index d7fe96cde..0bd46f574 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright (c) 2018, Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. @@ -6978,7 +6978,7 @@ spa_draid_feature_incr(void *arg, dmu_tx_t *tx) * Add a device to a storage pool. */ int -spa_vdev_add(spa_t *spa, nvlist_t *nvroot) +spa_vdev_add(spa_t *spa, nvlist_t *nvroot, boolean_t check_ashift) { uint64_t txg, ndraid = 0; int error; @@ -7069,6 +7069,16 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot) } } + if (check_ashift && spa->spa_max_ashift == spa->spa_min_ashift) { + for (int c = 0; c < vd->vdev_children; c++) { + tvd = vd->vdev_child[c]; + if (tvd->vdev_ashift != spa->spa_max_ashift) { + return (spa_vdev_exit(spa, vd, txg, + ZFS_ERR_ASHIFT_MISMATCH)); + } + } + } + for (int c = 0; c < vd->vdev_children; c++) { tvd = vd->vdev_child[c]; vdev_remove_child(vd, tvd); diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 2738385e2..ac8329185 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -27,7 +27,7 @@ * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved. * Copyright 2016 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2024 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright (c) 2014 Integros [integros.com] @@ -1887,7 +1887,7 @@ zfs_ioc_vdev_add(zfs_cmd_t *zc) error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, zc->zc_iflags, &config); if (error == 0) { - error = spa_vdev_add(spa, config); + error = spa_vdev_add(spa, config, zc->zc_flags); nvlist_free(config); } spa_close(spa, FTAG); diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index c4afde554..04a34a997 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -372,7 +372,8 @@ tags = ['functional', 'cli_root', 'zpool'] tests = ['zpool_add_001_pos', 'zpool_add_002_pos', 'zpool_add_003_pos', 'zpool_add_004_pos', 'zpool_add_006_pos', 'zpool_add_007_neg', 'zpool_add_008_neg', 'zpool_add_009_neg', 'zpool_add_010_pos', - 'add-o_ashift', 'add_prop_ashift', 'zpool_add_dryrun_output'] + 'add-o_ashift', 'add_prop_ashift', 'zpool_add_dryrun_output', + 'zpool_add--allow-ashift-mismatch'] tags = ['functional', 'cli_root', 'zpool_add'] [tests/functional/cli_root/zpool_attach] diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am index 2fc36c4d7..8befed077 100644 --- a/tests/zfs-tests/tests/Makefile.am +++ b/tests/zfs-tests/tests/Makefile.am @@ -989,6 +989,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_add/add_prop_ashift.ksh \ functional/cli_root/zpool_add/cleanup.ksh \ functional/cli_root/zpool_add/setup.ksh \ + functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh \ functional/cli_root/zpool_add/zpool_add_001_pos.ksh \ functional/cli_root/zpool_add/zpool_add_002_pos.ksh \ functional/cli_root/zpool_add/zpool_add_003_pos.ksh \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh index 7ecaf849e..51871934d 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh @@ -22,7 +22,7 @@ # # Copyright 2017, loli10K. All rights reserved. -# Copyright (c) 2020 by Delphix. All rights reserved. +# Copyright (c) 2020, 2024 by Delphix. All rights reserved. # . $STF_SUITE/include/libtest.shlib @@ -60,12 +60,23 @@ log_must mkfile $SIZE $disk2 logical_ashift=$(get_tunable VDEV_FILE_LOGICAL_ASHIFT) orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT) max_auto_ashift=$(get_tunable VDEV_MAX_AUTO_ASHIFT) +opt="" typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16") for ashift in ${ashifts[@]} do + # + # Need to add the --allow-ashift-mismatch option to disable the + # ashift mismatch checks in zpool add. + # + if [[ $ashift -eq $orig_ashift ]]; then + opt="" + else + opt="--allow-ashift-mismatch" + fi + log_must zpool create $TESTPOOL $disk1 - log_must zpool add -o ashift=$ashift $TESTPOOL $disk2 + log_must zpool add $opt -o ashift=$ashift $TESTPOOL $disk2 log_must verify_ashift $disk2 $ashift # clean things for the next run @@ -78,7 +89,7 @@ do # log_must zpool create $TESTPOOL $disk1 log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $ashift - log_must zpool add $TESTPOOL $disk2 + log_must zpool add $opt $TESTPOOL $disk2 exp=$(( (ashift <= max_auto_ashift) ? ashift : logical_ashift )) log_must verify_ashift $disk2 $exp diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh index 228f62232..6a3283d06 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh @@ -22,7 +22,7 @@ # # Copyright 2017, loli10K. All rights reserved. -# Copyright (c) 2020 by Delphix. All rights reserved. +# Copyright (c) 2020, 2024 by Delphix. All rights reserved. # . $STF_SUITE/include/libtest.shlib @@ -68,8 +68,13 @@ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16 typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16") for ashift in ${ashifts[@]} do + if [ $ashift -eq $orig_ashift ];then + opt="" + else + opt="--allow-ashift-mismatch" + fi log_must zpool create -o ashift=$ashift $TESTPOOL $disk1 - log_must zpool add $TESTPOOL $disk2 + log_must zpool add $opt $TESTPOOL $disk2 log_must verify_ashift $disk2 $ashift # clean things for the next run @@ -82,8 +87,13 @@ for ashift in ${ashifts[@]} do for cmdval in ${ashifts[@]} do + if [ $ashift -eq $cmdval ];then + opt="" + else + opt="--allow-ashift-mismatch" + fi log_must zpool create -o ashift=$ashift $TESTPOOL $disk1 - log_must zpool add -o ashift=$cmdval $TESTPOOL $disk2 + log_must zpool add $opt -o ashift=$cmdval $TESTPOOL $disk2 log_must verify_ashift $disk2 $cmdval # clean things for the next run diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh index c5c06f763..afee34a33 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh @@ -65,4 +65,15 @@ log_mustnot vdevs_in_pool $TESTPOOL $DISK2 log_must zpool add -f $TESTPOOL $DISK2 log_must vdevs_in_pool $TESTPOOL $DISK2 +log_must zpool destroy $TESTPOOL + +create_pool $TESTPOOL mirror $DISK0 $DISK1 +log_must poolexists $TESTPOOL + +log_mustnot zpool add $TESTPOOL $DISK2 +log_mustnot vdevs_in_pool $TESTPOOL $DISK2 + +log_must zpool add --allow-replication-mismatch $TESTPOOL $DISK2 +log_must vdevs_in_pool $TESTPOOL $DISK2 + log_pass "'zpool add -f <pool> <vdev> ...' executes successfully." diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh index 646edc1a4..cecda56ab 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh @@ -70,7 +70,7 @@ if is_freebsd; then recursive=$(get_tunable VOL_RECURSIVE) log_must set_tunable64 VOL_RECURSIVE 1 fi -log_must zpool add $TESTPOOL $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL +log_must zpool add --allow-ashift-mismatch $TESTPOOL $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL log_must vdevs_in_pool "$TESTPOOL" "$ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL" diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh index 4990ef9d2..0e9d9f5f0 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh @@ -75,7 +75,9 @@ log_must poolexists $TESTPOOL1 unset NOINUSE_CHECK log_mustnot zpool add -f $TESTPOOL $DISK1 +log_mustnot zpool add --allow-in-use $TESTPOOL $DISK1 log_mustnot zpool add -f $TESTPOOL $mnttab_dev +log_mustnot zpool add --allow-in-use $TESTPOOL $mnttab_dev if is_linux; then log_mustnot zpool add $TESTPOOL $vfstab_dev else diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh index d7f3a900e..a13a27160 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh @@ -64,7 +64,9 @@ log_mustnot zpool add -f $TESTPOOL $DISK0 for type in "" "mirror" "raidz" "draid" "spare" "log" "dedup" "special" "cache" do log_mustnot zpool add -f $TESTPOOL $type $DISK0 $DISK1 + log_mustnot zpool add --allow-in-use $TESTPOOL $type $DISK0 $DISK1 log_mustnot zpool add -f $TESTPOOL $type $DISK1 $DISK1 + log_mustnot zpool add --allow-in-use $TESTPOOL $type $DISK1 $DISK1 done log_pass "'zpool add' get fail as expected if vdevs are the same or vdev is " \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh index b8b25db1b..22860e9ca 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh @@ -138,7 +138,7 @@ function zpool_create_forced_add while ((j < ${#add_args[@]})); do log_must zpool create $TESTPOOL1 ${create_args[$i]} log_mustnot zpool add $TESTPOOL1 ${add_args[$j]} - log_must zpool add -f $TESTPOOL1 ${add_args[$j]} + log_must zpool add --allow-replication-mismatch $TESTPOOL1 ${add_args[$j]} log_must zpool destroy -f $TESTPOOL1 ((j += 1)) |