aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMateusz Piotrowski <[email protected]>2024-08-26 18:27:24 +0200
committerGitHub <[email protected]>2024-08-26 09:27:24 -0700
commit6be8bf5552b16475629a15ab62759eb7a6d73e3b (patch)
tree952fdb553ed76d231396e80fc72d030d60889b4e
parent2420ee6e12cb4bc4918fc88d44d59b486b86e58b (diff)
zpool: Provide GUID to zpool-reguid(8) with -g (#16239)
This commit extends the zpool-reguid(8) command with a -g flag, which allows the user to specify the GUID to set. This change also adds some general tests for zpool-reguid(8). Sponsored-by: Wasabi Technology, Inc. Sponsored-by: Klara, Inc. Signed-off-by: Mateusz Piotrowski <[email protected]> Reviewed-by: Rob Norris <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Tony Hutter <[email protected]>
-rw-r--r--cmd/zpool/zpool_main.c23
-rw-r--r--cmd/ztest.c2
-rw-r--r--include/libzfs.h1
-rw-r--r--include/sys/fs/zfs.h5
-rw-r--r--include/sys/spa.h2
-rw-r--r--lib/libzfs/libzfs.abi6
-rw-r--r--lib/libzfs/libzfs_pool.c41
-rw-r--r--man/man8/zpool-reguid.814
-rw-r--r--module/zfs/spa.c25
-rw-r--r--module/zfs/zfs_ioctl.c30
-rw-r--r--tests/runfiles/common.run4
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_reguid/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reguid/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reguid/setup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_001_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_002_neg.ksh60
16 files changed, 342 insertions, 16 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index 620746f8e..9cd26a865 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -537,7 +537,7 @@ get_usage(zpool_help_t idx)
"\t [-o property=value] <pool> <newpool> "
"[<device> ...]\n"));
case HELP_REGUID:
- return (gettext("\treguid <pool>\n"));
+ return (gettext("\treguid [-g guid] <pool>\n"));
case HELP_SYNC:
return (gettext("\tsync [pool] ...\n"));
case HELP_VERSION:
@@ -2025,7 +2025,7 @@ zpool_do_create(int argc, char **argv)
char *end;
u_longlong_t ver;
- ver = strtoull(propval, &end, 10);
+ ver = strtoull(propval, &end, 0);
if (*end == '\0' &&
ver < SPA_VERSION_FEATURES) {
enable_pool_features = B_FALSE;
@@ -8232,19 +8232,32 @@ zpool_do_clear(int argc, char **argv)
}
/*
- * zpool reguid <pool>
+ * zpool reguid [-g <guid>] <pool>
*/
int
zpool_do_reguid(int argc, char **argv)
{
+ uint64_t guid;
+ uint64_t *guidp = NULL;
int c;
+ char *endptr;
char *poolname;
zpool_handle_t *zhp;
int ret = 0;
/* check options */
- while ((c = getopt(argc, argv, "")) != -1) {
+ while ((c = getopt(argc, argv, "g:")) != -1) {
switch (c) {
+ case 'g':
+ errno = 0;
+ guid = strtoull(optarg, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ (void) fprintf(stderr,
+ gettext("invalid GUID: %s\n"), optarg);
+ usage(B_FALSE);
+ }
+ guidp = &guid;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -8270,7 +8283,7 @@ zpool_do_reguid(int argc, char **argv)
if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
return (1);
- ret = zpool_reguid(zhp);
+ ret = zpool_set_guid(zhp, guidp);
zpool_close(zhp);
return (ret);
diff --git a/cmd/ztest.c b/cmd/ztest.c
index 6a9264ddc..7c9db84d4 100644
--- a/cmd/ztest.c
+++ b/cmd/ztest.c
@@ -6746,7 +6746,7 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
load = spa_load_guid(spa);
(void) pthread_rwlock_wrlock(&ztest_name_lock);
- error = spa_change_guid(spa);
+ error = spa_change_guid(spa, NULL);
zs->zs_guid = spa_guid(spa);
(void) pthread_rwlock_unlock(&ztest_name_lock);
diff --git a/include/libzfs.h b/include/libzfs.h
index bf5579f38..241279754 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -300,6 +300,7 @@ _LIBZFS_H int zpool_trim(zpool_handle_t *, pool_trim_func_t, nvlist_t *,
_LIBZFS_H int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
_LIBZFS_H int zpool_reguid(zpool_handle_t *);
+_LIBZFS_H int zpool_set_guid(zpool_handle_t *, const uint64_t *);
_LIBZFS_H int zpool_reopen_one(zpool_handle_t *, void *);
_LIBZFS_H int zpool_sync_one(zpool_handle_t *, void *);
diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h
index c7e48d1ed..73d686a00 100644
--- a/include/sys/fs/zfs.h
+++ b/include/sys/fs/zfs.h
@@ -1711,6 +1711,11 @@ typedef enum {
#define ZPOOL_INITIALIZE_VDEVS "initialize_vdevs"
/*
+ * The following are names used when invoking ZFS_IOC_POOL_REGUID.
+ */
+#define ZPOOL_REGUID_GUID "guid"
+
+/*
* The following are names used when invoking ZFS_IOC_POOL_TRIM.
*/
#define ZPOOL_TRIM_COMMAND "trim_command"
diff --git a/include/sys/spa.h b/include/sys/spa.h
index a70912335..93f381aff 100644
--- a/include/sys/spa.h
+++ b/include/sys/spa.h
@@ -1092,7 +1092,7 @@ extern void spa_strfree(char *);
extern uint64_t spa_generate_guid(spa_t *spa);
extern void snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp);
extern void spa_freeze(spa_t *spa);
-extern int spa_change_guid(spa_t *spa);
+extern int spa_change_guid(spa_t *spa, const uint64_t *guidp);
extern void spa_upgrade(spa_t *spa, uint64_t version);
extern void spa_evict_all(void);
extern vdev_t *spa_lookup_by_guid(spa_t *spa, uint64_t guid,
diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi
index 88baa4168..87c5c4380 100644
--- a/lib/libzfs/libzfs.abi
+++ b/lib/libzfs/libzfs.abi
@@ -556,6 +556,7 @@
<elf-symbol name='zpool_scan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_search_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_set_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_skip_pool' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -6639,6 +6640,11 @@
<parameter type-id='9c313c2d' name='guid'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zpool_set_guid' mangled-name='zpool_set_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_guid'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='713a56f5' name='guid'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_reguid' mangled-name='zpool_reguid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_reguid'>
<parameter type-id='4c81de99' name='zhp'/>
<return type-id='95e97e5e'/>
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index e493e8562..dfa7c4db6 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -4310,22 +4310,55 @@ zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
/*
* Change the GUID for a pool.
+ *
+ * Similar to zpool_reguid(), but may take a GUID.
+ *
+ * If the guid argument is NULL, then no GUID is passed in the nvlist to the
+ * ioctl().
*/
int
-zpool_reguid(zpool_handle_t *zhp)
+zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid)
{
char errbuf[ERRBUFLEN];
libzfs_handle_t *hdl = zhp->zpool_hdl;
+ nvlist_t *nvl = NULL;
zfs_cmd_t zc = {"\0"};
+ int error = -1;
+
+ if (guid != NULL) {
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(hdl));
+
+ if (nvlist_add_uint64(nvl, ZPOOL_REGUID_GUID, *guid) != 0) {
+ nvlist_free(nvl);
+ return (no_memory(hdl));
+ }
+
+ zcmd_write_src_nvlist(hdl, &zc, nvl);
+ }
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
- if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0)
- return (0);
+ error = zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc);
+ if (error) {
+ return (zpool_standard_error(hdl, errno, errbuf));
+ }
+ if (guid != NULL) {
+ zcmd_free_nvlists(&zc);
+ nvlist_free(nvl);
+ }
+ return (0);
+}
- return (zpool_standard_error(hdl, errno, errbuf));
+/*
+ * Change the GUID for a pool.
+ */
+int
+zpool_reguid(zpool_handle_t *zhp)
+{
+ return (zpool_set_guid(zhp, NULL));
}
/*
diff --git a/man/man8/zpool-reguid.8 b/man/man8/zpool-reguid.8
index 1fd4ddd9a..4fda3f316 100644
--- a/man/man8/zpool-reguid.8
+++ b/man/man8/zpool-reguid.8
@@ -25,8 +25,10 @@
.\" 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, Klara Inc.
+.\" Copyright (c) 2024, Mateusz Piotrowski
.\"
-.Dd May 31, 2021
+.Dd June 21, 2023
.Dt ZPOOL-REGUID 8
.Os
.
@@ -36,6 +38,7 @@
.Sh SYNOPSIS
.Nm zpool
.Cm reguid
+.Op Fl g Ar guid
.Ar pool
.
.Sh DESCRIPTION
@@ -43,6 +46,15 @@ Generates a new unique identifier for the pool.
You must ensure that all devices in this pool are online and healthy before
performing this action.
.
+.Bl -tag -width Ds
+.It Fl g Ar guid
+Set the pool GUID to the provided value.
+The GUID can be any 64-bit value accepted by
+.Xr strtoull 3
+in base 10.
+.Nm
+will return an error if the provided GUID is already in use.
+.El
.Sh SEE ALSO
.Xr zpool-export 8 ,
.Xr zpool-import 8
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index 99a8d107e..d51cc4fcd 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -1040,16 +1040,34 @@ spa_change_guid_sync(void *arg, dmu_tx_t *tx)
* online when we do this, or else any vdevs that weren't present
* would be orphaned from our pool. We are also going to issue a
* sysevent to update any watchers.
+ *
+ * The GUID of the pool will be changed to the value pointed to by guidp.
+ * The GUID may not be set to the reserverd value of 0.
+ * The new GUID will be generated if guidp is NULL.
*/
int
-spa_change_guid(spa_t *spa)
+spa_change_guid(spa_t *spa, const uint64_t *guidp)
{
- int error;
uint64_t guid;
+ int error;
mutex_enter(&spa->spa_vdev_top_lock);
mutex_enter(&spa_namespace_lock);
- guid = spa_generate_guid(NULL);
+
+ if (guidp != NULL) {
+ guid = *guidp;
+ if (guid == 0) {
+ error = SET_ERROR(EINVAL);
+ goto out;
+ }
+
+ if (spa_guid_exists(guid, 0)) {
+ error = SET_ERROR(EEXIST);
+ goto out;
+ }
+ } else {
+ guid = spa_generate_guid(NULL);
+ }
error = dsl_sync_task(spa->spa_name, spa_change_guid_check,
spa_change_guid_sync, &guid, 5, ZFS_SPACE_CHECK_RESERVED);
@@ -1068,6 +1086,7 @@ spa_change_guid(spa_t *spa)
spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_REGUID);
}
+out:
mutex_exit(&spa_namespace_lock);
mutex_exit(&spa->spa_vdev_top_lock);
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 897335dd4..7ce2d9196 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -1794,17 +1794,45 @@ zfs_ioc_pool_get_history(zfs_cmd_t *zc)
return (error);
}
+/*
+ * inputs:
+ * zc_nvlist_src nvlist optionally containing ZPOOL_REGUID_GUID
+ * zc_nvlist_src_size size of the nvlist
+ */
static int
zfs_ioc_pool_reguid(zfs_cmd_t *zc)
{
+ uint64_t *guidp = NULL;
+ nvlist_t *props = NULL;
spa_t *spa;
+ uint64_t guid;
int error;
+ if (zc->zc_nvlist_src_size != 0) {
+ error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
+ zc->zc_iflags, &props);
+ if (error != 0)
+ return (error);
+
+ error = nvlist_lookup_uint64(props, ZPOOL_REGUID_GUID, &guid);
+ if (error == 0)
+ guidp = &guid;
+ else if (error == ENOENT)
+ guidp = NULL;
+ else
+ goto out;
+ }
+
error = spa_open(zc->zc_name, &spa, FTAG);
if (error == 0) {
- error = spa_change_guid(spa);
+ error = spa_change_guid(spa, guidp);
spa_close(spa, FTAG);
}
+
+out:
+ if (props != NULL)
+ nvlist_free(props);
+
return (error);
}
diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
index ad1316646..088e46ce5 100644
--- a/tests/runfiles/common.run
+++ b/tests/runfiles/common.run
@@ -514,6 +514,10 @@ tags = ['functional', 'cli_root', 'zpool_offline']
tests = ['zpool_online_001_pos', 'zpool_online_002_neg']
tags = ['functional', 'cli_root', 'zpool_online']
+[tests/functional/cli_root/zpool_reguid]
+tests = ['zpool_reguid_001_pos', 'zpool_reguid_002_neg']
+tags = ['functional', 'cli_root', 'zpool_reguid']
+
[tests/functional/cli_root/zpool_remove]
tests = ['zpool_remove_001_neg', 'zpool_remove_002_pos',
'zpool_remove_003_pos']
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/Makefile.am
new file mode 100644
index 000000000..87d46b394
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_reguid
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_reguid_001_pos.ksh \
+ zpool_reguid_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/cleanup.ksh
new file mode 100755
index 000000000..3167a5097
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/setup.ksh
new file mode 100755
index 000000000..3d866cfd9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/setup.ksh
@@ -0,0 +1,34 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_001_pos.ksh
new file mode 100755
index 000000000..4e18abd98
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_001_pos.ksh
@@ -0,0 +1,73 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright 2023 Mateusz Piotrowski
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool reguid' can change pool's GUID.
+#
+# STRATEGY:
+# 1. Use zpool get to obtain the initial GUID of a pool.
+# 2. Change pool's GUID with zpool reguid.
+# 3. Verify the GUID has changed to a random GUID.
+#
+# 4. Change pool's GUID with zpool reguid -g.
+# 5. Verify the GUID has changed to the specified GUID.
+#
+
+# set_guid guid [expected_guid]
+set_guid() {
+ gflag_guid="$1"
+ expected_guid="${2:-"$gflag_guid"}"
+
+ initial_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+ log_assert "Verify 'zpool reguid -g \"$gflag_guid\"' sets GUID as expected."
+ log_must zpool reguid -g "$gflag_guid" "$TESTPOOL"
+ retrieved_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+ if [[ "$retrieved_guid" == "" ]]; then
+ log_fail "Unable to obtain the new GUID of pool $TESTPOOL"
+ fi
+ if [[ "$expected_guid" != "$retrieved_guid" ]]; then
+ log_fail "GUID set to '$retrieved_guid' instead of '$expected_guid'"
+ fi
+}
+
+log_assert "Verify 'zpool reguid' picks a new random GUID for the pool."
+initial_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+if [[ $initial_guid == "" ]]; then
+ log_fail "Unable to obtain the initial GUID of pool $TESTPOOL"
+fi
+log_must zpool reguid "$TESTPOOL"
+new_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+if [[ "$new_guid" == "" ]]; then
+ log_fail "Unable to obtain the new GUID of pool $TESTPOOL"
+fi
+if [[ "$initial_guid" == "$new_guid" ]]; then
+ log_fail "GUID change failed; GUID has not changed: $initial_guid"
+fi
+
+for g in "$(bc -e '2^64 - 1')" 0; do
+ set_guid "$g"
+done
+# zpool-reguid(8) will strip the leading 0.
+set_guid 0123 "123"
+# GUID "-1" is effectively 2^64 - 1 in value.
+set_guid -1 "$(bc -e '2^64 - 1')"
+
+log_pass "'zpool reguid' changes GUID as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_002_neg.ksh
new file mode 100755
index 000000000..599041e28
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reguid/zpool_reguid_002_neg.ksh
@@ -0,0 +1,60 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright 2023 Mateusz Piotrowski
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool reguid' does not accept invalid GUIDs.
+#
+# STRATEGY:
+# 1. Call zpool reguid with an invalid GUID.
+# 2. Verify that the call fails.
+# 3. Verify that the pool GUID did not change.
+#
+# 4. Call zpool reguid with a GUID that is already in use.
+# 5. Verify that the call fails.
+#
+
+check_guid() {
+ invalid_guid="$1"
+ initial_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+ log_assert "'zpool reguid' will not accept invalid GUID '$invalid_guid'"
+ if zpool reguid -g "$invalid_guid" "$TESTPOOL"; then
+ log_fail "'zpool reguid' accepted invalid GUID: $invalid_guid"
+ fi
+ final_guid="$(zpool get -H -o value guid "$TESTPOOL")"
+ if [[ "$initial_guid" != "$final_guid" ]]; then
+ log_fail "Invalid GUID change from '$initial_guid' to '$final_guid'"
+ fi
+}
+
+log_assert "Verify 'zpool reguid' does not accept invalid GUIDs"
+
+for ig in "$(bc -e '2^64')" 0xA 0xa; do
+ check_guid "$ig"
+done
+
+guid="42"
+log_assert "Verify 'zpool reguid -g' does not accept GUID which are already in use"
+log_must zpool reguid -g "$guid" "$TESTPOOL"
+if zpool reguid -g "$guid" "$TESTPOOL"; then
+ log_fail "'zpool reguid' accepted GUID that was already in use: $invalid_guid"
+fi
+
+log_pass "'zpool reguid' does not accept invalid GUIDs."