From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Sasha Levin To: "linux-kernel@vger.kernel.org" , "stable@vger.kernel.org" CC: Chao Yu , Jaegeuk Kim , Sasha Levin Subject: [PATCH AUTOSEL for 4.15 033/124] f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem Date: Mon, 19 Mar 2018 15:47:33 +0000 Message-ID: <20180319154645.11350-33-alexander.levin@microsoft.com> References: <20180319154645.11350-1-alexander.levin@microsoft.com> In-Reply-To: <20180319154645.11350-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: From: Chao Yu [ Upstream commit 21020812c9e1ab593367fad9ce579f842a0b406d ] 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 Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/file.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7874bbd7311d..84a011a522a1 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1186,14 +1186,14 @@ static int f2fs_collapse_range(struct inode *inode,= loff_t offset, loff_t len) pg_start =3D offset >> PAGE_SHIFT; pg_end =3D (offset + len) >> PAGE_SHIFT; =20 + /* 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 =3D 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; =20 truncate_pagecache(inode, offset); =20 @@ -1212,9 +1212,8 @@ static int f2fs_collapse_range(struct inode *inode, l= off_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; } =20 @@ -1385,6 +1384,9 @@ static int f2fs_insert_range(struct inode *inode, lof= f_t offset, loff_t len) =20 f2fs_balance_fs(sbi, true); =20 + /* avoid gc operation during block exchange */ + down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); + down_write(&F2FS_I(inode)->i_mmap_sem); ret =3D truncate_blocks(inode, i_size_read(inode), true); if (ret) @@ -1395,9 +1397,6 @@ static int f2fs_insert_range(struct inode *inode, lof= f_t offset, loff_t len) if (ret) goto out; =20 - /* avoid gc operation during block exchange */ - down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); - truncate_pagecache(inode, offset); =20 pg_start =3D offset >> PAGE_SHIFT; @@ -1425,10 +1424,9 @@ static int f2fs_insert_range(struct inode *inode, lo= ff_t offset, loff_t len) =20 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; } =20 --=20 2.14.1