When __process_pages_contig() get called for extent_clear_unlock_delalloc(), if we hit the locked page, only Private2 bit is updated, but dirty/writeback/error bits are all skipped.
There are several call sites call extent_clear_unlock_delalloc() with @locked_page and PAGE_CLEAR_DIRTY/PAGE_SET_WRITEBACK/PAGE_END_WRITEBACK - cow_file_range() - run_delalloc_nocow() - cow_file_range_async() All for their error handling branches. For those call sites, since we skip the locked page for dirty/error/writeback bit update, the locked page will still have its dirty bit remaining. Thankfully, since all those call sites can only be hit with various serious errors, it's pretty hard to hit and shouldn't affect regular btrfs operations. But still, we shouldn't leave the locked_page with its dirty/error/writeback bits untouched. Fix this by only skipping lock/unlock page operations for locked_page. Signed-off-by: Qu Wenruo <w...@suse.com> --- fs/btrfs/extent_io.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 7f689ad7709c..3442f1746683 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1970,11 +1970,6 @@ static int __process_pages_contig(struct address_space *mapping, if (page_ops & PAGE_SET_PRIVATE2) SetPagePrivate2(pages[i]); - if (locked_page && pages[i] == locked_page) { - put_page(pages[i]); - pages_processed++; - continue; - } if (page_ops & PAGE_CLEAR_DIRTY) clear_page_dirty_for_io(pages[i]); if (page_ops & PAGE_SET_WRITEBACK) @@ -1983,6 +1978,11 @@ static int __process_pages_contig(struct address_space *mapping, SetPageError(pages[i]); if (page_ops & PAGE_END_WRITEBACK) end_page_writeback(pages[i]); + if (locked_page && pages[i] == locked_page) { + put_page(pages[i]); + pages_processed++; + continue; + } if (page_ops & PAGE_UNLOCK) unlock_page(pages[i]); if (page_ops & PAGE_LOCK) { -- 2.30.0