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>
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);
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 */