Commit 7e465baa authored by Tom Zanussi's avatar Tom Zanussi Committed by Steven Rostedt (VMware)

tracing: Make traceprobe parsing code reusable

traceprobe_probes_write() and traceprobe_command() actually contain
nothing that ties them to kprobes - the code is generically useful for
similar types of parsing elsewhere, so separate it out and move it to
trace.c/trace.h.

Other than moving it, the only change is in naming:
traceprobe_probes_write() becomes trace_parse_run_command() and
traceprobe_command() becomes trace_run_command().

Link: http://lkml.kernel.org/r/ae5c26ea40c196a8986854d921eb6e713ede7e3f.1506105045.git.tom.zanussi@linux.intel.comSigned-off-by: default avatarTom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 4f36c2d8
...@@ -8281,6 +8281,92 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) ...@@ -8281,6 +8281,92 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
} }
EXPORT_SYMBOL_GPL(ftrace_dump); EXPORT_SYMBOL_GPL(ftrace_dump);
int trace_run_command(const char *buf, int (*createfn)(int, char **))
{
char **argv;
int argc, ret;
argc = 0;
ret = 0;
argv = argv_split(GFP_KERNEL, buf, &argc);
if (!argv)
return -ENOMEM;
if (argc)
ret = createfn(argc, argv);
argv_free(argv);
return ret;
}
#define WRITE_BUFSIZE 4096
ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
int (*createfn)(int, char **))
{
char *kbuf, *buf, *tmp;
int ret = 0;
size_t done = 0;
size_t size;
kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
while (done < count) {
size = count - done;
if (size >= WRITE_BUFSIZE)
size = WRITE_BUFSIZE - 1;
if (copy_from_user(kbuf, buffer + done, size)) {
ret = -EFAULT;
goto out;
}
kbuf[size] = '\0';
buf = kbuf;
do {
tmp = strchr(buf, '\n');
if (tmp) {
*tmp = '\0';
size = tmp - buf + 1;
} else {
size = strlen(buf);
if (done + size < count) {
if (buf != kbuf)
break;
/* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */
pr_warn("Line length is too long: Should be less than %d\n",
WRITE_BUFSIZE - 2);
ret = -EINVAL;
goto out;
}
}
done += size;
/* Remove comments */
tmp = strchr(buf, '#');
if (tmp)
*tmp = '\0';
ret = trace_run_command(buf, createfn);
if (ret)
goto out;
buf += size;
} while (done < count);
}
ret = done;
out:
kfree(kbuf);
return ret;
}
__init static int tracer_alloc_buffers(void) __init static int tracer_alloc_buffers(void)
{ {
int ring_buf_size; int ring_buf_size;
......
...@@ -1752,6 +1752,13 @@ void trace_printk_start_comm(void); ...@@ -1752,6 +1752,13 @@ void trace_printk_start_comm(void);
int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set); int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled); int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled);
#define MAX_EVENT_NAME_LEN 64
extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
int (*createfn)(int, char**));
/* /*
* Normal trace_printk() and friends allocates special buffers * Normal trace_printk() and friends allocates special buffers
* to do the manipulation, as well as saves the print formats * to do the manipulation, as well as saves the print formats
......
...@@ -907,8 +907,8 @@ static int probes_open(struct inode *inode, struct file *file) ...@@ -907,8 +907,8 @@ static int probes_open(struct inode *inode, struct file *file)
static ssize_t probes_write(struct file *file, const char __user *buffer, static ssize_t probes_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
return traceprobe_probes_write(file, buffer, count, ppos, return trace_parse_run_command(file, buffer, count, ppos,
create_trace_kprobe); create_trace_kprobe);
} }
static const struct file_operations kprobe_events_ops = { static const struct file_operations kprobe_events_ops = {
...@@ -1433,9 +1433,9 @@ static __init int kprobe_trace_self_tests_init(void) ...@@ -1433,9 +1433,9 @@ static __init int kprobe_trace_self_tests_init(void)
pr_info("Testing kprobe tracing: "); pr_info("Testing kprobe tracing: ");
ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target " ret = trace_run_command("p:testprobe kprobe_trace_selftest_target "
"$stack $stack0 +0($stack)", "$stack $stack0 +0($stack)",
create_trace_kprobe); create_trace_kprobe);
if (WARN_ON_ONCE(ret)) { if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function entry.\n"); pr_warn("error on probing function entry.\n");
warn++; warn++;
...@@ -1455,8 +1455,8 @@ static __init int kprobe_trace_self_tests_init(void) ...@@ -1455,8 +1455,8 @@ static __init int kprobe_trace_self_tests_init(void)
} }
} }
ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " ret = trace_run_command("r:testprobe2 kprobe_trace_selftest_target "
"$retval", create_trace_kprobe); "$retval", create_trace_kprobe);
if (WARN_ON_ONCE(ret)) { if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function return.\n"); pr_warn("error on probing function return.\n");
warn++; warn++;
...@@ -1526,13 +1526,13 @@ static __init int kprobe_trace_self_tests_init(void) ...@@ -1526,13 +1526,13 @@ static __init int kprobe_trace_self_tests_init(void)
disable_trace_kprobe(tk, file); disable_trace_kprobe(tk, file);
} }
ret = traceprobe_command("-:testprobe", create_trace_kprobe); ret = trace_run_command("-:testprobe", create_trace_kprobe);
if (WARN_ON_ONCE(ret)) { if (WARN_ON_ONCE(ret)) {
pr_warn("error on deleting a probe.\n"); pr_warn("error on deleting a probe.\n");
warn++; warn++;
} }
ret = traceprobe_command("-:testprobe2", create_trace_kprobe); ret = trace_run_command("-:testprobe2", create_trace_kprobe);
if (WARN_ON_ONCE(ret)) { if (WARN_ON_ONCE(ret)) {
pr_warn("error on deleting a probe.\n"); pr_warn("error on deleting a probe.\n");
warn++; warn++;
......
...@@ -623,92 +623,6 @@ void traceprobe_free_probe_arg(struct probe_arg *arg) ...@@ -623,92 +623,6 @@ void traceprobe_free_probe_arg(struct probe_arg *arg)
kfree(arg->comm); kfree(arg->comm);
} }
int traceprobe_command(const char *buf, int (*createfn)(int, char **))
{
char **argv;
int argc, ret;
argc = 0;
ret = 0;
argv = argv_split(GFP_KERNEL, buf, &argc);
if (!argv)
return -ENOMEM;
if (argc)
ret = createfn(argc, argv);
argv_free(argv);
return ret;
}
#define WRITE_BUFSIZE 4096
ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
int (*createfn)(int, char **))
{
char *kbuf, *buf, *tmp;
int ret = 0;
size_t done = 0;
size_t size;
kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
while (done < count) {
size = count - done;
if (size >= WRITE_BUFSIZE)
size = WRITE_BUFSIZE - 1;
if (copy_from_user(kbuf, buffer + done, size)) {
ret = -EFAULT;
goto out;
}
kbuf[size] = '\0';
buf = kbuf;
do {
tmp = strchr(buf, '\n');
if (tmp) {
*tmp = '\0';
size = tmp - buf + 1;
} else {
size = strlen(buf);
if (done + size < count) {
if (buf != kbuf)
break;
/* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */
pr_warn("Line length is too long: Should be less than %d\n",
WRITE_BUFSIZE - 2);
ret = -EINVAL;
goto out;
}
}
done += size;
/* Remove comments */
tmp = strchr(buf, '#');
if (tmp)
*tmp = '\0';
ret = traceprobe_command(buf, createfn);
if (ret)
goto out;
buf += size;
} while (done < count);
}
ret = done;
out:
kfree(kbuf);
return ret;
}
static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
bool is_return) bool is_return)
{ {
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#define MAX_TRACE_ARGS 128 #define MAX_TRACE_ARGS 128
#define MAX_ARGSTR_LEN 63 #define MAX_ARGSTR_LEN 63
#define MAX_EVENT_NAME_LEN 64
#define MAX_STRING_SIZE PATH_MAX #define MAX_STRING_SIZE PATH_MAX
/* Reserved field names */ /* Reserved field names */
...@@ -356,12 +355,6 @@ extern void traceprobe_free_probe_arg(struct probe_arg *arg); ...@@ -356,12 +355,6 @@ extern void traceprobe_free_probe_arg(struct probe_arg *arg);
extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset); extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset);
extern ssize_t traceprobe_probes_write(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
int (*createfn)(int, char**));
extern int traceprobe_command(const char *buf, int (*createfn)(int, char**));
/* Sum up total data length for dynamic arraies (strings) */ /* Sum up total data length for dynamic arraies (strings) */
static nokprobe_inline int static nokprobe_inline int
__get_data_size(struct trace_probe *tp, struct pt_regs *regs) __get_data_size(struct trace_probe *tp, struct pt_regs *regs)
......
...@@ -651,7 +651,7 @@ static int probes_open(struct inode *inode, struct file *file) ...@@ -651,7 +651,7 @@ static int probes_open(struct inode *inode, struct file *file)
static ssize_t probes_write(struct file *file, const char __user *buffer, static ssize_t probes_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe); return trace_parse_run_command(file, buffer, count, ppos, create_trace_uprobe);
} }
static const struct file_operations uprobe_events_ops = { static const struct file_operations uprobe_events_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment