f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem
Chao Yu
maintainerPATCH 1/1 f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem
From: Chao Yu <[email protected]>
test/generic/208 reports a potential deadlock as below:
Chain exists of: &mm->mmap_sem --> &fi->i_mmap_sem --> &fi->dio_rwsem[WRITE] Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&fi->dio_rwsem[WRITE]);
lock(&fi->i_mmap_sem);
lock(&fi->dio_rwsem[WRITE]); lock(&mm->mmap_sem);
This patch changes the lock dependency as below in fallocate() to fix this issue:
- dio_rwsem
- i_mmap_sem
Fixes bb06664a534b ("f2fs: avoid race in between GC and block exchange")
Signed-off-by Chao Yu <[email protected]>
--- fs/f2fs/file.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
fs/f2fs/file.c +9 -11
@@ -1185,14 +1185,14 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) pg_start = offset >>PAGE_SHIFT ; pg_end = (offset + len) >>PAGE_SHIFT ; +/* avoid gc operation during block exchange */ +down_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); +down_write (&F2FS_I (inode)->i_mmap_sem);/* write out all dirty pages from offset */ ret =filemap_write_and_wait_range (inode->i_mapping, offset,LLONG_MAX );if (ret) - goto out; - -/* avoid gc operation during block exchange */ -down_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); + goto out_unlock;truncate_pagecache (inode, offset);
@@ -1211,9 +1211,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)if (!ret)f2fs_i_size_write (inode, new_size); out_unlock: -up_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); -out:up_write (&F2FS_I (inode)->i_mmap_sem); +up_write (&F2FS_I (inode)->dio_rwsem[WRITE ]);return ret; }
@@ -1384,6 +1383,9 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)f2fs_balance_fs (sbi, true); +/* avoid gc operation during block exchange */ +down_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); +down_write (&F2FS_I (inode)->i_mmap_sem); ret =truncate_blocks (inode,i_size_read (inode), true);if (ret)
@@ -1394,9 +1396,6 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)if (ret) goto out; -/* avoid gc operation during block exchange */ -down_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); -truncate_pagecache (inode, offset); pg_start = offset >>PAGE_SHIFT ;
@@ -1424,10 +1423,9 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)if (!ret)f2fs_i_size_write (inode, new_size); - -up_write (&F2FS_I (inode)->dio_rwsem[WRITE ]); out:up_write (&F2FS_I (inode)->i_mmap_sem); +up_write (&F2FS_I (inode)->dio_rwsem[WRITE ]);return ret; }
Signature · 1 line
2.14.1.145.gb3622a4ee