summaryrefslogtreecommitdiffstats
path: root/module/spl/spl-kmem.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-03-20 15:03:18 -0700
committerBrian Behlendorf <[email protected]>2011-03-20 15:12:08 -0700
commit2092cf68d89a51eb0d6193aeadabb579dfc4b4a0 (patch)
tree832474eb5e585d4853b6a2b6015e2826917efc27 /module/spl/spl-kmem.c
parentcb255ae57278be3206693b5116eff95e612e809a (diff)
Disable vmalloc() direct reclaim
As part of vmalloc() a __pte_alloc_kernel() allocation may occur. This internal allocation does not honor the gfp flags passed to vmalloc(). This means even when vmalloc(GFP_NOFS) is called it is possible that a synchronous reclaim will occur. This reclaim can trigger file IO which can result in a deadlock. This issue can be avoided by explicitly setting PF_MEMALLOC on the process to subvert synchronous reclaim when vmalloc() is called with !__GFP_FS. An example stack of the deadlock can be found here (1), along with the upstream kernel bug (2), and the original bug discussion on the linux-mm mailing list (3). This code can be properly autoconf'ed when the upstream bug is fixed. 1) http://github.com/behlendorf/zfs/issues/labels/Vmalloc#issue/133 2) http://bugzilla.kernel.org/show_bug.cgi?id=30702 3) http://marc.info/?l=linux-mm&m=128942194520631&w=4
Diffstat (limited to 'module/spl/spl-kmem.c')
-rw-r--r--module/spl/spl-kmem.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index 100d674e5..2f533bdf6 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -842,11 +842,31 @@ kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
ASSERT(ISP2(size));
- if (skc->skc_flags & KMC_KMEM)
+ if (skc->skc_flags & KMC_KMEM) {
ptr = (void *)__get_free_pages(flags, get_order(size));
- else
+ } else {
+ /*
+ * As part of vmalloc() an __pte_alloc_kernel() allocation
+ * may occur. This internal allocation does not honor the
+ * gfp flags passed to vmalloc(). This means even when
+ * vmalloc(GFP_NOFS) is called it is possible synchronous
+ * reclaim will occur. This reclaim can trigger file IO
+ * which can result in a deadlock. This issue can be avoided
+ * by explicitly setting PF_MEMALLOC on the process to
+ * subvert synchronous reclaim. The following bug has
+ * been filed at kernel.org to track the issue.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=30702
+ */
+ if (!(flags & __GFP_FS))
+ current->flags |= PF_MEMALLOC;
+
ptr = __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
+ if (!(flags & __GFP_FS))
+ current->flags &= ~PF_MEMALLOC;
+ }
+
/* Resulting allocated memory will be page aligned */
ASSERT(IS_P2ALIGNED(ptr, PAGE_SIZE));