]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/util.c
mm: fix global NR_SLAB_.*CLAIMABLE counter reads
[karo-tx-linux.git] / mm / util.c
index 26be6407abd7efe452a585d341a8d7e5b53d2b32..9ecddf568fe30e5cf1fba6db8eda3b7abe96d379 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -83,6 +83,8 @@ EXPORT_SYMBOL(kstrdup_const);
  * @s: the string to duplicate
  * @max: read at most @max chars from @s
  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ *
+ * Note: Use kmemdup_nul() instead if the size is known exactly.
  */
 char *kstrndup(const char *s, size_t max, gfp_t gfp)
 {
@@ -120,6 +122,28 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
 }
 EXPORT_SYMBOL(kmemdup);
 
+/**
+ * kmemdup_nul - Create a NUL-terminated string from unterminated data
+ * @s: The data to stringify
+ * @len: The size of the data
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ */
+char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
+{
+       char *buf;
+
+       if (!s)
+               return NULL;
+
+       buf = kmalloc_track_caller(len + 1, gfp);
+       if (buf) {
+               memcpy(buf, s, len);
+               buf[len] = '\0';
+       }
+       return buf;
+}
+EXPORT_SYMBOL(kmemdup_nul);
+
 /**
  * memdup_user - duplicate memory region from user space
  *
@@ -339,9 +363,9 @@ EXPORT_SYMBOL(vm_mmap);
  * Uses kmalloc to get the memory but if the allocation fails then falls back
  * to the vmalloc allocator. Use kvfree for freeing the memory.
  *
- * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported. __GFP_REPEAT
- * is supported only for large (>32kB) allocations, and it should be used only if
- * kmalloc is preferable to the vmalloc fallback, due to visible performance drawbacks.
+ * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported.
+ * __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.
  */
@@ -366,13 +390,7 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
        if (size > PAGE_SIZE) {
                kmalloc_flags |= __GFP_NOWARN;
 
-               /*
-                * We have to override __GFP_REPEAT by __GFP_NORETRY for !costly
-                * requests because there is no other way to tell the allocator
-                * that we want to fail rather than retry endlessly.
-                */
-               if (!(kmalloc_flags & __GFP_REPEAT) ||
-                               (size <= PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
+               if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL))
                        kmalloc_flags |= __GFP_NORETRY;
        }
 
@@ -615,7 +633,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
                 * which are reclaimable, under pressure.  The dentry
                 * cache and most inode caches should fall into this
                 */
-               free += global_page_state(NR_SLAB_RECLAIMABLE);
+               free += global_node_page_state(NR_SLAB_RECLAIMABLE);
 
                /*
                 * Leave reserved pages. The pages are not for anonymous pages.