Btrfs: setup a nofs context for memory allocation at btrfs_create_tree()
authorFilipe Manana <fdmanana@suse.com>
Thu, 13 Dec 2018 21:16:45 +0000 (21:16 +0000)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Feb 2019 13:13:16 +0000 (14:13 +0100)
We are holding a transaction handle when creating a tree, therefore we can
not allocate the root using GFP_KERNEL, as we could deadlock if reclaim is
triggered by the allocation, therefore setup a nofs context.

Fixes: 74e4d82757f74 ("btrfs: let callers of btrfs_alloc_root pass gfp flags")
CC: stable@vger.kernel.org # 4.9+
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c

index 6a2a2a9..888d72d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/semaphore.h>
 #include <linux/error-injection.h>
 #include <linux/crc32c.h>
+#include <linux/sched/mm.h>
 #include <asm/unaligned.h>
 #include "ctree.h"
 #include "disk-io.h"
@@ -1258,10 +1259,17 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
        struct btrfs_root *tree_root = fs_info->tree_root;
        struct btrfs_root *root;
        struct btrfs_key key;
+       unsigned int nofs_flag;
        int ret = 0;
        uuid_le uuid = NULL_UUID_LE;
 
+       /*
+        * We're holding a transaction handle, so use a NOFS memory allocation
+        * context to avoid deadlock if reclaim happens.
+        */
+       nofs_flag = memalloc_nofs_save();
        root = btrfs_alloc_root(fs_info, GFP_KERNEL);
+       memalloc_nofs_restore(nofs_flag);
        if (!root)
                return ERR_PTR(-ENOMEM);