Messages in this thread Patch in this message | | | From | jolsa@redhat ... | Subject | [PATCH 0/3] tracing - adding common method for reading/parsing user input | Date | Fri, 4 Sep 2009 15:31:11 +0200 |
| |
Defined 'trace_biter' structure to carry the properties of the input, through the multiple writes.
The 'trace_get_user' reads the user incput string separated by space (matched by isspace(ch). For each string found the 'struct trace_biter' iterator is updated, and the function returns.
wbr, jirka
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
--- kernel/trace/trace.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/trace/trace.h | 48 +++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 0 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index af15008..8cf8f99 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -335,6 +335,89 @@ static struct { int trace_clock_id; +/* + * trace_get_user - reads the user incput string separated by space + * (matched by isspace(ch)) + * + * For each string found the 'struct trace_biter' iterator is updated, + * and the function returns. + * + * Returns number of bytes read. + * + * see kernel/trace/trace.h for 'struct trace_biter' details. + */ +int trace_get_user(struct trace_biter *biter, const char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + char ch; + size_t read = 0; + ssize_t ret; + + if (!*ppos) + TRACE_BITER_CLEAR(biter); + + ret = get_user(ch, ubuf++); + if (ret) + goto out; + + read++; + cnt--; + + /* + * If the parser haven't finished with the last write, + * continue reading the user input without skipping spaces. + */ + if (!biter->cont) { + /* skip white space */ + while (cnt && isspace(ch)) { + ret = get_user(ch, ubuf++); + if (ret) + goto out; + read++; + cnt--; + } + + /* only spaces were written */ + if (isspace(ch)) { + *ppos += read; + ret = read; + goto out; + } + + biter->idx = 0; + } + + /* read the non-space input */ + while (cnt && !isspace(ch)) { + if (biter->idx < biter->size) + biter->buffer[biter->idx++] = ch; + else { + ret = -EINVAL; + goto out; + } + ret = get_user(ch, ubuf++); + if (ret) + goto out; + read++; + cnt--; + } + + /* We either got finished input or we have to wait for another call. */ + if (isspace(ch)) { + biter->buffer[biter->idx] = 0; + biter->cont = 0; + } else { + biter->cont = 1; + biter->buffer[biter->idx++] = ch; + } + + *ppos += read; + ret = read; + +out: + return ret; +} + ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) { int len; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index d881015..d4e38e8 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -652,6 +652,54 @@ static inline int ftrace_trace_task(struct task_struct *task) #endif /* + * struct trace_biter - servers for reading the user input separated by spaces + * @cont: set if the input is not complete - no final space char was found + * @buffer: holds the parsed user input + * @idx: user input lenght + * @size: buffer size + */ +struct trace_biter { + bool cont; + char *buffer; + unsigned idx; + unsigned size; +}; + +#define TRACE_BITER_LOADED(biter) (biter->idx) +#define TRACE_BITER_CONT(biter) (biter->cont) +#define TRACE_BITER_CLEAR(biter) \ +do { \ + biter->cont = false; \ + biter->idx = 0; \ +} while(0) + +/* + * trace_biter_alloc - allocates the buffer for trace buffer iterator + */ +static inline int trace_biter_alloc(struct trace_biter *biter, int size) +{ + memset(biter, 0, sizeof(*biter)); + + biter->buffer = kmalloc(size, GFP_KERNEL); + if (!biter->buffer) + return 1; + + biter->size = size; + return 0; +} + +/* + * trace_biter_free - frees the buffer for trace buffer iterator + */ +static inline void trace_biter_free(struct trace_biter *biter) +{ + kfree(biter->buffer); +} + +extern int trace_get_user(struct trace_biter *biter, const char __user *ubuf, + size_t cnt, loff_t *ppos); + +/* * trace_iterator_flags is an enumeration that defines bit * positions into trace_flags that controls the output. * -- 1.6.2.5
| |