From 21fc6bf96fb70d30637be926c19ef5fd26fefa44 Mon Sep 17 00:00:00 2001 From: Tim Chase Date: Fri, 22 Jan 2016 07:37:37 -0600 Subject: [PATCH] Prevent arc_c collapse Adjusting arc_c directly is racy because it can happen in the context of multiple threads. It should always be >= 2 * maxblocksize. Set it to a known valid value rather than adjusting it directly. In addition refactor arc_shrink() to a simpler structure, protect against underflow in the calculation of the new arc_c value. Signed-off-by: Tim Chase Signed-off-by: Brian Behlendorf Reverts: 935434ef Closes: #3904 Closes: #4161 --- module/zfs/arc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/zfs/arc.c b/module/zfs/arc.c index b8707474d523..88939d0d3765 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -3183,13 +3183,10 @@ arc_flush(spa_t *spa, boolean_t retry) void arc_shrink(int64_t to_free) { - if (arc_c > arc_c_min) { - - if (arc_c > arc_c_min + to_free) - atomic_add_64(&arc_c, -to_free); - else - arc_c = arc_c_min; + uint64_t c = arc_c; + if (c > to_free && c - to_free > arc_c_min) { + arc_c = c - to_free; atomic_add_64(&arc_p, -(arc_p >> arc_shrink_shift)); if (arc_c > arc_size) arc_c = MAX(arc_size, arc_c_min); @@ -3197,6 +3194,8 @@ arc_shrink(int64_t to_free) arc_p = (arc_c >> 1); ASSERT(arc_c >= arc_c_min); ASSERT((int64_t)arc_p >= 0); + } else { + arc_c = arc_c_min; } if (arc_size > arc_c) @@ -3767,7 +3766,6 @@ arc_adapt(int bytes, arc_state_t *state) * cache size, increment the target cache size */ ASSERT3U(arc_c, >=, 2ULL << SPA_MAXBLOCKSHIFT); - arc_c = MAX(arc_c, 2ULL << SPA_MAXBLOCKSHIFT); if (arc_size >= arc_c - (2ULL << SPA_MAXBLOCKSHIFT)) { atomic_add_64(&arc_c, (int64_t)bytes); if (arc_c > arc_c_max) @@ -5160,7 +5158,9 @@ arc_tempreserve_space(uint64_t reserve, uint64_t txg) int error; uint64_t anon_size; - if (reserve > arc_c/4 && !arc_no_grow) + if (!arc_no_grow && + reserve > arc_c/4 && + reserve * 4 > (2ULL << SPA_MAXBLOCKSHIFT)) arc_c = MIN(arc_c_max, reserve * 4); /*