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: Omar Sandoval <osandov@fb.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
4b5faeac46
commit
25ff17e82f
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue