Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25ff17e8 authored by Omar Sandoval's avatar Omar Sandoval Committed by David Sterba
Browse files

Btrfs: use memalloc_nofs and kvzalloc() for free space tree bitmaps



First, instead of open-coding the vmalloc() fallback, use the new
kvzalloc() helper. Second, use memalloc_nofs_{save,restore}() instead of
GFP_NOFS, as vmalloc() uses some GFP_KERNEL allocations internally which
could lead to deadlocks.

Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4b5faeac
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
 */

#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/sched/mm.h>
#include "ctree.h"
#include "disk-io.h"
#include "locking.h"
@@ -153,21 +153,21 @@ static inline u32 free_space_bitmap_size(u64 size, u32 sectorsize)

static u8 *alloc_bitmap(u32 bitmap_size)
{
	void *mem;
	u8 *ret;
	unsigned int nofs_flag;

	/*
	 * The allocation size varies, observed numbers were < 4K up to 16K.
	 * Using vmalloc unconditionally would be too heavy, we'll try
	 * contiguous allocations first.
	 * GFP_NOFS doesn't work with kvmalloc(), but we really can't recurse
	 * into the filesystem as the free space bitmap can be modified in the
	 * critical section of a transaction commit.
	 *
	 * TODO: push the memalloc_nofs_{save,restore}() to the caller where we
	 * know that recursion is unsafe.
	 */
	if  (bitmap_size <= PAGE_SIZE)
		return kzalloc(bitmap_size, GFP_NOFS);

	mem = kzalloc(bitmap_size, GFP_NOFS | __GFP_NOWARN);
	if (mem)
		return mem;

	return __vmalloc(bitmap_size, GFP_NOFS | __GFP_ZERO, PAGE_KERNEL);
	nofs_flag = memalloc_nofs_save();
	ret = kvzalloc(bitmap_size, GFP_KERNEL);
	memalloc_nofs_restore(nofs_flag);
	return ret;
}

int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,