mm: kvmalloc does not fallback to vmalloc for incompatible gfp flags
authorMichal Hocko <mhocko@suse.com>
Fri, 8 Jun 2018 00:09:40 +0000 (17:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jun 2018 00:34:38 +0000 (17:34 -0700)
kvmalloc warned about incompatible gfp_mask to catch abusers (mostly
GFP_NOFS) with an intention that this will motivate authors of the code
to fix those.  Linus argues that this just motivates people to do even
more hacks like

if (gfp == GFP_KERNEL)
kvmalloc
else
kmalloc

I haven't seen this happening much (Linus pointed to bucket_lock special
cases an atomic allocation but my git foo hasn't found much more) but it
is true that we can grow those in future.  Therefore Linus suggested to
simply not fallback to vmalloc for incompatible gfp flags and rather
stick with the kmalloc path.

Link: http://lkml.kernel.org/r/20180601115329.27807-1-mhocko@kernel.org
Signed-off-by: Michal Hocko <mhocko@suse.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Tom Herbert <tom@quantonium.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
lib/bucket_locks.c
mm/util.c

index 266a97c5708ba3ad6f35e94ff4c952c1450a2a15..ade3ce6c4af6a0974e6c1d0570b5201491f9debe 100644 (file)
@@ -30,10 +30,7 @@ int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask,
        }
 
        if (sizeof(spinlock_t) != 0) {
-               if (gfpflags_allow_blocking(gfp))
-                       tlocks = kvmalloc(size * sizeof(spinlock_t), gfp);
-               else
-                       tlocks = kmalloc_array(size, sizeof(spinlock_t), gfp);
+               tlocks = kvmalloc_array(size, sizeof(spinlock_t), gfp);
                if (!tlocks)
                        return -ENOMEM;
                for (i = 0; i < size; i++)
index c2d0a7cdb1898dfd1c94efb150cd1c2c9abe18bd..3351659200e658f6f9e71ab52a854531c974910d 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -391,7 +391,8 @@ EXPORT_SYMBOL(vm_mmap);
  * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is
  * preferable to the vmalloc fallback, due to visible performance drawbacks.
  *
- * Any use of gfp flags outside of GFP_KERNEL should be consulted with mm people.
+ * Please note that any use of gfp flags outside of GFP_KERNEL is careful to not
+ * fall back to vmalloc.
  */
 void *kvmalloc_node(size_t size, gfp_t flags, int node)
 {
@@ -402,7 +403,8 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
         * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
         * so the given set of flags has to be compatible.
         */
-       WARN_ON_ONCE((flags & GFP_KERNEL) != GFP_KERNEL);
+       if ((flags & GFP_KERNEL) != GFP_KERNEL)
+               return kmalloc_node(size, flags, node);
 
        /*
         * We want to attempt a large physically contiguous block first because