From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr690096.outbound.protection.outlook.com ([40.107.69.96]:35711 "EHLO NAM04-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727615AbeH3WGv (ORCPT ); Thu, 30 Aug 2018 18:06:51 -0400 From: Sasha Levin To: "stable@vger.kernel.org" CC: Chao Yu , Jaegeuk Kim , Sasha Levin Subject: [PATCH AUTOSEL 4.18 056/113] f2fs: avoid race between zero_range and background GC Date: Thu, 30 Aug 2018 18:03:28 +0000 Message-ID: <20180830180050.35735-56-alexander.levin@microsoft.com> References: <20180830180050.35735-1-alexander.levin@microsoft.com> In-Reply-To: <20180830180050.35735-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: stable-owner@vger.kernel.org List-ID: From: Chao Yu [ Upstream commit c7079853c859c910b9d047a37891b4aafb8f8dd7 ] Thread A Background GC - f2fs_zero_range - truncate_pagecache_range - gc_data_segment - get_read_data_page - move_data_page - set_page_dirty - set_cold_data - f2fs_do_zero_range - dn->data_blkaddr =3D NEW_ADDR; - f2fs_set_data_blkaddr Actually, we don't need to set dirty & checked flag on the page, since all valid data in the page should be zeroed by zero_range(). Use i_gc_rwsem[WRITE] to avoid such race condition. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/file.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 6880c6f78d58..abb0feffff11 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1295,8 +1295,6 @@ static int f2fs_zero_range(struct inode *inode, loff_= t offset, loff_t len, if (ret) goto out_sem; =20 - truncate_pagecache_range(inode, offset, offset + len - 1); - pg_start =3D ((unsigned long long) offset) >> PAGE_SHIFT; pg_end =3D ((unsigned long long) offset + len) >> PAGE_SHIFT; =20 @@ -1326,12 +1324,19 @@ static int f2fs_zero_range(struct inode *inode, lof= f_t offset, loff_t len, unsigned int end_offset; pgoff_t end; =20 + down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + + truncate_pagecache_range(inode, + (loff_t)index << PAGE_SHIFT, + ((loff_t)pg_end << PAGE_SHIFT) - 1); + f2fs_lock_op(sbi); =20 set_new_dnode(&dn, inode, NULL, NULL, 0); ret =3D f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE); if (ret) { f2fs_unlock_op(sbi); + up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); goto out; } =20 @@ -1340,7 +1345,9 @@ static int f2fs_zero_range(struct inode *inode, loff_= t offset, loff_t len, =20 ret =3D f2fs_do_zero_range(&dn, index, end); f2fs_put_dnode(&dn); + f2fs_unlock_op(sbi); + up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); =20 f2fs_balance_fs(sbi, dn.node_changed); =20 --=20 2.17.1