Mercurial > illumos > illumos-gate
changeset 2918:5e0808c08daa
6478928 buffer recycling causes long arc mutex spins
author | maybee |
---|---|
date | Fri, 13 Oct 2006 14:02:05 -0700 |
parents | 27816039d166 |
children | f56e9aa9c109 |
files | usr/src/uts/common/fs/zfs/arc.c |
diffstat | 1 files changed, 14 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/arc.c Fri Oct 13 12:08:49 2006 -0700 +++ b/usr/src/uts/common/fs/zfs/arc.c Fri Oct 13 14:02:05 2006 -0700 @@ -934,10 +934,10 @@ { arc_state_t *evicted_state; uint64_t bytes_evicted = 0, skipped = 0, missed = 0; - arc_buf_hdr_t *ab, *ab_prev; + arc_buf_hdr_t *ab, *ab_prev = NULL; kmutex_t *hash_lock; boolean_t have_lock; - void *steal = NULL; + void *stolen = NULL; ASSERT(state == arc.mru || state == arc.mfu); @@ -955,7 +955,9 @@ skipped++; continue; } - if (recycle && (ab->b_size != bytes || ab->b_datacnt > 1)) + /* "lookahead" for better eviction candidate */ + if (recycle && ab->b_size != bytes && + ab_prev && ab_prev->b_size == bytes) continue; hash_lock = HDR_LOCK(ab); have_lock = MUTEX_HELD(hash_lock); @@ -966,19 +968,23 @@ arc_buf_t *buf = ab->b_buf; if (buf->b_data) { bytes_evicted += ab->b_size; - if (recycle) - steal = buf->b_data; + if (recycle && ab->b_size == bytes) { + stolen = buf->b_data; + recycle = FALSE; + } } if (buf->b_efunc) { mutex_enter(&arc_eviction_mtx); - arc_buf_destroy(buf, recycle, FALSE); + arc_buf_destroy(buf, + buf->b_data == stolen, FALSE); ab->b_buf = buf->b_next; buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; arc_eviction_list = buf; mutex_exit(&arc_eviction_mtx); } else { - arc_buf_destroy(buf, recycle, TRUE); + arc_buf_destroy(buf, + buf->b_data == stolen, TRUE); } } ASSERT(ab->b_datacnt == 0); @@ -1005,7 +1011,7 @@ atomic_add_64(&arc.evict_skip, skipped); if (missed) atomic_add_64(&arc.mutex_miss, missed); - return (steal); + return (stolen); } /* @@ -1470,12 +1476,9 @@ state = (mfu_space > arc.mfu->size) ? arc.mru : arc.mfu; } if ((buf->b_data = arc_evict(state, size, TRUE)) == NULL) { - (void) arc_evict(state, size, FALSE); buf->b_data = zio_buf_alloc(size); atomic_add_64(&arc.size, size); atomic_add_64(&arc.recycle_miss, 1); - if (arc.size > arc.c) - arc_adjust(); } ASSERT(buf->b_data != NULL); out: