[PATCH -tip 2/2] ftrace: Introduce nr_saved_cmdlines I/F

2013-11-07 Thread Yoshihiro YUNOMAE
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

2013-11-07 Thread Yoshihiro YUNOMAE
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