Skip to content

Commit db6ec53

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 raspberrypi#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 <[email protected]>
1 parent c83414a commit db6ec53

File tree

3 files changed

+53
-27
lines changed

3 files changed

+53
-27
lines changed

fs/f2fs/checkpoint.c

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

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

11491156
/*
@@ -1162,26 +1169,22 @@ static int block_operations(struct f2fs_sb_info *sbi)
11621169
blk_start_plug(&plug);
11631170

11641171
retry_flush_quotas:
1172+
f2fs_lock_all(sbi);
11651173
if (__need_flush_quota(sbi)) {
11661174
int locked;
11671175

11681176
if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) {
11691177
set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
1170-
f2fs_lock_all(sbi);
1178+
set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
11711179
goto retry_flush_dents;
11721180
}
1173-
clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
1181+
f2fs_unlock_all(sbi);
11741182

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

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

fs/f2fs/f2fs.h

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

12581258
unsigned int nquota_files; /* # of quota sysfile */
1259+
struct rw_semaphore quota_sem; /* blocking cp for flags */
12591260

12601261
/* # of pages, see count_type */
12611262
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
@@ -1919,6 +1919,18 @@ int f2fs_quota_sync(struct super_block *sb, int type)
19191919
int cnt;
19201920
int ret;
19211921

1922+
/*
1923+
* do_quotactl
1924+
* f2fs_quota_sync
1925+
* down_read(quota_sem)
1926+
* dquot_writeback_dquots()
1927+
* f2fs_dquot_commit
1928+
* block_operation
1929+
* down_read(quota_sem)
1930+
*/
1931+
f2fs_lock_op(sbi);
1932+
1933+
down_read(&sbi->quota_sem);
19221934
ret = dquot_writeback_dquots(sb, type);
19231935
if (ret)
19241936
goto out;
@@ -1956,6 +1968,8 @@ int f2fs_quota_sync(struct super_block *sb, int type)
19561968
out:
19571969
if (ret)
19581970
set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
1971+
up_read(&sbi->quota_sem);
1972+
f2fs_unlock_op(sbi);
19591973
return ret;
19601974
}
19611975

@@ -2047,32 +2061,40 @@ static void f2fs_truncate_quota_inode_pages(struct super_block *sb)
20472061

20482062
static int f2fs_dquot_commit(struct dquot *dquot)
20492063
{
2064+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20502065
int ret;
20512066

2067+
down_read(&sbi->quota_sem);
20522068
ret = dquot_commit(dquot);
20532069
if (ret < 0)
2054-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2070+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2071+
up_read(&sbi->quota_sem);
20552072
return ret;
20562073
}
20572074

20582075
static int f2fs_dquot_acquire(struct dquot *dquot)
20592076
{
2077+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20602078
int ret;
20612079

2080+
down_read(&sbi->quota_sem);
20622081
ret = dquot_acquire(dquot);
20632082
if (ret < 0)
2064-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2065-
2083+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2084+
up_read(&sbi->quota_sem);
20662085
return ret;
20672086
}
20682087

20692088
static int f2fs_dquot_release(struct dquot *dquot)
20702089
{
2090+
struct f2fs_sb_info *sbi = F2FS_SB(dquot->dq_sb);
20712091
int ret;
20722092

2093+
down_read(&sbi->quota_sem);
20732094
ret = dquot_release(dquot);
20742095
if (ret < 0)
2075-
set_sbi_flag(F2FS_SB(dquot->dq_sb), SBI_QUOTA_NEED_REPAIR);
2096+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2097+
up_read(&sbi->quota_sem);
20762098
return ret;
20772099
}
20782100

@@ -2082,22 +2104,27 @@ static int f2fs_dquot_mark_dquot_dirty(struct dquot *dquot)
20822104
struct f2fs_sb_info *sbi = F2FS_SB(sb);
20832105
int ret;
20842106

2107+
down_read(&sbi->quota_sem);
20852108
ret = dquot_mark_dquot_dirty(dquot);
20862109

20872110
/* if we are using journalled quota */
20882111
if (is_journalled_quota(sbi))
20892112
set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
20902113

2114+
up_read(&sbi->quota_sem);
20912115
return ret;
20922116
}
20932117

20942118
static int f2fs_dquot_commit_info(struct super_block *sb, int type)
20952119
{
2120+
struct f2fs_sb_info *sbi = F2FS_SB(sb);
20962121
int ret;
20972122

2123+
down_read(&sbi->quota_sem);
20982124
ret = dquot_commit_info(sb, type);
20992125
if (ret < 0)
2100-
set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
2126+
set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
2127+
up_read(&sbi->quota_sem);
21012128
return ret;
21022129
}
21032130

@@ -3167,6 +3194,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
31673194
}
31683195

31693196
init_rwsem(&sbi->cp_rwsem);
3197+
init_rwsem(&sbi->quota_sem);
31703198
init_waitqueue_head(&sbi->cp_wait);
31713199
init_sb_info(sbi);
31723200

0 commit comments

Comments
 (0)