Switching a dirty inode to another wb can leave WB_has_dirty_io set on the old one. inode_do_switch_wbs() moves the inode onto new_wb->b_dirty through inode_io_list_move_locked(), which only updates new_wb, and nothing calls wb_io_lists_depopulated() on old_wb. A live wb clears the bit on its next dirty to clean transition, but a wb that gets no more inodes, such as a dying one, is freed with its avg_write_bandwidth still in bdi->tot_write_bandwidth, which wb_split_bdi_pages() and wb_min_max_ratio() divide by. Call wb_io_lists_depopulated(old_wb) after the switch loop in process_inode_switch_wbs(), while old_wb->list_lock is still held. Test: after the last patch in this series switched a replaced wb's dirty inodes away, BdiWriteBandwidth stayed at 411700 and 407820 kBps with no writers and b_dirty, b_io and b_more_io all empty; with this patch it read 0, in 3 of 3 runs. Suggested-by: Tejun Heo Assisted-by: Claude:claude-opus-5-5 checkpatch sparse Assisted-by: Claude:claude-fable-5-1 Acked-by: Tejun Heo Reviewed-by: Jan Kara Signed-off-by: Liz Fong-Jones --- fs/fs-writeback.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index d26b2cf05283..050d507aa554 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -566,6 +566,12 @@ static void process_inode_switch_wbs(struct bdi_writeback *new_wb, } } + /* + * inode_do_switch_wbs() only updates @new_wb's dirty IO state. Clear + * @old_wb's if its IO lists are now empty. + */ + wb_io_lists_depopulated(old_wb); + spin_unlock(&new_wb->list_lock); spin_unlock(&old_wb->list_lock); -- 2.53.0