bdi_get_bytes() multiplies unsigned long operands before assigning the result to u64. On 32-bit kernels, the intermediate product wraps and min_bytes and max_bytes report incorrect limits. For example, with vm.dirty_bytes set to 104857600 and max_ratio set to 100, max_bytes reports 268 instead of 104857600. Convert the page count to bytes in u64 and use mul_u64_u32_div() to avoid overflow in the subsequent multiplication. This also handles large dirty limits on systems with larger pages. Combining the two divisions keeps the existing rounding behavior. Fixes: 00df7d51263b ("mm: add bdi_get_max_bytes() function") Cc: stable@vger.kernel.org Signed-off-by: Hungyu Lin --- mm/page-writeback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 499a35473e4f..ddebec79d8d9 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -665,7 +665,8 @@ static u64 bdi_get_bytes(unsigned int ratio) u64 bytes; global_dirty_limits(&background_thresh, &dirty_thresh); - bytes = (dirty_thresh * PAGE_SIZE * ratio) / BDI_RATIO_SCALE / 100; + bytes = mul_u64_u32_div((u64)dirty_thresh << PAGE_SHIFT, ratio, + 100 * BDI_RATIO_SCALE); return bytes; } -- 2.43.0