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: Resize tgid_map to pid_max, not PID_MAX_DEFAULT

Currently tgid_map is sized at PID_MAX_DEFAULT entries, which means that
on systems where pid_max is configured higher than PID_MAX_DEFAULT the
ftrace record-tgid option doesn't work so well. Any tasks with PIDs
higher than PID_MAX_DEFAULT are simply not recorded in tgid_map, and
don't show up in the saved_tgids file.

In particular since systemd v243 & above configure pid_max to its
highest possible 1<<22 value by default on 64 bit systems this renders
the record-tgids option of little use.

Increase the size of tgid_map to the configured pid_max instead,
allowing it to cover the full range of PIDs up to the maximum value of
PID_MAX_LIMIT if the system is configured that way.

On 64 bit systems with pid_max == PID_MAX_LIMIT this will increase the
size of tgid_map from 256KiB to 16MiB. Whilst this 64x increase in
memory overhead sounds significant 64 bit systems are presumably best
placed to accommodate it, and since tgid_map is only allocated when the
record-tgid option is actually used presumably the user would rather it
spends sufficient memory to actually record the tgids they expect.

The size of tgid_map could also increase for CONFIG_BASE_SMALL=y
configurations, but these seem unlikely to be systems upon which people
are both configuring a large pid_max and running ftrace with record-tgid
anyway.

Of note is that we only allocate tgid_map once, the first time that the
record-tgid option is enabled. Therefore its size is only set once, to
the value of pid_max at the time the record-tgid option is first
enabled. If a user increases pid_max after that point, the saved_tgids
file will not contain entries for any tasks with pids beyond the earlier
value of pid_max.

Link: https://lkml.kernel.org/r/20210701172407.889626-2-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>
[ Fixed comment coding style ]
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Paul Burton and committed by
Steven Rostedt (VMware)
4030a6e6 b81b3e95

+47 -16
+47 -16
kernel/trace/trace.c
··· 2191 2191 } 2192 2192 } 2193 2193 2194 + /* 2195 + * The tgid_map array maps from pid to tgid; i.e. the value stored at index i 2196 + * is the tgid last observed corresponding to pid=i. 2197 + */ 2194 2198 static int *tgid_map; 2199 + 2200 + /* The maximum valid index into tgid_map. */ 2201 + static size_t tgid_map_max; 2195 2202 2196 2203 #define SAVED_CMDLINES_DEFAULT 128 2197 2204 #define NO_CMDLINE_MAP UINT_MAX ··· 2475 2468 preempt_enable(); 2476 2469 } 2477 2470 2471 + static int *trace_find_tgid_ptr(int pid) 2472 + { 2473 + /* 2474 + * Pairs with the smp_store_release in set_tracer_flag() to ensure that 2475 + * if we observe a non-NULL tgid_map then we also observe the correct 2476 + * tgid_map_max. 2477 + */ 2478 + int *map = smp_load_acquire(&tgid_map); 2479 + 2480 + if (unlikely(!map || pid > tgid_map_max)) 2481 + return NULL; 2482 + 2483 + return &map[pid]; 2484 + } 2485 + 2478 2486 int trace_find_tgid(int pid) 2479 2487 { 2480 - if (unlikely(!tgid_map || !pid || pid > PID_MAX_DEFAULT)) 2481 - return 0; 2488 + int *ptr = trace_find_tgid_ptr(pid); 2482 2489 2483 - return tgid_map[pid]; 2490 + return ptr ? *ptr : 0; 2484 2491 } 2485 2492 2486 2493 static int trace_save_tgid(struct task_struct *tsk) 2487 2494 { 2495 + int *ptr; 2496 + 2488 2497 /* treat recording of idle task as a success */ 2489 2498 if (!tsk->pid) 2490 2499 return 1; 2491 2500 2492 - if (unlikely(!tgid_map || tsk->pid > PID_MAX_DEFAULT)) 2501 + ptr = trace_find_tgid_ptr(tsk->pid); 2502 + if (!ptr) 2493 2503 return 0; 2494 2504 2495 - tgid_map[tsk->pid] = tsk->tgid; 2505 + *ptr = tsk->tgid; 2496 2506 return 1; 2497 2507 } 2498 2508 ··· 5249 5225 5250 5226 int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) 5251 5227 { 5228 + int *map; 5229 + 5252 5230 if ((mask == TRACE_ITER_RECORD_TGID) || 5253 5231 (mask == TRACE_ITER_RECORD_CMD)) 5254 5232 lockdep_assert_held(&event_mutex); ··· 5273 5247 trace_event_enable_cmd_record(enabled); 5274 5248 5275 5249 if (mask == TRACE_ITER_RECORD_TGID) { 5276 - if (!tgid_map) 5277 - tgid_map = kvcalloc(PID_MAX_DEFAULT + 1, 5278 - sizeof(*tgid_map), 5279 - GFP_KERNEL); 5250 + if (!tgid_map) { 5251 + tgid_map_max = pid_max; 5252 + map = kvcalloc(tgid_map_max + 1, sizeof(*tgid_map), 5253 + GFP_KERNEL); 5254 + 5255 + /* 5256 + * Pairs with smp_load_acquire() in 5257 + * trace_find_tgid_ptr() to ensure that if it observes 5258 + * the tgid_map we just allocated then it also observes 5259 + * the corresponding tgid_map_max value. 5260 + */ 5261 + smp_store_release(&tgid_map, map); 5262 + } 5280 5263 if (!tgid_map) { 5281 5264 tr->trace_flags &= ~TRACE_ITER_RECORD_TGID; 5282 5265 return -ENOMEM; ··· 5699 5664 { 5700 5665 int pid = ++(*pos); 5701 5666 5702 - if (pid > PID_MAX_DEFAULT) 5703 - return NULL; 5704 - 5705 - return &tgid_map[pid]; 5667 + return trace_find_tgid_ptr(pid); 5706 5668 } 5707 5669 5708 5670 static void *saved_tgids_start(struct seq_file *m, loff_t *pos) 5709 5671 { 5710 - if (!tgid_map || *pos > PID_MAX_DEFAULT) 5711 - return NULL; 5672 + int pid = *pos; 5712 5673 5713 - return &tgid_map[*pos]; 5674 + return trace_find_tgid_ptr(pid); 5714 5675 } 5715 5676 5716 5677 static void saved_tgids_stop(struct seq_file *m, void *v)