aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-04-29 20:59:51 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-05-18 15:29:44 -0400
commit1cf41dd79993389b012e4542ab502ce36ae7343f (patch)
treee1d0b58b2256d5936cff0c9d29ca8f68a80cedd8 /kernel/trace
parentb448c4e3ae6d20108dba1d7833f2c0d3dbad87ce (diff)
ftrace: Use hash instead for FTRACE_FL_FILTER
When multiple users are allowed to have their own set of functions to trace, having the FTRACE_FL_FILTER flag will not be enough to handle the accounting of those users. Each user will need their own set of functions. Replace the FTRACE_FL_FILTER with a filter_hash instead. This is temporary until the rest of the function filtering accounting gets in. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c151
1 files changed, 69 insertions, 82 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 04c002a491fb..222eca4c3022 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -883,7 +883,11 @@ static struct ftrace_hash notrace_hash = {
883 .buckets = notrace_buckets, 883 .buckets = notrace_buckets,
884}; 884};
885 885
886static int ftrace_filtered; 886static struct hlist_head filter_buckets[1 << FTRACE_HASH_MAX_BITS];
887static struct ftrace_hash filter_hash = {
888 .size_bits = FTRACE_HASH_MAX_BITS,
889 .buckets = filter_buckets,
890};
887 891
888static struct dyn_ftrace *ftrace_new_addrs; 892static struct dyn_ftrace *ftrace_new_addrs;
889 893
@@ -1123,7 +1127,7 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1123 * it's filtered 1127 * it's filtered
1124 */ 1128 */
1125 if (enable && !ftrace_lookup_ip(&notrace_hash, rec->ip)) { 1129 if (enable && !ftrace_lookup_ip(&notrace_hash, rec->ip)) {
1126 if (!ftrace_filtered || (rec->flags & FTRACE_FL_FILTER)) 1130 if (!filter_hash.count || ftrace_lookup_ip(&filter_hash, rec->ip))
1127 flag = FTRACE_FL_ENABLED; 1131 flag = FTRACE_FL_ENABLED;
1128 } 1132 }
1129 1133
@@ -1430,6 +1434,7 @@ struct ftrace_iterator {
1430 struct dyn_ftrace *func; 1434 struct dyn_ftrace *func;
1431 struct ftrace_func_probe *probe; 1435 struct ftrace_func_probe *probe;
1432 struct trace_parser parser; 1436 struct trace_parser parser;
1437 struct ftrace_hash *hash;
1433 int hidx; 1438 int hidx;
1434 int idx; 1439 int idx;
1435 unsigned flags; 1440 unsigned flags;
@@ -1552,7 +1557,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1552 if ((rec->flags & FTRACE_FL_FREE) || 1557 if ((rec->flags & FTRACE_FL_FREE) ||
1553 1558
1554 ((iter->flags & FTRACE_ITER_FILTER) && 1559 ((iter->flags & FTRACE_ITER_FILTER) &&
1555 !(rec->flags & FTRACE_FL_FILTER)) || 1560 !(ftrace_lookup_ip(&filter_hash, rec->ip))) ||
1556 1561
1557 ((iter->flags & FTRACE_ITER_NOTRACE) && 1562 ((iter->flags & FTRACE_ITER_NOTRACE) &&
1558 !ftrace_lookup_ip(&notrace_hash, rec->ip))) { 1563 !ftrace_lookup_ip(&notrace_hash, rec->ip))) {
@@ -1598,7 +1603,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1598 * off, we can short cut and just print out that all 1603 * off, we can short cut and just print out that all
1599 * functions are enabled. 1604 * functions are enabled.
1600 */ 1605 */
1601 if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) { 1606 if (iter->flags & FTRACE_ITER_FILTER && !filter_hash.count) {
1602 if (*pos > 0) 1607 if (*pos > 0)
1603 return t_hash_start(m, pos); 1608 return t_hash_start(m, pos);
1604 iter->flags |= FTRACE_ITER_PRINTALL; 1609 iter->flags |= FTRACE_ITER_PRINTALL;
@@ -1695,24 +1700,16 @@ ftrace_avail_open(struct inode *inode, struct file *file)
1695 return ret; 1700 return ret;
1696} 1701}
1697 1702
1698static void ftrace_filter_reset(int enable) 1703static void ftrace_filter_reset(struct ftrace_hash *hash)
1699{ 1704{
1700 struct ftrace_page *pg;
1701 struct dyn_ftrace *rec;
1702
1703 mutex_lock(&ftrace_lock); 1705 mutex_lock(&ftrace_lock);
1704 if (enable) { 1706 ftrace_hash_clear(hash);
1705 ftrace_filtered = 0;
1706 do_for_each_ftrace_rec(pg, rec) {
1707 rec->flags &= ~FTRACE_FL_FILTER;
1708 } while_for_each_ftrace_rec();
1709 } else
1710 ftrace_hash_clear(&notrace_hash);
1711 mutex_unlock(&ftrace_lock); 1707 mutex_unlock(&ftrace_lock);
1712} 1708}
1713 1709
1714static int 1710static int
1715ftrace_regex_open(struct inode *inode, struct file *file, int enable) 1711ftrace_regex_open(struct ftrace_hash *hash, int flag,
1712 struct inode *inode, struct file *file)
1716{ 1713{
1717 struct ftrace_iterator *iter; 1714 struct ftrace_iterator *iter;
1718 int ret = 0; 1715 int ret = 0;
@@ -1729,15 +1726,16 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
1729 return -ENOMEM; 1726 return -ENOMEM;
1730 } 1727 }
1731 1728
1729 iter->hash = hash;
1730
1732 mutex_lock(&ftrace_regex_lock); 1731 mutex_lock(&ftrace_regex_lock);
1733 if ((file->f_mode & FMODE_WRITE) && 1732 if ((file->f_mode & FMODE_WRITE) &&
1734 (file->f_flags & O_TRUNC)) 1733 (file->f_flags & O_TRUNC))
1735 ftrace_filter_reset(enable); 1734 ftrace_filter_reset(hash);
1736 1735
1737 if (file->f_mode & FMODE_READ) { 1736 if (file->f_mode & FMODE_READ) {
1738 iter->pg = ftrace_pages_start; 1737 iter->pg = ftrace_pages_start;
1739 iter->flags = enable ? FTRACE_ITER_FILTER : 1738 iter->flags = flag;
1740 FTRACE_ITER_NOTRACE;
1741 1739
1742 ret = seq_open(file, &show_ftrace_seq_ops); 1740 ret = seq_open(file, &show_ftrace_seq_ops);
1743 if (!ret) { 1741 if (!ret) {
@@ -1757,13 +1755,15 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
1757static int 1755static int
1758ftrace_filter_open(struct inode *inode, struct file *file) 1756ftrace_filter_open(struct inode *inode, struct file *file)
1759{ 1757{
1760 return ftrace_regex_open(inode, file, 1); 1758 return ftrace_regex_open(&filter_hash, FTRACE_ITER_FILTER,
1759 inode, file);
1761} 1760}
1762 1761
1763static int 1762static int
1764ftrace_notrace_open(struct inode *inode, struct file *file) 1763ftrace_notrace_open(struct inode *inode, struct file *file)
1765{ 1764{
1766 return ftrace_regex_open(inode, file, 0); 1765 return ftrace_regex_open(&notrace_hash, FTRACE_ITER_NOTRACE,
1766 inode, file);
1767} 1767}
1768 1768
1769static loff_t 1769static loff_t
@@ -1808,33 +1808,24 @@ static int ftrace_match(char *str, char *regex, int len, int type)
1808} 1808}
1809 1809
1810static int 1810static int
1811update_record(struct dyn_ftrace *rec, int enable, int not) 1811enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not)
1812{ 1812{
1813 struct ftrace_func_entry *entry; 1813 struct ftrace_func_entry *entry;
1814 struct ftrace_hash *hash = &notrace_hash;
1815 int ret = 0; 1814 int ret = 0;
1816 1815
1817 if (enable) { 1816 entry = ftrace_lookup_ip(hash, rec->ip);
1818 if (not) 1817 if (not) {
1819 rec->flags &= ~FTRACE_FL_FILTER; 1818 /* Do nothing if it doesn't exist */
1820 else 1819 if (!entry)
1821 rec->flags |= FTRACE_FL_FILTER; 1820 return 0;
1822 } else {
1823 if (not) {
1824 /* Do nothing if it doesn't exist */
1825 entry = ftrace_lookup_ip(hash, rec->ip);
1826 if (!entry)
1827 return 0;
1828 1821
1829 remove_hash_entry(hash, entry); 1822 remove_hash_entry(hash, entry);
1830 } else { 1823 } else {
1831 /* Do nothing if it exists */ 1824 /* Do nothing if it exists */
1832 entry = ftrace_lookup_ip(hash, rec->ip); 1825 if (entry)
1833 if (entry) 1826 return 0;
1834 return 0;
1835 1827
1836 ret = add_hash_entry(hash, rec->ip); 1828 ret = add_hash_entry(hash, rec->ip);
1837 }
1838 } 1829 }
1839 return ret; 1830 return ret;
1840} 1831}
@@ -1861,7 +1852,9 @@ ftrace_match_record(struct dyn_ftrace *rec, char *mod,
1861 return ftrace_match(str, regex, len, type); 1852 return ftrace_match(str, regex, len, type);
1862} 1853}
1863 1854
1864static int match_records(char *buff, int len, char *mod, int enable, int not) 1855static int
1856match_records(struct ftrace_hash *hash, char *buff,
1857 int len, char *mod, int not)
1865{ 1858{
1866 unsigned search_len = 0; 1859 unsigned search_len = 0;
1867 struct ftrace_page *pg; 1860 struct ftrace_page *pg;
@@ -1884,20 +1877,13 @@ static int match_records(char *buff, int len, char *mod, int enable, int not)
1884 do_for_each_ftrace_rec(pg, rec) { 1877 do_for_each_ftrace_rec(pg, rec) {
1885 1878
1886 if (ftrace_match_record(rec, mod, search, search_len, type)) { 1879 if (ftrace_match_record(rec, mod, search, search_len, type)) {
1887 ret = update_record(rec, enable, not); 1880 ret = enter_record(hash, rec, not);
1888 if (ret < 0) { 1881 if (ret < 0) {
1889 found = ret; 1882 found = ret;
1890 goto out_unlock; 1883 goto out_unlock;
1891 } 1884 }
1892 found = 1; 1885 found = 1;
1893 } 1886 }
1894 /*
1895 * Only enable filtering if we have a function that
1896 * is filtered on.
1897 */
1898 if (enable && (rec->flags & FTRACE_FL_FILTER))
1899 ftrace_filtered = 1;
1900
1901 } while_for_each_ftrace_rec(); 1887 } while_for_each_ftrace_rec();
1902 out_unlock: 1888 out_unlock:
1903 mutex_unlock(&ftrace_lock); 1889 mutex_unlock(&ftrace_lock);
@@ -1906,12 +1892,13 @@ static int match_records(char *buff, int len, char *mod, int enable, int not)
1906} 1892}
1907 1893
1908static int 1894static int
1909ftrace_match_records(char *buff, int len, int enable) 1895ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
1910{ 1896{
1911 return match_records(buff, len, NULL, enable, 0); 1897 return match_records(hash, buff, len, NULL, 0);
1912} 1898}
1913 1899
1914static int ftrace_match_module_records(char *buff, char *mod, int enable) 1900static int
1901ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
1915{ 1902{
1916 int not = 0; 1903 int not = 0;
1917 1904
@@ -1925,7 +1912,7 @@ static int ftrace_match_module_records(char *buff, char *mod, int enable)
1925 not = 1; 1912 not = 1;
1926 } 1913 }
1927 1914
1928 return match_records(buff, strlen(buff), mod, enable, not); 1915 return match_records(hash, buff, strlen(buff), mod, not);
1929} 1916}
1930 1917
1931/* 1918/*
@@ -1936,6 +1923,7 @@ static int ftrace_match_module_records(char *buff, char *mod, int enable)
1936static int 1923static int
1937ftrace_mod_callback(char *func, char *cmd, char *param, int enable) 1924ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
1938{ 1925{
1926 struct ftrace_hash *hash;
1939 char *mod; 1927 char *mod;
1940 int ret = -EINVAL; 1928 int ret = -EINVAL;
1941 1929
@@ -1955,7 +1943,12 @@ ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
1955 if (!strlen(mod)) 1943 if (!strlen(mod))
1956 return ret; 1944 return ret;
1957 1945
1958 ret = ftrace_match_module_records(func, mod, enable); 1946 if (enable)
1947 hash = &filter_hash;
1948 else
1949 hash = &notrace_hash;
1950
1951 ret = ftrace_match_module_records(hash, func, mod);
1959 if (!ret) 1952 if (!ret)
1960 ret = -EINVAL; 1953 ret = -EINVAL;
1961 if (ret < 0) 1954 if (ret < 0)
@@ -2253,12 +2246,18 @@ static int ftrace_process_regex(char *buff, int len, int enable)
2253{ 2246{
2254 char *func, *command, *next = buff; 2247 char *func, *command, *next = buff;
2255 struct ftrace_func_command *p; 2248 struct ftrace_func_command *p;
2249 struct ftrace_hash *hash;
2256 int ret; 2250 int ret;
2257 2251
2252 if (enable)
2253 hash = &filter_hash;
2254 else
2255 hash = &notrace_hash;
2256
2258 func = strsep(&next, ":"); 2257 func = strsep(&next, ":");
2259 2258
2260 if (!next) { 2259 if (!next) {
2261 ret = ftrace_match_records(func, len, enable); 2260 ret = ftrace_match_records(hash, func, len);
2262 if (!ret) 2261 if (!ret)
2263 ret = -EINVAL; 2262 ret = -EINVAL;
2264 if (ret < 0) 2263 if (ret < 0)
@@ -2340,16 +2339,16 @@ ftrace_notrace_write(struct file *file, const char __user *ubuf,
2340} 2339}
2341 2340
2342static void 2341static void
2343ftrace_set_regex(unsigned char *buf, int len, int reset, int enable) 2342ftrace_set_regex(struct ftrace_hash *hash, unsigned char *buf, int len, int reset)
2344{ 2343{
2345 if (unlikely(ftrace_disabled)) 2344 if (unlikely(ftrace_disabled))
2346 return; 2345 return;
2347 2346
2348 mutex_lock(&ftrace_regex_lock); 2347 mutex_lock(&ftrace_regex_lock);
2349 if (reset) 2348 if (reset)
2350 ftrace_filter_reset(enable); 2349 ftrace_filter_reset(hash);
2351 if (buf) 2350 if (buf)
2352 ftrace_match_records(buf, len, enable); 2351 ftrace_match_records(hash, buf, len);
2353 mutex_unlock(&ftrace_regex_lock); 2352 mutex_unlock(&ftrace_regex_lock);
2354} 2353}
2355 2354
@@ -2364,7 +2363,7 @@ ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
2364 */ 2363 */
2365void ftrace_set_filter(unsigned char *buf, int len, int reset) 2364void ftrace_set_filter(unsigned char *buf, int len, int reset)
2366{ 2365{
2367 ftrace_set_regex(buf, len, reset, 1); 2366 ftrace_set_regex(&filter_hash, buf, len, reset);
2368} 2367}
2369 2368
2370/** 2369/**
@@ -2379,7 +2378,7 @@ void ftrace_set_filter(unsigned char *buf, int len, int reset)
2379 */ 2378 */
2380void ftrace_set_notrace(unsigned char *buf, int len, int reset) 2379void ftrace_set_notrace(unsigned char *buf, int len, int reset)
2381{ 2380{
2382 ftrace_set_regex(buf, len, reset, 0); 2381 ftrace_set_regex(&notrace_hash, buf, len, reset);
2383} 2382}
2384 2383
2385/* 2384/*
@@ -2431,22 +2430,22 @@ static void __init set_ftrace_early_graph(char *buf)
2431} 2430}
2432#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2431#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2433 2432
2434static void __init set_ftrace_early_filter(char *buf, int enable) 2433static void __init set_ftrace_early_filter(struct ftrace_hash *hash, char *buf)
2435{ 2434{
2436 char *func; 2435 char *func;
2437 2436
2438 while (buf) { 2437 while (buf) {
2439 func = strsep(&buf, ","); 2438 func = strsep(&buf, ",");
2440 ftrace_set_regex(func, strlen(func), 0, enable); 2439 ftrace_set_regex(hash, func, strlen(func), 0);
2441 } 2440 }
2442} 2441}
2443 2442
2444static void __init set_ftrace_early_filters(void) 2443static void __init set_ftrace_early_filters(void)
2445{ 2444{
2446 if (ftrace_filter_buf[0]) 2445 if (ftrace_filter_buf[0])
2447 set_ftrace_early_filter(ftrace_filter_buf, 1); 2446 set_ftrace_early_filter(&filter_hash, ftrace_filter_buf);
2448 if (ftrace_notrace_buf[0]) 2447 if (ftrace_notrace_buf[0])
2449 set_ftrace_early_filter(ftrace_notrace_buf, 0); 2448 set_ftrace_early_filter(&notrace_hash, ftrace_notrace_buf);
2450#ifdef CONFIG_FUNCTION_GRAPH_TRACER 2449#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2451 if (ftrace_graph_buf[0]) 2450 if (ftrace_graph_buf[0])
2452 set_ftrace_early_graph(ftrace_graph_buf); 2451 set_ftrace_early_graph(ftrace_graph_buf);
@@ -2454,7 +2453,7 @@ static void __init set_ftrace_early_filters(void)
2454} 2453}
2455 2454
2456static int 2455static int
2457ftrace_regex_release(struct inode *inode, struct file *file, int enable) 2456ftrace_regex_release(struct inode *inode, struct file *file)
2458{ 2457{
2459 struct seq_file *m = (struct seq_file *)file->private_data; 2458 struct seq_file *m = (struct seq_file *)file->private_data;
2460 struct ftrace_iterator *iter; 2459 struct ftrace_iterator *iter;
@@ -2471,7 +2470,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
2471 parser = &iter->parser; 2470 parser = &iter->parser;
2472 if (trace_parser_loaded(parser)) { 2471 if (trace_parser_loaded(parser)) {
2473 parser->buffer[parser->idx] = 0; 2472 parser->buffer[parser->idx] = 0;
2474 ftrace_match_records(parser->buffer, parser->idx, enable); 2473 ftrace_match_records(iter->hash, parser->buffer, parser->idx);
2475 } 2474 }
2476 2475
2477 trace_parser_put(parser); 2476 trace_parser_put(parser);
@@ -2488,18 +2487,6 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
2488 return 0; 2487 return 0;
2489} 2488}
2490 2489
2491static int
2492ftrace_filter_release(struct inode *inode, struct file *file)
2493{
2494 return ftrace_regex_release(inode, file, 1);
2495}
2496
2497static int
2498ftrace_notrace_release(struct inode *inode, struct file *file)
2499{
2500 return ftrace_regex_release(inode, file, 0);
2501}
2502
2503static const struct file_operations ftrace_avail_fops = { 2490static const struct file_operations ftrace_avail_fops = {
2504 .open = ftrace_avail_open, 2491 .open = ftrace_avail_open,
2505 .read = seq_read, 2492 .read = seq_read,
@@ -2512,7 +2499,7 @@ static const struct file_operations ftrace_filter_fops = {
2512 .read = seq_read, 2499 .read = seq_read,
2513 .write = ftrace_filter_write, 2500 .write = ftrace_filter_write,
2514 .llseek = ftrace_regex_lseek, 2501 .llseek = ftrace_regex_lseek,
2515 .release = ftrace_filter_release, 2502 .release = ftrace_regex_release,
2516}; 2503};
2517 2504
2518static const struct file_operations ftrace_notrace_fops = { 2505static const struct file_operations ftrace_notrace_fops = {
@@ -2520,7 +2507,7 @@ static const struct file_operations ftrace_notrace_fops = {
2520 .read = seq_read, 2507 .read = seq_read,
2521 .write = ftrace_notrace_write, 2508 .write = ftrace_notrace_write,
2522 .llseek = ftrace_regex_lseek, 2509 .llseek = ftrace_regex_lseek,
2523 .release = ftrace_notrace_release, 2510 .release = ftrace_regex_release,
2524}; 2511};
2525 2512
2526#ifdef CONFIG_FUNCTION_GRAPH_TRACER 2513#ifdef CONFIG_FUNCTION_GRAPH_TRACER