mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-05-29 09:54:58 +03:00
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 <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Reviewed-by: Rob Norris <robn@despairlabs.com> Reviewed-by: Tony Hutter <hutter2@llnl.gov>
This commit is contained in:
parent
c5a6b4417d
commit
b1ccab1721
@ -4225,15 +4225,17 @@ static uint64_t
|
|||||||
arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
|
arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
|
||||||
uint_t balance)
|
uint_t balance)
|
||||||
{
|
{
|
||||||
if (total < 8 || up + down == 0)
|
if (total < 32 || up + down == 0)
|
||||||
return (frac);
|
return (frac);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We should not have more ghost hits than ghost size, but they
|
* We should not have more ghost hits than ghost size, but they may
|
||||||
* may get close. Restrict maximum adjustment in that case.
|
* get close. To avoid overflows below up/down should not be bigger
|
||||||
|
* than 1/5 of total. But to limit maximum adjustment speed restrict
|
||||||
|
* it some more.
|
||||||
*/
|
*/
|
||||||
if (up + down >= total / 4) {
|
if (up + down >= total / 16) {
|
||||||
uint64_t scale = (up + down) / (total / 8);
|
uint64_t scale = (up + down) / (total / 32);
|
||||||
up /= scale;
|
up /= scale;
|
||||||
down /= scale;
|
down /= scale;
|
||||||
}
|
}
|
||||||
@ -4242,6 +4244,7 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
|
|||||||
int s = highbit64(total);
|
int s = highbit64(total);
|
||||||
s = MIN(64 - s, 32);
|
s = MIN(64 - s, 32);
|
||||||
|
|
||||||
|
ASSERT3U(frac, <=, 1ULL << 32);
|
||||||
uint64_t ofrac = (1ULL << 32) - frac;
|
uint64_t ofrac = (1ULL << 32) - frac;
|
||||||
|
|
||||||
if (frac >= 4 * ofrac)
|
if (frac >= 4 * ofrac)
|
||||||
@ -4252,6 +4255,8 @@ arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
|
|||||||
down = (down << s) / (total >> (32 - s));
|
down = (down << s) / (total >> (32 - s));
|
||||||
down = down * 100 / balance;
|
down = down * 100 / balance;
|
||||||
|
|
||||||
|
ASSERT3U(up, <=, (1ULL << 32) - frac);
|
||||||
|
ASSERT3U(down, <=, frac);
|
||||||
return (frac + up - down);
|
return (frac + up - down);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user