Skip to content

Commit ad65662

Browse files
amotinrobn
authored andcommitted
ARC: Avoid overflows in arc_evict_adj() (openzfs#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 openzfs#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)
1 parent 894f241 commit ad65662

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
@@ -4200,15 +4200,17 @@ static uint64_t
42004200
arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42014201
uint_t balance)
42024202
{
4203-
if (total < 8 || up + down == 0)
4203+
if (total < 32 || up + down == 0)
42044204
return (frac);
42054205

42064206
/*
4207-
* We should not have more ghost hits than ghost size, but they
4208-
* may get close. Restrict maximum adjustment in that case.
4207+
* We should not have more ghost hits than ghost size, but they may
4208+
* get close. To avoid overflows below up/down should not be bigger
4209+
* than 1/5 of total. But to limit maximum adjustment speed restrict
4210+
* it some more.
42094211
*/
4210-
if (up + down >= total / 4) {
4211-
uint64_t scale = (up + down) / (total / 8);
4212+
if (up + down >= total / 16) {
4213+
uint64_t scale = (up + down) / (total / 32);
42124214
up /= scale;
42134215
down /= scale;
42144216
}
@@ -4217,6 +4219,7 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42174219
int s = highbit64(total);
42184220
s = MIN(64 - s, 32);
42194221

4222+
ASSERT3U(frac, <=, 1ULL << 32);
42204223
uint64_t ofrac = (1ULL << 32) - frac;
42214224

42224225
if (frac >= 4 * ofrac)
@@ -4227,6 +4230,8 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
42274230
down = (down << s) / (total >> (32 - s));
42284231
down = down * 100 / balance;
42294232

4233+
ASSERT3U(up, <=, (1ULL << 32) - frac);
4234+
ASSERT3U(down, <=, frac);
42304235
return (frac + up - down);
42314236
}
42324237

0 commit comments

Comments
 (0)