Skip to content

Commit

Permalink
f2fs: should avoid inode eviction in synchronous path
Browse files Browse the repository at this point in the history
[ Upstream commit b0f3b87 ]

https://bugzilla.kernel.org/show_bug.cgi?id=208565

PID: 257    TASK: ecdd0000  CPU: 0   COMMAND: "init"
  #0 [<c0b420ec>] (__schedule) from [<c0b423c8>]
  #1 [<c0b423c8>] (schedule) from [<c0b459d4>]
  #2 [<c0b459d4>] (rwsem_down_read_failed) from [<c0b44fa0>]
  #3 [<c0b44fa0>] (down_read) from [<c044233c>]
  #4 [<c044233c>] (f2fs_truncate_blocks) from [<c0442890>]
  #5 [<c0442890>] (f2fs_truncate) from [<c044d408>]
  #6 [<c044d408>] (f2fs_evict_inode) from [<c030be18>]
  #7 [<c030be18>] (evict) from [<c030a558>]
  #8 [<c030a558>] (iput) from [<c047c600>]
  #9 [<c047c600>] (f2fs_sync_node_pages) from [<c0465414>]
 torvalds#10 [<c0465414>] (f2fs_write_checkpoint) from [<c04575f4>]
 torvalds#11 [<c04575f4>] (f2fs_sync_fs) from [<c0441918>]
 torvalds#12 [<c0441918>] (f2fs_do_sync_file) from [<c0441098>]
 torvalds#13 [<c0441098>] (f2fs_sync_file) from [<c0323fa0>]
 torvalds#14 [<c0323fa0>] (vfs_fsync_range) from [<c0324294>]
 torvalds#15 [<c0324294>] (do_fsync) from [<c0324014>]
 torvalds#16 [<c0324014>] (sys_fsync) from [<c0108bc0>]

This can be caused by flush_dirty_inode() in f2fs_sync_node_pages() where
iput() requires f2fs_lock_op() again resulting in livelock.

Reported-by: Zhiguo Niu <Zhiguo.Niu@unisoc.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Jaegeuk Kim authored and gregkh committed Aug 26, 2020
1 parent a692a28 commit f6b2fb8
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions fs/f2fs/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1924,8 +1924,12 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
goto continue_unlock;
}

/* flush inline_data, if it's async context. */
if (do_balance && is_inline_node(page)) {
/* flush inline_data/inode, if it's async context. */
if (!do_balance)
goto write_node;

/* flush inline_data */
if (is_inline_node(page)) {
clear_inline_node(page);
unlock_page(page);
flush_inline_data(sbi, ino_of_node(page));
Expand All @@ -1938,7 +1942,7 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
if (flush_dirty_inode(page))
goto lock_node;
}

write_node:
f2fs_wait_on_page_writeback(page, NODE, true, true);

if (!clear_page_dirty_for_io(page))
Expand Down

0 comments on commit f6b2fb8

Please sign in to comment.