[PATCH -tip 2/2] ftrace: Introduce nr_saved_cmdlines I/F
Introduce nr_saved_cmdlines I/F for changing the number of pid-comm list. saved_cmdlines can store 128 command names using SAVED_CMDLINES now, but 'no-existing processes' names are often lost in saved_cmdlines when we read trace data. So, by introducing nr_saved_cmdlines I/F, the rule storing 128 command names is changed to the command numbers defined users. When we write a value to nr_saved_cmdlines, the number of the value will be stored in pid-comm list: # echo 1024 > /sys/kernel/debug/tracing/nr_saved_cmdlines Here, 1024 command names are stored. The default number is 128 and the maximum number is PID_MAX_DEFAULT (=32768 if CONFIG_BASE_SMALL is not set). So, if we want to avoid to lose command names, we need to set 32768 to nr_saved_cmdlines. We can read the maximum number of the list: # cat /sys/kernel/debug/tracing/nr_saved_cmdlines 128 Signed-off-by: Yoshihiro YUNOMAE Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: linux-kernel@vger.kernel.org --- kernel/trace/trace.c | 211 +- 1 file changed, 189 insertions(+), 22 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 90cf668..afdcdfd 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1237,22 +1237,96 @@ void tracing_reset_all_online_cpus(void) } } -#define SAVED_CMDLINES 128 +#define SAVED_CMDLINES_DEFAULT 128 #define NO_CMDLINE_MAP UINT_MAX -static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; -static unsigned map_cmdline_to_pid[SAVED_CMDLINES]; -static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN]; -static int cmdline_idx; static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED; +struct saved_cmdlines_buffer { + unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; + unsigned *map_cmdline_to_pid; + unsigned cmdline_num; + int cmdline_idx; + char *saved_cmdlines; +}; +static struct saved_cmdlines_buffer *savedcmd; /* temporary disable recording */ static atomic_t trace_record_cmdline_disabled __read_mostly; -static void trace_init_cmdlines(void) +static inline char *get_cmdline(int idx) +{ + return >saved_cmdlines[idx*TASK_COMM_LEN]; +} + +static inline void set_cmdline(int idx, char *cmdline) +{ + memcpy(get_cmdline(idx), cmdline, TASK_COMM_LEN); +} + +static int allocate_cmdlines_buffer(unsigned int val, + struct saved_cmdlines_buffer *s) { - memset(_pid_to_cmdline, NO_CMDLINE_MAP, sizeof(map_pid_to_cmdline)); - memset(_cmdline_to_pid, NO_CMDLINE_MAP, sizeof(map_cmdline_to_pid)); - cmdline_idx = 0; + s->map_cmdline_to_pid = kmalloc(val*sizeof(unsigned), GFP_KERNEL); + if (!s->map_cmdline_to_pid) + goto out; + + s->saved_cmdlines = kmalloc(val*TASK_COMM_LEN, GFP_KERNEL); + if (!s->saved_cmdlines) + goto out_free_map_cmdline_to_pid; + + return 0; + +out_free_map_cmdline_to_pid: + kfree(s->map_cmdline_to_pid); +out: + return -ENOMEM; +} + +static void trace_init_cmdlines_buffer(unsigned int val, + struct saved_cmdlines_buffer *s) +{ + s->cmdline_idx = 0; + s->cmdline_num = val; + memset(>map_pid_to_cmdline, NO_CMDLINE_MAP, + sizeof(s->map_pid_to_cmdline)); + memset(s->map_cmdline_to_pid, NO_CMDLINE_MAP, val*sizeof(unsigned)); +} + +static int trace_create_savedcmd(void) +{ + int ret; + + savedcmd = kmalloc(sizeof(struct saved_cmdlines_buffer), GFP_KERNEL); + if (!savedcmd) + goto out; + + ret = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd); + if (ret < 0) + goto out_free; + + return 0; + +out_free: + kfree(savedcmd); +out: + return -ENOMEM; +} + +static void trace_init_savedcmd(void) +{ + trace_init_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd); +} + +static int trace_create_and_init_savedcmd(void) +{ + int ret; + + ret = trace_create_savedcmd(); + if (ret < 0) + return ret; + + trace_init_savedcmd(); + + return 0; } int is_tracing_stopped(void) @@ -1424,9 +1498,9 @@ static void trace_save_cmdline(struct task_struct *tsk) if (!arch_spin_trylock(_cmdline_lock)) return; - idx = map_pid_to_cmdline[tsk->pid]; + idx = savedcmd->map_pid_to_cmdline[tsk->pid]; if (idx == NO_CMDLINE_MAP) { - idx = (cmdline_idx + 1) % SAVED_CMDLINES; + idx = (savedcmd->cmdline_idx + 1) % savedcmd->cmdline_num; /* * Check whether the cmdline buffer at idx has a pid @@ -1434,17 +1508,17 @@ static void trace_save_cmdline(struct task_struct *tsk) * need to clear the map_pid_to_cmdline. Otherwise we * would read the new comm for the old pid. */ - pid =
[PATCH -tip 2/2] ftrace: Introduce nr_saved_cmdlines I/F
Introduce nr_saved_cmdlines I/F for changing the number of pid-comm list. saved_cmdlines can store 128 command names using SAVED_CMDLINES now, but 'no-existing processes' names are often lost in saved_cmdlines when we read trace data. So, by introducing nr_saved_cmdlines I/F, the rule storing 128 command names is changed to the command numbers defined users. When we write a value to nr_saved_cmdlines, the number of the value will be stored in pid-comm list: # echo 1024 /sys/kernel/debug/tracing/nr_saved_cmdlines Here, 1024 command names are stored. The default number is 128 and the maximum number is PID_MAX_DEFAULT (=32768 if CONFIG_BASE_SMALL is not set). So, if we want to avoid to lose command names, we need to set 32768 to nr_saved_cmdlines. We can read the maximum number of the list: # cat /sys/kernel/debug/tracing/nr_saved_cmdlines 128 Signed-off-by: Yoshihiro YUNOMAE yoshihiro.yunomae...@hitachi.com Cc: Steven Rostedt rost...@goodmis.org Cc: Frederic Weisbecker fweis...@gmail.com Cc: Ingo Molnar mi...@redhat.com Cc: linux-kernel@vger.kernel.org --- kernel/trace/trace.c | 211 +- 1 file changed, 189 insertions(+), 22 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 90cf668..afdcdfd 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1237,22 +1237,96 @@ void tracing_reset_all_online_cpus(void) } } -#define SAVED_CMDLINES 128 +#define SAVED_CMDLINES_DEFAULT 128 #define NO_CMDLINE_MAP UINT_MAX -static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; -static unsigned map_cmdline_to_pid[SAVED_CMDLINES]; -static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN]; -static int cmdline_idx; static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED; +struct saved_cmdlines_buffer { + unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; + unsigned *map_cmdline_to_pid; + unsigned cmdline_num; + int cmdline_idx; + char *saved_cmdlines; +}; +static struct saved_cmdlines_buffer *savedcmd; /* temporary disable recording */ static atomic_t trace_record_cmdline_disabled __read_mostly; -static void trace_init_cmdlines(void) +static inline char *get_cmdline(int idx) +{ + return savedcmd-saved_cmdlines[idx*TASK_COMM_LEN]; +} + +static inline void set_cmdline(int idx, char *cmdline) +{ + memcpy(get_cmdline(idx), cmdline, TASK_COMM_LEN); +} + +static int allocate_cmdlines_buffer(unsigned int val, + struct saved_cmdlines_buffer *s) { - memset(map_pid_to_cmdline, NO_CMDLINE_MAP, sizeof(map_pid_to_cmdline)); - memset(map_cmdline_to_pid, NO_CMDLINE_MAP, sizeof(map_cmdline_to_pid)); - cmdline_idx = 0; + s-map_cmdline_to_pid = kmalloc(val*sizeof(unsigned), GFP_KERNEL); + if (!s-map_cmdline_to_pid) + goto out; + + s-saved_cmdlines = kmalloc(val*TASK_COMM_LEN, GFP_KERNEL); + if (!s-saved_cmdlines) + goto out_free_map_cmdline_to_pid; + + return 0; + +out_free_map_cmdline_to_pid: + kfree(s-map_cmdline_to_pid); +out: + return -ENOMEM; +} + +static void trace_init_cmdlines_buffer(unsigned int val, + struct saved_cmdlines_buffer *s) +{ + s-cmdline_idx = 0; + s-cmdline_num = val; + memset(s-map_pid_to_cmdline, NO_CMDLINE_MAP, + sizeof(s-map_pid_to_cmdline)); + memset(s-map_cmdline_to_pid, NO_CMDLINE_MAP, val*sizeof(unsigned)); +} + +static int trace_create_savedcmd(void) +{ + int ret; + + savedcmd = kmalloc(sizeof(struct saved_cmdlines_buffer), GFP_KERNEL); + if (!savedcmd) + goto out; + + ret = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd); + if (ret 0) + goto out_free; + + return 0; + +out_free: + kfree(savedcmd); +out: + return -ENOMEM; +} + +static void trace_init_savedcmd(void) +{ + trace_init_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd); +} + +static int trace_create_and_init_savedcmd(void) +{ + int ret; + + ret = trace_create_savedcmd(); + if (ret 0) + return ret; + + trace_init_savedcmd(); + + return 0; } int is_tracing_stopped(void) @@ -1424,9 +1498,9 @@ static void trace_save_cmdline(struct task_struct *tsk) if (!arch_spin_trylock(trace_cmdline_lock)) return; - idx = map_pid_to_cmdline[tsk-pid]; + idx = savedcmd-map_pid_to_cmdline[tsk-pid]; if (idx == NO_CMDLINE_MAP) { - idx = (cmdline_idx + 1) % SAVED_CMDLINES; + idx = (savedcmd-cmdline_idx + 1) % savedcmd-cmdline_num; /* * Check whether the cmdline buffer at idx has a pid @@ -1434,17 +1508,17 @@ static void trace_save_cmdline(struct task_struct *tsk) * need to clear the map_pid_to_cmdline. Otherwise we * would