Skip to content

Commit 1551237

Browse files
committed
quota: Fix possible corruption of dqi_flags
dqi_flags modifications are protected by dq_data_lock. However the modifications in vfs_load_quota_inode() and in mark_info_dirty() were not which could lead to corruption of dqi_flags. Since modifications to dqi_flags are rare, this is hard to observe in practice but in theory it could happen. Fix the problem by always using dq_data_lock for protection. Signed-off-by: Jan Kara <jack@suse.cz>
1 parent f98bbe3 commit 1551237

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

fs/quota/dquot.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,9 @@ static inline int clear_dquot_dirty(struct dquot *dquot)
389389

390390
void mark_info_dirty(struct super_block *sb, int type)
391391
{
392-
set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
392+
spin_lock(&dq_data_lock);
393+
sb_dqopt(sb)->info[type].dqi_flags |= DQF_INFO_DIRTY;
394+
spin_unlock(&dq_data_lock);
393395
}
394396
EXPORT_SYMBOL(mark_info_dirty);
395397

@@ -2316,8 +2318,11 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
23162318
error = dqopt->ops[type]->read_file_info(sb, type);
23172319
if (error < 0)
23182320
goto out_file_init;
2319-
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
2321+
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) {
2322+
spin_lock(&dq_data_lock);
23202323
dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
2324+
spin_unlock(&dq_data_lock);
2325+
}
23212326
spin_lock(&dq_state_lock);
23222327
dqopt->flags |= dquot_state_flag(flags, type);
23232328
spin_unlock(&dq_state_lock);

fs/quota/quota_v1.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,18 @@ static int v1_write_file_info(struct super_block *sb, int type)
189189
int ret;
190190

191191
down_write(&dqopt->dqio_sem);
192-
dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
193192
ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
194193
sizeof(struct v1_disk_dqblk), v1_dqoff(0));
195194
if (ret != sizeof(struct v1_disk_dqblk)) {
196195
if (ret >= 0)
197196
ret = -EIO;
198197
goto out;
199198
}
199+
spin_lock(&dq_data_lock);
200+
dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
200201
dqblk.dqb_itime = dqopt->info[type].dqi_igrace;
201202
dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;
203+
spin_unlock(&dq_data_lock);
202204
ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,
203205
sizeof(struct v1_disk_dqblk), v1_dqoff(0));
204206
if (ret == sizeof(struct v1_disk_dqblk))

0 commit comments

Comments
 (0)