Skip to content

Commit 537e11c

Browse files
Matthew Wilcox (Oracle)jankara
authored andcommitted
quota: Prevent memory allocation recursion while holding dq_lock
As described in commit 02117b8 ("f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read"), we must not enter filesystem reclaim while holding the dq_lock. Prevent this more generally by using memalloc_nofs_save() while holding the lock. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 10e1407 commit 537e11c

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

fs/quota/dquot.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include <linux/capability.h>
8080
#include <linux/quotaops.h>
8181
#include <linux/blkdev.h>
82+
#include <linux/sched/mm.h>
8283
#include "../internal.h" /* ugh */
8384

8485
#include <linux/uaccess.h>
@@ -425,9 +426,11 @@ EXPORT_SYMBOL(mark_info_dirty);
425426
int dquot_acquire(struct dquot *dquot)
426427
{
427428
int ret = 0, ret2 = 0;
429+
unsigned int memalloc;
428430
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
429431

430432
mutex_lock(&dquot->dq_lock);
433+
memalloc = memalloc_nofs_save();
431434
if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
432435
ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
433436
if (ret < 0)
@@ -458,6 +461,7 @@ int dquot_acquire(struct dquot *dquot)
458461
smp_mb__before_atomic();
459462
set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
460463
out_iolock:
464+
memalloc_nofs_restore(memalloc);
461465
mutex_unlock(&dquot->dq_lock);
462466
return ret;
463467
}
@@ -469,9 +473,11 @@ EXPORT_SYMBOL(dquot_acquire);
469473
int dquot_commit(struct dquot *dquot)
470474
{
471475
int ret = 0;
476+
unsigned int memalloc;
472477
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
473478

474479
mutex_lock(&dquot->dq_lock);
480+
memalloc = memalloc_nofs_save();
475481
if (!clear_dquot_dirty(dquot))
476482
goto out_lock;
477483
/* Inactive dquot can be only if there was error during read/init
@@ -481,6 +487,7 @@ int dquot_commit(struct dquot *dquot)
481487
else
482488
ret = -EIO;
483489
out_lock:
490+
memalloc_nofs_restore(memalloc);
484491
mutex_unlock(&dquot->dq_lock);
485492
return ret;
486493
}
@@ -492,9 +499,11 @@ EXPORT_SYMBOL(dquot_commit);
492499
int dquot_release(struct dquot *dquot)
493500
{
494501
int ret = 0, ret2 = 0;
502+
unsigned int memalloc;
495503
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
496504

497505
mutex_lock(&dquot->dq_lock);
506+
memalloc = memalloc_nofs_save();
498507
/* Check whether we are not racing with some other dqget() */
499508
if (dquot_is_busy(dquot))
500509
goto out_dqlock;
@@ -510,6 +519,7 @@ int dquot_release(struct dquot *dquot)
510519
}
511520
clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
512521
out_dqlock:
522+
memalloc_nofs_restore(memalloc);
513523
mutex_unlock(&dquot->dq_lock);
514524
return ret;
515525
}

0 commit comments

Comments
 (0)