Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 162950
b: refs/heads/master
c: b63f39e
h: refs/heads/master
v: v3
  • Loading branch information
jolsa@redhat.com authored and Steven Rostedt committed Sep 11, 2009
1 parent 8f99ec3 commit 383a79d
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f81c972d27c36729e65d4a815e3d7b782a540bad
refs/heads/master: b63f39ea50330f836e301ddda21c6a93dcf0d6a3
106 changes: 106 additions & 0 deletions trunk/kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,112 @@ static struct {

int trace_clock_id;

/*
* trace_parser_get_init - gets the buffer for trace parser
*/
int trace_parser_get_init(struct trace_parser *parser, int size)
{
memset(parser, 0, sizeof(*parser));

parser->buffer = kmalloc(size, GFP_KERNEL);
if (!parser->buffer)
return 1;

parser->size = size;
return 0;
}

/*
* trace_parser_put - frees the buffer for trace parser
*/
void trace_parser_put(struct trace_parser *parser)
{
kfree(parser->buffer);
}

/*
* trace_get_user - reads the user input string separated by space
* (matched by isspace(ch))
*
* For each string found the 'struct trace_parser' is updated,
* and the function returns.
*
* Returns number of bytes read.
*
* See kernel/trace/trace.h for 'struct trace_parser' details.
*/
int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
char ch;
size_t read = 0;
ssize_t ret;

if (!*ppos)
trace_parser_clear(parser);

ret = get_user(ch, ubuf++);
if (ret)
goto out;

read++;
cnt--;

/*
* The parser is not finished with the last write,
* continue reading the user input without skipping spaces.
*/
if (!parser->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;
}

parser->idx = 0;
}

/* read the non-space input */
while (cnt && !isspace(ch)) {
if (parser->idx < parser->size)
parser->buffer[parser->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)) {
parser->buffer[parser->idx] = 0;
parser->cont = false;
} else {
parser->cont = true;
parser->buffer[parser->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;
Expand Down
35 changes: 35 additions & 0 deletions trunk/kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,41 @@ static inline int ftrace_trace_task(struct task_struct *task)
}
#endif

/*
* struct trace_parser - 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_parser {
bool cont;
char *buffer;
unsigned idx;
unsigned size;
};

static inline bool trace_parser_loaded(struct trace_parser *parser)
{
return (parser->idx != 0);
}

static inline bool trace_parser_cont(struct trace_parser *parser)
{
return parser->cont;
}

static inline void trace_parser_clear(struct trace_parser *parser)
{
parser->cont = false;
parser->idx = 0;
}

extern int trace_parser_get_init(struct trace_parser *parser, int size);
extern void trace_parser_put(struct trace_parser *parser);
extern int trace_get_user(struct trace_parser *parser, 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.
Expand Down

0 comments on commit 383a79d

Please sign in to comment.