quota: Drop GFP_NOFS instances under dquot->dq_lock and dqio_sem
authorJan Kara <jack@suse.cz>
Mon, 22 Jan 2024 12:22:42 +0000 (13:22 +0100)
committerJan Kara <jack@suse.cz>
Tue, 23 Jan 2024 18:21:11 +0000 (19:21 +0100)
Quota code acquires dquot->dq_lock whenever reading / writing dquot.
When reading / writing quota info we hold dqio_sem.  Since these locks
can be acquired during inode reclaim (through dquot_drop() -> dqput() ->
dquot_release()) we are setting nofs allocation context whenever
acquiring these locks. Hence there's no need to use GFP_NOFS allocations
in quota code doing IO. Just switch it to GFP_KERNEL.

Signed-off-by: Jan Kara <jack@suse.cz>
fs/quota/quota_tree.c
fs/quota/quota_v2.c

index 0f1493e0f6d059b37032af363f5898415be6d79f..ef0461542d3a1d62ba2a26853b6b664fbab35a79 100644 (file)
@@ -108,7 +108,7 @@ static int check_dquot_block_header(struct qtree_mem_dqinfo *info,
 /* Remove empty block from list and return it */
 static int get_free_dqblk(struct qtree_mem_dqinfo *info)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
        int ret, blk;
 
@@ -160,7 +160,7 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)
 static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
                               uint blk)
 {
-       char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
        uint nextblk = le32_to_cpu(dh->dqdh_next_free);
        uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
@@ -207,7 +207,7 @@ out_buf:
 static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
                               uint blk)
 {
-       char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
        int err;
 
@@ -255,7 +255,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
 {
        uint blk, i;
        struct qt_disk_dqdbheader *dh;
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        char *ddquot;
 
        *err = 0;
@@ -329,7 +329,7 @@ out_buf:
 static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
                          uint *treeblk, int depth)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        int ret = 0, newson = 0, newact = 0;
        __le32 *ref;
        uint newblk;
@@ -410,7 +410,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
        int type = dquot->dq_id.type;
        struct super_block *sb = dquot->dq_sb;
        ssize_t ret;
-       char *ddquot = kmalloc(info->dqi_entry_size, GFP_NOFS);
+       char *ddquot = kmalloc(info->dqi_entry_size, GFP_KERNEL);
 
        if (!ddquot)
                return -ENOMEM;
@@ -449,7 +449,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
                        uint blk)
 {
        struct qt_disk_dqdbheader *dh;
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        int ret = 0;
 
        if (!buf)
@@ -513,7 +513,7 @@ out_buf:
 static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
                       uint *blk, int depth)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        int ret = 0;
        uint newblk;
        __le32 *ref = (__le32 *)buf;
@@ -577,7 +577,7 @@ EXPORT_SYMBOL(qtree_delete_dquot);
 static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
                                 struct dquot *dquot, uint blk)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        loff_t ret = 0;
        int i;
        char *ddquot;
@@ -615,7 +615,7 @@ out_buf:
 static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
                                struct dquot *dquot, uint blk, int depth)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        loff_t ret = 0;
        __le32 *ref = (__le32 *)buf;
 
@@ -684,7 +684,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
                }
                dquot->dq_off = offset;
        }
-       ddquot = kmalloc(info->dqi_entry_size, GFP_NOFS);
+       ddquot = kmalloc(info->dqi_entry_size, GFP_KERNEL);
        if (!ddquot)
                return -ENOMEM;
        ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size,
@@ -728,7 +728,7 @@ EXPORT_SYMBOL(qtree_release_dquot);
 static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id,
                        unsigned int blk, int depth)
 {
-       char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
+       char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);
        __le32 *ref = (__le32 *)buf;
        ssize_t ret;
        unsigned int epb = info->dqi_usable_bs >> 2;
index 48e0d610ceef680e1a400adb76cae61e0a1a4ea7..5eb0de8e7e40f58fc7cb940e26a88b43fedc5f3e 100644 (file)
@@ -121,7 +121,7 @@ static int v2_read_file_info(struct super_block *sb, int type)
                        ret = -EIO;
                goto out;
        }
-       info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS);
+       info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_KERNEL);
        if (!info->dqi_priv) {
                ret = -ENOMEM;
                goto out;