]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: fall back to vmalloc when allocation log vector buffers
authorDave Chinner <dchinner@redhat.com>
Wed, 7 Mar 2018 01:03:28 +0000 (17:03 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 12 Mar 2018 03:27:55 +0000 (20:27 -0700)
When using large directory blocks, we regularly see memory
allocations of >64k being made for the shadow log vector buffer.
When we are under memory pressure, kmalloc() may not be able to find
contiguous memory chunks large enough to satisfy these allocations
easily, and if memory is fragmented we can potentially stall here.

TO avoid this problem, switch the log vector buffer allocation to
use kmem_alloc_large(). This will allow failed allocations to fall
back to vmalloc and so remove the dependency on large contiguous
regions of memory being available. This should prevent slowdowns
and potential stalls when memory is low and/or fragmented.

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/kmem.c
fs/xfs/kmem.h
fs/xfs/xfs_log_cil.c

index 393b6849aeb31991ed43808ff213fb3cadba00d0..7bace03dc9dcfdb816347127066288aeda286470 100644 (file)
@@ -46,13 +46,13 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
 }
 
 void *
-kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
+kmem_alloc_large(size_t size, xfs_km_flags_t flags)
 {
        unsigned nofs_flag = 0;
        void    *ptr;
        gfp_t   lflags;
 
-       ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
+       ptr = kmem_alloc(size, flags | KM_MAYFAIL);
        if (ptr)
                return ptr;
 
@@ -67,7 +67,7 @@ kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
                nofs_flag = memalloc_nofs_save();
 
        lflags = kmem_flags_convert(flags);
-       ptr = __vmalloc(size, lflags | __GFP_ZERO, PAGE_KERNEL);
+       ptr = __vmalloc(size, lflags, PAGE_KERNEL);
 
        if (flags & KM_NOFS)
                memalloc_nofs_restore(nofs_flag);
index 4b87472f35bc9400c147ce811e2712b45a7717bb..6023b594ead71a42fdfc2d81c44e79bb914083ba 100644 (file)
@@ -71,7 +71,7 @@ kmem_flags_convert(xfs_km_flags_t flags)
 }
 
 extern void *kmem_alloc(size_t, xfs_km_flags_t);
-extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
+extern void *kmem_alloc_large(size_t size, xfs_km_flags_t);
 extern void *kmem_realloc(const void *, size_t, xfs_km_flags_t);
 static inline void  kmem_free(const void *ptr)
 {
@@ -85,6 +85,12 @@ kmem_zalloc(size_t size, xfs_km_flags_t flags)
        return kmem_alloc(size, flags | KM_ZERO);
 }
 
+static inline void *
+kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
+{
+       return kmem_alloc_large(size, flags | KM_ZERO);
+}
+
 /*
  * Zone interfaces
  */
index 43aa42a3a5d319fffff98417bff98055083f1a75..cb376ac8a595144e4db76db6cdf61931649b433e 100644 (file)
@@ -202,7 +202,7 @@ xlog_cil_alloc_shadow_bufs(
                         */
                        kmem_free(lip->li_lv_shadow);
 
-                       lv = kmem_alloc(buf_size, KM_SLEEP|KM_NOFS);
+                       lv = kmem_alloc_large(buf_size, KM_SLEEP | KM_NOFS);
                        memset(lv, 0, xlog_cil_iovec_space(niovecs));
 
                        lv->lv_item = lip;