diff usr/src/uts/common/fs/zfs/spa.c @ 6673:be079d6124af

6697301 deadlock between ZFS and devfs can hang system 6702485 enc_do_ucode() corrupts memory if image is not aligned 6702487 need to update product name for J4500 6702607 GRUB should allow explicit zfs-bootfs setting 6703082 need to update parsing of J4500 STRING IN data 6703124 fix for 6667023 was overaggressive and unnecessarily confusing 6703353 ZIO_FLAG_SPECULATIVE should not generate ereports 6703845 vdev_disk_read_rootlabel() leaks LDI handle 6703938 canceling an in-place replacement results in lingering '/old' pathname 6704037 autoreplace code should work for faulted devices 6704039 autoreplace code shouldn't use old devid 6704615 spa_import_rootpool() needs to do forced import
author eschrock
date Tue, 20 May 2008 16:11:57 -0700
parents 3a34b0dbb107
children 47572a2f5e73
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/spa.c	Tue May 20 15:17:46 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/spa.c	Tue May 20 16:11:57 2008 -0700
@@ -2059,6 +2059,7 @@
 
 	if (allowfaulted)
 		spa->spa_import_faulted = B_TRUE;
+	spa->spa_is_root = isroot;
 
 	/*
 	 * Pass off the heavy lifting to spa_load().
@@ -2288,7 +2289,13 @@
 
 	VERIFY(nvlist_lookup_string(conf, ZPOOL_CONFIG_POOL_NAME, &pname) == 0);
 
-	error = spa_import_common(pname, conf, NULL, B_TRUE, B_FALSE);
+	/*
+	 * We specify 'allowfaulted' for this to be treated like spa_open()
+	 * instead of spa_import().  This prevents us from marking vdevs as
+	 * persistently unavailable, and generates FMA ereports as if it were a
+	 * pool open, not import.
+	 */
+	error = spa_import_common(pname, conf, NULL, B_TRUE, B_TRUE);
 	if (error == EEXIST)
 		error = 0;
 
@@ -2852,6 +2859,7 @@
 	vdev_t *vd, *pvd, *cvd, *tvd;
 	boolean_t unspare = B_FALSE;
 	uint64_t unspare_guid;
+	size_t len;
 
 	txg = spa_vdev_enter(spa);
 
@@ -2928,6 +2936,24 @@
 		return (spa_vdev_exit(spa, NULL, txg, EBUSY));
 
 	/*
+	 * If we are detaching the second disk from a replacing vdev, then
+	 * check to see if we changed the original vdev's path to have "/old"
+	 * at the end in spa_vdev_attach().  If so, undo that change now.
+	 */
+	if (pvd->vdev_ops == &vdev_replacing_ops && vd->vdev_id == 1 &&
+	    pvd->vdev_child[0]->vdev_path != NULL &&
+	    pvd->vdev_child[1]->vdev_path != NULL) {
+		ASSERT(pvd->vdev_child[1] == vd);
+		cvd = pvd->vdev_child[0];
+		len = strlen(vd->vdev_path);
+		if (strncmp(cvd->vdev_path, vd->vdev_path, len) == 0 &&
+		    strcmp(cvd->vdev_path + len, "/old") == 0) {
+			spa_strfree(cvd->vdev_path);
+			cvd->vdev_path = spa_strdup(vd->vdev_path);
+		}
+	}
+
+	/*
 	 * If we are detaching the original disk from a spare, then it implies
 	 * that the spare should become a real disk, and be removed from the
 	 * active spare list for the pool.