diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/ftrace.c | 150 |
1 files changed, 40 insertions, 110 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8c804e24f96f..8b23d5670088 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1323,11 +1323,10 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) | |||
| 1323 | 1323 | ||
| 1324 | enum { | 1324 | enum { |
| 1325 | FTRACE_ITER_FILTER = (1 << 0), | 1325 | FTRACE_ITER_FILTER = (1 << 0), |
| 1326 | FTRACE_ITER_CONT = (1 << 1), | 1326 | FTRACE_ITER_NOTRACE = (1 << 1), |
| 1327 | FTRACE_ITER_NOTRACE = (1 << 2), | 1327 | FTRACE_ITER_FAILURES = (1 << 2), |
| 1328 | FTRACE_ITER_FAILURES = (1 << 3), | 1328 | FTRACE_ITER_PRINTALL = (1 << 3), |
| 1329 | FTRACE_ITER_PRINTALL = (1 << 4), | 1329 | FTRACE_ITER_HASH = (1 << 4), |
| 1330 | FTRACE_ITER_HASH = (1 << 5), | ||
| 1331 | }; | 1330 | }; |
| 1332 | 1331 | ||
| 1333 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ | 1332 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ |
| @@ -1337,8 +1336,7 @@ struct ftrace_iterator { | |||
| 1337 | int hidx; | 1336 | int hidx; |
| 1338 | int idx; | 1337 | int idx; |
| 1339 | unsigned flags; | 1338 | unsigned flags; |
| 1340 | unsigned char buffer[FTRACE_BUFF_MAX+1]; | 1339 | struct trace_parser parser; |
| 1341 | unsigned buffer_idx; | ||
| 1342 | }; | 1340 | }; |
| 1343 | 1341 | ||
| 1344 | static void * | 1342 | static void * |
| @@ -1604,6 +1602,11 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable) | |||
| 1604 | if (!iter) | 1602 | if (!iter) |
| 1605 | return -ENOMEM; | 1603 | return -ENOMEM; |
| 1606 | 1604 | ||
| 1605 | if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { | ||
| 1606 | kfree(iter); | ||
| 1607 | return -ENOMEM; | ||
| 1608 | } | ||
| 1609 | |||
| 1607 | mutex_lock(&ftrace_regex_lock); | 1610 | mutex_lock(&ftrace_regex_lock); |
| 1608 | if ((file->f_mode & FMODE_WRITE) && | 1611 | if ((file->f_mode & FMODE_WRITE) && |
| 1609 | (file->f_flags & O_TRUNC)) | 1612 | (file->f_flags & O_TRUNC)) |
| @@ -2196,9 +2199,8 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 2196 | size_t cnt, loff_t *ppos, int enable) | 2199 | size_t cnt, loff_t *ppos, int enable) |
| 2197 | { | 2200 | { |
| 2198 | struct ftrace_iterator *iter; | 2201 | struct ftrace_iterator *iter; |
| 2199 | char ch; | 2202 | struct trace_parser *parser; |
| 2200 | size_t read = 0; | 2203 | ssize_t ret, read; |
| 2201 | ssize_t ret; | ||
| 2202 | 2204 | ||
| 2203 | if (!cnt || cnt < 0) | 2205 | if (!cnt || cnt < 0) |
| 2204 | return 0; | 2206 | return 0; |
| @@ -2211,72 +2213,23 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 2211 | } else | 2213 | } else |
| 2212 | iter = file->private_data; | 2214 | iter = file->private_data; |
| 2213 | 2215 | ||
| 2214 | if (!*ppos) { | 2216 | parser = &iter->parser; |
| 2215 | iter->flags &= ~FTRACE_ITER_CONT; | 2217 | read = trace_get_user(parser, ubuf, cnt, ppos); |
| 2216 | iter->buffer_idx = 0; | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | ret = get_user(ch, ubuf++); | ||
| 2220 | if (ret) | ||
| 2221 | goto out; | ||
| 2222 | read++; | ||
| 2223 | cnt--; | ||
| 2224 | |||
| 2225 | /* | ||
| 2226 | * If the parser haven't finished with the last write, | ||
| 2227 | * continue reading the user input without skipping spaces. | ||
| 2228 | */ | ||
| 2229 | if (!(iter->flags & FTRACE_ITER_CONT)) { | ||
| 2230 | /* skip white space */ | ||
| 2231 | while (cnt && isspace(ch)) { | ||
| 2232 | ret = get_user(ch, ubuf++); | ||
| 2233 | if (ret) | ||
| 2234 | goto out; | ||
| 2235 | read++; | ||
| 2236 | cnt--; | ||
| 2237 | } | ||
| 2238 | 2218 | ||
| 2239 | /* only spaces were written */ | 2219 | if (trace_parser_loaded(parser) && |
| 2240 | if (isspace(ch)) { | 2220 | !trace_parser_cont(parser)) { |
| 2241 | *ppos += read; | 2221 | ret = ftrace_process_regex(parser->buffer, |
| 2242 | ret = read; | 2222 | parser->idx, enable); |
| 2243 | goto out; | ||
| 2244 | } | ||
| 2245 | |||
| 2246 | iter->buffer_idx = 0; | ||
| 2247 | } | ||
| 2248 | |||
| 2249 | while (cnt && !isspace(ch)) { | ||
| 2250 | if (iter->buffer_idx < FTRACE_BUFF_MAX) | ||
| 2251 | iter->buffer[iter->buffer_idx++] = ch; | ||
| 2252 | else { | ||
| 2253 | ret = -EINVAL; | ||
| 2254 | goto out; | ||
| 2255 | } | ||
| 2256 | ret = get_user(ch, ubuf++); | ||
| 2257 | if (ret) | 2223 | if (ret) |
| 2258 | goto out; | 2224 | goto out; |
| 2259 | read++; | ||
| 2260 | cnt--; | ||
| 2261 | } | ||
| 2262 | 2225 | ||
| 2263 | if (isspace(ch)) { | 2226 | trace_parser_clear(parser); |
| 2264 | iter->buffer[iter->buffer_idx] = 0; | ||
| 2265 | ret = ftrace_process_regex(iter->buffer, | ||
| 2266 | iter->buffer_idx, enable); | ||
| 2267 | if (ret) | ||
| 2268 | goto out; | ||
| 2269 | iter->buffer_idx = 0; | ||
| 2270 | } else { | ||
| 2271 | iter->flags |= FTRACE_ITER_CONT; | ||
| 2272 | iter->buffer[iter->buffer_idx++] = ch; | ||
| 2273 | } | 2227 | } |
| 2274 | 2228 | ||
| 2275 | *ppos += read; | ||
| 2276 | ret = read; | 2229 | ret = read; |
| 2277 | out: | ||
| 2278 | mutex_unlock(&ftrace_regex_lock); | ||
| 2279 | 2230 | ||
| 2231 | mutex_unlock(&ftrace_regex_lock); | ||
| 2232 | out: | ||
| 2280 | return ret; | 2233 | return ret; |
| 2281 | } | 2234 | } |
| 2282 | 2235 | ||
| @@ -2381,6 +2334,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) | |||
| 2381 | { | 2334 | { |
| 2382 | struct seq_file *m = (struct seq_file *)file->private_data; | 2335 | struct seq_file *m = (struct seq_file *)file->private_data; |
| 2383 | struct ftrace_iterator *iter; | 2336 | struct ftrace_iterator *iter; |
| 2337 | struct trace_parser *parser; | ||
| 2384 | 2338 | ||
| 2385 | mutex_lock(&ftrace_regex_lock); | 2339 | mutex_lock(&ftrace_regex_lock); |
| 2386 | if (file->f_mode & FMODE_READ) { | 2340 | if (file->f_mode & FMODE_READ) { |
| @@ -2390,9 +2344,10 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) | |||
| 2390 | } else | 2344 | } else |
| 2391 | iter = file->private_data; | 2345 | iter = file->private_data; |
| 2392 | 2346 | ||
| 2393 | if (iter->buffer_idx) { | 2347 | parser = &iter->parser; |
| 2394 | iter->buffer[iter->buffer_idx] = 0; | 2348 | if (trace_parser_loaded(parser)) { |
| 2395 | ftrace_match_records(iter->buffer, iter->buffer_idx, enable); | 2349 | parser->buffer[parser->idx] = 0; |
| 2350 | ftrace_match_records(parser->buffer, parser->idx, enable); | ||
| 2396 | } | 2351 | } |
| 2397 | 2352 | ||
| 2398 | mutex_lock(&ftrace_lock); | 2353 | mutex_lock(&ftrace_lock); |
| @@ -2400,7 +2355,9 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) | |||
| 2400 | ftrace_run_update_code(FTRACE_ENABLE_CALLS); | 2355 | ftrace_run_update_code(FTRACE_ENABLE_CALLS); |
| 2401 | mutex_unlock(&ftrace_lock); | 2356 | mutex_unlock(&ftrace_lock); |
| 2402 | 2357 | ||
| 2358 | trace_parser_put(parser); | ||
| 2403 | kfree(iter); | 2359 | kfree(iter); |
| 2360 | |||
| 2404 | mutex_unlock(&ftrace_regex_lock); | 2361 | mutex_unlock(&ftrace_regex_lock); |
| 2405 | return 0; | 2362 | return 0; |
| 2406 | } | 2363 | } |
| @@ -2499,7 +2456,7 @@ static int g_show(struct seq_file *m, void *v) | |||
| 2499 | return 0; | 2456 | return 0; |
| 2500 | } | 2457 | } |
| 2501 | 2458 | ||
| 2502 | seq_printf(m, "%pf\n", v); | 2459 | seq_printf(m, "%pf\n", (void *)*ptr); |
| 2503 | 2460 | ||
| 2504 | return 0; | 2461 | return 0; |
| 2505 | } | 2462 | } |
| @@ -2602,12 +2559,10 @@ static ssize_t | |||
| 2602 | ftrace_graph_write(struct file *file, const char __user *ubuf, | 2559 | ftrace_graph_write(struct file *file, const char __user *ubuf, |
| 2603 | size_t cnt, loff_t *ppos) | 2560 | size_t cnt, loff_t *ppos) |
| 2604 | { | 2561 | { |
| 2605 | unsigned char buffer[FTRACE_BUFF_MAX+1]; | 2562 | struct trace_parser parser; |
| 2606 | unsigned long *array; | 2563 | unsigned long *array; |
| 2607 | size_t read = 0; | 2564 | size_t read = 0; |
| 2608 | ssize_t ret; | 2565 | ssize_t ret; |
| 2609 | int index = 0; | ||
| 2610 | char ch; | ||
| 2611 | 2566 | ||
| 2612 | if (!cnt || cnt < 0) | 2567 | if (!cnt || cnt < 0) |
| 2613 | return 0; | 2568 | return 0; |
| @@ -2625,51 +2580,26 @@ ftrace_graph_write(struct file *file, const char __user *ubuf, | |||
| 2625 | } else | 2580 | } else |
| 2626 | array = file->private_data; | 2581 | array = file->private_data; |
| 2627 | 2582 | ||
| 2628 | ret = get_user(ch, ubuf++); | 2583 | if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) { |
| 2629 | if (ret) | 2584 | ret = -ENOMEM; |
| 2630 | goto out; | 2585 | goto out; |
| 2631 | read++; | ||
| 2632 | cnt--; | ||
| 2633 | |||
| 2634 | /* skip white space */ | ||
| 2635 | while (cnt && isspace(ch)) { | ||
| 2636 | ret = get_user(ch, ubuf++); | ||
| 2637 | if (ret) | ||
| 2638 | goto out; | ||
| 2639 | read++; | ||
| 2640 | cnt--; | ||
| 2641 | } | 2586 | } |
| 2642 | 2587 | ||
| 2643 | if (isspace(ch)) { | 2588 | read = trace_get_user(&parser, ubuf, cnt, ppos); |
| 2644 | *ppos += read; | ||
| 2645 | ret = read; | ||
| 2646 | goto out; | ||
| 2647 | } | ||
| 2648 | 2589 | ||
| 2649 | while (cnt && !isspace(ch)) { | 2590 | if (trace_parser_loaded((&parser))) { |
| 2650 | if (index < FTRACE_BUFF_MAX) | 2591 | parser.buffer[parser.idx] = 0; |
| 2651 | buffer[index++] = ch; | 2592 | |
| 2652 | else { | 2593 | /* we allow only one expression at a time */ |
| 2653 | ret = -EINVAL; | 2594 | ret = ftrace_set_func(array, &ftrace_graph_count, |
| 2654 | goto out; | 2595 | parser.buffer); |
| 2655 | } | ||
| 2656 | ret = get_user(ch, ubuf++); | ||
| 2657 | if (ret) | 2596 | if (ret) |
| 2658 | goto out; | 2597 | goto out; |
| 2659 | read++; | ||
| 2660 | cnt--; | ||
| 2661 | } | 2598 | } |
| 2662 | buffer[index] = 0; | ||
| 2663 | |||
| 2664 | /* we allow only one expression at a time */ | ||
| 2665 | ret = ftrace_set_func(array, &ftrace_graph_count, buffer); | ||
| 2666 | if (ret) | ||
| 2667 | goto out; | ||
| 2668 | |||
| 2669 | file->f_pos += read; | ||
| 2670 | 2599 | ||
| 2671 | ret = read; | 2600 | ret = read; |
| 2672 | out: | 2601 | out: |
| 2602 | trace_parser_put(&parser); | ||
| 2673 | mutex_unlock(&graph_lock); | 2603 | mutex_unlock(&graph_lock); |
| 2674 | 2604 | ||
| 2675 | return ret; | 2605 | return ret; |
