aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorjolsa@redhat.com <jolsa@redhat.com>2009-09-11 11:29:27 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-09-11 14:46:55 -0400
commitb63f39ea50330f836e301ddda21c6a93dcf0d6a3 (patch)
tree3fb5a88ca19da6417a52b83eff585b9413bfb9c9 /kernel
parentf81c972d27c36729e65d4a815e3d7b782a540bad (diff)
tracing: create generic trace parser
Create a "trace_parser" that can parse the user space input for separate words. struct trace_parser is the descriptor. Generic "trace_get_user" function that can be a helper to read multiple words passed in by user space. Signed-off-by: Jiri Olsa <jolsa@redhat.com> LKML-Reference: <1252682969-3366-2-git-send-email-jolsa@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c106
-rw-r--r--kernel/trace/trace.h35
2 files changed, 141 insertions, 0 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3b918283cf94..45c3f0352d78 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -339,6 +339,112 @@ static struct {
339 339
340int trace_clock_id; 340int trace_clock_id;
341 341
342/*
343 * trace_parser_get_init - gets the buffer for trace parser
344 */
345int trace_parser_get_init(struct trace_parser *parser, int size)
346{
347 memset(parser, 0, sizeof(*parser));
348
349 parser->buffer = kmalloc(size, GFP_KERNEL);
350 if (!parser->buffer)
351 return 1;
352
353 parser->size = size;
354 return 0;
355}
356
357/*
358 * trace_parser_put - frees the buffer for trace parser
359 */
360void trace_parser_put(struct trace_parser *parser)
361{
362 kfree(parser->buffer);
363}
364
365/*
366 * trace_get_user - reads the user input string separated by space
367 * (matched by isspace(ch))
368 *
369 * For each string found the 'struct trace_parser' is updated,
370 * and the function returns.
371 *
372 * Returns number of bytes read.
373 *
374 * See kernel/trace/trace.h for 'struct trace_parser' details.
375 */
376int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
377 size_t cnt, loff_t *ppos)
378{
379 char ch;
380 size_t read = 0;
381 ssize_t ret;
382
383 if (!*ppos)
384 trace_parser_clear(parser);
385
386 ret = get_user(ch, ubuf++);
387 if (ret)
388 goto out;
389
390 read++;
391 cnt--;
392
393 /*
394 * The parser is not finished with the last write,
395 * continue reading the user input without skipping spaces.
396 */
397 if (!parser->cont) {
398 /* skip white space */
399 while (cnt && isspace(ch)) {
400 ret = get_user(ch, ubuf++);
401 if (ret)
402 goto out;
403 read++;
404 cnt--;
405 }
406
407 /* only spaces were written */
408 if (isspace(ch)) {
409 *ppos += read;
410 ret = read;
411 goto out;
412 }
413
414 parser->idx = 0;
415 }
416
417 /* read the non-space input */
418 while (cnt && !isspace(ch)) {
419 if (parser->idx < parser->size)
420 parser->buffer[parser->idx++] = ch;
421 else {
422 ret = -EINVAL;
423 goto out;
424 }
425 ret = get_user(ch, ubuf++);
426 if (ret)
427 goto out;
428 read++;
429 cnt--;
430 }
431
432 /* We either got finished input or we have to wait for another call. */
433 if (isspace(ch)) {
434 parser->buffer[parser->idx] = 0;
435 parser->cont = false;
436 } else {
437 parser->cont = true;
438 parser->buffer[parser->idx++] = ch;
439 }
440
441 *ppos += read;
442 ret = read;
443
444out:
445 return ret;
446}
447
342ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) 448ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
343{ 449{
344 int len; 450 int len;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index b69697b4b846..28247cecd955 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -616,6 +616,41 @@ static inline int ftrace_trace_task(struct task_struct *task)
616#endif 616#endif
617 617
618/* 618/*
619 * struct trace_parser - servers for reading the user input separated by spaces
620 * @cont: set if the input is not complete - no final space char was found
621 * @buffer: holds the parsed user input
622 * @idx: user input lenght
623 * @size: buffer size
624 */
625struct trace_parser {
626 bool cont;
627 char *buffer;
628 unsigned idx;
629 unsigned size;
630};
631
632static inline bool trace_parser_loaded(struct trace_parser *parser)
633{
634 return (parser->idx != 0);
635}
636
637static inline bool trace_parser_cont(struct trace_parser *parser)
638{
639 return parser->cont;
640}
641
642static inline void trace_parser_clear(struct trace_parser *parser)
643{
644 parser->cont = false;
645 parser->idx = 0;
646}
647
648extern int trace_parser_get_init(struct trace_parser *parser, int size);
649extern void trace_parser_put(struct trace_parser *parser);
650extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
651 size_t cnt, loff_t *ppos);
652
653/*
619 * trace_iterator_flags is an enumeration that defines bit 654 * trace_iterator_flags is an enumeration that defines bit
620 * positions into trace_flags that controls the output. 655 * positions into trace_flags that controls the output.
621 * 656 *