Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tracing: Simplify & fix saved_tgids logic

The tgid_map array records a mapping from pid to tgid, where the index
of an entry within the array is the pid & the value stored at that index
is the tgid.

The saved_tgids_next() function iterates over pointers into the tgid_map
array & dereferences the pointers which results in the tgid, but then it
passes that dereferenced value to trace_find_tgid() which treats it as a
pid & does a further lookup within the tgid_map array. It seems likely
that the intent here was to skip over entries in tgid_map for which the
recorded tgid is zero, but instead we end up skipping over entries for
which the thread group leader hasn't yet had its own tgid recorded in
tgid_map.

A minimal fix would be to remove the call to trace_find_tgid, turning:

if (trace_find_tgid(*ptr))

into:

if (*ptr)

..but it seems like this logic can be much simpler if we simply let
seq_read() iterate over the whole tgid_map array & filter out empty
entries by returning SEQ_SKIP from saved_tgids_show(). Here we take that
approach, removing the incorrect logic here entirely.

Link: https://lkml.kernel.org/r/20210630003406.4013668-1-paulburton@google.com

Fixes: d914ba37d714 ("tracing: Add support for recording tgid of tasks")
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Joel Fernandes <joelaf@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Paul Burton <paulburton@google.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Paul Burton and committed by
Steven Rostedt (VMware)
b81b3e95 78c14b38

+13 -25
+13 -25
kernel/trace/trace.c
··· 5662 5662 5663 5663 static void *saved_tgids_next(struct seq_file *m, void *v, loff_t *pos) 5664 5664 { 5665 - int *ptr = v; 5665 + int pid = ++(*pos); 5666 5666 5667 - if (*pos || m->count) 5668 - ptr++; 5667 + if (pid > PID_MAX_DEFAULT) 5668 + return NULL; 5669 5669 5670 - (*pos)++; 5671 - 5672 - for (; ptr <= &tgid_map[PID_MAX_DEFAULT]; ptr++) { 5673 - if (trace_find_tgid(*ptr)) 5674 - return ptr; 5675 - } 5676 - 5677 - return NULL; 5670 + return &tgid_map[pid]; 5678 5671 } 5679 5672 5680 5673 static void *saved_tgids_start(struct seq_file *m, loff_t *pos) 5681 5674 { 5682 - void *v; 5683 - loff_t l = 0; 5684 - 5685 - if (!tgid_map) 5675 + if (!tgid_map || *pos > PID_MAX_DEFAULT) 5686 5676 return NULL; 5687 5677 5688 - v = &tgid_map[0]; 5689 - while (l <= *pos) { 5690 - v = saved_tgids_next(m, v, &l); 5691 - if (!v) 5692 - return NULL; 5693 - } 5694 - 5695 - return v; 5678 + return &tgid_map[*pos]; 5696 5679 } 5697 5680 5698 5681 static void saved_tgids_stop(struct seq_file *m, void *v) ··· 5684 5701 5685 5702 static int saved_tgids_show(struct seq_file *m, void *v) 5686 5703 { 5687 - int pid = (int *)v - tgid_map; 5704 + int *entry = (int *)v; 5705 + int pid = entry - tgid_map; 5706 + int tgid = *entry; 5688 5707 5689 - seq_printf(m, "%d %d\n", pid, trace_find_tgid(pid)); 5708 + if (tgid == 0) 5709 + return SEQ_SKIP; 5710 + 5711 + seq_printf(m, "%d %d\n", pid, tgid); 5690 5712 return 0; 5691 5713 } 5692 5714