aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zpool/zpool_main.c76
-rw-r--r--cmd/ztest.c8
-rw-r--r--include/libzfs.h5
-rw-r--r--include/sys/fs/zfs.h3
-rw-r--r--include/sys/spa.h4
-rw-r--r--lib/libzfs/libzfs.abi76
-rw-r--r--lib/libzfs/libzfs_pool.c5
-rw-r--r--lib/libzfs/libzfs_util.c8
-rw-r--r--man/man8/zpool-add.818
-rw-r--r--module/zfs/spa.c14
-rw-r--r--module/zfs/zfs_ioctl.c4
-rw-r--r--tests/runfiles/common.run3
-rw-r--r--tests/zfs-tests/tests/Makefile.am1
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh17
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh16
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh0
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh11
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh2
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))