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
--- 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);
}