diff options
author | Chao Yu <yuchao0@huawei.com> | 2017-08-31 18:56:05 +0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2017-09-05 10:50:22 -0700 |
commit | edd748e6c8e824a8281f8a8450f12c4a95ec61ee (patch) | |
tree | 69d2f53faab82737599b1c93534721c716f214ff /fs | |
parent | 025d63a486aad611b20fa39184fc86e4b76d260e (diff) | |
download | op-kernel-dev-edd748e6c8e824a8281f8a8450f12c4a95ec61ee.zip op-kernel-dev-edd748e6c8e824a8281f8a8450f12c4a95ec61ee.tar.gz |
f2fs: avoid race in between atomic_read & atomic_inc
Previously, we will miss merging flush command during fsync due to below
race condition:
Thread A Thread B Thread C
- f2fs_issue_flush
- atomic_read(&issing_flush)
- f2fs_issue_flush
- atomic_read(&issing_flush)
- f2fs_issue_flush
- atomic_read(&issing_flush)
- atomic_inc(&issing_flush)
- atomic_inc(&issing_flush)
- atomic_inc(&issing_flush)
- submit_flush_wait
- submit_flush_wait
- submit_flush_wait
It needs to use atomic_inc_return instead to avoid such race.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/f2fs/segment.c | 4 |
1 files changed, 1 insertions, 3 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d6c3f45..1215ca1 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -536,8 +536,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi) return ret; } - if (!atomic_read(&fcc->issing_flush)) { - atomic_inc(&fcc->issing_flush); + if (atomic_inc_return(&fcc->issing_flush) == 1) { ret = submit_flush_wait(sbi); atomic_dec(&fcc->issing_flush); @@ -547,7 +546,6 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi) init_completion(&cmd.wait); - atomic_inc(&fcc->issing_flush); llist_add(&cmd.llnode, &fcc->issue_list); /* update issue_list before we wake up issue_flush thread */ |