lkml.org 
[lkml]   [2022]   [Jun]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 15/84] quota: Prevent memory allocation recursion while holding dq_lock
    Date
    From: Matthew Wilcox (Oracle) <willy@infradead.org>

    [ Upstream commit 537e11cdc7a6b3ce94fa25ed41306193df9677b7 ]

    As described in commit 02117b8ae9c0 ("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/20220605143815.2330891-2-willy@infradead.org
    Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/quota/dquot.c | 10 ++++++++++
    1 file changed, 10 insertions(+)

    diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
    index 09fb8459bb5c..65f123d5809b 100644
    --- a/fs/quota/dquot.c
    +++ b/fs/quota/dquot.c
    @@ -79,6 +79,7 @@
    #include <linux/capability.h>
    #include <linux/quotaops.h>
    #include <linux/blkdev.h>
    +#include <linux/sched/mm.h>
    #include "../internal.h" /* ugh */

    #include <linux/uaccess.h>
    @@ -427,9 +428,11 @@ EXPORT_SYMBOL(mark_info_dirty);
    int dquot_acquire(struct dquot *dquot)
    {
    int ret = 0, ret2 = 0;
    + unsigned int memalloc;
    struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);

    mutex_lock(&dquot->dq_lock);
    + memalloc = memalloc_nofs_save();
    if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
    ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
    if (ret < 0)
    @@ -460,6 +463,7 @@ int dquot_acquire(struct dquot *dquot)
    smp_mb__before_atomic();
    set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
    out_iolock:
    + memalloc_nofs_restore(memalloc);
    mutex_unlock(&dquot->dq_lock);
    return ret;
    }
    @@ -471,9 +475,11 @@ EXPORT_SYMBOL(dquot_acquire);
    int dquot_commit(struct dquot *dquot)
    {
    int ret = 0;
    + unsigned int memalloc;
    struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);

    mutex_lock(&dquot->dq_lock);
    + memalloc = memalloc_nofs_save();
    if (!clear_dquot_dirty(dquot))
    goto out_lock;
    /* Inactive dquot can be only if there was error during read/init
    @@ -483,6 +489,7 @@ int dquot_commit(struct dquot *dquot)
    else
    ret = -EIO;
    out_lock:
    + memalloc_nofs_restore(memalloc);
    mutex_unlock(&dquot->dq_lock);
    return ret;
    }
    @@ -494,9 +501,11 @@ EXPORT_SYMBOL(dquot_commit);
    int dquot_release(struct dquot *dquot)
    {
    int ret = 0, ret2 = 0;
    + unsigned int memalloc;
    struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);

    mutex_lock(&dquot->dq_lock);
    + memalloc = memalloc_nofs_save();
    /* Check whether we are not racing with some other dqget() */
    if (dquot_is_busy(dquot))
    goto out_dqlock;
    @@ -512,6 +521,7 @@ int dquot_release(struct dquot *dquot)
    }
    clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
    out_dqlock:
    + memalloc_nofs_restore(memalloc);
    mutex_unlock(&dquot->dq_lock);
    return ret;
    }
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-06-20 15:12    [W:4.286 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site