Skip to content

Commit 81f2feb

Browse files
amotinrobn
authored andcommitted
ARC: Avoid overflows in arc_evict_adj() (#17255)
With certain combinations of target ARC states balance and ghost hit rates it was possible to get the fractions outside of allowed range. This patch limits maximum balance adjustment speed, which should make it impossible, and also asserts it. Fixes #17210 Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc. Reviewed-by: Rob Norris <[email protected]> Reviewed-by: Tony Hutter <[email protected]> (cherry picked from commit b1ccab1) (cherry picked from commit 677cb91)
1 parent 2f419f0 commit 81f2feb

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

module/zfs/arc.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4205,15 +4205,17 @@ static uint64_t
42054205
arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42064206
uint_t balance)
42074207
{
4208-
if (total < 8 || up + down == 0)
4208+
if (total < 32 || up + down == 0)
42094209
return (frac);
42104210

42114211
/*
4212-
* We should not have more ghost hits than ghost size, but they
4213-
* may get close. Restrict maximum adjustment in that case.
4212+
* We should not have more ghost hits than ghost size, but they may
4213+
* get close. To avoid overflows below up/down should not be bigger
4214+
* than 1/5 of total. But to limit maximum adjustment speed restrict
4215+
* it some more.
42144216
*/
4215-
if (up + down >= total / 4) {
4216-
uint64_t scale = (up + down) / (total / 8);
4217+
if (up + down >= total / 16) {
4218+
uint64_t scale = (up + down) / (total / 32);
42174219
up /= scale;
42184220
down /= scale;
42194221
}
@@ -4222,6 +4224,7 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42224224
int s = highbit64(total);
42234225
s = MIN(64 - s, 32);
42244226

4227+
ASSERT3U(frac, <=, 1ULL << 32);
42254228
uint64_t ofrac = (1ULL << 32) - frac;
42264229

42274230
if (frac >= 4 * ofrac)
@@ -4232,6 +4235,8 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42324235
down = (down << s) / (total >> (32 - s));
42334236
down = down * 100 / balance;
42344237

4238+
ASSERT3U(up, <=, (1ULL << 32) - frac);
4239+
ASSERT3U(down, <=, frac);
42354240
return (frac + up - down);
42364241
}
42374242

0 commit comments

Comments
 (0)