aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/ftrace.c8
-rw-r--r--arch/x86/mm/testmmiotrace.c29
-rw-r--r--include/linux/smp_lock.h21
-rw-r--r--include/trace/events/bkl.h61
-rw-r--r--kernel/trace/ftrace.c68
-rw-r--r--kernel/trace/trace.h36
-rw-r--r--kernel/trace/trace_events.c23
-rw-r--r--kernel/trace/trace_events_filter.c155
-rw-r--r--lib/kernel_lock.c20
9 files changed, 295 insertions, 126 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 9dbb527e1652..25e6f5fc4b1e 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -9,6 +9,8 @@
9 * the dangers of modifying code on the run. 9 * the dangers of modifying code on the run.
10 */ 10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
12#include <linux/spinlock.h> 14#include <linux/spinlock.h>
13#include <linux/hardirq.h> 15#include <linux/hardirq.h>
14#include <linux/uaccess.h> 16#include <linux/uaccess.h>
@@ -336,15 +338,15 @@ int __init ftrace_dyn_arch_init(void *data)
336 338
337 switch (faulted) { 339 switch (faulted) {
338 case 0: 340 case 0:
339 pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n"); 341 pr_info("converting mcount calls to 0f 1f 44 00 00\n");
340 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE); 342 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
341 break; 343 break;
342 case 1: 344 case 1:
343 pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n"); 345 pr_info("converting mcount calls to 66 66 66 66 90\n");
344 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE); 346 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
345 break; 347 break;
346 case 2: 348 case 2:
347 pr_info("ftrace: converting mcount calls to jmp . + 5\n"); 349 pr_info("converting mcount calls to jmp . + 5\n");
348 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE); 350 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
349 break; 351 break;
350 } 352 }
diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c
index 427fd1b56df5..8565d944f7cf 100644
--- a/arch/x86/mm/testmmiotrace.c
+++ b/arch/x86/mm/testmmiotrace.c
@@ -1,12 +1,13 @@
1/* 1/*
2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi> 2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
3 */ 3 */
4
5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6
4#include <linux/module.h> 7#include <linux/module.h>
5#include <linux/io.h> 8#include <linux/io.h>
6#include <linux/mmiotrace.h> 9#include <linux/mmiotrace.h>
7 10
8#define MODULE_NAME "testmmiotrace"
9
10static unsigned long mmio_address; 11static unsigned long mmio_address;
11module_param(mmio_address, ulong, 0); 12module_param(mmio_address, ulong, 0);
12MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB " 13MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
@@ -30,7 +31,7 @@ static unsigned v32(unsigned i)
30static void do_write_test(void __iomem *p) 31static void do_write_test(void __iomem *p)
31{ 32{
32 unsigned int i; 33 unsigned int i;
33 pr_info(MODULE_NAME ": write test.\n"); 34 pr_info("write test.\n");
34 mmiotrace_printk("Write test.\n"); 35 mmiotrace_printk("Write test.\n");
35 36
36 for (i = 0; i < 256; i++) 37 for (i = 0; i < 256; i++)
@@ -47,7 +48,7 @@ static void do_read_test(void __iomem *p)
47{ 48{
48 unsigned int i; 49 unsigned int i;
49 unsigned errs[3] = { 0 }; 50 unsigned errs[3] = { 0 };
50 pr_info(MODULE_NAME ": read test.\n"); 51 pr_info("read test.\n");
51 mmiotrace_printk("Read test.\n"); 52 mmiotrace_printk("Read test.\n");
52 53
53 for (i = 0; i < 256; i++) 54 for (i = 0; i < 256; i++)
@@ -68,7 +69,7 @@ static void do_read_test(void __iomem *p)
68 69
69static void do_read_far_test(void __iomem *p) 70static void do_read_far_test(void __iomem *p)
70{ 71{
71 pr_info(MODULE_NAME ": read far test.\n"); 72 pr_info("read far test.\n");
72 mmiotrace_printk("Read far test.\n"); 73 mmiotrace_printk("Read far test.\n");
73 74
74 ioread32(p + read_far); 75 ioread32(p + read_far);
@@ -78,7 +79,7 @@ static void do_test(unsigned long size)
78{ 79{
79 void __iomem *p = ioremap_nocache(mmio_address, size); 80 void __iomem *p = ioremap_nocache(mmio_address, size);
80 if (!p) { 81 if (!p) {
81 pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); 82 pr_err("could not ioremap, aborting.\n");
82 return; 83 return;
83 } 84 }
84 mmiotrace_printk("ioremap returned %p.\n", p); 85 mmiotrace_printk("ioremap returned %p.\n", p);
@@ -94,24 +95,22 @@ static int __init init(void)
94 unsigned long size = (read_far) ? (8 << 20) : (16 << 10); 95 unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
95 96
96 if (mmio_address == 0) { 97 if (mmio_address == 0) {
97 pr_err(MODULE_NAME ": you have to use the module argument " 98 pr_err("you have to use the module argument mmio_address.\n");
98 "mmio_address.\n"); 99 pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");
99 pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
100 " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
101 return -ENXIO; 100 return -ENXIO;
102 } 101 }
103 102
104 pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI " 103 pr_warning("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, "
105 "address space, and writing 16 kB of rubbish in there.\n", 104 "and writing 16 kB of rubbish in there.\n",
106 size >> 10, mmio_address); 105 size >> 10, mmio_address);
107 do_test(size); 106 do_test(size);
108 pr_info(MODULE_NAME ": All done.\n"); 107 pr_info("All done.\n");
109 return 0; 108 return 0;
110} 109}
111 110
112static void __exit cleanup(void) 111static void __exit cleanup(void)
113{ 112{
114 pr_debug(MODULE_NAME ": unloaded.\n"); 113 pr_debug("unloaded.\n");
115} 114}
116 115
117module_init(init); 116module_init(init);
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index 813be59bf345..2ea1dd1ba21c 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -24,8 +24,21 @@ static inline int reacquire_kernel_lock(struct task_struct *task)
24 return 0; 24 return 0;
25} 25}
26 26
27extern void __lockfunc lock_kernel(void) __acquires(kernel_lock); 27extern void __lockfunc
28extern void __lockfunc unlock_kernel(void) __releases(kernel_lock); 28_lock_kernel(const char *func, const char *file, int line)
29__acquires(kernel_lock);
30
31extern void __lockfunc
32_unlock_kernel(const char *func, const char *file, int line)
33__releases(kernel_lock);
34
35#define lock_kernel() do { \
36 _lock_kernel(__func__, __FILE__, __LINE__); \
37} while (0)
38
39#define unlock_kernel() do { \
40 _unlock_kernel(__func__, __FILE__, __LINE__); \
41} while (0)
29 42
30/* 43/*
31 * Various legacy drivers don't really need the BKL in a specific 44 * Various legacy drivers don't really need the BKL in a specific
@@ -41,8 +54,8 @@ static inline void cycle_kernel_lock(void)
41 54
42#else 55#else
43 56
44#define lock_kernel() do { } while(0) 57#define lock_kernel()
45#define unlock_kernel() do { } while(0) 58#define unlock_kernel()
46#define release_kernel_lock(task) do { } while(0) 59#define release_kernel_lock(task) do { } while(0)
47#define cycle_kernel_lock() do { } while(0) 60#define cycle_kernel_lock() do { } while(0)
48#define reacquire_kernel_lock(task) 0 61#define reacquire_kernel_lock(task) 0
diff --git a/include/trace/events/bkl.h b/include/trace/events/bkl.h
new file mode 100644
index 000000000000..8abd620a490e
--- /dev/null
+++ b/include/trace/events/bkl.h
@@ -0,0 +1,61 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM bkl
3
4#if !defined(_TRACE_BKL_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_BKL_H
6
7#include <linux/tracepoint.h>
8
9TRACE_EVENT(lock_kernel,
10
11 TP_PROTO(const char *func, const char *file, int line),
12
13 TP_ARGS(func, file, line),
14
15 TP_STRUCT__entry(
16 __field( int, lock_depth )
17 __field_ext( const char *, func, FILTER_PTR_STRING )
18 __field_ext( const char *, file, FILTER_PTR_STRING )
19 __field( int, line )
20 ),
21
22 TP_fast_assign(
23 /* We want to record the lock_depth after lock is acquired */
24 __entry->lock_depth = current->lock_depth + 1;
25 __entry->func = func;
26 __entry->file = file;
27 __entry->line = line;
28 ),
29
30 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth,
31 __entry->file, __entry->line, __entry->func)
32);
33
34TRACE_EVENT(unlock_kernel,
35
36 TP_PROTO(const char *func, const char *file, int line),
37
38 TP_ARGS(func, file, line),
39
40 TP_STRUCT__entry(
41 __field(int, lock_depth)
42 __field(const char *, func)
43 __field(const char *, file)
44 __field(int, line)
45 ),
46
47 TP_fast_assign(
48 __entry->lock_depth = current->lock_depth;
49 __entry->func = func;
50 __entry->file = file;
51 __entry->line = line;
52 ),
53
54 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth,
55 __entry->file, __entry->line, __entry->func)
56);
57
58#endif /* _TRACE_BKL_H */
59
60/* This part must be outside protection */
61#include <trace/define_trace.h>
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f136fe5da07a..1a7f6abd06bf 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -225,7 +225,11 @@ static void ftrace_update_pid_func(void)
225 if (ftrace_trace_function == ftrace_stub) 225 if (ftrace_trace_function == ftrace_stub)
226 return; 226 return;
227 227
228#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
228 func = ftrace_trace_function; 229 func = ftrace_trace_function;
230#else
231 func = __ftrace_trace_function;
232#endif
229 233
230 if (ftrace_pid_trace) { 234 if (ftrace_pid_trace) {
231 set_ftrace_pid_function(func); 235 set_ftrace_pid_function(func);
@@ -1652,60 +1656,6 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
1652 return ret; 1656 return ret;
1653} 1657}
1654 1658
1655enum {
1656 MATCH_FULL,
1657 MATCH_FRONT_ONLY,
1658 MATCH_MIDDLE_ONLY,
1659 MATCH_END_ONLY,
1660};
1661
1662/*
1663 * (static function - no need for kernel doc)
1664 *
1665 * Pass in a buffer containing a glob and this function will
1666 * set search to point to the search part of the buffer and
1667 * return the type of search it is (see enum above).
1668 * This does modify buff.
1669 *
1670 * Returns enum type.
1671 * search returns the pointer to use for comparison.
1672 * not returns 1 if buff started with a '!'
1673 * 0 otherwise.
1674 */
1675static int
1676ftrace_setup_glob(char *buff, int len, char **search, int *not)
1677{
1678 int type = MATCH_FULL;
1679 int i;
1680
1681 if (buff[0] == '!') {
1682 *not = 1;
1683 buff++;
1684 len--;
1685 } else
1686 *not = 0;
1687
1688 *search = buff;
1689
1690 for (i = 0; i < len; i++) {
1691 if (buff[i] == '*') {
1692 if (!i) {
1693 *search = buff + 1;
1694 type = MATCH_END_ONLY;
1695 } else {
1696 if (type == MATCH_END_ONLY)
1697 type = MATCH_MIDDLE_ONLY;
1698 else
1699 type = MATCH_FRONT_ONLY;
1700 buff[i] = 0;
1701 break;
1702 }
1703 }
1704 }
1705
1706 return type;
1707}
1708
1709static int ftrace_match(char *str, char *regex, int len, int type) 1659static int ftrace_match(char *str, char *regex, int len, int type)
1710{ 1660{
1711 int matched = 0; 1661 int matched = 0;
@@ -1754,7 +1704,7 @@ static void ftrace_match_records(char *buff, int len, int enable)
1754 int not; 1704 int not;
1755 1705
1756 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1706 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1757 type = ftrace_setup_glob(buff, len, &search, &not); 1707 type = filter_parse_regex(buff, len, &search, &not);
1758 1708
1759 search_len = strlen(search); 1709 search_len = strlen(search);
1760 1710
@@ -1822,7 +1772,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)
1822 } 1772 }
1823 1773
1824 if (strlen(buff)) { 1774 if (strlen(buff)) {
1825 type = ftrace_setup_glob(buff, strlen(buff), &search, &not); 1775 type = filter_parse_regex(buff, strlen(buff), &search, &not);
1826 search_len = strlen(search); 1776 search_len = strlen(search);
1827 } 1777 }
1828 1778
@@ -1987,7 +1937,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
1987 int count = 0; 1937 int count = 0;
1988 char *search; 1938 char *search;
1989 1939
1990 type = ftrace_setup_glob(glob, strlen(glob), &search, &not); 1940 type = filter_parse_regex(glob, strlen(glob), &search, &not);
1991 len = strlen(search); 1941 len = strlen(search);
1992 1942
1993 /* we do not support '!' for function probes */ 1943 /* we do not support '!' for function probes */
@@ -2064,7 +2014,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
2064 else if (glob) { 2014 else if (glob) {
2065 int not; 2015 int not;
2066 2016
2067 type = ftrace_setup_glob(glob, strlen(glob), &search, &not); 2017 type = filter_parse_regex(glob, strlen(glob), &search, &not);
2068 len = strlen(search); 2018 len = strlen(search);
2069 2019
2070 /* we do not support '!' for function probes */ 2020 /* we do not support '!' for function probes */
@@ -2509,7 +2459,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2509 return -ENODEV; 2459 return -ENODEV;
2510 2460
2511 /* decode regex */ 2461 /* decode regex */
2512 type = ftrace_setup_glob(buffer, strlen(buffer), &search, &not); 2462 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
2513 if (not) 2463 if (not)
2514 return -EINVAL; 2464 return -EINVAL;
2515 2465
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 405cb850b75d..365fb19d9e11 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -699,22 +699,40 @@ struct event_subsystem {
699}; 699};
700 700
701struct filter_pred; 701struct filter_pred;
702struct regex;
702 703
703typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, 704typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
704 int val1, int val2); 705 int val1, int val2);
705 706
707typedef int (*regex_match_func)(char *str, struct regex *r, int len);
708
709enum regex_type {
710 MATCH_FULL,
711 MATCH_FRONT_ONLY,
712 MATCH_MIDDLE_ONLY,
713 MATCH_END_ONLY,
714};
715
716struct regex {
717 char pattern[MAX_FILTER_STR_VAL];
718 int len;
719 int field_len;
720 regex_match_func match;
721};
722
706struct filter_pred { 723struct filter_pred {
707 filter_pred_fn_t fn; 724 filter_pred_fn_t fn;
708 u64 val; 725 u64 val;
709 char str_val[MAX_FILTER_STR_VAL]; 726 struct regex regex;
710 int str_len; 727 char *field_name;
711 char *field_name; 728 int offset;
712 int offset; 729 int not;
713 int not; 730 int op;
714 int op; 731 int pop_n;
715 int pop_n;
716}; 732};
717 733
734extern enum regex_type
735filter_parse_regex(char *buff, int len, char **search, int *not);
718extern void print_event_filter(struct ftrace_event_call *call, 736extern void print_event_filter(struct ftrace_event_call *call,
719 struct trace_seq *s); 737 struct trace_seq *s);
720extern int apply_event_filter(struct ftrace_event_call *call, 738extern int apply_event_filter(struct ftrace_event_call *call,
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index d128f65778e6..5e9ffc33f6db 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -878,9 +878,9 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
878 "'%s/filter' entry\n", name); 878 "'%s/filter' entry\n", name);
879 } 879 }
880 880
881 entry = trace_create_file("enable", 0644, system->entry, 881 trace_create_file("enable", 0644, system->entry,
882 (void *)system->name, 882 (void *)system->name,
883 &ftrace_system_enable_fops); 883 &ftrace_system_enable_fops);
884 884
885 return system->entry; 885 return system->entry;
886} 886}
@@ -892,7 +892,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
892 const struct file_operations *filter, 892 const struct file_operations *filter,
893 const struct file_operations *format) 893 const struct file_operations *format)
894{ 894{
895 struct dentry *entry;
896 int ret; 895 int ret;
897 896
898 /* 897 /*
@@ -910,12 +909,12 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
910 } 909 }
911 910
912 if (call->regfunc) 911 if (call->regfunc)
913 entry = trace_create_file("enable", 0644, call->dir, call, 912 trace_create_file("enable", 0644, call->dir, call,
914 enable); 913 enable);
915 914
916 if (call->id && call->profile_enable) 915 if (call->id && call->profile_enable)
917 entry = trace_create_file("id", 0444, call->dir, call, 916 trace_create_file("id", 0444, call->dir, call,
918 id); 917 id);
919 918
920 if (call->define_fields) { 919 if (call->define_fields) {
921 ret = call->define_fields(call); 920 ret = call->define_fields(call);
@@ -924,16 +923,16 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
924 " events/%s\n", call->name); 923 " events/%s\n", call->name);
925 return ret; 924 return ret;
926 } 925 }
927 entry = trace_create_file("filter", 0644, call->dir, call, 926 trace_create_file("filter", 0644, call->dir, call,
928 filter); 927 filter);
929 } 928 }
930 929
931 /* A trace may not want to export its format */ 930 /* A trace may not want to export its format */
932 if (!call->show_format) 931 if (!call->show_format)
933 return 0; 932 return 0;
934 933
935 entry = trace_create_file("format", 0444, call->dir, call, 934 trace_create_file("format", 0444, call->dir, call,
936 format); 935 format);
937 936
938 return 0; 937 return 0;
939} 938}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 98a6cc5c64ed..92672016da28 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -18,8 +18,6 @@
18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
19 */ 19 */
20 20
21#include <linux/debugfs.h>
22#include <linux/uaccess.h>
23#include <linux/module.h> 21#include <linux/module.h>
24#include <linux/ctype.h> 22#include <linux/ctype.h>
25#include <linux/mutex.h> 23#include <linux/mutex.h>
@@ -197,9 +195,9 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
197 char *addr = (char *)(event + pred->offset); 195 char *addr = (char *)(event + pred->offset);
198 int cmp, match; 196 int cmp, match;
199 197
200 cmp = strncmp(addr, pred->str_val, pred->str_len); 198 cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len);
201 199
202 match = (!cmp) ^ pred->not; 200 match = cmp ^ pred->not;
203 201
204 return match; 202 return match;
205} 203}
@@ -211,9 +209,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
211 char **addr = (char **)(event + pred->offset); 209 char **addr = (char **)(event + pred->offset);
212 int cmp, match; 210 int cmp, match;
213 211
214 cmp = strncmp(*addr, pred->str_val, pred->str_len); 212 cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len);
215 213
216 match = (!cmp) ^ pred->not; 214 match = cmp ^ pred->not;
217 215
218 return match; 216 return match;
219} 217}
@@ -237,9 +235,9 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,
237 char *addr = (char *)(event + str_loc); 235 char *addr = (char *)(event + str_loc);
238 int cmp, match; 236 int cmp, match;
239 237
240 cmp = strncmp(addr, pred->str_val, str_len); 238 cmp = pred->regex.match(addr, &pred->regex, str_len);
241 239
242 match = (!cmp) ^ pred->not; 240 match = cmp ^ pred->not;
243 241
244 return match; 242 return match;
245} 243}
@@ -250,6 +248,124 @@ static int filter_pred_none(struct filter_pred *pred, void *event,
250 return 0; 248 return 0;
251} 249}
252 250
251/* Basic regex callbacks */
252static int regex_match_full(char *str, struct regex *r, int len)
253{
254 if (strncmp(str, r->pattern, len) == 0)
255 return 1;
256 return 0;
257}
258
259static int regex_match_front(char *str, struct regex *r, int len)
260{
261 if (strncmp(str, r->pattern, len) == 0)
262 return 1;
263 return 0;
264}
265
266static int regex_match_middle(char *str, struct regex *r, int len)
267{
268 if (strstr(str, r->pattern))
269 return 1;
270 return 0;
271}
272
273static int regex_match_end(char *str, struct regex *r, int len)
274{
275 char *ptr = strstr(str, r->pattern);
276
277 if (ptr && (ptr[r->len] == 0))
278 return 1;
279 return 0;
280}
281
282/**
283 * filter_parse_regex - parse a basic regex
284 * @buff: the raw regex
285 * @len: length of the regex
286 * @search: will point to the beginning of the string to compare
287 * @not: tell whether the match will have to be inverted
288 *
289 * This passes in a buffer containing a regex and this function will
290 * set search to point to the search part of the buffer and
291 * return the type of search it is (see enum above).
292 * This does modify buff.
293 *
294 * Returns enum type.
295 * search returns the pointer to use for comparison.
296 * not returns 1 if buff started with a '!'
297 * 0 otherwise.
298 */
299enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
300{
301 int type = MATCH_FULL;
302 int i;
303
304 if (buff[0] == '!') {
305 *not = 1;
306 buff++;
307 len--;
308 } else
309 *not = 0;
310
311 *search = buff;
312
313 for (i = 0; i < len; i++) {
314 if (buff[i] == '*') {
315 if (!i) {
316 *search = buff + 1;
317 type = MATCH_END_ONLY;
318 } else {
319 if (type == MATCH_END_ONLY)
320 type = MATCH_MIDDLE_ONLY;
321 else
322 type = MATCH_FRONT_ONLY;
323 buff[i] = 0;
324 break;
325 }
326 }
327 }
328
329 return type;
330}
331
332static int filter_build_regex(struct filter_pred *pred)
333{
334 struct regex *r = &pred->regex;
335 char *search, *dup;
336 enum regex_type type;
337 int not;
338
339 type = filter_parse_regex(r->pattern, r->len, &search, &not);
340 dup = kstrdup(search, GFP_KERNEL);
341 if (!dup)
342 return -ENOMEM;
343
344 strcpy(r->pattern, dup);
345 kfree(dup);
346
347 r->len = strlen(r->pattern);
348
349 switch (type) {
350 case MATCH_FULL:
351 r->match = regex_match_full;
352 break;
353 case MATCH_FRONT_ONLY:
354 r->match = regex_match_front;
355 break;
356 case MATCH_MIDDLE_ONLY:
357 r->match = regex_match_middle;
358 break;
359 case MATCH_END_ONLY:
360 r->match = regex_match_end;
361 break;
362 }
363
364 pred->not ^= not;
365
366 return 0;
367}
368
253/* return 1 if event matches, 0 otherwise (discard) */ 369/* return 1 if event matches, 0 otherwise (discard) */
254int filter_match_preds(struct ftrace_event_call *call, void *rec) 370int filter_match_preds(struct ftrace_event_call *call, void *rec)
255{ 371{
@@ -396,7 +512,7 @@ static void filter_clear_pred(struct filter_pred *pred)
396{ 512{
397 kfree(pred->field_name); 513 kfree(pred->field_name);
398 pred->field_name = NULL; 514 pred->field_name = NULL;
399 pred->str_len = 0; 515 pred->regex.len = 0;
400} 516}
401 517
402static int filter_set_pred(struct filter_pred *dest, 518static int filter_set_pred(struct filter_pred *dest,
@@ -660,21 +776,24 @@ static int filter_add_pred(struct filter_parse_state *ps,
660 } 776 }
661 777
662 if (is_string_field(field)) { 778 if (is_string_field(field)) {
663 pred->str_len = field->size; 779 ret = filter_build_regex(pred);
780 if (ret)
781 return ret;
664 782
665 if (field->filter_type == FILTER_STATIC_STRING) 783 if (field->filter_type == FILTER_STATIC_STRING) {
666 fn = filter_pred_string; 784 fn = filter_pred_string;
667 else if (field->filter_type == FILTER_DYN_STRING) 785 pred->regex.field_len = field->size;
668 fn = filter_pred_strloc; 786 } else if (field->filter_type == FILTER_DYN_STRING)
787 fn = filter_pred_strloc;
669 else { 788 else {
670 fn = filter_pred_pchar; 789 fn = filter_pred_pchar;
671 pred->str_len = strlen(pred->str_val); 790 pred->regex.field_len = strlen(pred->regex.pattern);
672 } 791 }
673 } else { 792 } else {
674 if (field->is_signed) 793 if (field->is_signed)
675 ret = strict_strtoll(pred->str_val, 0, &val); 794 ret = strict_strtoll(pred->regex.pattern, 0, &val);
676 else 795 else
677 ret = strict_strtoull(pred->str_val, 0, &val); 796 ret = strict_strtoull(pred->regex.pattern, 0, &val);
678 if (ret) { 797 if (ret) {
679 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0); 798 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
680 return -EINVAL; 799 return -EINVAL;
@@ -1045,8 +1164,8 @@ static struct filter_pred *create_pred(int op, char *operand1, char *operand2)
1045 return NULL; 1164 return NULL;
1046 } 1165 }
1047 1166
1048 strcpy(pred->str_val, operand2); 1167 strcpy(pred->regex.pattern, operand2);
1049 pred->str_len = strlen(operand2); 1168 pred->regex.len = strlen(pred->regex.pattern);
1050 1169
1051 pred->op = op; 1170 pred->op = op;
1052 1171
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 39f1029e3525..4ebfa5a164d7 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -5,10 +5,13 @@
5 * relegated to obsolescence, but used by various less 5 * relegated to obsolescence, but used by various less
6 * important (or lazy) subsystems. 6 * important (or lazy) subsystems.
7 */ 7 */
8#include <linux/smp_lock.h>
9#include <linux/module.h> 8#include <linux/module.h>
10#include <linux/kallsyms.h> 9#include <linux/kallsyms.h>
11#include <linux/semaphore.h> 10#include <linux/semaphore.h>
11#include <linux/smp_lock.h>
12
13#define CREATE_TRACE_POINTS
14#include <trace/events/bkl.h>
12 15
13/* 16/*
14 * The 'big kernel lock' 17 * The 'big kernel lock'
@@ -113,21 +116,26 @@ static inline void __unlock_kernel(void)
113 * This cannot happen asynchronously, so we only need to 116 * This cannot happen asynchronously, so we only need to
114 * worry about other CPU's. 117 * worry about other CPU's.
115 */ 118 */
116void __lockfunc lock_kernel(void) 119void __lockfunc _lock_kernel(const char *func, const char *file, int line)
117{ 120{
118 int depth = current->lock_depth+1; 121 int depth = current->lock_depth + 1;
122
123 trace_lock_kernel(func, file, line);
124
119 if (likely(!depth)) 125 if (likely(!depth))
120 __lock_kernel(); 126 __lock_kernel();
121 current->lock_depth = depth; 127 current->lock_depth = depth;
122} 128}
123 129
124void __lockfunc unlock_kernel(void) 130void __lockfunc _unlock_kernel(const char *func, const char *file, int line)
125{ 131{
126 BUG_ON(current->lock_depth < 0); 132 BUG_ON(current->lock_depth < 0);
127 if (likely(--current->lock_depth < 0)) 133 if (likely(--current->lock_depth < 0))
128 __unlock_kernel(); 134 __unlock_kernel();
135
136 trace_unlock_kernel(func, file, line);
129} 137}
130 138
131EXPORT_SYMBOL(lock_kernel); 139EXPORT_SYMBOL(_lock_kernel);
132EXPORT_SYMBOL(unlock_kernel); 140EXPORT_SYMBOL(_unlock_kernel);
133 141