--- arc.c.orig 2010-05-06 20:32:47.563544528 +0200 +++ arc.c 2010-05-06 20:34:56.875774714 +0200 @@ -1475,16 +1475,16 @@ arc_hdr_destroy(arc_buf_hdr_t *hdr) arc_buf_t *buf = hdr->b_buf; if (buf->b_efunc) { - mutex_enter(&arc_eviction_mtx); mutex_enter(&buf->b_evict_lock); + mutex_enter(&arc_eviction_mtx); ASSERT(buf->b_hdr != NULL); arc_buf_destroy(hdr->b_buf, FALSE, FALSE); hdr->b_buf = buf->b_next; buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; arc_eviction_list = buf; - mutex_exit(&buf->b_evict_lock); mutex_exit(&arc_eviction_mtx); + mutex_exit(&buf->b_evict_lock); } else { arc_buf_destroy(hdr->b_buf, FALSE, TRUE); } @@ -1882,14 +1882,20 @@ arc_adjust(void) static void arc_do_user_evicts(void) { + static arc_buf_t *tmp_arc_eviction_list; + +restart: mutex_enter(&arc_eviction_mtx); - while (arc_eviction_list != NULL) { - arc_buf_t *buf = arc_eviction_list; - arc_eviction_list = buf->b_next; + tmp_arc_eviction_list = arc_eviction_list; + arc_eviction_list = NULL; + mutex_exit(&arc_eviction_mtx); + + while (tmp_arc_eviction_list != NULL) { + arc_buf_t *buf = tmp_arc_eviction_list; + tmp_arc_eviction_list = buf->b_next; mutex_enter(&buf->b_evict_lock); buf->b_hdr = NULL; mutex_exit(&buf->b_evict_lock); - mutex_exit(&arc_eviction_mtx); if (buf->b_efunc != NULL) VERIFY(buf->b_efunc(buf) == 0); @@ -1897,9 +1903,10 @@ arc_do_user_evicts(void) buf->b_efunc = NULL; buf->b_private = NULL; kmem_cache_free(buf_cache, buf); - mutex_enter(&arc_eviction_mtx); } - mutex_exit(&arc_eviction_mtx); + + if (arc_eviction_list != NULL) + goto restart; } /*