Skip to content

Commit

Permalink
tracing: Make traceprobe parsing code reusable
Browse files Browse the repository at this point in the history
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.com

Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
  • Loading branch information
Tom Zanussi authored and Steven Rostedt (VMware) committed Oct 4, 2017
1 parent 4f36c2d commit 7e465ba
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 103 deletions.
86 changes: 86 additions & 0 deletions kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -8281,6 +8281,92 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
}
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)
{
int ring_buf_size;
Expand Down
7 changes: 7 additions & 0 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,13 @@ void trace_printk_start_comm(void);
int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
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
* to do the manipulation, as well as saves the print formats
Expand Down
18 changes: 9 additions & 9 deletions kernel/trace/trace_kprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
size_t count, loff_t *ppos)
{
return traceprobe_probes_write(file, buffer, count, ppos,
create_trace_kprobe);
return trace_parse_run_command(file, buffer, count, ppos,
create_trace_kprobe);
}

static const struct file_operations kprobe_events_ops = {
Expand Down Expand Up @@ -1433,9 +1433,9 @@ static __init int kprobe_trace_self_tests_init(void)

pr_info("Testing kprobe tracing: ");

ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target "
"$stack $stack0 +0($stack)",
create_trace_kprobe);
ret = trace_run_command("p:testprobe kprobe_trace_selftest_target "
"$stack $stack0 +0($stack)",
create_trace_kprobe);
if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function entry.\n");
warn++;
Expand All @@ -1455,8 +1455,8 @@ static __init int kprobe_trace_self_tests_init(void)
}
}

ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
"$retval", create_trace_kprobe);
ret = trace_run_command("r:testprobe2 kprobe_trace_selftest_target "
"$retval", create_trace_kprobe);
if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function return.\n");
warn++;
Expand Down Expand Up @@ -1526,13 +1526,13 @@ static __init int kprobe_trace_self_tests_init(void)
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)) {
pr_warn("error on deleting a probe.\n");
warn++;
}

ret = traceprobe_command("-:testprobe2", create_trace_kprobe);
ret = trace_run_command("-:testprobe2", create_trace_kprobe);
if (WARN_ON_ONCE(ret)) {
pr_warn("error on deleting a probe.\n");
warn++;
Expand Down
86 changes: 0 additions & 86 deletions kernel/trace/trace_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,92 +623,6 @@ void traceprobe_free_probe_arg(struct probe_arg *arg)
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,
bool is_return)
{
Expand Down
7 changes: 0 additions & 7 deletions kernel/trace/trace_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

#define MAX_TRACE_ARGS 128
#define MAX_ARGSTR_LEN 63
#define MAX_EVENT_NAME_LEN 64
#define MAX_STRING_SIZE PATH_MAX

/* Reserved field names */
Expand Down Expand Up @@ -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 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) */
static nokprobe_inline int
__get_data_size(struct trace_probe *tp, struct pt_regs *regs)
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_uprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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 = {
Expand Down

0 comments on commit 7e465ba

Please sign in to comment.