From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <yuchao0@huawei.com>
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v3] f2fs: fix to keep isolation of atomic write
Date: Mon, 12 Apr 2021 20:27:08 -0700 [thread overview]
Message-ID: <YHUPjDY9ifsffk4z@google.com> (raw)
In-Reply-To: <20210412081512.103592-1-yuchao0@huawei.com>
On 04/12, Chao Yu wrote:
> As Yi Chen reported, there is a potential race case described as below:
>
> Thread A Thread B
> - f2fs_ioc_start_atomic_write
> - mkwrite
> - set_page_dirty
> - f2fs_set_page_private(page, 0)
> - set_inode_flag(FI_ATOMIC_FILE)
> - mkwrite same page
> - set_page_dirty
> - f2fs_register_inmem_page
> - f2fs_set_page_private(ATOMIC_WRITTEN_PAGE)
> failed due to PagePrivate flag has been set
> - list_add_tail
> - truncate_inode_pages
> - f2fs_invalidate_page
> - clear page private but w/o remove it from
> inmem_list
> - set page->mapping to NULL
> - f2fs_ioc_commit_atomic_write
> - __f2fs_commit_inmem_pages
> - __revoke_inmem_pages
> - f2fs_put_page panic as page->mapping is NULL
>
> The root cause is we missed to keep isolation of atomic write in the case
> of start_atomic_write vs mkwrite, let start_atomic_write helds i_mmap_sem
> lock to avoid this issue.
My only concern is performance regression. Could you please verify the numbers?
>
> Reported-by: Yi Chen <chenyi77@huawei.com>
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
> v3:
> - rebase to last dev branch
> - update commit message because this patch fixes a different racing issue
> of atomic write
> fs/f2fs/file.c | 3 +++
> fs/f2fs/segment.c | 6 ++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index d697c8900fa7..6284b2f4a60b 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2054,6 +2054,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> goto out;
>
> down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
> + down_write(&F2FS_I(inode)->i_mmap_sem);
>
> /*
> * Should wait end_io to count F2FS_WB_CP_DATA correctly by
> @@ -2064,6 +2065,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> inode->i_ino, get_dirty_pages(inode));
> ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
> if (ret) {
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
> goto out;
> }
> @@ -2077,6 +2079,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> /* add inode in inmem_list first and set atomic_file */
> set_inode_flag(inode, FI_ATOMIC_FILE);
> clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
>
> f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 0cb1ca88d4aa..78c8342f52fd 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -325,6 +325,7 @@ void f2fs_drop_inmem_pages(struct inode *inode)
> struct f2fs_inode_info *fi = F2FS_I(inode);
>
> do {
> + down_write(&F2FS_I(inode)->i_mmap_sem);
> mutex_lock(&fi->inmem_lock);
> if (list_empty(&fi->inmem_pages)) {
> fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
> @@ -339,11 +340,13 @@ void f2fs_drop_inmem_pages(struct inode *inode)
> spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
>
> mutex_unlock(&fi->inmem_lock);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> break;
> }
> __revoke_inmem_pages(inode, &fi->inmem_pages,
> true, false, true);
> mutex_unlock(&fi->inmem_lock);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> } while (1);
> }
>
> @@ -468,6 +471,7 @@ int f2fs_commit_inmem_pages(struct inode *inode)
> f2fs_balance_fs(sbi, true);
>
> down_write(&fi->i_gc_rwsem[WRITE]);
> + down_write(&F2FS_I(inode)->i_mmap_sem);
>
> f2fs_lock_op(sbi);
> set_inode_flag(inode, FI_ATOMIC_COMMIT);
> @@ -479,6 +483,8 @@ int f2fs_commit_inmem_pages(struct inode *inode)
> clear_inode_flag(inode, FI_ATOMIC_COMMIT);
>
> f2fs_unlock_op(sbi);
> +
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&fi->i_gc_rwsem[WRITE]);
>
> return err;
> --
> 2.29.2
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
WARNING: multiple messages have this Message-ID (diff)
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <yuchao0@huawei.com>
Cc: linux-f2fs-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org, chao@kernel.org,
Yi Chen <chenyi77@huawei.com>
Subject: Re: [PATCH v3] f2fs: fix to keep isolation of atomic write
Date: Mon, 12 Apr 2021 20:27:08 -0700 [thread overview]
Message-ID: <YHUPjDY9ifsffk4z@google.com> (raw)
In-Reply-To: <20210412081512.103592-1-yuchao0@huawei.com>
On 04/12, Chao Yu wrote:
> As Yi Chen reported, there is a potential race case described as below:
>
> Thread A Thread B
> - f2fs_ioc_start_atomic_write
> - mkwrite
> - set_page_dirty
> - f2fs_set_page_private(page, 0)
> - set_inode_flag(FI_ATOMIC_FILE)
> - mkwrite same page
> - set_page_dirty
> - f2fs_register_inmem_page
> - f2fs_set_page_private(ATOMIC_WRITTEN_PAGE)
> failed due to PagePrivate flag has been set
> - list_add_tail
> - truncate_inode_pages
> - f2fs_invalidate_page
> - clear page private but w/o remove it from
> inmem_list
> - set page->mapping to NULL
> - f2fs_ioc_commit_atomic_write
> - __f2fs_commit_inmem_pages
> - __revoke_inmem_pages
> - f2fs_put_page panic as page->mapping is NULL
>
> The root cause is we missed to keep isolation of atomic write in the case
> of start_atomic_write vs mkwrite, let start_atomic_write helds i_mmap_sem
> lock to avoid this issue.
My only concern is performance regression. Could you please verify the numbers?
>
> Reported-by: Yi Chen <chenyi77@huawei.com>
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
> v3:
> - rebase to last dev branch
> - update commit message because this patch fixes a different racing issue
> of atomic write
> fs/f2fs/file.c | 3 +++
> fs/f2fs/segment.c | 6 ++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index d697c8900fa7..6284b2f4a60b 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2054,6 +2054,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> goto out;
>
> down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
> + down_write(&F2FS_I(inode)->i_mmap_sem);
>
> /*
> * Should wait end_io to count F2FS_WB_CP_DATA correctly by
> @@ -2064,6 +2065,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> inode->i_ino, get_dirty_pages(inode));
> ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
> if (ret) {
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
> goto out;
> }
> @@ -2077,6 +2079,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
> /* add inode in inmem_list first and set atomic_file */
> set_inode_flag(inode, FI_ATOMIC_FILE);
> clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
>
> f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 0cb1ca88d4aa..78c8342f52fd 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -325,6 +325,7 @@ void f2fs_drop_inmem_pages(struct inode *inode)
> struct f2fs_inode_info *fi = F2FS_I(inode);
>
> do {
> + down_write(&F2FS_I(inode)->i_mmap_sem);
> mutex_lock(&fi->inmem_lock);
> if (list_empty(&fi->inmem_pages)) {
> fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
> @@ -339,11 +340,13 @@ void f2fs_drop_inmem_pages(struct inode *inode)
> spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
>
> mutex_unlock(&fi->inmem_lock);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> break;
> }
> __revoke_inmem_pages(inode, &fi->inmem_pages,
> true, false, true);
> mutex_unlock(&fi->inmem_lock);
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> } while (1);
> }
>
> @@ -468,6 +471,7 @@ int f2fs_commit_inmem_pages(struct inode *inode)
> f2fs_balance_fs(sbi, true);
>
> down_write(&fi->i_gc_rwsem[WRITE]);
> + down_write(&F2FS_I(inode)->i_mmap_sem);
>
> f2fs_lock_op(sbi);
> set_inode_flag(inode, FI_ATOMIC_COMMIT);
> @@ -479,6 +483,8 @@ int f2fs_commit_inmem_pages(struct inode *inode)
> clear_inode_flag(inode, FI_ATOMIC_COMMIT);
>
> f2fs_unlock_op(sbi);
> +
> + up_write(&F2FS_I(inode)->i_mmap_sem);
> up_write(&fi->i_gc_rwsem[WRITE]);
>
> return err;
> --
> 2.29.2
next prev parent reply other threads:[~2021-04-13 3:27 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-12 8:15 [f2fs-dev] [PATCH v3] f2fs: fix to keep isolation of atomic write Chao Yu
2021-04-12 8:15 ` Chao Yu
2021-04-13 3:27 ` Jaegeuk Kim [this message]
2021-04-13 3:27 ` Jaegeuk Kim
2021-04-13 3:41 ` [f2fs-dev] " Chao Yu
2021-04-13 3:41 ` Chao Yu
2021-04-13 17:46 ` [f2fs-dev] " Jaegeuk Kim
2021-04-13 17:46 ` Jaegeuk Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YHUPjDY9ifsffk4z@google.com \
--to=jaegeuk@kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=yuchao0@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.