aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorYoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>2014-02-20 03:44:31 -0500
committerSteven Rostedt <rostedt@goodmis.org>2014-05-29 23:08:07 -0400
commit42584c81c5adc1737a6fe0687facc5e62a5dc8c1 (patch)
tree25dbedd93aa7618d436495cce800627cf1761d8e /kernel
parent81dc9f0ef21e40114cc895894c7acf3055f6d1fb (diff)
tracing: Have saved_cmdlines use the seq_read infrastructure
Current tracing_saved_cmdlines_read() implementation is naive; It allocates a large buffer, constructs output data to that buffer for each read operation, and then copies a portion of the buffer to the user space buffer. This has several issues such as slow memory allocation, high CPU usage, and even corruption of the output data. The seq_read infrastructure is made to handle this type of work. By converting it to use seq_read() the code becomes smaller, simplified, as well as correct. Link: http://lkml.kernel.org/p/20140220084431.3839.51793.stgit@yunodevel Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: linux-kernel@vger.kernel.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c89
1 files changed, 54 insertions, 35 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index eb228b9de170..1855dae73f34 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3699,55 +3699,74 @@ static const struct file_operations tracing_readme_fops = {
3699 .llseek = generic_file_llseek, 3699 .llseek = generic_file_llseek,
3700}; 3700};
3701 3701
3702static ssize_t 3702static void *saved_cmdlines_next(struct seq_file *m, void *v, loff_t *pos)
3703tracing_saved_cmdlines_read(struct file *file, char __user *ubuf,
3704 size_t cnt, loff_t *ppos)
3705{ 3703{
3706 char *buf_comm; 3704 unsigned int *ptr = v;
3707 char *file_buf;
3708 char *buf;
3709 int len = 0;
3710 int pid;
3711 int i;
3712 3705
3713 file_buf = kmalloc(SAVED_CMDLINES*(16+TASK_COMM_LEN), GFP_KERNEL); 3706 if (*pos || m->count)
3714 if (!file_buf) 3707 ptr++;
3715 return -ENOMEM;
3716 3708
3717 buf_comm = kmalloc(TASK_COMM_LEN, GFP_KERNEL); 3709 (*pos)++;
3718 if (!buf_comm) { 3710
3719 kfree(file_buf); 3711 for (; ptr < &map_cmdline_to_pid[SAVED_CMDLINES]; ptr++) {
3720 return -ENOMEM; 3712 if (*ptr == -1 || *ptr == NO_CMDLINE_MAP)
3721 } 3713 continue;
3722 3714
3723 buf = file_buf; 3715 return ptr;
3716 }
3724 3717
3725 for (i = 0; i < SAVED_CMDLINES; i++) { 3718 return NULL;
3726 int r; 3719}
3727 3720
3728 pid = map_cmdline_to_pid[i]; 3721static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos)
3729 if (pid == -1 || pid == NO_CMDLINE_MAP) 3722{
3730 continue; 3723 void *v;
3724 loff_t l = 0;
3731 3725
3732 trace_find_cmdline(pid, buf_comm); 3726 v = &map_cmdline_to_pid[0];
3733 r = sprintf(buf, "%d %s\n", pid, buf_comm); 3727 while (l <= *pos) {
3734 buf += r; 3728 v = saved_cmdlines_next(m, v, &l);
3735 len += r; 3729 if (!v)
3730 return NULL;
3736 } 3731 }
3737 3732
3738 len = simple_read_from_buffer(ubuf, cnt, ppos, 3733 return v;
3739 file_buf, len); 3734}
3740 3735
3741 kfree(file_buf); 3736static void saved_cmdlines_stop(struct seq_file *m, void *v)
3742 kfree(buf_comm); 3737{
3738}
3743 3739
3744 return len; 3740static int saved_cmdlines_show(struct seq_file *m, void *v)
3741{
3742 char buf[TASK_COMM_LEN];
3743 unsigned int *pid = v;
3744
3745 trace_find_cmdline(*pid, buf);
3746 seq_printf(m, "%d %s\n", *pid, buf);
3747 return 0;
3748}
3749
3750static const struct seq_operations tracing_saved_cmdlines_seq_ops = {
3751 .start = saved_cmdlines_start,
3752 .next = saved_cmdlines_next,
3753 .stop = saved_cmdlines_stop,
3754 .show = saved_cmdlines_show,
3755};
3756
3757static int tracing_saved_cmdlines_open(struct inode *inode, struct file *filp)
3758{
3759 if (tracing_disabled)
3760 return -ENODEV;
3761
3762 return seq_open(filp, &tracing_saved_cmdlines_seq_ops);
3745} 3763}
3746 3764
3747static const struct file_operations tracing_saved_cmdlines_fops = { 3765static const struct file_operations tracing_saved_cmdlines_fops = {
3748 .open = tracing_open_generic, 3766 .open = tracing_saved_cmdlines_open,
3749 .read = tracing_saved_cmdlines_read, 3767 .read = seq_read,
3750 .llseek = generic_file_llseek, 3768 .llseek = seq_lseek,
3769 .release = seq_release,
3751}; 3770};
3752 3771
3753static ssize_t 3772static ssize_t