6715111 A removed L2ARC device should show status REMOVED
authorBrendan Gregg - Sun Microsystems <Brendan.Gregg@Sun.COM>
Mon, 18 Aug 2008 17:28:31 -0700
changeset 7361 e7d1b928b483
parent 7360 75a2fa5e303d
child 7362 0b07b96ed3bd
6715111 A removed L2ARC device should show status REMOVED 6724373 removing cache devices from a pool with spares doesn't work 6731223 L2ARC: arc_hdr_destroy(), ASSERT(hdr->b_l2hdr != NULL) 6731256 failed L2ARC read should not return EIO
usr/src/uts/common/fs/zfs/arc.c
usr/src/uts/common/fs/zfs/spa.c
--- a/usr/src/uts/common/fs/zfs/arc.c	Mon Aug 18 18:01:31 2008 -0600
+++ b/usr/src/uts/common/fs/zfs/arc.c	Mon Aug 18 17:28:31 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * DVA-based Adjustable Replacement Cache
  *
@@ -1288,11 +1286,15 @@
 			 * a FREE_IN_PROGRESS flag is given to arc_free() to
 			 * give it priority.  l2arc_evict() can't destroy this
 			 * header while we are waiting on l2arc_buflist_mtx.
+			 *
+			 * The hdr may be removed from l2ad_buflist before we
+			 * grab l2arc_buflist_mtx, so b_l2hdr is rechecked.
 			 */
 			mutex_enter(&l2arc_buflist_mtx);
-			ASSERT(hdr->b_l2hdr != NULL);
-
-			list_remove(hdr->b_l2hdr->b_dev->l2ad_buflist, hdr);
+			if (hdr->b_l2hdr != NULL) {
+				list_remove(hdr->b_l2hdr->b_dev->l2ad_buflist,
+				    hdr);
+			}
 			mutex_exit(&l2arc_buflist_mtx);
 		} else {
 			list_remove(hdr->b_l2hdr->b_dev->l2ad_buflist, hdr);
@@ -2643,8 +2645,8 @@
 				rzio = zio_read_phys(pio, vd, addr, size,
 				    buf->b_data, ZIO_CHECKSUM_OFF,
 				    l2arc_read_done, cb, priority, zio_flags |
-				    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL,
-				    B_FALSE);
+				    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
+				    ZIO_FLAG_DONT_PROPAGATE, B_FALSE);
 				DTRACE_PROBE2(l2arc__read, vdev_t *, vd,
 				    zio_t *, rzio);
 				spa_config_exit(spa, FTAG);
@@ -3840,9 +3842,10 @@
 			zio->io_done = NULL;
 			zio->io_flags &= ~ZIO_FLAG_DONT_CACHE;
 
-			rzio = zio_read(NULL, cb->l2rcb_spa, &cb->l2rcb_bp,
-			    buf->b_data, zio->io_size, arc_read_done, buf,
-			    zio->io_priority, cb->l2rcb_flags, &cb->l2rcb_zb);
+			rzio = zio_read(zio->io_parent, cb->l2rcb_spa,
+			    &cb->l2rcb_bp, buf->b_data, zio->io_size,
+			    arc_read_done, buf, zio->io_priority,
+			    cb->l2rcb_flags, &cb->l2rcb_zb);
 
 			(void) zio_nowait(rzio);
 		}
--- a/usr/src/uts/common/fs/zfs/spa.c	Mon Aug 18 18:01:31 2008 -0600
+++ b/usr/src/uts/common/fs/zfs/spa.c	Mon Aug 18 17:28:31 2008 -0700
@@ -3322,12 +3322,13 @@
 	    ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
 		if ((error = spa_remove_spares(&spa->spa_spares, guid, unspare,
 		    spares, nspares, vd)) != 0)
-			goto out;
+			goto cache;
 		spa_load_spares(spa);
 		spa->spa_spares.sav_sync = B_TRUE;
 		goto out;
 	}
 
+cache:
 	if (spa->spa_l2cache.sav_vdevs != NULL &&
 	    nvlist_lookup_nvlist_array(spa->spa_l2cache.sav_config,
 	    ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0) {
@@ -3532,26 +3533,23 @@
 static void
 spa_async_remove(spa_t *spa, vdev_t *vd)
 {
-	vdev_t *tvd;
 	int c;
 
-	for (c = 0; c < vd->vdev_children; c++) {
-		tvd = vd->vdev_child[c];
-		if (tvd->vdev_remove_wanted) {
-			tvd->vdev_remove_wanted = 0;
-			vdev_set_state(tvd, B_FALSE, VDEV_STATE_REMOVED,
-			    VDEV_AUX_NONE);
-			vdev_clear(spa, tvd, B_TRUE);
-			vdev_config_dirty(tvd->vdev_top);
-		}
-		spa_async_remove(spa, tvd);
+	if (vd->vdev_remove_wanted) {
+		vd->vdev_remove_wanted = 0;
+		vdev_set_state(vd, B_FALSE, VDEV_STATE_REMOVED, VDEV_AUX_NONE);
+		vdev_clear(spa, vd, B_TRUE);
+		vdev_config_dirty(vd->vdev_top);
 	}
+
+	for (c = 0; c < vd->vdev_children; c++)
+		spa_async_remove(spa, vd->vdev_child[c]);
 }
 
 static void
 spa_async_thread(spa_t *spa)
 {
-	int tasks;
+	int tasks, i;
 	uint64_t txg;
 
 	ASSERT(spa->spa_sync_on);
@@ -3582,6 +3580,10 @@
 	    spa_state(spa) != POOL_STATE_IO_FAILURE) {
 		txg = spa_vdev_enter(spa);
 		spa_async_remove(spa, spa->spa_root_vdev);
+		for (i = 0; i < spa->spa_l2cache.sav_count; i++)
+			spa_async_remove(spa, spa->spa_l2cache.sav_vdevs[i]);
+		for (i = 0; i < spa->spa_spares.sav_count; i++)
+			spa_async_remove(spa, spa->spa_spares.sav_vdevs[i]);
 		(void) spa_vdev_exit(spa, NULL, txg, 0);
 	}