Skip to content

Commit 065e63f

Browse files
committed
tracing: Only have rmmod clear buffers that its events were active in
Currently, when a module event is enabled, when that module is removed, it clears all ring buffers. This is to prevent another module from being loaded and having one of its trace event IDs from reusing a trace event ID of the removed module. This could cause undesirable effects as the trace event of the new module would be using its own processing algorithms to process raw data of another event. To prevent this, when a module is loaded, if any of its events have been used (signified by the WAS_ENABLED event call flag, which is never cleared), all ring buffers are cleared, just in case any one of them contains event data of the removed event. The problem is, there's no reason to clear all ring buffers if only one (or less than all of them) uses one of the events. Instead, only clear the ring buffers that recorded the events of a module that is being removed. To do this, instead of keeping the WAS_ENABLED flag with the trace event call, move it to the per instance (per ring buffer) event file descriptor. The event file descriptor maps each event to a separate ring buffer instance. Then when the module is removed, only the ring buffers that activated one of the module's events get cleared. The rest are not touched. Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 60361e1 commit 065e63f

File tree

4 files changed

+14
-13
lines changed

4 files changed

+14
-13
lines changed

include/linux/trace_events.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ enum {
217217
TRACE_EVENT_FL_CAP_ANY_BIT,
218218
TRACE_EVENT_FL_NO_SET_FILTER_BIT,
219219
TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
220-
TRACE_EVENT_FL_WAS_ENABLED_BIT,
221220
TRACE_EVENT_FL_TRACEPOINT_BIT,
222221
TRACE_EVENT_FL_KPROBE_BIT,
223222
TRACE_EVENT_FL_UPROBE_BIT,
@@ -229,9 +228,6 @@ enum {
229228
* CAP_ANY - Any user can enable for perf
230229
* NO_SET_FILTER - Set when filter has error and is to be ignored
231230
* IGNORE_ENABLE - For trace internal events, do not enable with debugfs file
232-
* WAS_ENABLED - Set and stays set when an event was ever enabled
233-
* (used for module unloading, if a module event is enabled,
234-
* it is best to clear the buffers that used it).
235231
* TRACEPOINT - Event is a tracepoint
236232
* KPROBE - Event is a kprobe
237233
* UPROBE - Event is a uprobe
@@ -241,7 +237,6 @@ enum {
241237
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
242238
TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
243239
TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
244-
TRACE_EVENT_FL_WAS_ENABLED = (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT),
245240
TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
246241
TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
247242
TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
@@ -306,6 +301,7 @@ enum {
306301
EVENT_FILE_FL_TRIGGER_MODE_BIT,
307302
EVENT_FILE_FL_TRIGGER_COND_BIT,
308303
EVENT_FILE_FL_PID_FILTER_BIT,
304+
EVENT_FILE_FL_WAS_ENABLED_BIT,
309305
};
310306

311307
/*
@@ -321,6 +317,7 @@ enum {
321317
* TRIGGER_MODE - When set, invoke the triggers associated with the event
322318
* TRIGGER_COND - When set, one or more triggers has an associated filter
323319
* PID_FILTER - When set, the event is filtered based on pid
320+
* WAS_ENABLED - Set when enabled to know to clear trace on module removal
324321
*/
325322
enum {
326323
EVENT_FILE_FL_ENABLED = (1 << EVENT_FILE_FL_ENABLED_BIT),
@@ -333,6 +330,7 @@ enum {
333330
EVENT_FILE_FL_TRIGGER_MODE = (1 << EVENT_FILE_FL_TRIGGER_MODE_BIT),
334331
EVENT_FILE_FL_TRIGGER_COND = (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
335332
EVENT_FILE_FL_PID_FILTER = (1 << EVENT_FILE_FL_PID_FILTER_BIT),
333+
EVENT_FILE_FL_WAS_ENABLED = (1 << EVENT_FILE_FL_WAS_ENABLED_BIT),
336334
};
337335

338336
struct trace_event_file {

kernel/trace/trace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,9 @@ void tracing_reset_all_online_cpus(void)
17021702
struct trace_array *tr;
17031703

17041704
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
1705+
if (!tr->clear_trace)
1706+
continue;
1707+
tr->clear_trace = false;
17051708
tracing_reset_online_cpus(&tr->trace_buffer);
17061709
#ifdef CONFIG_TRACER_MAX_TRACE
17071710
tracing_reset_online_cpus(&tr->max_buffer);

kernel/trace/trace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ struct trace_array {
245245
int stop_count;
246246
int clock_id;
247247
int nr_topts;
248+
bool clear_trace;
248249
struct tracer *current_trace;
249250
unsigned int trace_flags;
250251
unsigned char trace_flags_index[TRACE_FLAGS_MAX_SIZE];

kernel/trace/trace_events.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
466466
set_bit(EVENT_FILE_FL_ENABLED_BIT, &file->flags);
467467

468468
/* WAS_ENABLED gets set but never cleared. */
469-
call->flags |= TRACE_EVENT_FL_WAS_ENABLED;
469+
set_bit(EVENT_FILE_FL_WAS_ENABLED_BIT, &file->flags);
470470
}
471471
break;
472472
}
@@ -2058,6 +2058,10 @@ static void event_remove(struct trace_event_call *call)
20582058
do_for_each_event_file(tr, file) {
20592059
if (file->event_call != call)
20602060
continue;
2061+
2062+
if (file->flags & EVENT_FILE_FL_WAS_ENABLED)
2063+
tr->clear_trace = true;
2064+
20612065
ftrace_event_enable_disable(file, 0);
20622066
/*
20632067
* The do_for_each_event_file() is
@@ -2396,15 +2400,11 @@ static void trace_module_add_events(struct module *mod)
23962400
static void trace_module_remove_events(struct module *mod)
23972401
{
23982402
struct trace_event_call *call, *p;
2399-
bool clear_trace = false;
24002403

24012404
down_write(&trace_event_sem);
24022405
list_for_each_entry_safe(call, p, &ftrace_events, list) {
2403-
if (call->mod == mod) {
2404-
if (call->flags & TRACE_EVENT_FL_WAS_ENABLED)
2405-
clear_trace = true;
2406+
if (call->mod == mod)
24062407
__trace_remove_event_call(call);
2407-
}
24082408
}
24092409
up_write(&trace_event_sem);
24102410

@@ -2416,8 +2416,7 @@ static void trace_module_remove_events(struct module *mod)
24162416
* over from this module may be passed to the new module events and
24172417
* unexpected results may occur.
24182418
*/
2419-
if (clear_trace)
2420-
tracing_reset_all_online_cpus();
2419+
tracing_reset_all_online_cpus();
24212420
}
24222421

24232422
static int trace_module_notify(struct notifier_block *self,

0 commit comments

Comments
 (0)