Commit 6b3a4d60 authored by Shilong Wang's avatar Shilong Wang Committed by Chris Mason

Btrfs: fix allocationg memory failure for btrfsic_state structure

size of @btrfsic_state needs more than 2M, it is very likely to
fail allocating memory using kzalloc(). see following mesage:

[91428.902148] Call Trace:
[<ffffffff816f6e0f>] dump_stack+0x4d/0x66
[<ffffffff811b1c7f>] warn_alloc_failed+0xff/0x170
[<ffffffff811b66e1>] __alloc_pages_nodemask+0x951/0xc30
[<ffffffff811fd9da>] alloc_pages_current+0x11a/0x1f0
[<ffffffff811b1e0b>] ? alloc_kmem_pages+0x3b/0xf0
[<ffffffff811b1e0b>] alloc_kmem_pages+0x3b/0xf0
[<ffffffff811d1018>] kmalloc_order+0x18/0x50
[<ffffffff811d1074>] kmalloc_order_trace+0x24/0x140
[<ffffffffa06c097b>] btrfsic_mount+0x8b/0xae0 [btrfs]
[<ffffffff810af555>] ? check_preempt_curr+0x85/0xa0
[<ffffffff810b2de3>] ? try_to_wake_up+0x103/0x430
[<ffffffffa063d200>] open_ctree+0x1bd0/0x2130 [btrfs]
[<ffffffffa060fdde>] btrfs_mount+0x62e/0x8b0 [btrfs]
[<ffffffff811fd9da>] ? alloc_pages_current+0x11a/0x1f0
[<ffffffff811b0a5e>] ? __get_free_pages+0xe/0x50
[<ffffffff81230429>] mount_fs+0x39/0x1b0
[<ffffffff812509fb>] vfs_kern_mount+0x6b/0x150
[<ffffffff812537fb>] do_mount+0x27b/0xc30
[<ffffffff811b0a5e>] ? __get_free_pages+0xe/0x50
[<ffffffff812544f6>] SyS_mount+0x96/0xf0
[<ffffffff81701970>] system_call_fastpath+0x16/0x1b

Since we are allocating memory for hash table array, so
it will be good if we could allocate continuous pages here.

Fix this problem by firstly trying kzalloc(), if we fail,
use vzalloc() instead.
Signed-off-by: default avatarWang Shilong <wangshilong1991@gmail.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent e6eb4314
...@@ -3130,11 +3130,14 @@ int btrfsic_mount(struct btrfs_root *root, ...@@ -3130,11 +3130,14 @@ int btrfsic_mount(struct btrfs_root *root,
root->sectorsize, PAGE_CACHE_SIZE); root->sectorsize, PAGE_CACHE_SIZE);
return -1; return -1;
} }
state = kzalloc(sizeof(*state), GFP_NOFS); state = kzalloc(sizeof(*state), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
if (NULL == state) { if (!state) {
printk(KERN_INFO "btrfs check-integrity: kmalloc() failed!\n"); state = vzalloc(sizeof(*state));
if (!state) {
printk(KERN_INFO "btrfs check-integrity: vzalloc() failed!\n");
return -1; return -1;
} }
}
if (!btrfsic_is_initialized) { if (!btrfsic_is_initialized) {
mutex_init(&btrfsic_mutex); mutex_init(&btrfsic_mutex);
...@@ -3277,5 +3280,8 @@ void btrfsic_unmount(struct btrfs_root *root, ...@@ -3277,5 +3280,8 @@ void btrfsic_unmount(struct btrfs_root *root,
mutex_unlock(&btrfsic_mutex); mutex_unlock(&btrfsic_mutex);
if (is_vmalloc_addr(state))
vfree(state);
else
kfree(state); kfree(state);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment