f2fs: add a rw_sem to cover quota flag changes

Two paths to update quota and f2fs_lock_op:

1.
 - lock_op
 |  - quota_update
 `- unlock_op

2.
 - quota_update
 - lock_op
 `- unlock_op

But, we need to make a transaction on quota_update + lock_op in #2 case.
So, this patch introduces:
1. lock_op
2. down_write
3. check __need_flush
4. up_write
5. if there is dirty quota entries, flush them
6. otherwise, good to go

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Jaegeuk Kim
2019-05-29 10:58:45 -07:00
parent c83414aedf
commit db6ec53b7e
3 changed files with 53 additions and 27 deletions

View File

@@ -1133,17 +1133,24 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi)
static bool __need_flush_quota(struct f2fs_sb_info *sbi)
{
bool ret = false;
if (!is_journalled_quota(sbi))
return false;
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH))
return false;
if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR))
return false;
if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH))
return true;
if (get_pages(sbi, F2FS_DIRTY_QDATA))
return true;
return false;
down_write(&sbi->quota_sem);
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) {
ret = false;
} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) {
ret = false;
} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH)) {
clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
ret = true;
} else if (get_pages(sbi, F2FS_DIRTY_QDATA)) {
ret = true;
}
up_write(&sbi->quota_sem);
return ret;
}
/*
@@ -1162,26 +1169,22 @@ static int block_operations(struct f2fs_sb_info *sbi)
blk_start_plug(&plug);
retry_flush_quotas:
f2fs_lock_all(sbi);
if (__need_flush_quota(sbi)) {
int locked;
if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) {
set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
f2fs_lock_all(sbi);
set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
goto retry_flush_dents;
}
clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
f2fs_unlock_all(sbi);
/* only failed during mount/umount/freeze/quotactl */
locked = down_read_trylock(&sbi->sb->s_umount);
f2fs_quota_sync(sbi->sb, -1);
if (locked)
up_read(&sbi->sb->s_umount);
}
f2fs_lock_all(sbi);
if (__need_flush_quota(sbi)) {
f2fs_unlock_all(sbi);
cond_resched();
goto retry_flush_quotas;
}
@@ -1203,12 +1206,6 @@ retry_flush_dents:
*/
down_write(&sbi->node_change);
if (__need_flush_quota(sbi)) {
up_write(&sbi->node_change);
f2fs_unlock_all(sbi);
goto retry_flush_quotas;
}
if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
up_write(&sbi->node_change);
f2fs_unlock_all(sbi);