]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
tracing: Freeable reserved ring buffer
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Tue, 18 Feb 2025 15:09:08 +0000 (00:09 +0900)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Fri, 28 Mar 2025 12:39:28 +0000 (08:39 -0400)
Make the ring buffer on reserved memory to be freeable. This allows us
to free the trace instance on the reserved memory without changing
cmdline and rebooting. Even if we can not change the kernel cmdline
for security reason, we can release the reserved memory for the ring
buffer as free (available) memory.

For example, boot kernel with reserved memory;
"reserve_mem=20M:2M:trace trace_instance=boot_mapped^traceoff@trace"

~ # free
              total        used        free      shared  buff/cache   available
Mem:        1995548       50544     1927568       14964       17436     1911480
Swap:             0           0           0
~ # rmdir /sys/kernel/tracing/instances/boot_mapped/
[   23.704023] Freeing reserve_mem:trace memory: 20476K
~ # free
              total        used        free      shared  buff/cache   available
Mem:        2016024       41844     1956740       14968       17440     1940572
Swap:             0           0           0

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Mike Rapoport <rppt@kernel.org>
Link: https://lore.kernel.org/173989134814.230693.18199312930337815629.stgit@devnote2
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
kernel/trace/trace.c
kernel/trace/trace.h

index 66c1683fa1dda2a209b10562dd322774802df2d8..e7a14bb7d7aae83c4af8d0f33239689ca084fb53 100644 (file)
@@ -9479,6 +9479,9 @@ static void free_trace_buffers(struct trace_array *tr)
 #ifdef CONFIG_TRACER_MAX_TRACE
        free_trace_buffer(&tr->max_buffer);
 #endif
+
+       if (tr->range_addr_start)
+               vunmap((void *)tr->range_addr_start);
 }
 
 static void init_trace_flags_index(struct trace_array *tr)
@@ -9640,6 +9643,7 @@ trace_array_create_systems(const char *name, const char *systems,
        free_cpumask_var(tr->pipe_cpumask);
        free_cpumask_var(tr->tracing_cpumask);
        kfree_const(tr->system_names);
+       kfree(tr->range_name);
        kfree(tr->name);
        kfree(tr);
 
@@ -9766,6 +9770,11 @@ static int __remove_instance(struct trace_array *tr)
        free_trace_buffers(tr);
        clear_tracing_err_log(tr);
 
+       if (tr->range_name) {
+               reserve_mem_release_by_name(tr->range_name);
+               kfree(tr->range_name);
+       }
+
        for (i = 0; i < tr->nr_topts; i++) {
                kfree(tr->topts[i].topts);
        }
@@ -10590,6 +10599,7 @@ __init static void enable_instances(void)
                bool traceoff = false;
                char *flag_delim;
                char *addr_delim;
+               char *rname __free(kfree) = NULL;
 
                tok = strsep(&curr_str, ",");
 
@@ -10646,6 +10656,7 @@ __init static void enable_instances(void)
                                pr_warn("Failed to map boot instance %s to %s\n", name, tok);
                                continue;
                        }
+                       rname = kstrdup(tok, GFP_KERNEL);
                }
 
                if (start) {
@@ -10682,7 +10693,7 @@ __init static void enable_instances(void)
                 */
                if (start) {
                        tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT;
-                       tr->ref++;
+                       tr->range_name = no_free_ptr(rname);
                }
 
                while ((tok = strsep(&curr_str, ","))) {
index 90493220c3624f4893ebbccbc77d1740c1a0106f..0d6efb8a1179c244ffaae07f1e5e71a35d90cbc3 100644 (file)
@@ -348,6 +348,7 @@ struct trace_array {
        unsigned int            mapped;
        unsigned long           range_addr_start;
        unsigned long           range_addr_size;
+       char                    *range_name;
        long                    text_delta;
        void                    *scratch; /* pointer in persistent memory */
        int                     scratch_size;