Since commit cc5095747edf ("ext4: don't BUG if someone dirty pages without asking ext4 first"), mpage_prepare_extent_to_map() handles dirty folios without buffer heads by warning, clearing PG_dirty, and skipping them. ext4 cannot write these folios because there are no buffer heads to map and submit. That recovery leaves dirty accounting behind: folio_clear_dirty() clears PG_dirty but does not undo the accounting charged when the folio was dirtied. We have seen this in production as Dirty/nr_dirty staying high while Writeback/nr_writeback and device write IO stayed near zero, with many writer tasks blocked in balance_dirty_pages() throttling. Thus the warning-and-skip recovery can still become a dirty-throttle DoS. Use folio_cancel_dirty() so dropping PG_dirty also cancels the dirty accounting. Then cycle the folio through writeback state so the generic writeback helpers update the xarray DIRTY/TOWRITE tags. Fixes: cc5095747edf ("ext4: don't BUG if someone dirty pages without asking ext4 first") Cc: stable@vger.kernel.org Suggested-by: Zhang Yi Reviewed-by: Jan Kara Signed-off-by: Zhu Jia --- Changes since v1: - After folio_cancel_dirty(), cycle the folio through writeback state so generic writeback helpers update PAGECACHE_TAG_DIRTY/TOWRITE, as suggested by Yi and Jan. fs/ext4/inode.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c2c2d6ac7f3d1..4c25dcd47fb15 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2715,7 +2715,15 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd) */ if (!folio_buffers(folio)) { ext4_warning_inode(mpd->inode, "page %lu does not have buffers attached", folio->index); - folio_clear_dirty(folio); + /* + * folio_cancel_dirty() pairs the dropped dirty + * state with dirty accounting. Cycle through + * writeback state so the generic writeback + * helpers update the xarray tags. + */ + folio_cancel_dirty(folio); + folio_start_writeback(folio); + folio_end_writeback(folio); folio_unlock(folio); continue; } -- 2.20.1