Skip to content

Commit 783ea2b

Browse files
author
Jaegeuk Kim
committed
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>
1 parent e115c85 commit 783ea2b

3 files changed

Lines changed: 53 additions & 27 deletions

File tree

fs/f2fs/checkpoint.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,17 +1134,24 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi)
11341134

11351135
static bool __need_flush_quota(struct f2fs_sb_info *sbi)
11361136
{
1137+
bool ret = false;
1138+
11371139
if (!is_journalled_quota(sbi))
11381140
return false;
1139-
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH))
1140-
return false;
1141-
if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR))
1142-
return false;
1143-
if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH))
1144-
return true;
1145-
if (get_pages(sbi, F2FS_DIRTY_QDATA))
1146-
return true;
1147-
return false;
1141+
1142+
down_write(&sbi->quota_sem);
1143+
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) {
1144+
ret = false;
1145+
} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) {
1146+
ret = false;
1147+
} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH)) {
1148+
clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
1149+
ret = true;
1150+
} else if (get_pages(sbi, F2FS_DIRTY_QDATA)) {
1151+
ret = true;
1152+
}
1153+
up_write(&sbi->quota_sem);
1154+
return ret;
11481155
}
11491156

11501157
/*
@@ -1163,26 +1170,22 @@ static int block_operations(struct f2fs_sb_info *sbi)
11631170
blk_start_plug(&plug);
11641171

11651172
retry_flush_quotas:
1173+
f2fs_lock_all(sbi);
11661174
if (__need_flush_quota(sbi)) {
11671175
int locked;
11681176

11691177
if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) {
11701178
set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
1171-
f2fs_lock_all(sbi);
1179+
set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
11721180
goto retry_flush_dents;
11731181
}
1174-
clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
1182+
f2fs_unlock_all(sbi);
11751183

11761184
/* only failed during mount/umount/freeze/quotactl */
11771185
locked = down_read_trylock(&sbi->sb->s_umount);
11781186
f2fs_quota_sync(sbi->sb, -1);
11791187
if (locked)
11801188
up_read(&sbi->sb->s_umount);
1181-
}
1182-
1183-
f2fs_lock_all(sbi);
1184-
if (__need_flush_quota(sbi)) {
1185-
f2fs_unlock_all(sbi);
11861189
cond_resched();
11871190
goto retry_flush_quotas;
11881191
}
@@ -1204,12 +1207,6 @@ static int block_operations(struct f2fs_sb_info *sbi)
12041207
*/
12051208
down_write(&sbi->node_change);
12061209

1207-
if (__need_flush_quota(sbi)) {
1208-
up_write(&sbi->node_change);
1209-
f2fs_unlock_all(sbi);
1210-
goto retry_flush_quotas;
1211-
}
1212-
12131210
if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
12141211
up_write(&sbi->node_change);
12151212
f2fs_unlock_all(sbi);

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,7 @@ struct f2fs_sb_info {
13221322
block_t unusable_block_count; /* # of blocks saved by last cp */
13231323

13241324
unsigned int nquota_files; /* # of quota sysfile */
1325+
struct rw_semaphore quota_sem; /* blocking cp for flags */
13251326

13261327
/* # of pages, see count_type */
13271328
atomic_t nr_pages[NR_COUNT_TYPE];

fs/f2fs/super.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,18 @@ int f2fs_quota_sync(struct super_block *sb, int type)
19251925
int cnt;
19261926
int ret;
19271927

1928+
/*
1929+
* do_quotactl
1930+
* f2fs_quota_sync
1931+
* down_read(quota_sem)
1932+
* dquot_writeback_dquots()
1933+
* f2fs_dquot_commit
1934+
* block_operation
1935+
* down_read(quota_sem)
1936+
*/
1937+
f2fs_lock_op(sbi);
1938+
1939+
down_read(&sbi->quota_sem);
19281940
ret = dquot_writeback_dquots(sb, type);
19291941
if (ret)
19301942
goto out;
@@ -1962,6 +1974,8 @@ int f2fs_quota_sync(struct super_block *sb, int type)
19621974
out:
19631975
if (ret)
19641976
set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
1977+
up_read(&sbi->quota_sem);
1978+
f2fs_unlock_op(sbi);
19651979
return ret;
19661980
}
19671981

@@ -2053,32 +2067,40 @@ static void f2fs_truncate_quota_inode_pages(struct super_block *sb)
20532067

20542068
static int f2fs_dquot_commit(struct dquot *dquot)
20552069
{
2070+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20562071
int ret;
20572072

2073+
down_read(&sbi->quota_sem);
20582074
ret = dquot_commit(dquot);
20592075
if (ret < 0)
2060-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2076+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2077+
up_read(&sbi->quota_sem);
20612078
return ret;
20622079
}
20632080

20642081
static int f2fs_dquot_acquire(struct dquot *dquot)
20652082
{
2083+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20662084
int ret;
20672085

2086+
down_read(&sbi->quota_sem);
20682087
ret = dquot_acquire(dquot);
20692088
if (ret < 0)
2070-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2071-
2089+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2090+
up_read(&sbi->quota_sem);
20722091
return ret;
20732092
}
20742093

20752094
static int f2fs_dquot_release(struct dquot *dquot)
20762095
{
2096+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20772097
int ret;
20782098

2099+
down_read(&sbi->quota_sem);
20792100
ret = dquot_release(dquot);
20802101
if (ret < 0)
2081-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2102+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2103+
up_read(&sbi->quota_sem);
20822104
return ret;
20832105
}
20842106

@@ -2088,22 +2110,27 @@ static int f2fs_dquot_mark_dquot_dirty(struct dquot *dquot)
20882110
struct f2fs_sb_info *sbi = F2FS_SB(sb);
20892111
int ret;
20902112

2113+
down_read(&sbi->quota_sem);
20912114
ret = dquot_mark_dquot_dirty(dquot);
20922115

20932116
/* if we are using journalled quota */
20942117
if (is_journalled_quota(sbi))
20952118
set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
20962119

2120+
up_read(&sbi->quota_sem);
20972121
return ret;
20982122
}
20992123

21002124
static int f2fs_dquot_commit_info(struct super_block *sb, int type)
21012125
{
2126+
struct f2fs_sb_info *sbi = F2FS_SB(sb);
21022127
int ret;
21032128

2129+
down_read(&sbi->quota_sem);
21042130
ret = dquot_commit_info(sb, type);
21052131
if (ret < 0)
2106-
set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
2132+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2133+
up_read(&sbi->quota_sem);
21072134
return ret;
21082135
}
21092136

@@ -3180,6 +3207,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
31803207
}
31813208

31823209
init_rwsem(&sbi->cp_rwsem);
3210+
init_rwsem(&sbi->quota_sem);
31833211
init_waitqueue_head(&sbi->cp_wait);
31843212
init_sb_info(sbi);
31853213

0 commit comments

Comments
 (0)