提交 b58beeee 编写于 作者: M Matthew Wilcox (Oracle) 提交者: Zheng Zengkai

quota: Prevent memory allocation recursion while holding dq_lock

stable inclusion
from stable-v5.10.124
commit 8656623bdc0d12ac0659a264cc8db6e0e770f3ce
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5L6E7

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8656623bdc0d12ac0659a264cc8db6e0e770f3ce

--------------------------------

[ Upstream commit 537e11cd ]

As described in commit 02117b8a ("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.orgSigned-off-by: NMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: NJan Kara <jack@suse.cz>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 1bb176cd
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/sched/mm.h>
#include "../internal.h" /* ugh */ #include "../internal.h" /* ugh */
#include <linux/uaccess.h> #include <linux/uaccess.h>
...@@ -427,9 +428,11 @@ EXPORT_SYMBOL(mark_info_dirty); ...@@ -427,9 +428,11 @@ EXPORT_SYMBOL(mark_info_dirty);
int dquot_acquire(struct dquot *dquot) int dquot_acquire(struct dquot *dquot)
{ {
int ret = 0, ret2 = 0; int ret = 0, ret2 = 0;
unsigned int memalloc;
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
mutex_lock(&dquot->dq_lock); mutex_lock(&dquot->dq_lock);
memalloc = memalloc_nofs_save();
if (!test_bit(DQ_READ_B, &dquot->dq_flags)) { if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
if (ret < 0) if (ret < 0)
...@@ -460,6 +463,7 @@ int dquot_acquire(struct dquot *dquot) ...@@ -460,6 +463,7 @@ int dquot_acquire(struct dquot *dquot)
smp_mb__before_atomic(); smp_mb__before_atomic();
set_bit(DQ_ACTIVE_B, &dquot->dq_flags); set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
out_iolock: out_iolock:
memalloc_nofs_restore(memalloc);
mutex_unlock(&dquot->dq_lock); mutex_unlock(&dquot->dq_lock);
return ret; return ret;
} }
...@@ -471,9 +475,11 @@ EXPORT_SYMBOL(dquot_acquire); ...@@ -471,9 +475,11 @@ EXPORT_SYMBOL(dquot_acquire);
int dquot_commit(struct dquot *dquot) int dquot_commit(struct dquot *dquot)
{ {
int ret = 0; int ret = 0;
unsigned int memalloc;
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
mutex_lock(&dquot->dq_lock); mutex_lock(&dquot->dq_lock);
memalloc = memalloc_nofs_save();
if (!clear_dquot_dirty(dquot)) if (!clear_dquot_dirty(dquot))
goto out_lock; goto out_lock;
/* Inactive dquot can be only if there was error during read/init /* Inactive dquot can be only if there was error during read/init
...@@ -483,6 +489,7 @@ int dquot_commit(struct dquot *dquot) ...@@ -483,6 +489,7 @@ int dquot_commit(struct dquot *dquot)
else else
ret = -EIO; ret = -EIO;
out_lock: out_lock:
memalloc_nofs_restore(memalloc);
mutex_unlock(&dquot->dq_lock); mutex_unlock(&dquot->dq_lock);
return ret; return ret;
} }
...@@ -494,9 +501,11 @@ EXPORT_SYMBOL(dquot_commit); ...@@ -494,9 +501,11 @@ EXPORT_SYMBOL(dquot_commit);
int dquot_release(struct dquot *dquot) int dquot_release(struct dquot *dquot)
{ {
int ret = 0, ret2 = 0; int ret = 0, ret2 = 0;
unsigned int memalloc;
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
mutex_lock(&dquot->dq_lock); mutex_lock(&dquot->dq_lock);
memalloc = memalloc_nofs_save();
/* Check whether we are not racing with some other dqget() */ /* Check whether we are not racing with some other dqget() */
if (dquot_is_busy(dquot)) if (dquot_is_busy(dquot))
goto out_dqlock; goto out_dqlock;
...@@ -512,6 +521,7 @@ int dquot_release(struct dquot *dquot) ...@@ -512,6 +521,7 @@ int dquot_release(struct dquot *dquot)
} }
clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
out_dqlock: out_dqlock:
memalloc_nofs_restore(memalloc);
mutex_unlock(&dquot->dq_lock); mutex_unlock(&dquot->dq_lock);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册