aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2013-02-27 16:28:06 -0500
committerSteven Rostedt <rostedt@goodmis.org>2013-03-15 00:34:46 -0400
commit772482216f170ddc62fa92a3cc3271cdd1993525 (patch)
tree77b874b932c082e4de2abc73a68ba813455affbd /kernel/trace/trace_events.c
parent0c8916c34203734d3b05953ebace52d7c2969f16 (diff)
tracing: Get trace_events kernel command line working again
With the new descriptors used to allow multiple buffers in the tracing directory added, the kernel command line parameter trace_events=... no longer works. This is because the top level (global) trace array now has a list of descriptors associated with the events and the files in the debugfs directory. But in early bootup, when the command line is processed and the events enabled, the trace array list of events has not been set up yet. Without the list of events in the trace array, the setting of events to record will fail because it would not match any events. The solution is to set up the top level array in two stages. The first is to just add the ftrace file descriptors that just point to the events. This will allow events to be enabled and start tracing. The second stage is called after the filesystem is set up, and this stage will create the debugfs event files and directories associated with the trace array events. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c143
1 files changed, 136 insertions, 7 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 06d6bc275221..21fe83b4106a 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1473,6 +1473,28 @@ __trace_add_new_event(struct ftrace_event_call *call,
1473 return event_create_dir(tr->event_dir, file, id, enable, filter, format); 1473 return event_create_dir(tr->event_dir, file, id, enable, filter, format);
1474} 1474}
1475 1475
1476/*
1477 * Just create a decriptor for early init. A descriptor is required
1478 * for enabling events at boot. We want to enable events before
1479 * the filesystem is initialized.
1480 */
1481static __init int
1482__trace_early_add_new_event(struct ftrace_event_call *call,
1483 struct trace_array *tr)
1484{
1485 struct ftrace_event_file *file;
1486
1487 file = kzalloc(sizeof(*file), GFP_KERNEL);
1488 if (!file)
1489 return -ENOMEM;
1490
1491 file->event_call = call;
1492 file->tr = tr;
1493 list_add(&file->list, &tr->events);
1494
1495 return 0;
1496}
1497
1476struct ftrace_module_file_ops; 1498struct ftrace_module_file_ops;
1477static void __add_event_to_tracers(struct ftrace_event_call *call, 1499static void __add_event_to_tracers(struct ftrace_event_call *call,
1478 struct ftrace_module_file_ops *file_ops); 1500 struct ftrace_module_file_ops *file_ops);
@@ -1709,6 +1731,56 @@ __trace_add_event_dirs(struct trace_array *tr)
1709 } 1731 }
1710} 1732}
1711 1733
1734/*
1735 * The top level array has already had its ftrace_event_file
1736 * descriptors created in order to allow for early events to
1737 * be recorded. This function is called after the debugfs has been
1738 * initialized, and we now have to create the files associated
1739 * to the events.
1740 */
1741static __init void
1742__trace_early_add_event_dirs(struct trace_array *tr)
1743{
1744 struct ftrace_event_file *file;
1745 int ret;
1746
1747
1748 list_for_each_entry(file, &tr->events, list) {
1749 ret = event_create_dir(tr->event_dir, file,
1750 &ftrace_event_id_fops,
1751 &ftrace_enable_fops,
1752 &ftrace_event_filter_fops,
1753 &ftrace_event_format_fops);
1754 if (ret < 0)
1755 pr_warning("Could not create directory for event %s\n",
1756 file->event_call->name);
1757 }
1758}
1759
1760/*
1761 * For early boot up, the top trace array requires to have
1762 * a list of events that can be enabled. This must be done before
1763 * the filesystem is set up in order to allow events to be traced
1764 * early.
1765 */
1766static __init void
1767__trace_early_add_events(struct trace_array *tr)
1768{
1769 struct ftrace_event_call *call;
1770 int ret;
1771
1772 list_for_each_entry(call, &ftrace_events, list) {
1773 /* Early boot up should not have any modules loaded */
1774 if (WARN_ON_ONCE(call->mod))
1775 continue;
1776
1777 ret = __trace_early_add_new_event(call, tr);
1778 if (ret < 0)
1779 pr_warning("Could not create early event %s\n",
1780 call->name);
1781 }
1782}
1783
1712/* Remove the event directory structure for a trace directory. */ 1784/* Remove the event directory structure for a trace directory. */
1713static void 1785static void
1714__trace_remove_event_dirs(struct trace_array *tr) 1786__trace_remove_event_dirs(struct trace_array *tr)
@@ -1763,25 +1835,23 @@ static __init int setup_trace_event(char *str)
1763} 1835}
1764__setup("trace_event=", setup_trace_event); 1836__setup("trace_event=", setup_trace_event);
1765 1837
1766int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr) 1838/* Expects to have event_mutex held when called */
1839static int
1840create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
1767{ 1841{
1768 struct dentry *d_events; 1842 struct dentry *d_events;
1769 struct dentry *entry; 1843 struct dentry *entry;
1770 1844
1771 mutex_lock(&event_mutex);
1772
1773 entry = debugfs_create_file("set_event", 0644, parent, 1845 entry = debugfs_create_file("set_event", 0644, parent,
1774 tr, &ftrace_set_event_fops); 1846 tr, &ftrace_set_event_fops);
1775 if (!entry) { 1847 if (!entry) {
1776 pr_warning("Could not create debugfs 'set_event' entry\n"); 1848 pr_warning("Could not create debugfs 'set_event' entry\n");
1777 mutex_unlock(&event_mutex);
1778 return -ENOMEM; 1849 return -ENOMEM;
1779 } 1850 }
1780 1851
1781 d_events = debugfs_create_dir("events", parent); 1852 d_events = debugfs_create_dir("events", parent);
1782 if (!d_events) { 1853 if (!d_events) {
1783 pr_warning("Could not create debugfs 'events' directory\n"); 1854 pr_warning("Could not create debugfs 'events' directory\n");
1784 mutex_unlock(&event_mutex);
1785 return -ENOMEM; 1855 return -ENOMEM;
1786 } 1856 }
1787 1857
@@ -1798,13 +1868,64 @@ int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr)
1798 tr, &ftrace_tr_enable_fops); 1868 tr, &ftrace_tr_enable_fops);
1799 1869
1800 tr->event_dir = d_events; 1870 tr->event_dir = d_events;
1871
1872 return 0;
1873}
1874
1875/**
1876 * event_trace_add_tracer - add a instance of a trace_array to events
1877 * @parent: The parent dentry to place the files/directories for events in
1878 * @tr: The trace array associated with these events
1879 *
1880 * When a new instance is created, it needs to set up its events
1881 * directory, as well as other files associated with events. It also
1882 * creates the event hierachry in the @parent/events directory.
1883 *
1884 * Returns 0 on success.
1885 */
1886int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr)
1887{
1888 int ret;
1889
1890 mutex_lock(&event_mutex);
1891
1892 ret = create_event_toplevel_files(parent, tr);
1893 if (ret)
1894 goto out_unlock;
1895
1801 down_write(&trace_event_mutex); 1896 down_write(&trace_event_mutex);
1802 __trace_add_event_dirs(tr); 1897 __trace_add_event_dirs(tr);
1803 up_write(&trace_event_mutex); 1898 up_write(&trace_event_mutex);
1804 1899
1900 out_unlock:
1805 mutex_unlock(&event_mutex); 1901 mutex_unlock(&event_mutex);
1806 1902
1807 return 0; 1903 return ret;
1904}
1905
1906/*
1907 * The top trace array already had its file descriptors created.
1908 * Now the files themselves need to be created.
1909 */
1910static __init int
1911early_event_add_tracer(struct dentry *parent, struct trace_array *tr)
1912{
1913 int ret;
1914
1915 mutex_lock(&event_mutex);
1916
1917 ret = create_event_toplevel_files(parent, tr);
1918 if (ret)
1919 goto out_unlock;
1920
1921 down_write(&trace_event_mutex);
1922 __trace_early_add_event_dirs(tr);
1923 up_write(&trace_event_mutex);
1924
1925 out_unlock:
1926 mutex_unlock(&event_mutex);
1927
1928 return ret;
1808} 1929}
1809 1930
1810int event_trace_del_tracer(struct trace_array *tr) 1931int event_trace_del_tracer(struct trace_array *tr)
@@ -1842,6 +1963,14 @@ static __init int event_trace_enable(void)
1842 list_add(&call->list, &ftrace_events); 1963 list_add(&call->list, &ftrace_events);
1843 } 1964 }
1844 1965
1966 /*
1967 * We need the top trace array to have a working set of trace
1968 * points at early init, before the debug files and directories
1969 * are created. Create the file entries now, and attach them
1970 * to the actual file dentries later.
1971 */
1972 __trace_early_add_events(tr);
1973
1845 while (true) { 1974 while (true) {
1846 token = strsep(&buf, ","); 1975 token = strsep(&buf, ",");
1847 1976
@@ -1882,7 +2011,7 @@ static __init int event_trace_init(void)
1882 if (trace_define_common_fields()) 2011 if (trace_define_common_fields())
1883 pr_warning("tracing: Failed to allocate common fields"); 2012 pr_warning("tracing: Failed to allocate common fields");
1884 2013
1885 ret = event_trace_add_tracer(d_tracer, tr); 2014 ret = early_event_add_tracer(d_tracer, tr);
1886 if (ret) 2015 if (ret)
1887 return ret; 2016 return ret;
1888 2017