summaryrefslogtreecommitdiffstats
path: root/fs/xfs/kmem.c
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-06-17 17:30:23 -0400
committerPaul Moore <pmoore@redhat.com>2014-06-17 17:30:23 -0400
commit170b5910d9fbea79de1bb40df22eda5f98250c0c (patch)
treeca9560e878d2842d45c6f99077d0d8b8f8b0f9ba /fs/xfs/kmem.c
parent47dd0b76ace953bd2c0479076db0d3e3b9594003 (diff)
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
Merge tag 'v3.15' into next
Linux 3.15
Diffstat (limited to 'fs/xfs/kmem.c')
-rw-r--r--fs/xfs/kmem.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index 66a36befc5c..844e288b957 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -65,12 +65,31 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
void *
kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
{
+ unsigned noio_flag = 0;
void *ptr;
+ gfp_t lflags;
ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
if (ptr)
return ptr;
- return vzalloc(size);
+
+ /*
+ * __vmalloc() will allocate data pages and auxillary structures (e.g.
+ * pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context
+ * here. Hence we need to tell memory reclaim that we are in such a
+ * context via PF_MEMALLOC_NOIO to prevent memory reclaim re-entering
+ * the filesystem here and potentially deadlocking.
+ */
+ if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
+ noio_flag = memalloc_noio_save();
+
+ lflags = kmem_flags_convert(flags);
+ ptr = __vmalloc(size, lflags | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+
+ if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
+ memalloc_noio_restore(noio_flag);
+
+ return ptr;
}
void