changeset 3975:6674f5d79069

6282725 hostname/hostid should be stored in the label
author ek110237
date Thu, 05 Apr 2007 13:22:27 -0700
parents a01a9d07ea67
children f77f0b15fc3b
files usr/src/cmd/fm/dicts/ZFS.dict usr/src/cmd/fm/dicts/ZFS.po usr/src/cmd/zpool/zpool_main.c usr/src/lib/libzfs/common/libzfs.h usr/src/lib/libzfs/common/libzfs_import.c usr/src/lib/libzfs/common/libzfs_status.c usr/src/lib/libzpool/common/kernel.c usr/src/lib/libzpool/common/sys/zfs_context.h usr/src/uts/common/fs/zfs/spa.c usr/src/uts/common/fs/zfs/spa_config.c usr/src/uts/common/sys/fs/zfs.h
diffstat 11 files changed, 176 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fm/dicts/ZFS.dict	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/cmd/fm/dicts/ZFS.dict	Thu Apr 05 13:22:27 2007 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # CDDL HEADER START
@@ -40,3 +40,4 @@
 ereport.fs.zfs.device.version_mismatch=10
 fault.fs.zfs.pool=11
 fault.fs.zfs.device=12
+ereport.fs.zfs.pool.hostname_mismatch=13
--- a/usr/src/cmd/fm/dicts/ZFS.po	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/cmd/fm/dicts/ZFS.po	Thu Apr 05 13:22:27 2007 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # CDDL HEADER START
@@ -217,3 +217,19 @@
 msgstr "Fault tolerance of the pool may be compromised."
 msgid "ZFS-8000-D3.action"
 msgstr "Run 'zpool status -x' and replace the bad device."
+#
+# code: ZFS-8000-EY
+# keys: ereport.fs.zfs.pool.hostname_mismatch
+#
+msgid "ZFS-8000-EY.type"
+msgstr "Error"
+msgid "ZFS-8000-EY.severity"
+msgstr "Major"
+msgid "ZFS-8000-EY.description"
+msgstr "The ZFS pool was last accessed by another system  Refer to %s for more information."
+msgid "ZFS-8000-EY.response"
+msgstr "No automated response will be taken."
+msgid "ZFS-8000-EY.impact"
+msgstr "ZFS filesystems are not available"
+msgid "ZFS-8000-EY.action"
+msgstr "\nTo determine which system last accessed the pool, run the 'zpool import'\ncommand:\n\n\n# zpool import\n  pool: test\n    id: 14702934086626715962\nstate: ONLINE\nstatus: The pool was last accessed by another system.\naction: The pool can be imported using its name or numeric identifier and\n        the '-f' flag.\n   see: http://www.sun.com/msg/ZFS-XXXXXXX\nconfig:\n\n        test              ONLINE\n          c0t0d0          ONLINE\n\n# zpool import test\ncannot import 'test': pool may be in use from other system, it was last\naccessed by 'tank' (hostid: 0x1435718c) on Fri Mar  9 15:42:47 2007\nuse '-f' to import anyway\n#\n\n\nIf you are certain that the pool is not being actively accessed by another\nsystem, then you can use the '-f' option to 'zpool import' to forcible\nimport the pool.\n "
--- a/usr/src/cmd/zpool/zpool_main.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/cmd/zpool/zpool_main.c	Thu Apr 05 13:22:27 2007 -0700
@@ -1079,7 +1079,10 @@
 		(void) printf(gettext("status: The pool is formatted using an "
 		    "incompatible version.\n"));
 		break;
-
+	case ZPOOL_STATUS_HOSTID_MISMATCH:
+		(void) printf(gettext("status: The pool was last accessed by "
+		    "another system.\n"));
+		break;
 	default:
 		/*
 		 * No other status can be seen when importing pools.
@@ -1096,6 +1099,10 @@
 			    "imported using its name or numeric identifier, "
 			    "though\n\tsome features will not be available "
 			    "without an explicit 'zpool upgrade'.\n"));
+		else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
+			(void) printf(gettext("action: The pool can be "
+			    "imported using its name or numeric "
+			    "identifier and\n\tthe '-f' flag.\n"));
 		else
 			(void) printf(gettext("action: The pool can be "
 			    "imported using its name or numeric "
@@ -1185,10 +1192,37 @@
 		    "is formatted using a newer ZFS version\n"), name);
 		return (1);
 	} else if (state != POOL_STATE_EXPORTED && !force) {
-		(void) fprintf(stderr, gettext("cannot import '%s': pool "
-		    "may be in use from other system\n"), name);
-		(void) fprintf(stderr, gettext("use '-f' to import anyway\n"));
-		return (1);
+		uint64_t hostid;
+
+		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
+		    &hostid) == 0) {
+			if ((unsigned long)hostid != gethostid()) {
+				char *hostname;
+				uint64_t timestamp;
+				time_t t;
+
+				verify(nvlist_lookup_string(config,
+				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
+				verify(nvlist_lookup_uint64(config,
+				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
+				t = timestamp;
+				(void) fprintf(stderr, gettext("cannot import "
+				    "'%s': pool may be in use from other "
+				    "system, it was last accessed by %s "
+				    "(hostid: 0x%lx) on %s"), name, hostname,
+				    (unsigned long)hostid,
+				    asctime(localtime(&t)));
+				(void) fprintf(stderr, gettext("use '-f' to "
+				    "import anyway\n"));
+				return (1);
+			}
+		} else {
+			(void) fprintf(stderr, gettext("cannot import '%s': "
+			    "pool may be in use from other system\n"), name);
+			(void) fprintf(stderr, gettext("use '-f' to import "
+			    "anyway\n"));
+			return (1);
+		}
 	}
 
 	if (zpool_import(g_zfs, config, newname, altroot) != 0)
--- a/usr/src/lib/libzfs/common/libzfs.h	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/lib/libzfs/common/libzfs.h	Thu Apr 05 13:22:27 2007 -0700
@@ -191,6 +191,7 @@
 	ZPOOL_STATUS_CORRUPT_DATA,	/* data errors in user (meta)data */
 	ZPOOL_STATUS_FAILING_DEV,	/* device experiencing errors */
 	ZPOOL_STATUS_VERSION_NEWER,	/* newer on-disk version */
+	ZPOOL_STATUS_HOSTID_MISMATCH,	/* last accessed by another system */
 
 	/*
 	 * The following are not faults per se, but still an error possibly
--- a/usr/src/lib/libzfs/common/libzfs_import.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_import.c	Thu Apr 05 13:22:27 2007 -0700
@@ -379,7 +379,7 @@
 	uint_t i, nspares;
 	boolean_t config_seen;
 	uint64_t best_txg;
-	char *name;
+	char *name, *hostname;
 	zfs_cmd_t zc = { 0 };
 	uint64_t version, guid;
 	size_t len;
@@ -388,6 +388,7 @@
 	nvlist_t **child = NULL;
 	uint_t c;
 	boolean_t isactive;
+	uint64_t hostid;
 
 	if (nvlist_alloc(&ret, 0, 0) != 0)
 		goto nomem;
@@ -430,6 +431,8 @@
 				 * 	pool guid
 				 * 	name
 				 * 	pool state
+				 *	hostid (if available)
+				 *	hostname (if available)
 				 */
 				uint64_t state;
 
@@ -453,6 +456,20 @@
 				if (nvlist_add_uint64(config,
 				    ZPOOL_CONFIG_POOL_STATE, state) != 0)
 					goto nomem;
+				hostid = 0;
+				if (nvlist_lookup_uint64(tmp,
+				    ZPOOL_CONFIG_HOSTID, &hostid) == 0) {
+					if (nvlist_add_uint64(config,
+					    ZPOOL_CONFIG_HOSTID, hostid) != 0)
+						goto nomem;
+					verify(nvlist_lookup_string(tmp,
+					    ZPOOL_CONFIG_HOSTNAME,
+					    &hostname) == 0);
+					if (nvlist_add_string(config,
+					    ZPOOL_CONFIG_HOSTNAME,
+					    hostname) != 0)
+						goto nomem;
+				}
 
 				config_seen = B_TRUE;
 			}
@@ -622,6 +639,20 @@
 		}
 
 		/*
+		 * Restore the original information read from the actual label.
+		 */
+		(void) nvlist_remove(config, ZPOOL_CONFIG_HOSTID,
+		    DATA_TYPE_UINT64);
+		(void) nvlist_remove(config, ZPOOL_CONFIG_HOSTNAME,
+		    DATA_TYPE_STRING);
+		if (hostid != 0) {
+			verify(nvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID,
+			    hostid) == 0);
+			verify(nvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME,
+			    hostname) == 0);
+		}
+
+		/*
 		 * Add this pool to the list of configs.
 		 */
 		verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
--- a/usr/src/lib/libzfs/common/libzfs_status.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_status.c	Thu Apr 05 13:22:27 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,6 +43,7 @@
 
 #include <libzfs.h>
 #include <string.h>
+#include <unistd.h>
 #include "libzfs_impl.h"
 
 /*
@@ -50,7 +51,7 @@
  * in libzfs.h.  Note that there are some status results which go past the end
  * of this table, and hence have no associated message ID.
  */
-static char *msgid_table[] = {
+static char *zfs_msgid_table[] = {
 	"ZFS-8000-14",
 	"ZFS-8000-2Q",
 	"ZFS-8000-3C",
@@ -60,7 +61,8 @@
 	"ZFS-8000-72",
 	"ZFS-8000-8A",
 	"ZFS-8000-9P",
-	"ZFS-8000-A5"
+	"ZFS-8000-A5",
+	"ZFS-8000-EY"
 };
 
 /*
@@ -69,7 +71,7 @@
  * and the article referred to by 'zpool status' must match that indicated by
  * the syslog error message.  We override missing data as well as corrupt pool.
  */
-static char *msgid_table_active[] = {
+static char *zfs_msgid_table_active[] = {
 	"ZFS-8000-14",
 	"ZFS-8000-D3",		/* overridden */
 	"ZFS-8000-D3",		/* overridden */
@@ -82,7 +84,7 @@
 	"ZFS-8000-CS",		/* overridden */
 };
 
-#define	NMSGID	(sizeof (msgid_table) / sizeof (msgid_table[0]))
+#define	NMSGID	(sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
 
 /* ARGSUSED */
 static int
@@ -178,6 +180,8 @@
 	uint_t vsc;
 	uint64_t nerr;
 	uint64_t version;
+	uint64_t stateval;
+	uint64_t hostid = 0;
 
 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
 	    &version) == 0);
@@ -185,6 +189,16 @@
 	    &nvroot) == 0);
 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
 	    (uint64_t **)&vs, &vsc) == 0);
+	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
+	    &stateval) == 0);
+	(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
+
+	/*
+	 * Pool last accessed by another system.
+	 */
+	if (hostid != 0 && (unsigned long)hostid != gethostid() &&
+	    stateval == POOL_STATE_ACTIVE)
+		return (ZPOOL_STATUS_HOSTID_MISMATCH);
 
 	/*
 	 * Newer on-disk version.
@@ -270,7 +284,7 @@
 	if (ret >= NMSGID)
 		*msgid = NULL;
 	else
-		*msgid = msgid_table_active[ret];
+		*msgid = zfs_msgid_table_active[ret];
 
 	return (ret);
 }
@@ -283,7 +297,7 @@
 	if (ret >= NMSGID)
 		*msgid = NULL;
 	else
-		*msgid = msgid_table[ret];
+		*msgid = zfs_msgid_table[ret];
 
 	return (ret);
 }
--- a/usr/src/lib/libzpool/common/kernel.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/lib/libzpool/common/kernel.c	Thu Apr 05 13:22:27 2007 -0700
@@ -37,6 +37,7 @@
 #include <sys/processor.h>
 #include <sys/zfs_context.h>
 #include <sys/zmod.h>
+#include <sys/utsname.h>
 
 /*
  * Emulation of kernel services in userland.
@@ -44,6 +45,11 @@
 
 uint64_t physmem;
 vnode_t *rootdir = (vnode_t *)0xabcd1234;
+char hw_serial[11];
+
+struct utsname utsname = {
+	"userland", "libzpool", "1", "1", "na"
+};
 
 /*
  * =========================================================================
@@ -723,6 +729,17 @@
 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
 }
 
+int
+ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
+{
+	char *end;
+
+	*result = strtoul(hw_serial, &end, base);
+	if (*result == 0)
+		return (errno);
+	return (0);
+}
+
 /*
  * =========================================================================
  * kernel emulation setup & teardown
@@ -748,6 +765,8 @@
 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
 
+	snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
+
 	spa_init(mode);
 }
 
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h	Thu Apr 05 13:22:27 2007 -0700
@@ -425,6 +425,13 @@
 #define	zone_dataset_visible(x, y)	(1)
 #define	INGLOBALZONE(z)			(1)
 
+/*
+ * Hostname information
+ */
+extern char hw_serial[];
+extern int ddi_strtoul(const char *str, char **nptr, int base,
+    unsigned long *result);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/uts/common/fs/zfs/spa.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/spa.c	Thu Apr 05 13:22:27 2007 -0700
@@ -57,6 +57,8 @@
 #include <sys/dsl_synctask.h>
 #include <sys/fs/zfs.h>
 #include <sys/callb.h>
+#include <sys/systeminfo.h>
+#include <sys/sunddi.h>
 
 int zio_taskq_threads = 8;
 
@@ -572,6 +574,7 @@
 
 	if (!mosconfig) {
 		nvlist_t *newconfig;
+		uint64_t hostid;
 
 		if (load_nvlist(spa, spa->spa_config_object, &newconfig) != 0) {
 			vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN,
@@ -580,6 +583,27 @@
 			goto out;
 		}
 
+		if (nvlist_lookup_uint64(newconfig, ZPOOL_CONFIG_HOSTID,
+		    &hostid) == 0) {
+			char *hostname;
+			unsigned long myhostid = 0;
+
+			VERIFY(nvlist_lookup_string(newconfig,
+			    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
+
+			(void) ddi_strtoul(hw_serial, NULL, 10, &myhostid);
+			if ((unsigned long)hostid != myhostid) {
+				cmn_err(CE_WARN, "pool '%s' could not be "
+				    "loaded as it was last accessed by "
+				    "another system (host: %s hostid: 0x%lx).  "
+				    "See: http://www.sun.com/msg/ZFS-8000-EY",
+				    spa->spa_name, hostname,
+				    (unsigned long)hostid);
+				error = EBADF;
+				goto out;
+			}
+		}
+
 		spa_config_set(spa, newconfig);
 		spa_unload(spa);
 		spa_deactivate(spa);
@@ -1359,6 +1383,8 @@
 		    poolname) == 0);
 		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_STATE,
 		    state) == 0);
+		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_TIMESTAMP,
+		    spa->spa_uberblock.ub_timestamp) == 0);
 
 		/*
 		 * Add the list of hot spares.
--- a/usr/src/uts/common/fs/zfs/spa_config.c	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/spa_config.c	Thu Apr 05 13:22:27 2007 -0700
@@ -33,6 +33,9 @@
 #include <sys/fs/zfs.h>
 #include <sys/vdev_impl.h>
 #include <sys/zfs_ioctl.h>
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+#include <sys/sunddi.h>
 #ifdef _KERNEL
 #include <sys/kobj.h>
 #endif
@@ -265,6 +268,7 @@
 {
 	nvlist_t *config, *nvroot;
 	vdev_t *rvd = spa->spa_root_vdev;
+	unsigned long hostid = 0;
 
 	ASSERT(spa_config_held(spa, RW_READER));
 
@@ -289,6 +293,11 @@
 	    txg) == 0);
 	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 	    spa_guid(spa)) == 0);
+	(void) ddi_strtoul(hw_serial, NULL, 10, &hostid);
+	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID,
+	    hostid) == 0);
+	VERIFY(nvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME,
+	    utsname.nodename) == 0);
 
 	if (vd != rvd) {
 		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_TOP_GUID,
--- a/usr/src/uts/common/sys/fs/zfs.h	Thu Apr 05 11:27:36 2007 -0700
+++ b/usr/src/uts/common/sys/fs/zfs.h	Thu Apr 05 13:22:27 2007 -0700
@@ -207,6 +207,9 @@
 #define	ZPOOL_CONFIG_SPARES		"spares"
 #define	ZPOOL_CONFIG_IS_SPARE		"is_spare"
 #define	ZPOOL_CONFIG_NPARITY		"nparity"
+#define	ZPOOL_CONFIG_HOSTID		"hostid"
+#define	ZPOOL_CONFIG_HOSTNAME		"hostname"
+#define	ZPOOL_CONFIG_TIMESTAMP		"timestamp" /* not stored on disk */
 
 #define	VDEV_TYPE_ROOT			"root"
 #define	VDEV_TYPE_MIRROR		"mirror"