1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
235e8e302SSteven Rostedt /*
335e8e302SSteven Rostedt * trace context switch
435e8e302SSteven Rostedt *
535e8e302SSteven Rostedt * Copyright (C) 2007 Steven Rostedt <[email protected]>
635e8e302SSteven Rostedt *
735e8e302SSteven Rostedt */
835e8e302SSteven Rostedt #include <linux/module.h>
935e8e302SSteven Rostedt #include <linux/kallsyms.h>
1035e8e302SSteven Rostedt #include <linux/uaccess.h>
112cc621fdSSteven Rostedt (Google) #include <linux/kmemleak.h>
1235e8e302SSteven Rostedt #include <linux/ftrace.h>
13ad8d75ffSSteven Rostedt #include <trace/events/sched.h>
1435e8e302SSteven Rostedt
1535e8e302SSteven Rostedt #include "trace.h"
1635e8e302SSteven Rostedt
17d914ba37SJoel Fernandes #define RECORD_CMDLINE 1
18d914ba37SJoel Fernandes #define RECORD_TGID 2
19d914ba37SJoel Fernandes
20d914ba37SJoel Fernandes static int sched_cmdline_ref;
21d914ba37SJoel Fernandes static int sched_tgid_ref;
22efade6e7SFrederic Weisbecker static DEFINE_MUTEX(sched_register_mutex);
2382e04af4SFrederic Weisbecker
24e309b41dSIngo Molnar static void
probe_sched_switch(void * ignore,bool preempt,struct task_struct * prev,struct task_struct * next,unsigned int prev_state)25c73464b1SPeter Zijlstra probe_sched_switch(void *ignore, bool preempt,
269c2136beSDelyan Kratunov struct task_struct *prev, struct task_struct *next,
279c2136beSDelyan Kratunov unsigned int prev_state)
2835e8e302SSteven Rostedt {
29d914ba37SJoel Fernandes int flags;
30b07c3f19SMathieu Desnoyers
31d914ba37SJoel Fernandes flags = (RECORD_TGID * !!sched_tgid_ref) +
32d914ba37SJoel Fernandes (RECORD_CMDLINE * !!sched_cmdline_ref);
33d914ba37SJoel Fernandes
34d914ba37SJoel Fernandes if (!flags)
35d914ba37SJoel Fernandes return;
36d914ba37SJoel Fernandes tracing_record_taskinfo_sched_switch(prev, next, flags);
3735e8e302SSteven Rostedt }
3835e8e302SSteven Rostedt
395b82a1b0SMathieu Desnoyers static void
probe_sched_wakeup(void * ignore,struct task_struct * wakee)40fbd705a0SPeter Zijlstra probe_sched_wakeup(void *ignore, struct task_struct *wakee)
415b82a1b0SMathieu Desnoyers {
42d914ba37SJoel Fernandes int flags;
43dcef788eSZhaolei
44d914ba37SJoel Fernandes flags = (RECORD_TGID * !!sched_tgid_ref) +
45d914ba37SJoel Fernandes (RECORD_CMDLINE * !!sched_cmdline_ref);
46d914ba37SJoel Fernandes
47d914ba37SJoel Fernandes if (!flags)
48d914ba37SJoel Fernandes return;
4955bc8384SSteven Rostedt (Google) tracing_record_taskinfo_sched_switch(current, wakee, flags);
5057422797SIngo Molnar }
5157422797SIngo Molnar
tracing_sched_register(void)525b82a1b0SMathieu Desnoyers static int tracing_sched_register(void)
535b82a1b0SMathieu Desnoyers {
545b82a1b0SMathieu Desnoyers int ret;
555b82a1b0SMathieu Desnoyers
5638516ab5SSteven Rostedt ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
575b82a1b0SMathieu Desnoyers if (ret) {
58b07c3f19SMathieu Desnoyers pr_info("wakeup trace: Couldn't activate tracepoint"
595b82a1b0SMathieu Desnoyers " probe to kernel_sched_wakeup\n");
605b82a1b0SMathieu Desnoyers return ret;
615b82a1b0SMathieu Desnoyers }
625b82a1b0SMathieu Desnoyers
6338516ab5SSteven Rostedt ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
645b82a1b0SMathieu Desnoyers if (ret) {
65b07c3f19SMathieu Desnoyers pr_info("wakeup trace: Couldn't activate tracepoint"
665b82a1b0SMathieu Desnoyers " probe to kernel_sched_wakeup_new\n");
675b82a1b0SMathieu Desnoyers goto fail_deprobe;
685b82a1b0SMathieu Desnoyers }
695b82a1b0SMathieu Desnoyers
7038516ab5SSteven Rostedt ret = register_trace_sched_switch(probe_sched_switch, NULL);
715b82a1b0SMathieu Desnoyers if (ret) {
72b07c3f19SMathieu Desnoyers pr_info("sched trace: Couldn't activate tracepoint"
7373d8b8bcSWenji Huang " probe to kernel_sched_switch\n");
745b82a1b0SMathieu Desnoyers goto fail_deprobe_wake_new;
755b82a1b0SMathieu Desnoyers }
765b82a1b0SMathieu Desnoyers
775b82a1b0SMathieu Desnoyers return ret;
785b82a1b0SMathieu Desnoyers fail_deprobe_wake_new:
7938516ab5SSteven Rostedt unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
805b82a1b0SMathieu Desnoyers fail_deprobe:
8138516ab5SSteven Rostedt unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
825b82a1b0SMathieu Desnoyers return ret;
835b82a1b0SMathieu Desnoyers }
845b82a1b0SMathieu Desnoyers
tracing_sched_unregister(void)855b82a1b0SMathieu Desnoyers static void tracing_sched_unregister(void)
865b82a1b0SMathieu Desnoyers {
8738516ab5SSteven Rostedt unregister_trace_sched_switch(probe_sched_switch, NULL);
8838516ab5SSteven Rostedt unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
8938516ab5SSteven Rostedt unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
905b82a1b0SMathieu Desnoyers }
915b82a1b0SMathieu Desnoyers
tracing_start_sched_switch(int ops)92d914ba37SJoel Fernandes static void tracing_start_sched_switch(int ops)
935b82a1b0SMathieu Desnoyers {
9464ae572bSMathieu Desnoyers bool sched_register;
9564ae572bSMathieu Desnoyers
96efade6e7SFrederic Weisbecker mutex_lock(&sched_register_mutex);
9764ae572bSMathieu Desnoyers sched_register = (!sched_cmdline_ref && !sched_tgid_ref);
98d914ba37SJoel Fernandes
99d914ba37SJoel Fernandes switch (ops) {
100d914ba37SJoel Fernandes case RECORD_CMDLINE:
101d914ba37SJoel Fernandes sched_cmdline_ref++;
102d914ba37SJoel Fernandes break;
103d914ba37SJoel Fernandes
104d914ba37SJoel Fernandes case RECORD_TGID:
105d914ba37SJoel Fernandes sched_tgid_ref++;
106d914ba37SJoel Fernandes break;
107d914ba37SJoel Fernandes }
108d914ba37SJoel Fernandes
109d914ba37SJoel Fernandes if (sched_register && (sched_cmdline_ref || sched_tgid_ref))
1105b82a1b0SMathieu Desnoyers tracing_sched_register();
111efade6e7SFrederic Weisbecker mutex_unlock(&sched_register_mutex);
1125b82a1b0SMathieu Desnoyers }
1135b82a1b0SMathieu Desnoyers
tracing_stop_sched_switch(int ops)114d914ba37SJoel Fernandes static void tracing_stop_sched_switch(int ops)
1155b82a1b0SMathieu Desnoyers {
116efade6e7SFrederic Weisbecker mutex_lock(&sched_register_mutex);
117d914ba37SJoel Fernandes
118d914ba37SJoel Fernandes switch (ops) {
119d914ba37SJoel Fernandes case RECORD_CMDLINE:
120d914ba37SJoel Fernandes sched_cmdline_ref--;
121d914ba37SJoel Fernandes break;
122d914ba37SJoel Fernandes
123d914ba37SJoel Fernandes case RECORD_TGID:
124d914ba37SJoel Fernandes sched_tgid_ref--;
125d914ba37SJoel Fernandes break;
126d914ba37SJoel Fernandes }
127d914ba37SJoel Fernandes
128d914ba37SJoel Fernandes if (!sched_cmdline_ref && !sched_tgid_ref)
1295b82a1b0SMathieu Desnoyers tracing_sched_unregister();
130efade6e7SFrederic Weisbecker mutex_unlock(&sched_register_mutex);
1315b82a1b0SMathieu Desnoyers }
1325b82a1b0SMathieu Desnoyers
tracing_start_cmdline_record(void)13341bc8144SSteven Rostedt void tracing_start_cmdline_record(void)
13441bc8144SSteven Rostedt {
135d914ba37SJoel Fernandes tracing_start_sched_switch(RECORD_CMDLINE);
13641bc8144SSteven Rostedt }
13741bc8144SSteven Rostedt
tracing_stop_cmdline_record(void)13841bc8144SSteven Rostedt void tracing_stop_cmdline_record(void)
13941bc8144SSteven Rostedt {
140d914ba37SJoel Fernandes tracing_stop_sched_switch(RECORD_CMDLINE);
141d914ba37SJoel Fernandes }
142d914ba37SJoel Fernandes
tracing_start_tgid_record(void)143d914ba37SJoel Fernandes void tracing_start_tgid_record(void)
144d914ba37SJoel Fernandes {
145d914ba37SJoel Fernandes tracing_start_sched_switch(RECORD_TGID);
146d914ba37SJoel Fernandes }
147d914ba37SJoel Fernandes
tracing_stop_tgid_record(void)148d914ba37SJoel Fernandes void tracing_stop_tgid_record(void)
149d914ba37SJoel Fernandes {
150d914ba37SJoel Fernandes tracing_stop_sched_switch(RECORD_TGID);
15141bc8144SSteven Rostedt }
1522cc621fdSSteven Rostedt (Google)
1532cc621fdSSteven Rostedt (Google) /*
1542cc621fdSSteven Rostedt (Google) * The tgid_map array maps from pid to tgid; i.e. the value stored at index i
1552cc621fdSSteven Rostedt (Google) * is the tgid last observed corresponding to pid=i.
1562cc621fdSSteven Rostedt (Google) */
1572cc621fdSSteven Rostedt (Google) static int *tgid_map;
1582cc621fdSSteven Rostedt (Google)
1592cc621fdSSteven Rostedt (Google) /* The maximum valid index into tgid_map. */
1602cc621fdSSteven Rostedt (Google) static size_t tgid_map_max;
1612cc621fdSSteven Rostedt (Google)
1622cc621fdSSteven Rostedt (Google) #define SAVED_CMDLINES_DEFAULT 128
1632cc621fdSSteven Rostedt (Google) #define NO_CMDLINE_MAP UINT_MAX
1642cc621fdSSteven Rostedt (Google) /*
1652cc621fdSSteven Rostedt (Google) * Preemption must be disabled before acquiring trace_cmdline_lock.
1662cc621fdSSteven Rostedt (Google) * The various trace_arrays' max_lock must be acquired in a context
1672cc621fdSSteven Rostedt (Google) * where interrupt is disabled.
1682cc621fdSSteven Rostedt (Google) */
1692cc621fdSSteven Rostedt (Google) static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED;
1702cc621fdSSteven Rostedt (Google) struct saved_cmdlines_buffer {
1712cc621fdSSteven Rostedt (Google) unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
1722cc621fdSSteven Rostedt (Google) unsigned *map_cmdline_to_pid;
1732cc621fdSSteven Rostedt (Google) unsigned cmdline_num;
1742cc621fdSSteven Rostedt (Google) int cmdline_idx;
1752cc621fdSSteven Rostedt (Google) char saved_cmdlines[];
1762cc621fdSSteven Rostedt (Google) };
1772cc621fdSSteven Rostedt (Google) static struct saved_cmdlines_buffer *savedcmd;
1782cc621fdSSteven Rostedt (Google)
1792cc621fdSSteven Rostedt (Google) /* Holds the size of a cmdline and pid element */
1802cc621fdSSteven Rostedt (Google) #define SAVED_CMDLINE_MAP_ELEMENT_SIZE(s) \
1812cc621fdSSteven Rostedt (Google) (TASK_COMM_LEN + sizeof((s)->map_cmdline_to_pid[0]))
1822cc621fdSSteven Rostedt (Google)
get_saved_cmdlines(int idx)1832cc621fdSSteven Rostedt (Google) static inline char *get_saved_cmdlines(int idx)
1842cc621fdSSteven Rostedt (Google) {
1852cc621fdSSteven Rostedt (Google) return &savedcmd->saved_cmdlines[idx * TASK_COMM_LEN];
1862cc621fdSSteven Rostedt (Google) }
1872cc621fdSSteven Rostedt (Google)
set_cmdline(int idx,const char * cmdline)1882cc621fdSSteven Rostedt (Google) static inline void set_cmdline(int idx, const char *cmdline)
1892cc621fdSSteven Rostedt (Google) {
190242b32d8SJinjie Ruan strscpy(get_saved_cmdlines(idx), cmdline, TASK_COMM_LEN);
1912cc621fdSSteven Rostedt (Google) }
1922cc621fdSSteven Rostedt (Google)
free_saved_cmdlines_buffer(struct saved_cmdlines_buffer * s)1932cc621fdSSteven Rostedt (Google) static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
1942cc621fdSSteven Rostedt (Google) {
1952cc621fdSSteven Rostedt (Google) int order = get_order(sizeof(*s) + s->cmdline_num * TASK_COMM_LEN);
1962cc621fdSSteven Rostedt (Google)
1972cc621fdSSteven Rostedt (Google) kmemleak_free(s);
1982cc621fdSSteven Rostedt (Google) free_pages((unsigned long)s, order);
1992cc621fdSSteven Rostedt (Google) }
2002cc621fdSSteven Rostedt (Google)
allocate_cmdlines_buffer(unsigned int val)2012cc621fdSSteven Rostedt (Google) static struct saved_cmdlines_buffer *allocate_cmdlines_buffer(unsigned int val)
2022cc621fdSSteven Rostedt (Google) {
2032cc621fdSSteven Rostedt (Google) struct saved_cmdlines_buffer *s;
2042cc621fdSSteven Rostedt (Google) struct page *page;
2052cc621fdSSteven Rostedt (Google) int orig_size, size;
2062cc621fdSSteven Rostedt (Google) int order;
2072cc621fdSSteven Rostedt (Google)
2082cc621fdSSteven Rostedt (Google) /* Figure out how much is needed to hold the given number of cmdlines */
2092cc621fdSSteven Rostedt (Google) orig_size = sizeof(*s) + val * SAVED_CMDLINE_MAP_ELEMENT_SIZE(s);
2102cc621fdSSteven Rostedt (Google) order = get_order(orig_size);
2112cc621fdSSteven Rostedt (Google) size = 1 << (order + PAGE_SHIFT);
2122cc621fdSSteven Rostedt (Google) page = alloc_pages(GFP_KERNEL, order);
2132cc621fdSSteven Rostedt (Google) if (!page)
2142cc621fdSSteven Rostedt (Google) return NULL;
2152cc621fdSSteven Rostedt (Google)
2162cc621fdSSteven Rostedt (Google) s = page_address(page);
2172cc621fdSSteven Rostedt (Google) kmemleak_alloc(s, size, 1, GFP_KERNEL);
2182cc621fdSSteven Rostedt (Google) memset(s, 0, sizeof(*s));
2192cc621fdSSteven Rostedt (Google)
2202cc621fdSSteven Rostedt (Google) /* Round up to actual allocation */
2212cc621fdSSteven Rostedt (Google) val = (size - sizeof(*s)) / SAVED_CMDLINE_MAP_ELEMENT_SIZE(s);
2222cc621fdSSteven Rostedt (Google) s->cmdline_num = val;
2232cc621fdSSteven Rostedt (Google)
2242cc621fdSSteven Rostedt (Google) /* Place map_cmdline_to_pid array right after saved_cmdlines */
2252cc621fdSSteven Rostedt (Google) s->map_cmdline_to_pid = (unsigned *)&s->saved_cmdlines[val * TASK_COMM_LEN];
2262cc621fdSSteven Rostedt (Google)
2272cc621fdSSteven Rostedt (Google) s->cmdline_idx = 0;
2282cc621fdSSteven Rostedt (Google) memset(&s->map_pid_to_cmdline, NO_CMDLINE_MAP,
2292cc621fdSSteven Rostedt (Google) sizeof(s->map_pid_to_cmdline));
2302cc621fdSSteven Rostedt (Google) memset(s->map_cmdline_to_pid, NO_CMDLINE_MAP,
2312cc621fdSSteven Rostedt (Google) val * sizeof(*s->map_cmdline_to_pid));
2322cc621fdSSteven Rostedt (Google)
2332cc621fdSSteven Rostedt (Google) return s;
2342cc621fdSSteven Rostedt (Google) }
2352cc621fdSSteven Rostedt (Google)
trace_create_savedcmd(void)2362cc621fdSSteven Rostedt (Google) int trace_create_savedcmd(void)
2372cc621fdSSteven Rostedt (Google) {
2382cc621fdSSteven Rostedt (Google) savedcmd = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT);
2392cc621fdSSteven Rostedt (Google)
2402cc621fdSSteven Rostedt (Google) return savedcmd ? 0 : -ENOMEM;
2412cc621fdSSteven Rostedt (Google) }
2422cc621fdSSteven Rostedt (Google)
trace_save_cmdline(struct task_struct * tsk)2432cc621fdSSteven Rostedt (Google) int trace_save_cmdline(struct task_struct *tsk)
2442cc621fdSSteven Rostedt (Google) {
2452cc621fdSSteven Rostedt (Google) unsigned tpid, idx;
2462cc621fdSSteven Rostedt (Google)
2472cc621fdSSteven Rostedt (Google) /* treat recording of idle task as a success */
2482cc621fdSSteven Rostedt (Google) if (!tsk->pid)
2492cc621fdSSteven Rostedt (Google) return 1;
2502cc621fdSSteven Rostedt (Google)
2512cc621fdSSteven Rostedt (Google) tpid = tsk->pid & (PID_MAX_DEFAULT - 1);
2522cc621fdSSteven Rostedt (Google)
2532cc621fdSSteven Rostedt (Google) /*
2542cc621fdSSteven Rostedt (Google) * It's not the end of the world if we don't get
2552cc621fdSSteven Rostedt (Google) * the lock, but we also don't want to spin
2562cc621fdSSteven Rostedt (Google) * nor do we want to disable interrupts,
2572cc621fdSSteven Rostedt (Google) * so if we miss here, then better luck next time.
2582cc621fdSSteven Rostedt (Google) *
2592cc621fdSSteven Rostedt (Google) * This is called within the scheduler and wake up, so interrupts
2602cc621fdSSteven Rostedt (Google) * had better been disabled and run queue lock been held.
2612cc621fdSSteven Rostedt (Google) */
2622cc621fdSSteven Rostedt (Google) lockdep_assert_preemption_disabled();
2632cc621fdSSteven Rostedt (Google) if (!arch_spin_trylock(&trace_cmdline_lock))
2642cc621fdSSteven Rostedt (Google) return 0;
2652cc621fdSSteven Rostedt (Google)
2662cc621fdSSteven Rostedt (Google) idx = savedcmd->map_pid_to_cmdline[tpid];
2672cc621fdSSteven Rostedt (Google) if (idx == NO_CMDLINE_MAP) {
2682cc621fdSSteven Rostedt (Google) idx = (savedcmd->cmdline_idx + 1) % savedcmd->cmdline_num;
2692cc621fdSSteven Rostedt (Google)
2702cc621fdSSteven Rostedt (Google) savedcmd->map_pid_to_cmdline[tpid] = idx;
2712cc621fdSSteven Rostedt (Google) savedcmd->cmdline_idx = idx;
2722cc621fdSSteven Rostedt (Google) }
2732cc621fdSSteven Rostedt (Google)
2742cc621fdSSteven Rostedt (Google) savedcmd->map_cmdline_to_pid[idx] = tsk->pid;
2752cc621fdSSteven Rostedt (Google) set_cmdline(idx, tsk->comm);
2762cc621fdSSteven Rostedt (Google)
2772cc621fdSSteven Rostedt (Google) arch_spin_unlock(&trace_cmdline_lock);
2782cc621fdSSteven Rostedt (Google)
2792cc621fdSSteven Rostedt (Google) return 1;
2802cc621fdSSteven Rostedt (Google) }
2812cc621fdSSteven Rostedt (Google)
__trace_find_cmdline(int pid,char comm[])2822cc621fdSSteven Rostedt (Google) static void __trace_find_cmdline(int pid, char comm[])
2832cc621fdSSteven Rostedt (Google) {
2842cc621fdSSteven Rostedt (Google) unsigned map;
2852cc621fdSSteven Rostedt (Google) int tpid;
2862cc621fdSSteven Rostedt (Google)
2872cc621fdSSteven Rostedt (Google) if (!pid) {
2882cc621fdSSteven Rostedt (Google) strcpy(comm, "<idle>");
2892cc621fdSSteven Rostedt (Google) return;
2902cc621fdSSteven Rostedt (Google) }
2912cc621fdSSteven Rostedt (Google)
2922cc621fdSSteven Rostedt (Google) if (WARN_ON_ONCE(pid < 0)) {
2932cc621fdSSteven Rostedt (Google) strcpy(comm, "<XXX>");
2942cc621fdSSteven Rostedt (Google) return;
2952cc621fdSSteven Rostedt (Google) }
2962cc621fdSSteven Rostedt (Google)
2972cc621fdSSteven Rostedt (Google) tpid = pid & (PID_MAX_DEFAULT - 1);
2982cc621fdSSteven Rostedt (Google) map = savedcmd->map_pid_to_cmdline[tpid];
2992cc621fdSSteven Rostedt (Google) if (map != NO_CMDLINE_MAP) {
3002cc621fdSSteven Rostedt (Google) tpid = savedcmd->map_cmdline_to_pid[map];
3012cc621fdSSteven Rostedt (Google) if (tpid == pid) {
3022cc621fdSSteven Rostedt (Google) strscpy(comm, get_saved_cmdlines(map), TASK_COMM_LEN);
3032cc621fdSSteven Rostedt (Google) return;
3042cc621fdSSteven Rostedt (Google) }
3052cc621fdSSteven Rostedt (Google) }
3062cc621fdSSteven Rostedt (Google) strcpy(comm, "<...>");
3072cc621fdSSteven Rostedt (Google) }
3082cc621fdSSteven Rostedt (Google)
trace_find_cmdline(int pid,char comm[])3092cc621fdSSteven Rostedt (Google) void trace_find_cmdline(int pid, char comm[])
3102cc621fdSSteven Rostedt (Google) {
3112cc621fdSSteven Rostedt (Google) preempt_disable();
3122cc621fdSSteven Rostedt (Google) arch_spin_lock(&trace_cmdline_lock);
3132cc621fdSSteven Rostedt (Google)
3142cc621fdSSteven Rostedt (Google) __trace_find_cmdline(pid, comm);
3152cc621fdSSteven Rostedt (Google)
3162cc621fdSSteven Rostedt (Google) arch_spin_unlock(&trace_cmdline_lock);
3172cc621fdSSteven Rostedt (Google) preempt_enable();
3182cc621fdSSteven Rostedt (Google) }
3192cc621fdSSteven Rostedt (Google)
trace_find_tgid_ptr(int pid)3202cc621fdSSteven Rostedt (Google) static int *trace_find_tgid_ptr(int pid)
3212cc621fdSSteven Rostedt (Google) {
3222cc621fdSSteven Rostedt (Google) /*
3232cc621fdSSteven Rostedt (Google) * Pairs with the smp_store_release in set_tracer_flag() to ensure that
3242cc621fdSSteven Rostedt (Google) * if we observe a non-NULL tgid_map then we also observe the correct
3252cc621fdSSteven Rostedt (Google) * tgid_map_max.
3262cc621fdSSteven Rostedt (Google) */
3272cc621fdSSteven Rostedt (Google) int *map = smp_load_acquire(&tgid_map);
3282cc621fdSSteven Rostedt (Google)
3292cc621fdSSteven Rostedt (Google) if (unlikely(!map || pid > tgid_map_max))
3302cc621fdSSteven Rostedt (Google) return NULL;
3312cc621fdSSteven Rostedt (Google)
3322cc621fdSSteven Rostedt (Google) return &map[pid];
3332cc621fdSSteven Rostedt (Google) }
3342cc621fdSSteven Rostedt (Google)
trace_find_tgid(int pid)3352cc621fdSSteven Rostedt (Google) int trace_find_tgid(int pid)
3362cc621fdSSteven Rostedt (Google) {
3372cc621fdSSteven Rostedt (Google) int *ptr = trace_find_tgid_ptr(pid);
3382cc621fdSSteven Rostedt (Google)
3392cc621fdSSteven Rostedt (Google) return ptr ? *ptr : 0;
3402cc621fdSSteven Rostedt (Google) }
3412cc621fdSSteven Rostedt (Google)
trace_save_tgid(struct task_struct * tsk)3422cc621fdSSteven Rostedt (Google) static int trace_save_tgid(struct task_struct *tsk)
3432cc621fdSSteven Rostedt (Google) {
3442cc621fdSSteven Rostedt (Google) int *ptr;
3452cc621fdSSteven Rostedt (Google)
3462cc621fdSSteven Rostedt (Google) /* treat recording of idle task as a success */
3472cc621fdSSteven Rostedt (Google) if (!tsk->pid)
3482cc621fdSSteven Rostedt (Google) return 1;
3492cc621fdSSteven Rostedt (Google)
3502cc621fdSSteven Rostedt (Google) ptr = trace_find_tgid_ptr(tsk->pid);
3512cc621fdSSteven Rostedt (Google) if (!ptr)
3522cc621fdSSteven Rostedt (Google) return 0;
3532cc621fdSSteven Rostedt (Google)
3542cc621fdSSteven Rostedt (Google) *ptr = tsk->tgid;
3552cc621fdSSteven Rostedt (Google) return 1;
3562cc621fdSSteven Rostedt (Google) }
3572cc621fdSSteven Rostedt (Google)
tracing_record_taskinfo_skip(int flags)3582cc621fdSSteven Rostedt (Google) static bool tracing_record_taskinfo_skip(int flags)
3592cc621fdSSteven Rostedt (Google) {
3602cc621fdSSteven Rostedt (Google) if (unlikely(!(flags & (TRACE_RECORD_CMDLINE | TRACE_RECORD_TGID))))
3612cc621fdSSteven Rostedt (Google) return true;
3622cc621fdSSteven Rostedt (Google) if (!__this_cpu_read(trace_taskinfo_save))
3632cc621fdSSteven Rostedt (Google) return true;
3642cc621fdSSteven Rostedt (Google) return false;
3652cc621fdSSteven Rostedt (Google) }
3662cc621fdSSteven Rostedt (Google)
3672cc621fdSSteven Rostedt (Google) /**
3682cc621fdSSteven Rostedt (Google) * tracing_record_taskinfo - record the task info of a task
3692cc621fdSSteven Rostedt (Google) *
3702cc621fdSSteven Rostedt (Google) * @task: task to record
3712cc621fdSSteven Rostedt (Google) * @flags: TRACE_RECORD_CMDLINE for recording comm
3722cc621fdSSteven Rostedt (Google) * TRACE_RECORD_TGID for recording tgid
3732cc621fdSSteven Rostedt (Google) */
tracing_record_taskinfo(struct task_struct * task,int flags)3742cc621fdSSteven Rostedt (Google) void tracing_record_taskinfo(struct task_struct *task, int flags)
3752cc621fdSSteven Rostedt (Google) {
3762cc621fdSSteven Rostedt (Google) bool done;
3772cc621fdSSteven Rostedt (Google)
3782cc621fdSSteven Rostedt (Google) if (tracing_record_taskinfo_skip(flags))
3792cc621fdSSteven Rostedt (Google) return;
3802cc621fdSSteven Rostedt (Google)
3812cc621fdSSteven Rostedt (Google) /*
3822cc621fdSSteven Rostedt (Google) * Record as much task information as possible. If some fail, continue
3832cc621fdSSteven Rostedt (Google) * to try to record the others.
3842cc621fdSSteven Rostedt (Google) */
3852cc621fdSSteven Rostedt (Google) done = !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(task);
3862cc621fdSSteven Rostedt (Google) done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(task);
3872cc621fdSSteven Rostedt (Google)
3882cc621fdSSteven Rostedt (Google) /* If recording any information failed, retry again soon. */
3892cc621fdSSteven Rostedt (Google) if (!done)
3902cc621fdSSteven Rostedt (Google) return;
3912cc621fdSSteven Rostedt (Google)
3922cc621fdSSteven Rostedt (Google) __this_cpu_write(trace_taskinfo_save, false);
3932cc621fdSSteven Rostedt (Google) }
3942cc621fdSSteven Rostedt (Google)
3952cc621fdSSteven Rostedt (Google) /**
3962cc621fdSSteven Rostedt (Google) * tracing_record_taskinfo_sched_switch - record task info for sched_switch
3972cc621fdSSteven Rostedt (Google) *
3982cc621fdSSteven Rostedt (Google) * @prev: previous task during sched_switch
3992cc621fdSSteven Rostedt (Google) * @next: next task during sched_switch
4002cc621fdSSteven Rostedt (Google) * @flags: TRACE_RECORD_CMDLINE for recording comm
4012cc621fdSSteven Rostedt (Google) * TRACE_RECORD_TGID for recording tgid
4022cc621fdSSteven Rostedt (Google) */
tracing_record_taskinfo_sched_switch(struct task_struct * prev,struct task_struct * next,int flags)4032cc621fdSSteven Rostedt (Google) void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
4042cc621fdSSteven Rostedt (Google) struct task_struct *next, int flags)
4052cc621fdSSteven Rostedt (Google) {
4062cc621fdSSteven Rostedt (Google) bool done;
4072cc621fdSSteven Rostedt (Google)
4082cc621fdSSteven Rostedt (Google) if (tracing_record_taskinfo_skip(flags))
4092cc621fdSSteven Rostedt (Google) return;
4102cc621fdSSteven Rostedt (Google)
4112cc621fdSSteven Rostedt (Google) /*
4122cc621fdSSteven Rostedt (Google) * Record as much task information as possible. If some fail, continue
4132cc621fdSSteven Rostedt (Google) * to try to record the others.
4142cc621fdSSteven Rostedt (Google) */
4152cc621fdSSteven Rostedt (Google) done = !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(prev);
4162cc621fdSSteven Rostedt (Google) done &= !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(next);
4172cc621fdSSteven Rostedt (Google) done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(prev);
4182cc621fdSSteven Rostedt (Google) done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(next);
4192cc621fdSSteven Rostedt (Google)
4202cc621fdSSteven Rostedt (Google) /* If recording any information failed, retry again soon. */
4212cc621fdSSteven Rostedt (Google) if (!done)
4222cc621fdSSteven Rostedt (Google) return;
4232cc621fdSSteven Rostedt (Google)
4242cc621fdSSteven Rostedt (Google) __this_cpu_write(trace_taskinfo_save, false);
4252cc621fdSSteven Rostedt (Google) }
4262cc621fdSSteven Rostedt (Google)
4272cc621fdSSteven Rostedt (Google) /* Helpers to record a specific task information */
tracing_record_cmdline(struct task_struct * task)4282cc621fdSSteven Rostedt (Google) void tracing_record_cmdline(struct task_struct *task)
4292cc621fdSSteven Rostedt (Google) {
4302cc621fdSSteven Rostedt (Google) tracing_record_taskinfo(task, TRACE_RECORD_CMDLINE);
4312cc621fdSSteven Rostedt (Google) }
4322cc621fdSSteven Rostedt (Google)
tracing_record_tgid(struct task_struct * task)4332cc621fdSSteven Rostedt (Google) void tracing_record_tgid(struct task_struct *task)
4342cc621fdSSteven Rostedt (Google) {
4352cc621fdSSteven Rostedt (Google) tracing_record_taskinfo(task, TRACE_RECORD_TGID);
4362cc621fdSSteven Rostedt (Google) }
4372cc621fdSSteven Rostedt (Google)
trace_alloc_tgid_map(void)4382cc621fdSSteven Rostedt (Google) int trace_alloc_tgid_map(void)
4392cc621fdSSteven Rostedt (Google) {
4402cc621fdSSteven Rostedt (Google) int *map;
4412cc621fdSSteven Rostedt (Google)
4422cc621fdSSteven Rostedt (Google) if (tgid_map)
4432cc621fdSSteven Rostedt (Google) return 0;
4442cc621fdSSteven Rostedt (Google)
445*7863dcc7SChristian Brauner tgid_map_max = init_pid_ns.pid_max;
4462cc621fdSSteven Rostedt (Google) map = kvcalloc(tgid_map_max + 1, sizeof(*tgid_map),
4472cc621fdSSteven Rostedt (Google) GFP_KERNEL);
4482cc621fdSSteven Rostedt (Google) if (!map)
4492cc621fdSSteven Rostedt (Google) return -ENOMEM;
4502cc621fdSSteven Rostedt (Google)
4512cc621fdSSteven Rostedt (Google) /*
4522cc621fdSSteven Rostedt (Google) * Pairs with smp_load_acquire() in
4532cc621fdSSteven Rostedt (Google) * trace_find_tgid_ptr() to ensure that if it observes
4542cc621fdSSteven Rostedt (Google) * the tgid_map we just allocated then it also observes
4552cc621fdSSteven Rostedt (Google) * the corresponding tgid_map_max value.
4562cc621fdSSteven Rostedt (Google) */
4572cc621fdSSteven Rostedt (Google) smp_store_release(&tgid_map, map);
4582cc621fdSSteven Rostedt (Google) return 0;
4592cc621fdSSteven Rostedt (Google) }
4602cc621fdSSteven Rostedt (Google)
saved_tgids_next(struct seq_file * m,void * v,loff_t * pos)4612cc621fdSSteven Rostedt (Google) static void *saved_tgids_next(struct seq_file *m, void *v, loff_t *pos)
4622cc621fdSSteven Rostedt (Google) {
4632cc621fdSSteven Rostedt (Google) int pid = ++(*pos);
4642cc621fdSSteven Rostedt (Google)
4652cc621fdSSteven Rostedt (Google) return trace_find_tgid_ptr(pid);
4662cc621fdSSteven Rostedt (Google) }
4672cc621fdSSteven Rostedt (Google)
saved_tgids_start(struct seq_file * m,loff_t * pos)4682cc621fdSSteven Rostedt (Google) static void *saved_tgids_start(struct seq_file *m, loff_t *pos)
4692cc621fdSSteven Rostedt (Google) {
4702cc621fdSSteven Rostedt (Google) int pid = *pos;
4712cc621fdSSteven Rostedt (Google)
4722cc621fdSSteven Rostedt (Google) return trace_find_tgid_ptr(pid);
4732cc621fdSSteven Rostedt (Google) }
4742cc621fdSSteven Rostedt (Google)
saved_tgids_stop(struct seq_file * m,void * v)4752cc621fdSSteven Rostedt (Google) static void saved_tgids_stop(struct seq_file *m, void *v)
4762cc621fdSSteven Rostedt (Google) {
4772cc621fdSSteven Rostedt (Google) }
4782cc621fdSSteven Rostedt (Google)
saved_tgids_show(struct seq_file * m,void * v)4792cc621fdSSteven Rostedt (Google) static int saved_tgids_show(struct seq_file *m, void *v)
4802cc621fdSSteven Rostedt (Google) {
4812cc621fdSSteven Rostedt (Google) int *entry = (int *)v;
4822cc621fdSSteven Rostedt (Google) int pid = entry - tgid_map;
4832cc621fdSSteven Rostedt (Google) int tgid = *entry;
4842cc621fdSSteven Rostedt (Google)
4852cc621fdSSteven Rostedt (Google) if (tgid == 0)
4862cc621fdSSteven Rostedt (Google) return SEQ_SKIP;
4872cc621fdSSteven Rostedt (Google)
4882cc621fdSSteven Rostedt (Google) seq_printf(m, "%d %d\n", pid, tgid);
4892cc621fdSSteven Rostedt (Google) return 0;
4902cc621fdSSteven Rostedt (Google) }
4912cc621fdSSteven Rostedt (Google)
4922cc621fdSSteven Rostedt (Google) static const struct seq_operations tracing_saved_tgids_seq_ops = {
4932cc621fdSSteven Rostedt (Google) .start = saved_tgids_start,
4942cc621fdSSteven Rostedt (Google) .stop = saved_tgids_stop,
4952cc621fdSSteven Rostedt (Google) .next = saved_tgids_next,
4962cc621fdSSteven Rostedt (Google) .show = saved_tgids_show,
4972cc621fdSSteven Rostedt (Google) };
4982cc621fdSSteven Rostedt (Google)
tracing_saved_tgids_open(struct inode * inode,struct file * filp)4992cc621fdSSteven Rostedt (Google) static int tracing_saved_tgids_open(struct inode *inode, struct file *filp)
5002cc621fdSSteven Rostedt (Google) {
5012cc621fdSSteven Rostedt (Google) int ret;
5022cc621fdSSteven Rostedt (Google)
5032cc621fdSSteven Rostedt (Google) ret = tracing_check_open_get_tr(NULL);
5042cc621fdSSteven Rostedt (Google) if (ret)
5052cc621fdSSteven Rostedt (Google) return ret;
5062cc621fdSSteven Rostedt (Google)
5072cc621fdSSteven Rostedt (Google) return seq_open(filp, &tracing_saved_tgids_seq_ops);
5082cc621fdSSteven Rostedt (Google) }
5092cc621fdSSteven Rostedt (Google)
5102cc621fdSSteven Rostedt (Google)
5112cc621fdSSteven Rostedt (Google) const struct file_operations tracing_saved_tgids_fops = {
5122cc621fdSSteven Rostedt (Google) .open = tracing_saved_tgids_open,
5132cc621fdSSteven Rostedt (Google) .read = seq_read,
5142cc621fdSSteven Rostedt (Google) .llseek = seq_lseek,
5152cc621fdSSteven Rostedt (Google) .release = seq_release,
5162cc621fdSSteven Rostedt (Google) };
5172cc621fdSSteven Rostedt (Google)
saved_cmdlines_next(struct seq_file * m,void * v,loff_t * pos)5182cc621fdSSteven Rostedt (Google) static void *saved_cmdlines_next(struct seq_file *m, void *v, loff_t *pos)
5192cc621fdSSteven Rostedt (Google) {
5202cc621fdSSteven Rostedt (Google) unsigned int *ptr = v;
5212cc621fdSSteven Rostedt (Google)
5222cc621fdSSteven Rostedt (Google) if (*pos || m->count)
5232cc621fdSSteven Rostedt (Google) ptr++;
5242cc621fdSSteven Rostedt (Google)
5252cc621fdSSteven Rostedt (Google) (*pos)++;
5262cc621fdSSteven Rostedt (Google)
5272cc621fdSSteven Rostedt (Google) for (; ptr < &savedcmd->map_cmdline_to_pid[savedcmd->cmdline_num];
5282cc621fdSSteven Rostedt (Google) ptr++) {
5292cc621fdSSteven Rostedt (Google) if (*ptr == -1 || *ptr == NO_CMDLINE_MAP)
5302cc621fdSSteven Rostedt (Google) continue;
5312cc621fdSSteven Rostedt (Google)
5322cc621fdSSteven Rostedt (Google) return ptr;
5332cc621fdSSteven Rostedt (Google) }
5342cc621fdSSteven Rostedt (Google)
5352cc621fdSSteven Rostedt (Google) return NULL;
5362cc621fdSSteven Rostedt (Google) }
5372cc621fdSSteven Rostedt (Google)
saved_cmdlines_start(struct seq_file * m,loff_t * pos)5382cc621fdSSteven Rostedt (Google) static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos)
5392cc621fdSSteven Rostedt (Google) {
5402cc621fdSSteven Rostedt (Google) void *v;
5412cc621fdSSteven Rostedt (Google) loff_t l = 0;
5422cc621fdSSteven Rostedt (Google)
5432cc621fdSSteven Rostedt (Google) preempt_disable();
5442cc621fdSSteven Rostedt (Google) arch_spin_lock(&trace_cmdline_lock);
5452cc621fdSSteven Rostedt (Google)
5462cc621fdSSteven Rostedt (Google) v = &savedcmd->map_cmdline_to_pid[0];
5472cc621fdSSteven Rostedt (Google) while (l <= *pos) {
5482cc621fdSSteven Rostedt (Google) v = saved_cmdlines_next(m, v, &l);
5492cc621fdSSteven Rostedt (Google) if (!v)
5502cc621fdSSteven Rostedt (Google) return NULL;
5512cc621fdSSteven Rostedt (Google) }
5522cc621fdSSteven Rostedt (Google)
5532cc621fdSSteven Rostedt (Google) return v;
5542cc621fdSSteven Rostedt (Google) }
5552cc621fdSSteven Rostedt (Google)
saved_cmdlines_stop(struct seq_file * m,void * v)5562cc621fdSSteven Rostedt (Google) static void saved_cmdlines_stop(struct seq_file *m, void *v)
5572cc621fdSSteven Rostedt (Google) {
5582cc621fdSSteven Rostedt (Google) arch_spin_unlock(&trace_cmdline_lock);
5592cc621fdSSteven Rostedt (Google) preempt_enable();
5602cc621fdSSteven Rostedt (Google) }
5612cc621fdSSteven Rostedt (Google)
saved_cmdlines_show(struct seq_file * m,void * v)5622cc621fdSSteven Rostedt (Google) static int saved_cmdlines_show(struct seq_file *m, void *v)
5632cc621fdSSteven Rostedt (Google) {
5642cc621fdSSteven Rostedt (Google) char buf[TASK_COMM_LEN];
5652cc621fdSSteven Rostedt (Google) unsigned int *pid = v;
5662cc621fdSSteven Rostedt (Google)
5672cc621fdSSteven Rostedt (Google) __trace_find_cmdline(*pid, buf);
5682cc621fdSSteven Rostedt (Google) seq_printf(m, "%d %s\n", *pid, buf);
5692cc621fdSSteven Rostedt (Google) return 0;
5702cc621fdSSteven Rostedt (Google) }
5712cc621fdSSteven Rostedt (Google)
5722cc621fdSSteven Rostedt (Google) static const struct seq_operations tracing_saved_cmdlines_seq_ops = {
5732cc621fdSSteven Rostedt (Google) .start = saved_cmdlines_start,
5742cc621fdSSteven Rostedt (Google) .next = saved_cmdlines_next,
5752cc621fdSSteven Rostedt (Google) .stop = saved_cmdlines_stop,
5762cc621fdSSteven Rostedt (Google) .show = saved_cmdlines_show,
5772cc621fdSSteven Rostedt (Google) };
5782cc621fdSSteven Rostedt (Google)
tracing_saved_cmdlines_open(struct inode * inode,struct file * filp)5792cc621fdSSteven Rostedt (Google) static int tracing_saved_cmdlines_open(struct inode *inode, struct file *filp)
5802cc621fdSSteven Rostedt (Google) {
5812cc621fdSSteven Rostedt (Google) int ret;
5822cc621fdSSteven Rostedt (Google)
5832cc621fdSSteven Rostedt (Google) ret = tracing_check_open_get_tr(NULL);
5842cc621fdSSteven Rostedt (Google) if (ret)
5852cc621fdSSteven Rostedt (Google) return ret;
5862cc621fdSSteven Rostedt (Google)
5872cc621fdSSteven Rostedt (Google) return seq_open(filp, &tracing_saved_cmdlines_seq_ops);
5882cc621fdSSteven Rostedt (Google) }
5892cc621fdSSteven Rostedt (Google)
5902cc621fdSSteven Rostedt (Google) const struct file_operations tracing_saved_cmdlines_fops = {
5912cc621fdSSteven Rostedt (Google) .open = tracing_saved_cmdlines_open,
5922cc621fdSSteven Rostedt (Google) .read = seq_read,
5932cc621fdSSteven Rostedt (Google) .llseek = seq_lseek,
5942cc621fdSSteven Rostedt (Google) .release = seq_release,
5952cc621fdSSteven Rostedt (Google) };
5962cc621fdSSteven Rostedt (Google)
5972cc621fdSSteven Rostedt (Google) static ssize_t
tracing_saved_cmdlines_size_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)5982cc621fdSSteven Rostedt (Google) tracing_saved_cmdlines_size_read(struct file *filp, char __user *ubuf,
5992cc621fdSSteven Rostedt (Google) size_t cnt, loff_t *ppos)
6002cc621fdSSteven Rostedt (Google) {
6012cc621fdSSteven Rostedt (Google) char buf[64];
6022cc621fdSSteven Rostedt (Google) int r;
6032cc621fdSSteven Rostedt (Google)
6042cc621fdSSteven Rostedt (Google) preempt_disable();
6052cc621fdSSteven Rostedt (Google) arch_spin_lock(&trace_cmdline_lock);
6062cc621fdSSteven Rostedt (Google) r = scnprintf(buf, sizeof(buf), "%u\n", savedcmd->cmdline_num);
6072cc621fdSSteven Rostedt (Google) arch_spin_unlock(&trace_cmdline_lock);
6082cc621fdSSteven Rostedt (Google) preempt_enable();
6092cc621fdSSteven Rostedt (Google)
6102cc621fdSSteven Rostedt (Google) return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
6112cc621fdSSteven Rostedt (Google) }
6122cc621fdSSteven Rostedt (Google)
trace_free_saved_cmdlines_buffer(void)6132cc621fdSSteven Rostedt (Google) void trace_free_saved_cmdlines_buffer(void)
6142cc621fdSSteven Rostedt (Google) {
6152cc621fdSSteven Rostedt (Google) free_saved_cmdlines_buffer(savedcmd);
6162cc621fdSSteven Rostedt (Google) }
6172cc621fdSSteven Rostedt (Google)
tracing_resize_saved_cmdlines(unsigned int val)6182cc621fdSSteven Rostedt (Google) static int tracing_resize_saved_cmdlines(unsigned int val)
6192cc621fdSSteven Rostedt (Google) {
6202cc621fdSSteven Rostedt (Google) struct saved_cmdlines_buffer *s, *savedcmd_temp;
6212cc621fdSSteven Rostedt (Google)
6222cc621fdSSteven Rostedt (Google) s = allocate_cmdlines_buffer(val);
6232cc621fdSSteven Rostedt (Google) if (!s)
6242cc621fdSSteven Rostedt (Google) return -ENOMEM;
6252cc621fdSSteven Rostedt (Google)
6262cc621fdSSteven Rostedt (Google) preempt_disable();
6272cc621fdSSteven Rostedt (Google) arch_spin_lock(&trace_cmdline_lock);
6282cc621fdSSteven Rostedt (Google) savedcmd_temp = savedcmd;
6292cc621fdSSteven Rostedt (Google) savedcmd = s;
6302cc621fdSSteven Rostedt (Google) arch_spin_unlock(&trace_cmdline_lock);
6312cc621fdSSteven Rostedt (Google) preempt_enable();
6322cc621fdSSteven Rostedt (Google) free_saved_cmdlines_buffer(savedcmd_temp);
6332cc621fdSSteven Rostedt (Google)
6342cc621fdSSteven Rostedt (Google) return 0;
6352cc621fdSSteven Rostedt (Google) }
6362cc621fdSSteven Rostedt (Google)
6372cc621fdSSteven Rostedt (Google) static ssize_t
tracing_saved_cmdlines_size_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)6382cc621fdSSteven Rostedt (Google) tracing_saved_cmdlines_size_write(struct file *filp, const char __user *ubuf,
6392cc621fdSSteven Rostedt (Google) size_t cnt, loff_t *ppos)
6402cc621fdSSteven Rostedt (Google) {
6412cc621fdSSteven Rostedt (Google) unsigned long val;
6422cc621fdSSteven Rostedt (Google) int ret;
6432cc621fdSSteven Rostedt (Google)
6442cc621fdSSteven Rostedt (Google) ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
6452cc621fdSSteven Rostedt (Google) if (ret)
6462cc621fdSSteven Rostedt (Google) return ret;
6472cc621fdSSteven Rostedt (Google)
6482cc621fdSSteven Rostedt (Google) /* must have at least 1 entry or less than PID_MAX_DEFAULT */
6492cc621fdSSteven Rostedt (Google) if (!val || val > PID_MAX_DEFAULT)
6502cc621fdSSteven Rostedt (Google) return -EINVAL;
6512cc621fdSSteven Rostedt (Google)
6522cc621fdSSteven Rostedt (Google) ret = tracing_resize_saved_cmdlines((unsigned int)val);
6532cc621fdSSteven Rostedt (Google) if (ret < 0)
6542cc621fdSSteven Rostedt (Google) return ret;
6552cc621fdSSteven Rostedt (Google)
6562cc621fdSSteven Rostedt (Google) *ppos += cnt;
6572cc621fdSSteven Rostedt (Google)
6582cc621fdSSteven Rostedt (Google) return cnt;
6592cc621fdSSteven Rostedt (Google) }
6602cc621fdSSteven Rostedt (Google)
6612cc621fdSSteven Rostedt (Google) const struct file_operations tracing_saved_cmdlines_size_fops = {
6622cc621fdSSteven Rostedt (Google) .open = tracing_open_generic,
6632cc621fdSSteven Rostedt (Google) .read = tracing_saved_cmdlines_size_read,
6642cc621fdSSteven Rostedt (Google) .write = tracing_saved_cmdlines_size_write,
6652cc621fdSSteven Rostedt (Google) };
666