--- uts/common/fs/zfs/arc.c +++ uts/common/fs/zfs/arc.c @@ -1138,6 +1138,7 @@ buf->b_efunc = NULL; buf->b_private = NULL; buf->b_next = NULL; + rw_init(&buf->b_lock, NULL, RW_DEFAULT, NULL); hdr->b_buf = buf; arc_get_data_buf(buf); hdr->b_datacnt = 1; @@ -1161,6 +1162,7 @@ buf->b_efunc = NULL; buf->b_private = NULL; buf->b_next = hdr->b_buf; + rw_init(&buf->b_lock, NULL, RW_DEFAULT, NULL); hdr->b_buf = buf; arc_get_data_buf(buf); bcopy(from->b_data, buf->b_data, size); @@ -1283,6 +1285,7 @@ /* clean up the buf */ buf->b_hdr = NULL; + rw_destroy(&buf->b_lock); kmem_cache_free(buf_cache, buf); } @@ -1332,8 +1335,10 @@ ASSERT(buf->b_hdr != NULL); arc_buf_destroy(hdr->b_buf, FALSE, FALSE); hdr->b_buf = buf->b_next; + rw_enter(&buf->b_lock, RW_WRITER); buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; + rw_exit(&buf->b_lock); arc_eviction_list = buf; mutex_exit(&arc_eviction_mtx); } else { @@ -1497,8 +1502,10 @@ arc_buf_destroy(buf, buf->b_data == stolen, FALSE); ab->b_buf = buf->b_next; + rw_enter(&buf->b_lock, RW_WRITER); buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; + rw_exit(&buf->b_lock); arc_eviction_list = buf; mutex_exit(&arc_eviction_mtx); } else { @@ -1697,7 +1704,9 @@ while (arc_eviction_list != NULL) { arc_buf_t *buf = arc_eviction_list; arc_eviction_list = buf->b_next; + rw_enter(&buf->b_lock, RW_WRITER); buf->b_hdr = NULL; + rw_exit(&buf->b_lock); mutex_exit(&arc_eviction_mtx); if (buf->b_efunc != NULL) @@ -1705,6 +1714,7 @@ buf->b_efunc = NULL; buf->b_private = NULL; + rw_destroy(&buf->b_lock); kmem_cache_free(buf_cache, buf); mutex_enter(&arc_eviction_mtx); } @@ -2464,6 +2474,7 @@ ASSERT(!refcount_is_zero(&pbuf->b_hdr->b_refcnt)); ASSERT3U((char *)bp - (char *)pbuf->b_data, <, pbuf->b_hdr->b_size); + rw_enter(&pbuf->b_lock, RW_READER); rw_enter(&pbuf->b_hdr->b_datalock, RW_READER); err = arc_read_nolock(pio, spa, bp, done, private, priority, @@ -2471,6 +2482,7 @@ ASSERT3P(hdr, ==, pbuf->b_hdr); rw_exit(&pbuf->b_hdr->b_datalock); + rw_exit(&pbuf->b_lock); return (err); } @@ -2610,6 +2622,7 @@ buf->b_efunc = NULL; buf->b_private = NULL; buf->b_next = NULL; + rw_init(&buf->b_lock, NULL, RW_DEFAULT, NULL); hdr->b_buf = buf; arc_get_data_buf(buf); ASSERT(hdr->b_datacnt == 0); @@ -2865,6 +2878,7 @@ buf->b_efunc = NULL; buf->b_private = NULL; buf->b_hdr = NULL; + rw_destroy(&buf->b_lock); kmem_cache_free(buf_cache, buf); return (1); } @@ -2951,7 +2965,9 @@ nhdr->b_datacnt = 1; nhdr->b_freeze_cksum = NULL; (void) refcount_add(&nhdr->b_refcnt, tag); + rw_enter(&buf->b_lock, RW_WRITER); buf->b_hdr = nhdr; + rw_exit(&buf->b_lock); atomic_add_64(&arc_anon->arcs_size, blksz); } else { ASSERT(refcount_count(&hdr->b_refcnt) == 1); --- uts/common/fs/zfs/sys/arc.h +++ uts/common/fs/zfs/sys/arc.h @@ -53,6 +53,7 @@ void *b_data; arc_evict_func_t *b_efunc; void *b_private; + krwlock_t b_lock; }; typedef enum arc_buf_contents {