changeset 13514:417c34452f03

1748 desire support for reguid in zfs Reviewed by: George Wilson <gwilson@zfsmail.com> Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com> Reviewed by: Alexander Stetsenko <ams@nexenta.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Garrett D'Amore <garrett@nexenta.com>
date Fri, 11 Nov 2011 14:07:54 -0800
parents f84d4672fdbd
children 3e8376ea8eb0
files usr/src/cmd/truss/codes.c usr/src/cmd/zpool/zpool_main.c usr/src/cmd/ztest/ztest.c usr/src/lib/libzfs/common/libzfs.h usr/src/lib/libzfs/common/libzfs_pool.c usr/src/lib/libzfs/common/mapfile-vers usr/src/man/man1m/zpool.1m usr/src/uts/common/fs/zfs/arc.c usr/src/uts/common/fs/zfs/spa.c usr/src/uts/common/fs/zfs/spa_misc.c usr/src/uts/common/fs/zfs/sys/spa.h usr/src/uts/common/fs/zfs/sys/spa_impl.h usr/src/uts/common/fs/zfs/vdev.c usr/src/uts/common/fs/zfs/zfs_ioctl.c usr/src/uts/common/sys/fs/zfs.h usr/src/uts/common/sys/sysevent/eventdefs.h
diffstat 16 files changed, 234 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/truss/codes.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/cmd/truss/codes.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  */
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
@@ -1248,6 +1250,8 @@
 		"zfs_cmd_t" },
 	{ (uint_t)ZFS_IOC_OBJ_TO_STATS,		"ZFS_IOC_OBJ_TO_STATS",
 		"zfs_cmd_t" },
+	{ (uint_t)ZFS_IOC_POOL_REGUID,		"ZFS_IOC_POOL_REGUID",
+		"zfs_cmd_t" },
 
 	/* kssl ioctls */
 	{ (uint_t)KSSL_ADD_ENTRY,		"KSSL_ADD_ENTRY",
--- a/usr/src/cmd/zpool/zpool_main.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/cmd/zpool/zpool_main.c	Fri Nov 11 14:07:54 2011 -0800
@@ -22,6 +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 by Delphix. All rights reserved.
  */
 
 #include <assert.h>
@@ -65,6 +66,8 @@
 static int zpool_do_offline(int, char **);
 static int zpool_do_clear(int, char **);
 
+static int zpool_do_reguid(int, char **);
+
 static int zpool_do_attach(int, char **);
 static int zpool_do_detach(int, char **);
 static int zpool_do_replace(int, char **);
@@ -122,7 +125,8 @@
 	HELP_UPGRADE,
 	HELP_GET,
 	HELP_SET,
-	HELP_SPLIT
+	HELP_SPLIT,
+	HELP_REGUID
 } zpool_help_t;
 
 
@@ -166,6 +170,7 @@
 	{ "import",	zpool_do_import,	HELP_IMPORT		},
 	{ "export",	zpool_do_export,	HELP_EXPORT		},
 	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
+	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
 	{ NULL },
 	{ "history",	zpool_do_history,	HELP_HISTORY		},
 	{ "get",	zpool_do_get,		HELP_GET		},
@@ -244,6 +249,8 @@
 		return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
 		    "\t    [-o property=value] <pool> <newpool> "
 		    "[<device> ...]\n"));
+	case HELP_REGUID:
+		return (gettext("\treguid <pool>\n"));
 	}
 
 	abort();
@@ -3193,6 +3200,52 @@
 	return (ret);
 }
 
+/*
+ * zpool reguid <pool>
+ */
+int
+zpool_do_reguid(int argc, char **argv)
+{
+	int c;
+	char *poolname;
+	zpool_handle_t *zhp;
+	int ret = 0;
+
+	/* check options */
+	while ((c = getopt(argc, argv, "")) != -1) {
+		switch (c) {
+		case '?':
+			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
+			    optopt);
+			usage(B_FALSE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	/* get pool name and check number of arguments */
+	if (argc < 1) {
+		(void) fprintf(stderr, gettext("missing pool name\n"));
+		usage(B_FALSE);
+	}
+
+	if (argc > 1) {
+		(void) fprintf(stderr, gettext("too many arguments\n"));
+		usage(B_FALSE);
+	}
+
+	poolname = argv[0];
+	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
+		return (1);
+
+	ret = zpool_reguid(zhp);
+
+	zpool_close(zhp);
+	return (ret);
+}
+
+
 typedef struct scrub_cbdata {
 	int	cb_type;
 	int	cb_argc;
--- a/usr/src/cmd/ztest/ztest.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/cmd/ztest/ztest.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -257,6 +258,7 @@
 ztest_func_t ztest_vdev_add_remove;
 ztest_func_t ztest_vdev_aux_add_remove;
 ztest_func_t ztest_split_pool;
+ztest_func_t ztest_reguid;
 
 uint64_t zopt_always = 0ULL * NANOSEC;		/* all the time */
 uint64_t zopt_incessant = 1ULL * NANOSEC / 10;	/* every 1/10 second */
@@ -287,6 +289,7 @@
 	{ ztest_fault_inject,			1,	&zopt_sometimes	},
 	{ ztest_ddt_repair,			1,	&zopt_sometimes	},
 	{ ztest_dmu_snapshot_hold,		1,	&zopt_sometimes	},
+	{ ztest_reguid,				1,	&zopt_sometimes },
 	{ ztest_spa_rename,			1,	&zopt_rarely	},
 	{ ztest_scrub,				1,	&zopt_rarely	},
 	{ ztest_dsl_dataset_promote_busy,	1,	&zopt_rarely	},
@@ -323,6 +326,7 @@
 	uint64_t	zs_vdev_aux;
 	uint64_t	zs_alloc;
 	uint64_t	zs_space;
+	uint64_t	zs_guid;
 	mutex_t		zs_vdev_lock;
 	rwlock_t	zs_name_lock;
 	ztest_info_t	zs_info[ZTEST_FUNCS];
@@ -4641,7 +4645,7 @@
 
 	object = od[0].od_object;
 	blocksize = od[0].od_blocksize;
-	pattern = spa_guid(spa) ^ dmu_objset_fsid_guid(os);
+	pattern = zs->zs_guid ^ dmu_objset_fsid_guid(os);
 
 	ASSERT(object != 0);
 
@@ -4712,6 +4716,31 @@
 }
 
 /*
+ * Change the guid for the pool.
+ */
+/* ARGSUSED */
+void
+ztest_reguid(ztest_ds_t *zd, uint64_t id)
+{
+	ztest_shared_t *zs = ztest_shared;
+	spa_t *spa = zs->zs_spa;
+	uint64_t orig, load;
+
+	orig = spa_guid(spa);
+	load = spa_load_guid(spa);
+	if (spa_change_guid(spa) != 0)
+		return;
+
+	if (zopt_verbose >= 3) {
+		(void) printf("Changed guid old %llu -> %llu\n",
+		    (u_longlong_t)orig, (u_longlong_t)spa_guid(spa));
+	}
+
+	VERIFY3U(orig, !=, spa_guid(spa));
+	VERIFY3U(load, ==, spa_load_guid(spa));
+}
+
+/*
  * Rename the pool to a different name and then rename it back.
  */
 /* ARGSUSED */
@@ -5139,6 +5168,7 @@
 {
 	thread_t *tid;
 	spa_t *spa;
+	objset_t *os;
 	thread_t resume_tid;
 	int error;
 
@@ -5170,6 +5200,10 @@
 	spa->spa_debug = B_TRUE;
 	zs->zs_spa = spa;
 
+	VERIFY3U(0, ==, dmu_objset_hold(zs->zs_pool, FTAG, &os));
+	zs->zs_guid = dmu_objset_fsid_guid(os);
+	dmu_objset_rele(os, FTAG);
+
 	spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
 
 	/*
--- a/usr/src/lib/libzfs/common/libzfs.h	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/lib/libzfs/common/libzfs.h	Fri Nov 11 14:07:54 2011 -0800
@@ -21,7 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 #ifndef	_LIBZFS_H
@@ -230,6 +231,7 @@
  */
 extern int zpool_scan(zpool_handle_t *, pool_scan_func_t);
 extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
+extern int zpool_reguid(zpool_handle_t *);
 
 extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
     vdev_state_t *);
--- a/usr/src/lib/libzfs/common/libzfs_pool.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 #include <ctype.h>
@@ -2967,6 +2969,26 @@
 }
 
 /*
+ * Change the GUID for a pool.
+ */
+int
+zpool_reguid(zpool_handle_t *zhp)
+{
+	char msg[1024];
+	libzfs_handle_t *hdl = zhp->zpool_hdl;
+	zfs_cmd_t zc = { 0 };
+
+	(void) snprintf(msg, sizeof (msg),
+	    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);
+
+	return (zpool_standard_error(hdl, errno, msg));
+}
+
+/*
  * Convert from a devid string to a path.
  */
 static char *
--- a/usr/src/lib/libzfs/common/mapfile-vers	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/lib/libzfs/common/mapfile-vers	Fri Nov 11 14:07:54 2011 -0800
@@ -19,7 +19,8 @@
 # CDDL HEADER END
 #
 # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+# Copyright (c) 2011 by Delphix. All rights reserved.
 #
 # MAPFILE HEADER START
 #
@@ -199,6 +200,7 @@
 	zpool_prop_values;
 	zpool_read_label;
 	zpool_refresh_stats;
+	zpool_reguid;
 	zpool_scan;
 	zpool_search_import;
 	zpool_set_history_str;
--- a/usr/src/man/man1m/zpool.1m	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/man/man1m/zpool.1m	Fri Nov 11 14:07:54 2011 -0800
@@ -3,7 +3,8 @@
 .\" 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 http://www.opensolaris.org/os/licensing.
 .\" 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]
-.TH ZPOOL 1M "Sep 21, 2009"
+.\" Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+.TH ZPOOL 1M "Oct 25, 2011"
 .SH NAME
 zpool \- configures ZFS storage pools
 .SH SYNOPSIS
@@ -97,6 +98,11 @@
 
 .LP
 .nf
+\fBzpool reguid\fR \fIpool\fR
+.fi
+
+.LP
+.nf
 \fBzpool remove\fR \fIpool\fR \fIdevice\fR ...
 .fi
 
@@ -1439,6 +1445,17 @@
 .sp
 .ne 2
 .na
+\fB\fBzpool reguid\fR \fIpool\fR
+.ad
+.sp .6
+.RS 4n
+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.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBzpool remove\fR \fIpool\fR \fIdevice\fR ...\fR
 .ad
 .sp .6
--- a/usr/src/uts/common/fs/zfs/arc.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/arc.c	Fri Nov 11 14:07:54 2011 -0800
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 /*
@@ -1217,7 +1219,7 @@
 	ASSERT(BUF_EMPTY(hdr));
 	hdr->b_size = size;
 	hdr->b_type = type;
-	hdr->b_spa = spa_guid(spa);
+	hdr->b_spa = spa_load_guid(spa);
 	hdr->b_state = arc_anon;
 	hdr->b_arc_access = 0;
 	buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE);
@@ -1919,7 +1921,7 @@
 	uint64_t guid = 0;
 
 	if (spa)
-		guid = spa_guid(spa);
+		guid = spa_load_guid(spa);
 
 	while (list_head(&arc_mru->arcs_list[ARC_BUFC_DATA])) {
 		(void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_DATA);
@@ -2676,7 +2678,7 @@
 	arc_buf_t *buf;
 	kmutex_t *hash_lock;
 	zio_t *rzio;
-	uint64_t guid = spa_guid(spa);
+	uint64_t guid = spa_load_guid(spa);
 
 top:
 	hdr = buf_hash_find(guid, BP_IDENTITY(bp), BP_PHYSICAL_BIRTH(bp),
@@ -4234,7 +4236,7 @@
 	boolean_t have_lock, full;
 	l2arc_write_callback_t *cb;
 	zio_t *pio, *wzio;
-	uint64_t guid = spa_guid(spa);
+	uint64_t guid = spa_load_guid(spa);
 
 	ASSERT(dev->l2ad_vdev != NULL);
 
--- a/usr/src/uts/common/fs/zfs/spa.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/spa.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,9 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-/*
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 /*
@@ -566,6 +565,43 @@
 }
 
 /*
+ * Change the GUID for the pool.  This is done so that we can later
+ * re-import a pool built from a clone of our own vdevs.  We will modify
+ * the root vdev's guid, our own pool guid, and then mark all of our
+ * vdevs dirty.  Note that we must make sure that all our vdevs are
+ * 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.
+ */
+int
+spa_change_guid(spa_t *spa)
+{
+	uint64_t	oldguid, newguid;
+	uint64_t	txg;
+
+	if (!(spa_mode_global & FWRITE))
+		return (EROFS);
+
+	txg = spa_vdev_enter(spa);
+
+	if (spa->spa_root_vdev->vdev_state != VDEV_STATE_HEALTHY)
+		return (spa_vdev_exit(spa, NULL, txg, ENXIO));
+
+	oldguid = spa_guid(spa);
+	newguid = spa_generate_guid(NULL);
+	ASSERT3U(oldguid, !=, newguid);
+
+	spa->spa_root_vdev->vdev_guid = newguid;
+	spa->spa_root_vdev->vdev_guid_sum += (newguid - oldguid);
+
+	vdev_config_dirty(spa->spa_root_vdev);
+
+	spa_event_notify(spa, NULL, ESC_ZFS_POOL_REGUID);
+
+	return (spa_vdev_exit(spa, NULL, txg, 0));
+}
+
+/*
  * ==========================================================================
  * SPA state manipulation (open/create/destroy/import/export)
  * ==========================================================================
@@ -1743,7 +1779,7 @@
 	    spa_guid_exists(pool_guid, 0)) {
 		error = EEXIST;
 	} else {
-		spa->spa_load_guid = pool_guid;
+		spa->spa_config_guid = pool_guid;
 
 		if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_SPLIT,
 		    &nvl) == 0) {
--- a/usr/src/uts/common/fs/zfs/spa_misc.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -1304,13 +1305,24 @@
 	/*
 	 * If we fail to parse the config during spa_load(), we can go through
 	 * the error path (which posts an ereport) and end up here with no root
-	 * vdev.  We stash the original pool guid in 'spa_load_guid' to handle
+	 * vdev.  We stash the original pool guid in 'spa_config_guid' to handle
 	 * this case.
 	 */
 	if (spa->spa_root_vdev != NULL)
 		return (spa->spa_root_vdev->vdev_guid);
 	else
-		return (spa->spa_load_guid);
+		return (spa->spa_config_guid);
+}
+
+uint64_t
+spa_load_guid(spa_t *spa)
+{
+	/*
+	 * This is a GUID that exists solely as a reference for the
+	 * purposes of the arc.  It is generated at load time, and
+	 * is never written to persistent storage.
+	 */
+	return (spa->spa_load_guid);
 }
 
 uint64_t
--- a/usr/src/uts/common/fs/zfs/sys/spa.h	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/sys/spa.h	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SYS_SPA_H
@@ -578,6 +579,7 @@
 extern int spa_sync_pass(spa_t *spa);
 extern char *spa_name(spa_t *spa);
 extern uint64_t spa_guid(spa_t *spa);
+extern uint64_t spa_load_guid(spa_t *spa);
 extern uint64_t spa_last_synced_txg(spa_t *spa);
 extern uint64_t spa_first_txg(spa_t *spa);
 extern uint64_t spa_syncing_txg(spa_t *spa);
@@ -611,6 +613,7 @@
 extern uint64_t spa_generate_guid(spa_t *spa);
 extern void sprintf_blkptr(char *buf, const blkptr_t *bp);
 extern void spa_freeze(spa_t *spa);
+extern int spa_change_guid(spa_t *spa);
 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,
--- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SYS_SPA_IMPL_H
@@ -136,7 +137,8 @@
 	objset_t	*spa_meta_objset;	/* copy of dp->dp_meta_objset */
 	txg_list_t	spa_vdev_txg_list;	/* per-txg dirty vdev list */
 	vdev_t		*spa_root_vdev;		/* top-level vdev container */
-	uint64_t	spa_load_guid;		/* initial guid for spa_load */
+	uint64_t	spa_config_guid;	/* config pool guid */
+	uint64_t	spa_load_guid;		/* spa_load initialized guid */
 	list_t		spa_config_dirty_list;	/* vdevs with dirty config */
 	list_t		spa_state_dirty_list;	/* vdevs with dirty state */
 	spa_aux_vdev_t	spa_spares;		/* hot spares */
--- a/usr/src/uts/common/fs/zfs/vdev.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/vdev.c	Fri Nov 11 14:07:54 2011 -0800
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -286,6 +288,7 @@
 	if (spa->spa_root_vdev == NULL) {
 		ASSERT(ops == &vdev_root_ops);
 		spa->spa_root_vdev = vd;
+		spa->spa_load_guid = spa_generate_guid(NULL);
 	}
 
 	if (guid == 0 && ops != &vdev_hole_ops) {
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Fri Nov 11 14:07:54 2011 -0800
@@ -22,6 +22,10 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Portions Copyright 2011 Martin Matuska
  */
+/*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -1449,6 +1453,20 @@
 }
 
 static int
+zfs_ioc_pool_reguid(zfs_cmd_t *zc)
+{
+	spa_t *spa;
+	int error;
+
+	error = spa_open(zc->zc_name, &spa, FTAG);
+	if (error == 0) {
+		error = spa_change_guid(spa);
+		spa_close(spa, FTAG);
+	}
+	return (error);
+}
+
+static int
 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc)
 {
 	int error;
@@ -4745,7 +4763,9 @@
 	{ zfs_ioc_tmp_snapshot, zfs_secpolicy_tmp_snapshot, DATASET_NAME,
 	    B_FALSE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
 	{ zfs_ioc_obj_to_stats, zfs_secpolicy_diff, DATASET_NAME, B_FALSE,
-	    POOL_CHECK_SUSPENDED }
+	    POOL_CHECK_SUSPENDED },
+	{ zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE,
+	    POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }
 };
 
 int
--- a/usr/src/uts/common/sys/fs/zfs.h	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/sys/fs/zfs.h	Fri Nov 11 14:07:54 2011 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -776,7 +777,8 @@
 	ZFS_IOC_NEXT_OBJ,
 	ZFS_IOC_DIFF,
 	ZFS_IOC_TMP_SNAPSHOT,
-	ZFS_IOC_OBJ_TO_STATS
+	ZFS_IOC_OBJ_TO_STATS,
+	ZFS_IOC_POOL_REGUID
 } zfs_ioc_t;
 
 /*
@@ -839,6 +841,7 @@
  *	ESC_ZFS_RESILVER_START
  *	ESC_ZFS_RESILVER_END
  *	ESC_ZFS_POOL_DESTROY
+ *	ESC_ZFS_POOL_REGUID
  *
  *		ZFS_EV_POOL_NAME	DATA_TYPE_STRING
  *		ZFS_EV_POOL_GUID	DATA_TYPE_UINT64
--- a/usr/src/uts/common/sys/sysevent/eventdefs.h	Wed Nov 09 18:47:36 2011 -0500
+++ b/usr/src/uts/common/sys/sysevent/eventdefs.h	Fri Nov 11 14:07:54 2011 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef	_SYS_SYSEVENT_EVENTDEFS_H
@@ -256,6 +257,7 @@
 #define	ESC_ZFS_SCRUB_FINISH		"ESC_ZFS_scrub_finish"
 #define	ESC_ZFS_VDEV_SPARE		"ESC_ZFS_vdev_spare"
 #define	ESC_ZFS_BOOTFS_VDEV_ATTACH	"ESC_ZFS_bootfs_vdev_attach"
+#define	ESC_ZFS_POOL_REGUID		"ESC_ZFS_pool_reguid"
 
 /*
  * datalink subclass definitions.