usr/src/uts/common/fs/zfs/spa.c
changeset 1732 9e3ae798af31
parent 1635 0ab1193d47cb
child 1733 a7c3bc84e012
--- a/usr/src/uts/common/fs/zfs/spa.c	Sat Apr 01 21:50:51 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/spa.c	Sun Apr 02 00:47:06 2006 -0800
@@ -341,8 +341,7 @@
 	 * If the vdev guid sum doesn't match the uberblock, we have an
 	 * incomplete configuration.
 	 */
-	if (rvd->vdev_guid_sum != ub->ub_guid_sum && (mosconfig ||
-	    state == SPA_LOAD_IMPORT || state == SPA_LOAD_TRYIMPORT)) {
+	if (rvd->vdev_guid_sum != ub->ub_guid_sum && mosconfig) {
 		vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN,
 		    VDEV_AUX_BAD_GUID_SUM);
 		error = ENXIO;
@@ -842,8 +841,10 @@
 
 	/*
 	 * Pass off the heavy lifting to spa_load().
+	 * Pass TRUE for mosconfig because the user-supplied config
+	 * is actually the one to trust when doing an import.
 	 */
-	error = spa_load(spa, config, SPA_LOAD_IMPORT, B_FALSE);
+	error = spa_load(spa, config, SPA_LOAD_IMPORT, B_TRUE);
 
 	if (error) {
 		spa_unload(spa);
@@ -898,8 +899,10 @@
 
 	/*
 	 * Pass off the heavy lifting to spa_load().
+	 * Pass TRUE for mosconfig because the user-supplied config
+	 * is actually the one to trust when doing an import.
 	 */
-	(void) spa_load(spa, tryconfig, SPA_LOAD_TRYIMPORT, B_FALSE);
+	(void) spa_load(spa, tryconfig, SPA_LOAD_TRYIMPORT, B_TRUE);
 
 	/*
 	 * If 'tryconfig' was at least parsable, return the current config.
@@ -1163,7 +1166,11 @@
 	if (newvd->vdev_psize < vdev_get_rsize(oldvd))
 		return (spa_vdev_exit(spa, newrootvd, txg, EOVERFLOW));
 
-	if (newvd->vdev_ashift != oldvd->vdev_ashift && oldvd->vdev_ashift != 0)
+	/*
+	 * The new device cannot have a higher alignment requirement
+	 * than the top-level vdev.
+	 */
+	if (newvd->vdev_ashift > oldvd->vdev_top->vdev_ashift)
 		return (spa_vdev_exit(spa, newrootvd, txg, EDOM));
 
 	/*
@@ -1228,8 +1235,7 @@
 	/*
 	 * Mark newvd's DTL dirty in this txg.
 	 */
-	vdev_dirty(tvd, VDD_DTL, txg);
-	(void) txg_list_add(&tvd->vdev_dtl_list, newvd, txg);
+	vdev_dirty(tvd, VDD_DTL, newvd, txg);
 
 	(void) spa_vdev_exit(spa, newrootvd, open_txg, 0);
 
@@ -1356,12 +1362,11 @@
 
 	/*
 	 * If the device we just detached was smaller than the others,
-	 * it may be possible to add metaslabs (i.e. grow the pool).  We ignore
-	 * the error here because the detach still succeeded - we just weren't
-	 * able to reinitialize the metaslabs.  This pool is in for a world of
-	 * hurt, in any case.
+	 * it may be possible to add metaslabs (i.e. grow the pool).
+	 * vdev_metaslab_init() can't fail because the existing metaslabs
+	 * are already in core, so there's nothing to read from disk.
 	 */
-	(void) vdev_metaslab_init(tvd, txg);
+	VERIFY(vdev_metaslab_init(tvd, txg) == 0);
 
 	vdev_config_dirty(tvd);
 
@@ -1372,11 +1377,10 @@
 	 * But first make sure we're not on any *other* txg's DTL list,
 	 * to prevent vd from being accessed after it's freed.
 	 */
-	vdev_dirty(tvd, VDD_DTL, txg);
-	vd->vdev_detached = B_TRUE;
 	for (t = 0; t < TXG_SIZE; t++)
 		(void) txg_list_remove_this(&tvd->vdev_dtl_list, vd, t);
-	(void) txg_list_add(&tvd->vdev_dtl_list, vd, txg);
+	vd->vdev_detached = B_TRUE;
+	vdev_dirty(tvd, VDD_DTL, vd, txg);
 
 	dprintf("detached %s in txg %llu\n", vd->vdev_path, txg);
 
@@ -1798,10 +1802,13 @@
 	if (rvd->vdev_dtl_map.sm_space == 0) {
 		/*
 		 * The pool-wide DTL is empty.
-		 * If this is a resilver, there's nothing to do.
+		 * If this is a resilver, there's nothing to do except
+		 * check whether any in-progress replacements have completed.
 		 */
-		if (type == POOL_SCRUB_RESILVER)
+		if (type == POOL_SCRUB_RESILVER) {
 			type = POOL_SCRUB_NONE;
+			spa_async_request(spa, SPA_ASYNC_REPLACE_DONE);
+		}
 	} else {
 		/*
 		 * The pool-wide DTL is non-empty.