Skip to content

Commit c72efb6

Browse files
htejunaxboe
authored andcommitted
writeback: fix possible underflow in write bandwidth calculation
From 1ebf339 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 23 Mar 2015 00:08:19 -0400 2f800fb ("writeback: fix dirtied pages accounting on redirty") introduced account_page_redirty() which reverts stat updates for a redirtied page, making BDI_DIRTIED no longer monotonically increasing. bdi_update_write_bandwidth() uses the delta in BDI_DIRTIED as the basis for bandwidth calculation. While unlikely, since the above patch, the newer value may be lower than the recorded past value and underflow the bandwidth calculation leading to a wild result. Fix it by subtracing min of the old and new values when calculating delta. AFAIK, there hasn't been any report of it happening but the resulting erratic behavior would be non-critical and temporary, so it's possible that the issue is happening without being reported. The risk of the fix is very low, so tagged for -stable. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Jan Kara <jack@suse.cz> Cc: Wu Fengguang <fengguang.wu@intel.com> Cc: Greg Thelen <gthelen@google.com> Fixes: 2f800fb ("writeback: fix dirtied pages accounting on redirty") Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent e6e96d7 commit c72efb6

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

mm/page-writeback.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,8 +857,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi,
857857
* bw * elapsed + write_bandwidth * (period - elapsed)
858858
* write_bandwidth = ---------------------------------------------------
859859
* period
860+
*
861+
* @written may have decreased due to account_page_redirty().
862+
* Avoid underflowing @bw calculation.
860863
*/
861-
bw = written - bdi->written_stamp;
864+
bw = written - min(written, bdi->written_stamp);
862865
bw *= HZ;
863866
if (unlikely(elapsed > period)) {
864867
do_div(bw, elapsed);

0 commit comments

Comments
 (0)