Fix some signedness issues in arc_evict()

It may happen that "wanted total ARC size" (wt) is negative, that was
expected.  But multiplication product of it and unsigned fractions
result in unsigned value, incorrectly shifted right with a sing loss.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Prakash Surya <prakash.surya@delphix.com>
Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Signed-off-by:  Alexander Motin <mav@FreeBSD.org>
Sponsored by:   iXsystems, Inc.
Closes #14692
This commit is contained in:
Alexander Motin 2023-04-06 02:42:22 +09:00 committed by GitHub
parent 8eb2f26057
commit 1038f87c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4465,7 +4465,7 @@ arc_evict(void)
*/
int64_t prune = 0;
int64_t dn = wmsum_value(&arc_sums.arcstat_dnode_size);
w = wt * (arc_meta >> 16) >> 16;
w = wt * (int64_t)(arc_meta >> 16) >> 16;
if (zfs_refcount_count(&arc_mru->arcs_size[ARC_BUFC_METADATA]) +
zfs_refcount_count(&arc_mfu->arcs_size[ARC_BUFC_METADATA]) -
zfs_refcount_count(&arc_mru->arcs_esize[ARC_BUFC_METADATA]) -
@ -4481,7 +4481,7 @@ arc_evict(void)
arc_prune_async(prune);
/* Evict MRU metadata. */
w = wt * (arc_meta * arc_pm >> 48) >> 16;
w = wt * (int64_t)(arc_meta * arc_pm >> 48) >> 16;
e = MIN((int64_t)(asize - arc_c), (int64_t)(mrum - w));
bytes = arc_evict_impl(arc_mru, ARC_BUFC_METADATA, e);
total_evicted += bytes;
@ -4489,7 +4489,7 @@ arc_evict(void)
asize -= bytes;
/* Evict MFU metadata. */
w = wt * (arc_meta >> 16) >> 16;
w = wt * (int64_t)(arc_meta >> 16) >> 16;
e = MIN((int64_t)(asize - arc_c), (int64_t)(m - w));
bytes = arc_evict_impl(arc_mfu, ARC_BUFC_METADATA, e);
total_evicted += bytes;
@ -4498,7 +4498,7 @@ arc_evict(void)
/* Evict MRU data. */
wt -= m - total_evicted;
w = wt * (arc_pd >> 16) >> 16;
w = wt * (int64_t)(arc_pd >> 16) >> 16;
e = MIN((int64_t)(asize - arc_c), (int64_t)(mrud - w));
bytes = arc_evict_impl(arc_mru, ARC_BUFC_DATA, e);
total_evicted += bytes;