]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.15.17/f2fs-fix-lock-dependency-in-between-dio_rwsem-i_mmap_sem.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 4.15.17 / f2fs-fix-lock-dependency-in-between-dio_rwsem-i_mmap_sem.patch
CommitLineData
72fc6108
GKH
1From foo@baz Mon Apr 9 10:16:32 CEST 2018
2From: Chao Yu <yuchao0@huawei.com>
3Date: Thu, 23 Nov 2017 23:26:52 +0800
4Subject: f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem
5
6From: Chao Yu <yuchao0@huawei.com>
7
8
9[ Upstream commit 21020812c9e1ab593367fad9ce579f842a0b406d ]
10
11test/generic/208 reports a potential deadlock as below:
12
13Chain exists of:
14 &mm->mmap_sem --> &fi->i_mmap_sem --> &fi->dio_rwsem[WRITE]
15
16 Possible unsafe locking scenario:
17
18 CPU0 CPU1
19 ---- ----
20 lock(&fi->dio_rwsem[WRITE]);
21 lock(&fi->i_mmap_sem);
22 lock(&fi->dio_rwsem[WRITE]);
23 lock(&mm->mmap_sem);
24
25This patch changes the lock dependency as below in fallocate() to
26fix this issue:
27- dio_rwsem
28 - i_mmap_sem
29
30Fixes: bb06664a534b ("f2fs: avoid race in between GC and block exchange")
31Signed-off-by: Chao Yu <yuchao0@huawei.com>
32Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
33Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
34Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35---
36 fs/f2fs/file.c | 20 +++++++++-----------
37 1 file changed, 9 insertions(+), 11 deletions(-)
38
39--- a/fs/f2fs/file.c
40+++ b/fs/f2fs/file.c
41@@ -1186,14 +1186,14 @@ static int f2fs_collapse_range(struct in
42 pg_start = offset >> PAGE_SHIFT;
43 pg_end = (offset + len) >> PAGE_SHIFT;
44
45+ /* avoid gc operation during block exchange */
46+ down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
47+
48 down_write(&F2FS_I(inode)->i_mmap_sem);
49 /* write out all dirty pages from offset */
50 ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
51 if (ret)
52- goto out;
53-
54- /* avoid gc operation during block exchange */
55- down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
56+ goto out_unlock;
57
58 truncate_pagecache(inode, offset);
59
60@@ -1212,9 +1212,8 @@ static int f2fs_collapse_range(struct in
61 if (!ret)
62 f2fs_i_size_write(inode, new_size);
63 out_unlock:
64- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
65-out:
66 up_write(&F2FS_I(inode)->i_mmap_sem);
67+ up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
68 return ret;
69 }
70
71@@ -1385,6 +1384,9 @@ static int f2fs_insert_range(struct inod
72
73 f2fs_balance_fs(sbi, true);
74
75+ /* avoid gc operation during block exchange */
76+ down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
77+
78 down_write(&F2FS_I(inode)->i_mmap_sem);
79 ret = truncate_blocks(inode, i_size_read(inode), true);
80 if (ret)
81@@ -1395,9 +1397,6 @@ static int f2fs_insert_range(struct inod
82 if (ret)
83 goto out;
84
85- /* avoid gc operation during block exchange */
86- down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
87-
88 truncate_pagecache(inode, offset);
89
90 pg_start = offset >> PAGE_SHIFT;
91@@ -1425,10 +1424,9 @@ static int f2fs_insert_range(struct inod
92
93 if (!ret)
94 f2fs_i_size_write(inode, new_size);
95-
96- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
97 out:
98 up_write(&F2FS_I(inode)->i_mmap_sem);
99+ up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
100 return ret;
101 }
102