Skip to content

Commit 6c5026c

Browse files
committed
quota: Set nofs allocation context when acquiring dqio_sem
dqio_sem can be acquired during inode reclaim through dquot_drop() -> dqput() -> dquot_release() -> write_file_info() context. In some cases (most notably through dquot_get_next_id()) it can be acquired without holding dquot->dq_lock (which already sets nofs allocation context). So we need to set nofs allocation context when acquiring it as well. Signed-off-by: Jan Kara <jack@suse.cz>
1 parent c3e637c commit 6c5026c

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

fs/ocfs2/quota_global.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,14 +447,17 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
447447
int err;
448448
struct quota_info *dqopt = sb_dqopt(sb);
449449
struct ocfs2_mem_dqinfo *info = dqopt->info[type].dqi_priv;
450+
unsigned int memalloc;
450451

451452
down_write(&dqopt->dqio_sem);
453+
memalloc = memalloc_nofs_save();
452454
err = ocfs2_qinfo_lock(info, 1);
453455
if (err < 0)
454456
goto out_sem;
455457
err = __ocfs2_global_write_info(sb, type);
456458
ocfs2_qinfo_unlock(info, 1);
457459
out_sem:
460+
memalloc_nofs_restore(memalloc);
458461
up_write(&dqopt->dqio_sem);
459462
return err;
460463
}
@@ -601,6 +604,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
601604
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
602605
struct ocfs2_super *osb = OCFS2_SB(sb);
603606
int status = 0;
607+
unsigned int memalloc;
604608

605609
trace_ocfs2_sync_dquot_helper(from_kqid(&init_user_ns, dquot->dq_id),
606610
dquot->dq_id.type,
@@ -618,13 +622,15 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
618622
goto out_ilock;
619623
}
620624
down_write(&sb_dqopt(sb)->dqio_sem);
625+
memalloc = memalloc_nofs_save();
621626
status = ocfs2_sync_dquot(dquot);
622627
if (status < 0)
623628
mlog_errno(status);
624629
/* We have to write local structure as well... */
625630
status = ocfs2_local_write_dquot(dquot);
626631
if (status < 0)
627632
mlog_errno(status);
633+
memalloc_nofs_restore(memalloc);
628634
up_write(&sb_dqopt(sb)->dqio_sem);
629635
ocfs2_commit_trans(osb, handle);
630636
out_ilock:
@@ -662,6 +668,7 @@ static int ocfs2_write_dquot(struct dquot *dquot)
662668
handle_t *handle;
663669
struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
664670
int status = 0;
671+
unsigned int memalloc;
665672

666673
trace_ocfs2_write_dquot(from_kqid(&init_user_ns, dquot->dq_id),
667674
dquot->dq_id.type);
@@ -673,7 +680,9 @@ static int ocfs2_write_dquot(struct dquot *dquot)
673680
goto out;
674681
}
675682
down_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
683+
memalloc = memalloc_nofs_save();
676684
status = ocfs2_local_write_dquot(dquot);
685+
memalloc_nofs_restore(memalloc);
677686
up_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
678687
ocfs2_commit_trans(osb, handle);
679688
out:
@@ -920,6 +929,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
920929
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
921930
handle_t *handle;
922931
struct ocfs2_super *osb = OCFS2_SB(sb);
932+
unsigned int memalloc;
923933

924934
trace_ocfs2_mark_dquot_dirty(from_kqid(&init_user_ns, dquot->dq_id),
925935
type);
@@ -946,6 +956,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
946956
goto out_ilock;
947957
}
948958
down_write(&sb_dqopt(sb)->dqio_sem);
959+
memalloc = memalloc_nofs_save();
949960
status = ocfs2_sync_dquot(dquot);
950961
if (status < 0) {
951962
mlog_errno(status);
@@ -954,6 +965,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
954965
/* Now write updated local dquot structure */
955966
status = ocfs2_local_write_dquot(dquot);
956967
out_dlock:
968+
memalloc_nofs_restore(memalloc);
957969
up_write(&sb_dqopt(sb)->dqio_sem);
958970
ocfs2_commit_trans(osb, handle);
959971
out_ilock:

fs/ocfs2/quota_local.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
470470
int bit, chunk;
471471
struct ocfs2_recovery_chunk *rchunk, *next;
472472
qsize_t spacechange, inodechange;
473+
unsigned int memalloc;
473474

474475
trace_ocfs2_recover_local_quota_file((unsigned long)lqinode->i_ino, type);
475476

@@ -521,6 +522,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
521522
goto out_drop_lock;
522523
}
523524
down_write(&sb_dqopt(sb)->dqio_sem);
525+
memalloc = memalloc_nofs_save();
524526
spin_lock(&dquot->dq_dqb_lock);
525527
/* Add usage from quota entry into quota changes
526528
* of our node. Auxiliary variables are important
@@ -553,6 +555,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
553555
unlock_buffer(qbh);
554556
ocfs2_journal_dirty(handle, qbh);
555557
out_commit:
558+
memalloc_nofs_restore(memalloc);
556559
up_write(&sb_dqopt(sb)->dqio_sem);
557560
ocfs2_commit_trans(OCFS2_SB(sb), handle);
558561
out_drop_lock:

fs/quota/quota_v1.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,11 @@ static int v1_read_file_info(struct super_block *sb, int type)
160160
{
161161
struct quota_info *dqopt = sb_dqopt(sb);
162162
struct v1_disk_dqblk dqblk;
163+
unsigned int memalloc;
163164
int ret;
164165

165166
down_read(&dqopt->dqio_sem);
167+
memalloc = memalloc_nofs_save();
166168
ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
167169
sizeof(struct v1_disk_dqblk), v1_dqoff(0));
168170
if (ret != sizeof(struct v1_disk_dqblk)) {
@@ -179,6 +181,7 @@ static int v1_read_file_info(struct super_block *sb, int type)
179181
dqopt->info[type].dqi_bgrace =
180182
dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
181183
out:
184+
memalloc_nofs_restore(memalloc);
182185
up_read(&dqopt->dqio_sem);
183186
return ret;
184187
}
@@ -187,9 +190,11 @@ static int v1_write_file_info(struct super_block *sb, int type)
187190
{
188191
struct quota_info *dqopt = sb_dqopt(sb);
189192
struct v1_disk_dqblk dqblk;
193+
unsigned int memalloc;
190194
int ret;
191195

192196
down_write(&dqopt->dqio_sem);
197+
memalloc = memalloc_nofs_save();
193198
ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,
194199
sizeof(struct v1_disk_dqblk), v1_dqoff(0));
195200
if (ret != sizeof(struct v1_disk_dqblk)) {
@@ -209,6 +214,7 @@ static int v1_write_file_info(struct super_block *sb, int type)
209214
else if (ret >= 0)
210215
ret = -EIO;
211216
out:
217+
memalloc_nofs_restore(memalloc);
212218
up_write(&dqopt->dqio_sem);
213219
return ret;
214220
}

fs/quota/quota_v2.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@ static int v2_read_file_info(struct super_block *sb, int type)
9696
struct qtree_mem_dqinfo *qinfo;
9797
ssize_t size;
9898
unsigned int version;
99+
unsigned int memalloc;
99100
int ret;
100101

101102
down_read(&dqopt->dqio_sem);
103+
memalloc = memalloc_nofs_save();
102104
ret = v2_read_header(sb, type, &dqhead);
103105
if (ret < 0)
104106
goto out;
@@ -183,6 +185,7 @@ static int v2_read_file_info(struct super_block *sb, int type)
183185
info->dqi_priv = NULL;
184186
}
185187
out:
188+
memalloc_nofs_restore(memalloc);
186189
up_read(&dqopt->dqio_sem);
187190
return ret;
188191
}
@@ -195,8 +198,10 @@ static int v2_write_file_info(struct super_block *sb, int type)
195198
struct mem_dqinfo *info = &dqopt->info[type];
196199
struct qtree_mem_dqinfo *qinfo = info->dqi_priv;
197200
ssize_t size;
201+
unsigned int memalloc;
198202

199203
down_write(&dqopt->dqio_sem);
204+
memalloc = memalloc_nofs_save();
200205
spin_lock(&dq_data_lock);
201206
info->dqi_flags &= ~DQF_INFO_DIRTY;
202207
dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
@@ -209,6 +214,7 @@ static int v2_write_file_info(struct super_block *sb, int type)
209214
dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry);
210215
size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
211216
sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
217+
memalloc_nofs_restore(memalloc);
212218
up_write(&dqopt->dqio_sem);
213219
if (size != sizeof(struct v2_disk_dqinfo)) {
214220
quota_error(sb, "Can't write info structure");
@@ -328,11 +334,14 @@ static int v2_read_dquot(struct dquot *dquot)
328334
{
329335
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
330336
int ret;
337+
unsigned int memalloc;
331338

332339
down_read(&dqopt->dqio_sem);
340+
memalloc = memalloc_nofs_save();
333341
ret = qtree_read_dquot(
334342
sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv,
335343
dquot);
344+
memalloc_nofs_restore(memalloc);
336345
up_read(&dqopt->dqio_sem);
337346
return ret;
338347
}
@@ -342,6 +351,7 @@ static int v2_write_dquot(struct dquot *dquot)
342351
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
343352
int ret;
344353
bool alloc = false;
354+
unsigned int memalloc;
345355

346356
/*
347357
* If space for dquot is already allocated, we don't need any
@@ -355,9 +365,11 @@ static int v2_write_dquot(struct dquot *dquot)
355365
} else {
356366
down_read(&dqopt->dqio_sem);
357367
}
368+
memalloc = memalloc_nofs_save();
358369
ret = qtree_write_dquot(
359370
sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv,
360371
dquot);
372+
memalloc_nofs_restore(memalloc);
361373
if (alloc)
362374
up_write(&dqopt->dqio_sem);
363375
else
@@ -368,10 +380,13 @@ static int v2_write_dquot(struct dquot *dquot)
368380
static int v2_release_dquot(struct dquot *dquot)
369381
{
370382
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
383+
unsigned int memalloc;
371384
int ret;
372385

373386
down_write(&dqopt->dqio_sem);
387+
memalloc = memalloc_nofs_save();
374388
ret = qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot);
389+
memalloc_nofs_restore(memalloc);
375390
up_write(&dqopt->dqio_sem);
376391

377392
return ret;
@@ -386,10 +401,13 @@ static int v2_free_file_info(struct super_block *sb, int type)
386401
static int v2_get_next_id(struct super_block *sb, struct kqid *qid)
387402
{
388403
struct quota_info *dqopt = sb_dqopt(sb);
404+
unsigned int memalloc;
389405
int ret;
390406

391407
down_read(&dqopt->dqio_sem);
408+
memalloc = memalloc_nofs_save();
392409
ret = qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid);
410+
memalloc_nofs_restore(memalloc);
393411
up_read(&dqopt->dqio_sem);
394412
return ret;
395413
}

0 commit comments

Comments
 (0)