f2fs: fix to wait page writeback before setting gcing flag

[ Upstream commit a4d7f2b323 ]

Soft IRQ				Thread
- f2fs_write_end_io
					- f2fs_defragment_range
					 - set_page_private_gcing
 - type = WB_DATA_TYPE(page, false);
 : assign type w/ F2FS_WB_CP_DATA
 due to page_private_gcing() is true
  - dec_page_count() w/ wrong type
  - end_page_writeback()

Value of F2FS_WB_CP_DATA reference count may become negative under above
race condition, the root cause is we missed to wait page writeback before
setting gcing page private flag, let's fix it.

Fixes: 2d1fe8a86b ("f2fs: fix to tag gcing flag on page during file defragment")
Fixes: 4961acdd65 ("f2fs: fix to tag gcing flag on page during block migration")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Chao Yu 2024-08-12 22:12:42 +08:00 committed by Greg Kroah-Hartman
parent 87f9d26fcc
commit 1bb0686a2e

View File

@ -2743,6 +2743,8 @@ do_map:
goto clear_out; goto clear_out;
} }
f2fs_wait_on_page_writeback(page, DATA, true, true);
set_page_dirty(page); set_page_dirty(page);
set_page_private_gcing(page); set_page_private_gcing(page);
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
@ -4137,6 +4139,8 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
/* It will never fail, when page has pinned above */ /* It will never fail, when page has pinned above */
f2fs_bug_on(F2FS_I_SB(inode), !page); f2fs_bug_on(F2FS_I_SB(inode), !page);
f2fs_wait_on_page_writeback(page, DATA, true, true);
set_page_dirty(page); set_page_dirty(page);
set_page_private_gcing(page); set_page_private_gcing(page);
f2fs_put_page(page, 1); f2fs_put_page(page, 1);