]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
writeback: avoid division by 0 in wb_update_dirty_ratelimit()
authorJan Kara <jack@suse.cz>
Mon, 23 Aug 2021 23:59:07 +0000 (09:59 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 25 Aug 2021 23:33:39 +0000 (09:33 +1000)
Fixup patch "writeback: Fix bandwidth estimate for spiky workload" which
introduced possibility of __wb_update_bandwidth() getting called at a
moment when 'elapsed' evaluates to 0.

Cc: Jan Kara <jack@suse.cz>
Cc: Michael Stapelberg <stapelberg+linux@google.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
mm/page-writeback.c

index eb55c8882db012ea49e44f1c4b27cabbf08e3b02..156f5888c09da5e4547003a69e8ab3c4f85992c3 100644 (file)
@@ -1336,11 +1336,19 @@ static void __wb_update_bandwidth(struct dirty_throttle_control *gdtc,
 {
        struct bdi_writeback *wb = gdtc->wb;
        unsigned long now = jiffies;
-       unsigned long elapsed = now - wb->bw_time_stamp;
+       unsigned long elapsed;
        unsigned long dirtied;
        unsigned long written;
 
        spin_lock(&wb->list_lock);
+
+       /*
+        * Lockless checks for elapsed time are racy and delayed update after
+        * IO completion doesn't do it at all (to make sure written pages are
+        * accounted reasonably quickly). Make sure elapsed >= 1 to avoid
+        * division errors.
+        */
+       elapsed = max(now - wb->bw_time_stamp, 1UL);
        dirtied = percpu_counter_read(&wb->stat[WB_DIRTIED]);
        written = percpu_counter_read(&wb->stat[WB_WRITTEN]);