Skip to content

Commit d914ba3

Browse files
Joel Fernandesrostedt
authored andcommitted
tracing: Add support for recording tgid of tasks
Inorder to support recording of tgid, the following changes are made: * Introduce a new API (tracing_record_taskinfo) to additionally record the tgid along with the task's comm at the same time. This has has the benefit of not setting trace_cmdline_save before all the information for a task is saved. * Add a new API tracing_record_taskinfo_sched_switch to record task information for 2 tasks at a time (previous and next) and use it from sched_switch probe. * Preserve the old API (tracing_record_cmdline) and create it as a wrapper around the new one so that existing callers aren't affected. * Reuse the existing sched_switch and sched_wakeup probes to record tgid information and add a new option 'record-tgid' to enable recording of tgid When record-tgid option isn't enabled to being with, we take care to make sure that there's isn't memory or runtime overhead. Link: http://lkml.kernel.org/r/20170627020155.5139-1-joelaf@google.com Cc: kernel-team@android.com Cc: Ingo Molnar <mingo@redhat.com> Tested-by: Michael Sartain <mikesart@gmail.com> Signed-off-by: Joel Fernandes <joelaf@google.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 83dd149 commit d914ba3

File tree

5 files changed

+213
-26
lines changed

5 files changed

+213
-26
lines changed

include/linux/trace_events.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,15 @@ trace_event_buffer_lock_reserve(struct ring_buffer **current_buffer,
151151
int type, unsigned long len,
152152
unsigned long flags, int pc);
153153

154-
void tracing_record_cmdline(struct task_struct *tsk);
154+
#define TRACE_RECORD_CMDLINE BIT(0)
155+
#define TRACE_RECORD_TGID BIT(1)
156+
157+
void tracing_record_taskinfo(struct task_struct *task, int flags);
158+
void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
159+
struct task_struct *next, int flags);
160+
161+
void tracing_record_cmdline(struct task_struct *task);
162+
void tracing_record_tgid(struct task_struct *task);
155163

156164
int trace_output_call(struct trace_iterator *iter, char *name, char *fmt, ...);
157165

@@ -290,6 +298,7 @@ struct trace_subsystem_dir;
290298
enum {
291299
EVENT_FILE_FL_ENABLED_BIT,
292300
EVENT_FILE_FL_RECORDED_CMD_BIT,
301+
EVENT_FILE_FL_RECORDED_TGID_BIT,
293302
EVENT_FILE_FL_FILTERED_BIT,
294303
EVENT_FILE_FL_NO_SET_FILTER_BIT,
295304
EVENT_FILE_FL_SOFT_MODE_BIT,
@@ -303,6 +312,7 @@ enum {
303312
* Event file flags:
304313
* ENABLED - The event is enabled
305314
* RECORDED_CMD - The comms should be recorded at sched_switch
315+
* RECORDED_TGID - The tgids should be recorded at sched_switch
306316
* FILTERED - The event has a filter attached
307317
* NO_SET_FILTER - Set when filter has error and is to be ignored
308318
* SOFT_MODE - The event is enabled/disabled by SOFT_DISABLED
@@ -315,6 +325,7 @@ enum {
315325
enum {
316326
EVENT_FILE_FL_ENABLED = (1 << EVENT_FILE_FL_ENABLED_BIT),
317327
EVENT_FILE_FL_RECORDED_CMD = (1 << EVENT_FILE_FL_RECORDED_CMD_BIT),
328+
EVENT_FILE_FL_RECORDED_TGID = (1 << EVENT_FILE_FL_RECORDED_TGID_BIT),
318329
EVENT_FILE_FL_FILTERED = (1 << EVENT_FILE_FL_FILTERED_BIT),
319330
EVENT_FILE_FL_NO_SET_FILTER = (1 << EVENT_FILE_FL_NO_SET_FILTER_BIT),
320331
EVENT_FILE_FL_SOFT_MODE = (1 << EVENT_FILE_FL_SOFT_MODE_BIT),

kernel/trace/trace.c

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ dummy_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
8787
* tracing is active, only save the comm when a trace event
8888
* occurred.
8989
*/
90-
static DEFINE_PER_CPU(bool, trace_cmdline_save);
90+
static DEFINE_PER_CPU(bool, trace_taskinfo_save);
9191

9292
/*
9393
* Kill all tracing for good (never come back).
@@ -790,7 +790,7 @@ EXPORT_SYMBOL_GPL(tracing_on);
790790
static __always_inline void
791791
__buffer_unlock_commit(struct ring_buffer *buffer, struct ring_buffer_event *event)
792792
{
793-
__this_cpu_write(trace_cmdline_save, true);
793+
__this_cpu_write(trace_taskinfo_save, true);
794794

795795
/* If this is the temp buffer, we need to commit fully */
796796
if (this_cpu_read(trace_buffered_event) == event) {
@@ -1709,6 +1709,8 @@ void tracing_reset_all_online_cpus(void)
17091709
}
17101710
}
17111711

1712+
static int *tgid_map;
1713+
17121714
#define SAVED_CMDLINES_DEFAULT 128
17131715
#define NO_CMDLINE_MAP UINT_MAX
17141716
static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED;
@@ -1722,7 +1724,7 @@ struct saved_cmdlines_buffer {
17221724
static struct saved_cmdlines_buffer *savedcmd;
17231725

17241726
/* temporary disable recording */
1725-
static atomic_t trace_record_cmdline_disabled __read_mostly;
1727+
static atomic_t trace_record_taskinfo_disabled __read_mostly;
17261728

17271729
static inline char *get_saved_cmdlines(int idx)
17281730
{
@@ -1990,16 +1992,87 @@ void trace_find_cmdline(int pid, char comm[])
19901992
preempt_enable();
19911993
}
19921994

1993-
void tracing_record_cmdline(struct task_struct *tsk)
1995+
int trace_find_tgid(int pid)
1996+
{
1997+
if (unlikely(!tgid_map || !pid || pid > PID_MAX_DEFAULT))
1998+
return 0;
1999+
2000+
return tgid_map[pid];
2001+
}
2002+
2003+
static int trace_save_tgid(struct task_struct *tsk)
19942004
{
1995-
if (atomic_read(&trace_record_cmdline_disabled) || !tracing_is_on())
2005+
if (unlikely(!tgid_map || !tsk->pid || tsk->pid > PID_MAX_DEFAULT))
2006+
return 0;
2007+
2008+
tgid_map[tsk->pid] = tsk->tgid;
2009+
return 1;
2010+
}
2011+
2012+
static bool tracing_record_taskinfo_skip(int flags)
2013+
{
2014+
if (unlikely(!(flags & (TRACE_RECORD_CMDLINE | TRACE_RECORD_TGID))))
2015+
return true;
2016+
if (atomic_read(&trace_record_taskinfo_disabled) || !tracing_is_on())
2017+
return true;
2018+
if (!__this_cpu_read(trace_taskinfo_save))
2019+
return true;
2020+
return false;
2021+
}
2022+
2023+
/**
2024+
* tracing_record_taskinfo - record the task info of a task
2025+
*
2026+
* @task - task to record
2027+
* @flags - TRACE_RECORD_CMDLINE for recording comm
2028+
* - TRACE_RECORD_TGID for recording tgid
2029+
*/
2030+
void tracing_record_taskinfo(struct task_struct *task, int flags)
2031+
{
2032+
if (tracing_record_taskinfo_skip(flags))
2033+
return;
2034+
if ((flags & TRACE_RECORD_CMDLINE) && !trace_save_cmdline(task))
2035+
return;
2036+
if ((flags & TRACE_RECORD_TGID) && !trace_save_tgid(task))
19962037
return;
19972038

1998-
if (!__this_cpu_read(trace_cmdline_save))
2039+
__this_cpu_write(trace_taskinfo_save, false);
2040+
}
2041+
2042+
/**
2043+
* tracing_record_taskinfo_sched_switch - record task info for sched_switch
2044+
*
2045+
* @prev - previous task during sched_switch
2046+
* @next - next task during sched_switch
2047+
* @flags - TRACE_RECORD_CMDLINE for recording comm
2048+
* TRACE_RECORD_TGID for recording tgid
2049+
*/
2050+
void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
2051+
struct task_struct *next, int flags)
2052+
{
2053+
if (tracing_record_taskinfo_skip(flags))
19992054
return;
20002055

2001-
if (trace_save_cmdline(tsk))
2002-
__this_cpu_write(trace_cmdline_save, false);
2056+
if ((flags & TRACE_RECORD_CMDLINE) &&
2057+
(!trace_save_cmdline(prev) || !trace_save_cmdline(next)))
2058+
return;
2059+
2060+
if ((flags & TRACE_RECORD_TGID) &&
2061+
(!trace_save_tgid(prev) || !trace_save_tgid(next)))
2062+
return;
2063+
2064+
__this_cpu_write(trace_taskinfo_save, false);
2065+
}
2066+
2067+
/* Helpers to record a specific task information */
2068+
void tracing_record_cmdline(struct task_struct *task)
2069+
{
2070+
tracing_record_taskinfo(task, TRACE_RECORD_CMDLINE);
2071+
}
2072+
2073+
void tracing_record_tgid(struct task_struct *task)
2074+
{
2075+
tracing_record_taskinfo(task, TRACE_RECORD_TGID);
20032076
}
20042077

20052078
/*
@@ -3144,7 +3217,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
31443217
#endif
31453218

31463219
if (!iter->snapshot)
3147-
atomic_inc(&trace_record_cmdline_disabled);
3220+
atomic_inc(&trace_record_taskinfo_disabled);
31483221

31493222
if (*pos != iter->pos) {
31503223
iter->ent = NULL;
@@ -3189,7 +3262,7 @@ static void s_stop(struct seq_file *m, void *p)
31893262
#endif
31903263

31913264
if (!iter->snapshot)
3192-
atomic_dec(&trace_record_cmdline_disabled);
3265+
atomic_dec(&trace_record_taskinfo_disabled);
31933266

31943267
trace_access_unlock(iter->cpu_file);
31953268
trace_event_read_unlock();
@@ -4236,6 +4309,18 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
42364309
if (mask == TRACE_ITER_RECORD_CMD)
42374310
trace_event_enable_cmd_record(enabled);
42384311

4312+
if (mask == TRACE_ITER_RECORD_TGID) {
4313+
if (!tgid_map)
4314+
tgid_map = kzalloc((PID_MAX_DEFAULT + 1) * sizeof(*tgid_map),
4315+
GFP_KERNEL);
4316+
if (!tgid_map) {
4317+
tr->trace_flags &= ~TRACE_ITER_RECORD_TGID;
4318+
return -ENOMEM;
4319+
}
4320+
4321+
trace_event_enable_tgid_record(enabled);
4322+
}
4323+
42394324
if (mask == TRACE_ITER_EVENT_FORK)
42404325
trace_event_follow_fork(tr, enabled);
42414326

kernel/trace/trace.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,9 @@ void set_graph_array(struct trace_array *tr);
640640

641641
void tracing_start_cmdline_record(void);
642642
void tracing_stop_cmdline_record(void);
643+
void tracing_start_tgid_record(void);
644+
void tracing_stop_tgid_record(void);
645+
643646
int register_tracer(struct tracer *type);
644647
int is_tracing_stopped(void);
645648

@@ -700,6 +703,7 @@ static inline void __trace_stack(struct trace_array *tr, unsigned long flags,
700703
extern u64 ftrace_now(int cpu);
701704

702705
extern void trace_find_cmdline(int pid, char comm[]);
706+
extern int trace_find_tgid(int pid);
703707
extern void trace_event_follow_fork(struct trace_array *tr, bool enable);
704708

705709
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -1124,6 +1128,7 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
11241128
C(CONTEXT_INFO, "context-info"), /* Print pid/cpu/time */ \
11251129
C(LATENCY_FMT, "latency-format"), \
11261130
C(RECORD_CMD, "record-cmd"), \
1131+
C(RECORD_TGID, "record-tgid"), \
11271132
C(OVERWRITE, "overwrite"), \
11281133
C(STOP_ON_FREE, "disable_on_free"), \
11291134
C(IRQ_INFO, "irq-info"), \
@@ -1440,6 +1445,8 @@ struct ftrace_event_field *
14401445
trace_find_event_field(struct trace_event_call *call, char *name);
14411446

14421447
extern void trace_event_enable_cmd_record(bool enable);
1448+
extern void trace_event_enable_tgid_record(bool enable);
1449+
14431450
extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
14441451
extern int event_trace_del_tracer(struct trace_array *tr);
14451452

kernel/trace/trace_events.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,28 @@ void trace_event_enable_cmd_record(bool enable)
343343
mutex_unlock(&event_mutex);
344344
}
345345

346+
void trace_event_enable_tgid_record(bool enable)
347+
{
348+
struct trace_event_file *file;
349+
struct trace_array *tr;
350+
351+
mutex_lock(&event_mutex);
352+
do_for_each_event_file(tr, file) {
353+
if (!(file->flags & EVENT_FILE_FL_ENABLED))
354+
continue;
355+
356+
if (enable) {
357+
tracing_start_tgid_record();
358+
set_bit(EVENT_FILE_FL_RECORDED_TGID_BIT, &file->flags);
359+
} else {
360+
tracing_stop_tgid_record();
361+
clear_bit(EVENT_FILE_FL_RECORDED_TGID_BIT,
362+
&file->flags);
363+
}
364+
} while_for_each_event_file();
365+
mutex_unlock(&event_mutex);
366+
}
367+
346368
static int __ftrace_event_enable_disable(struct trace_event_file *file,
347369
int enable, int soft_disable)
348370
{
@@ -381,6 +403,12 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
381403
tracing_stop_cmdline_record();
382404
clear_bit(EVENT_FILE_FL_RECORDED_CMD_BIT, &file->flags);
383405
}
406+
407+
if (file->flags & EVENT_FILE_FL_RECORDED_TGID) {
408+
tracing_stop_tgid_record();
409+
clear_bit(EVENT_FILE_FL_RECORDED_CMD_BIT, &file->flags);
410+
}
411+
384412
call->class->reg(call, TRACE_REG_UNREGISTER, file);
385413
}
386414
/* If in SOFT_MODE, just set the SOFT_DISABLE_BIT, else clear it */
@@ -407,18 +435,30 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
407435
}
408436

409437
if (!(file->flags & EVENT_FILE_FL_ENABLED)) {
438+
bool cmd = false, tgid = false;
410439

411440
/* Keep the event disabled, when going to SOFT_MODE. */
412441
if (soft_disable)
413442
set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags);
414443

415444
if (tr->trace_flags & TRACE_ITER_RECORD_CMD) {
445+
cmd = true;
416446
tracing_start_cmdline_record();
417447
set_bit(EVENT_FILE_FL_RECORDED_CMD_BIT, &file->flags);
418448
}
449+
450+
if (tr->trace_flags & TRACE_ITER_RECORD_TGID) {
451+
tgid = true;
452+
tracing_start_tgid_record();
453+
set_bit(EVENT_FILE_FL_RECORDED_TGID_BIT, &file->flags);
454+
}
455+
419456
ret = call->class->reg(call, TRACE_REG_REGISTER, file);
420457
if (ret) {
421-
tracing_stop_cmdline_record();
458+
if (cmd)
459+
tracing_stop_cmdline_record();
460+
if (tgid)
461+
tracing_stop_tgid_record();
422462
pr_info("event trace: Could not enable event "
423463
"%s\n", trace_event_name(call));
424464
break;

0 commit comments

Comments
 (0)