From: Tao Cui <[email protected]>

Creating an instance immediately allocates two full sets of per-cpu
ring buffers, array buffer plus snapshot, about 1.375MB per cpu per set
on the default config, plus the trace_array and its name.  None of it
is charged: neither trace.c nor ring_buffer.c passes __GFP_ACCOUNT,
while user_events in the same directory accounts everything it
allocates.

Instance creation is currently gated by tracefs file permissions
alone, so a
rootful container with the host tracefs bound in can create instances
until the host runs out of memory.  Charge the ring buffer pages and
the trace_array metadata to the creating cgroup.

Signed-off-by: Tao Cui <[email protected]>
---
 kernel/trace/ring_buffer.c | 8 +++++++-
 kernel/trace/trace.c       | 6 +++---
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 1fd28a72e6ee..676c059c112c 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -441,7 +441,13 @@ static struct buffer_data_page *alloc_cpu_data(int cpu, 
int order)
         * gracefully without invoking oom-killer and the system is not
         * destabilized.
         */
-       mflags = GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_COMP | __GFP_ZERO;
+       /*
+        * The subbuffers are charged to the memcg of whoever caused the
+        * allocation: the creator of a trace instance, or root at boot for
+        * the global trace.
+        */
+       mflags = GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_COMP | __GFP_ZERO |
+                 __GFP_ACCOUNT;
 
        page = alloc_pages_node(cpu_to_node(cpu), mflags, order);
        if (!page)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e8c4efa8107b..04b60b9cc4f5 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8693,11 +8693,11 @@ trace_array_create_systems(const char *name, const char 
*systems,
        int ret;
 
        ret = -ENOMEM;
-       tr = kzalloc_obj(*tr);
+       tr = kzalloc_obj(*tr, GFP_KERNEL_ACCOUNT);
        if (!tr)
                return ERR_PTR(ret);
 
-       tr->name = kstrdup(name, GFP_KERNEL);
+       tr->name = kstrdup(name, GFP_KERNEL_ACCOUNT);
        if (!tr->name)
                goto out_free_tr;
 
@@ -8708,7 +8708,7 @@ trace_array_create_systems(const char *name, const char 
*systems,
                goto out_free_tr;
 
        if (systems) {
-               tr->system_names = kstrdup_const(systems, GFP_KERNEL);
+               tr->system_names = kstrdup_const(systems, GFP_KERNEL_ACCOUNT);
                if (!tr->system_names)
                        goto out_free_tr;
        }
-- 
2.43.0


Reply via email to