]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fork: define a local GFP_VMAP_STACK
authorLinus Walleij <linus.walleij@linaro.org>
Fri, 9 May 2025 07:25:09 +0000 (09:25 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 10 Jul 2025 05:57:50 +0000 (22:57 -0700)
The current allocation of VMAP stack memory is using (THREADINFO_GFP &
~__GFP_ACCOUNT) which is a complicated way of saying (GFP_KERNEL |
__GFP_ZERO):

<linux/thread_info.h>:
define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_ZERO)
<linux/gfp_types.h>:
define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT)

This is an unfortunate side-effect of independent changes blurring the
picture:

commit 19809c2da28aee5860ad9a2eff760730a0710df0 changed (THREADINFO_GFP |
__GFP_HIGHMEM) to just THREADINFO_GFP since highmem became implicit.

commit 9b6f7e163cd0f468d1b9696b785659d3c27c8667 then added stack caching
and rewrote the allocation to (THREADINFO_GFP & ~__GFP_ACCOUNT) as cached
stacks need to be accounted separately.  However that code, when it
eventually accounts the memory does this:

  ret = memcg_kmem_charge(vm->pages[i], GFP_KERNEL, 0)

so the memory is charged as a GFP_KERNEL allocation.

Define a unique GFP_VMAP_STACK to use
GFP_KERNEL | __GFP_ZERO and move the comment there.

Link: https://lkml.kernel.org/r/20250509-gfp-stack-v1-1-82f6f7efc210@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reported-by: Mateusz Guzik <mjguzik@gmail.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
kernel/fork.c

index 5fd893c907a5e620b9ef2f7d0d08e84e751d6cae..6616d173307a92a238fd5b8b74c97b90d551c968 100644 (file)
@@ -201,6 +201,12 @@ static inline void free_task_struct(struct task_struct *tsk)
  */
 #define NR_CACHED_STACKS 2
 static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);
+/*
+ * Allocated stacks are cached and later reused by new threads, so memcg
+ * accounting is performed by the code assigning/releasing stacks to tasks.
+ * We need a zeroed memory without __GFP_ACCOUNT.
+ */
+#define GFP_VMAP_STACK (GFP_KERNEL | __GFP_ZERO)
 
 struct vm_stack {
        struct rcu_head rcu;
@@ -307,13 +313,8 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node)
                return 0;
        }
 
-       /*
-        * Allocated stacks are cached and later reused by new threads,
-        * so memcg accounting is performed manually on assigning/releasing
-        * stacks to tasks. Drop __GFP_ACCOUNT.
-        */
        stack = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN,
-                                    THREADINFO_GFP & ~__GFP_ACCOUNT,
+                                    GFP_VMAP_STACK,
                                     node, __builtin_return_address(0));
        if (!stack)
                return -ENOMEM;