summaryrefslogtreecommitdiffstats
path: root/module/spl
diff options
context:
space:
mode:
authorChunwei Chen <[email protected]>2014-04-22 16:45:36 +0800
committerBrian Behlendorf <[email protected]>2014-04-25 15:26:52 -0700
commitae16ed992bd0ef5a55b04d9edaaa6456674315f9 (patch)
tree8f0835bcb39f22f18d93baf9504c6bc82fb4d86a /module/spl
parentd6e6e4a98eef03971213044d4277edd56dda61ab (diff)
Fix crash when using ZFS on Ceph rbd
When using __get_free_pages to get high order memory, only the first page's _count will set to 1, other's will be 0. When an internal page get passed into rbd, it will eventully go into tcp_sendpage. There, it will be called with get_page and put_page, and get freed erroneously when _count jump back to 0. The solution to this problem is to use compound page. All pages in a high order compound page share a single _count. So get_page and put_page in tcp_sendpage will not cause _count jump to 0. Signed-off-by: Chunwei Chen <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #251
Diffstat (limited to 'module/spl')
-rw-r--r--module/spl/spl-kmem.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index 55c467b97..b673c2915 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -864,7 +864,8 @@ kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
ASSERT(ISP2(size));
if (skc->skc_flags & KMC_KMEM)
- ptr = (void *)__get_free_pages(flags, get_order(size));
+ ptr = (void *)__get_free_pages(flags | __GFP_COMP,
+ get_order(size));
else
ptr = __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);