Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tracing: Add support for named hist triggers

Allow users to define 'named' hist triggers. All triggers created
with the same 'name=xxx' option will update the same shared histogram
data.

This expands the hist trigger syntax from this:

# echo hist:keys=xxx ... [ if filter] > event/trigger

to this:

# echo hist:name=xxx:keys=xxx ... [ if filter] > event/trigger

Named histograms must use a 'compatible' set of keys and values, which
means each event added to a set of named triggers must have the same
names and types.

Reading the 'hist' file of any of the participating events will
produce the same output as any other participating event, which is to
be expected since they share the same data.

Link: http://lkml.kernel.org/r/1dbc84ee3322a75daaf5b3ef1d0cc0a2fb682fc7.1457029949.git.tom.zanussi@linux.intel.com

Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Tested-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

authored by

Tom Zanussi and committed by
Steven Rostedt
5463bfda db1388b4

+407 -29
+266 -8
Documentation/trace/events.txt
··· 524 524 525 525 hist:keys=<field1[,field2,...]>[:values=<field1[,field2,...]>] 526 526 [:sort=<field1[,field2,...]>][:size=#entries][:pause][:continue] 527 - [:clear] [if <filter>] 527 + [:clear][:name=histname1] [if <filter>] 528 528 529 529 When a matching event is hit, an entry is added to a hash table 530 530 using the key(s) and value(s) named. Keys and values correspond to ··· 546 546 specified by the 'sort' keyword. If more than one field is 547 547 specified, the result will be a 'sort within a sort': the first key 548 548 is taken to be the primary sort key and the second the secondary 549 - key. 549 + key. If a hist trigger is given a name using the 'name' parameter, 550 + its histogram data will be shared with other triggers of the same 551 + name, and trigger hits will update this common data. Only triggers 552 + with 'compatible' fields can be combined in this way; triggers are 553 + 'compatible' if the fields named in the trigger share the same 554 + number and type of fields and those fields also have the same names. 555 + Note that any two events always share the compatible 'hitcount' and 556 + 'stacktrace' fields and can therefore be combined using those 557 + fields, however pointless that may be. 550 558 551 559 'hist' triggers add a 'hist' file to each event's subdirectory. 552 560 Reading the 'hist' file for the event will dump the hash table in 553 561 its entirety to stdout. If there are multiple hist triggers 554 562 attached to an event, there will be a table for each trigger in the 555 - output. Each printed hash table entry is a simple list of the keys 556 - and values comprising the entry; keys are printed first and are 557 - delineated by curly braces, and are followed by the set of value 558 - fields for the entry. By default, numeric fields are displayed as 559 - base-10 integers. This can be modified by appending any of the 560 - following modifiers to the field name: 563 + output. The table displayed for a named trigger will be the same as 564 + any other instance having the same name. Each printed hash table 565 + entry is a simple list of the keys and values comprising the entry; 566 + keys are printed first and are delineated by curly braces, and are 567 + followed by the set of value fields for the entry. By default, 568 + numeric fields are displayed as base-10 integers. This can be 569 + modified by appending any of the following modifiers to the field 570 + name: 561 571 562 572 .hex display a number as a hex value 563 573 .sym display an address as a symbol ··· 1818 1808 Totals: 1819 1809 Hits: 0 1820 1810 Entries: 0 1811 + Dropped: 0 1812 + 1813 + Named triggers can be used to have triggers share a common set of 1814 + histogram data. This capability is mostly useful for combining the 1815 + output of events generated by tracepoints contained inside inline 1816 + functions, but names can be used in a hist trigger on any event. 1817 + For example, these two triggers when hit will update the same 'len' 1818 + field in the shared 'foo' histogram data: 1819 + 1820 + # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \ 1821 + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger 1822 + # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \ 1823 + /sys/kernel/debug/tracing/events/net/netif_rx/trigger 1824 + 1825 + You can see that they're updating common histogram data by reading 1826 + each event's hist files at the same time: 1827 + 1828 + # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist; 1829 + cat /sys/kernel/debug/tracing/events/net/netif_rx/hist 1830 + 1831 + # event histogram 1832 + # 1833 + # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active] 1834 + # 1835 + 1836 + { skbaddr: ffff88000ad53500 } hitcount: 1 len: 46 1837 + { skbaddr: ffff8800af5a1500 } hitcount: 1 len: 76 1838 + { skbaddr: ffff8800d62a1900 } hitcount: 1 len: 46 1839 + { skbaddr: ffff8800d2bccb00 } hitcount: 1 len: 468 1840 + { skbaddr: ffff8800d3c69900 } hitcount: 1 len: 46 1841 + { skbaddr: ffff88009ff09100 } hitcount: 1 len: 52 1842 + { skbaddr: ffff88010f13ab00 } hitcount: 1 len: 168 1843 + { skbaddr: ffff88006a54f400 } hitcount: 1 len: 46 1844 + { skbaddr: ffff8800d2bcc500 } hitcount: 1 len: 260 1845 + { skbaddr: ffff880064505000 } hitcount: 1 len: 46 1846 + { skbaddr: ffff8800baf24e00 } hitcount: 1 len: 32 1847 + { skbaddr: ffff88009fe0ad00 } hitcount: 1 len: 46 1848 + { skbaddr: ffff8800d3edff00 } hitcount: 1 len: 44 1849 + { skbaddr: ffff88009fe0b400 } hitcount: 1 len: 168 1850 + { skbaddr: ffff8800a1c55a00 } hitcount: 1 len: 40 1851 + { skbaddr: ffff8800d2bcd100 } hitcount: 1 len: 40 1852 + { skbaddr: ffff880064505f00 } hitcount: 1 len: 174 1853 + { skbaddr: ffff8800a8bff200 } hitcount: 1 len: 160 1854 + { skbaddr: ffff880044e3cc00 } hitcount: 1 len: 76 1855 + { skbaddr: ffff8800a8bfe700 } hitcount: 1 len: 46 1856 + { skbaddr: ffff8800d2bcdc00 } hitcount: 1 len: 32 1857 + { skbaddr: ffff8800a1f64800 } hitcount: 1 len: 46 1858 + { skbaddr: ffff8800d2bcde00 } hitcount: 1 len: 988 1859 + { skbaddr: ffff88006a5dea00 } hitcount: 1 len: 46 1860 + { skbaddr: ffff88002e37a200 } hitcount: 1 len: 44 1861 + { skbaddr: ffff8800a1f32c00 } hitcount: 2 len: 676 1862 + { skbaddr: ffff88000ad52600 } hitcount: 2 len: 107 1863 + { skbaddr: ffff8800a1f91e00 } hitcount: 2 len: 92 1864 + { skbaddr: ffff8800af5a0200 } hitcount: 2 len: 142 1865 + { skbaddr: ffff8800d2bcc600 } hitcount: 2 len: 220 1866 + { skbaddr: ffff8800ba36f500 } hitcount: 2 len: 92 1867 + { skbaddr: ffff8800d021f800 } hitcount: 2 len: 92 1868 + { skbaddr: ffff8800a1f33600 } hitcount: 2 len: 675 1869 + { skbaddr: ffff8800a8bfff00 } hitcount: 3 len: 138 1870 + { skbaddr: ffff8800d62a1300 } hitcount: 3 len: 138 1871 + { skbaddr: ffff88002e37a100 } hitcount: 4 len: 184 1872 + { skbaddr: ffff880064504400 } hitcount: 4 len: 184 1873 + { skbaddr: ffff8800a8bfec00 } hitcount: 4 len: 184 1874 + { skbaddr: ffff88000ad53700 } hitcount: 5 len: 230 1875 + { skbaddr: ffff8800d2bcdb00 } hitcount: 5 len: 196 1876 + { skbaddr: ffff8800a1f90000 } hitcount: 6 len: 276 1877 + { skbaddr: ffff88006a54f900 } hitcount: 6 len: 276 1878 + 1879 + Totals: 1880 + Hits: 81 1881 + Entries: 42 1882 + Dropped: 0 1883 + # event histogram 1884 + # 1885 + # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active] 1886 + # 1887 + 1888 + { skbaddr: ffff88000ad53500 } hitcount: 1 len: 46 1889 + { skbaddr: ffff8800af5a1500 } hitcount: 1 len: 76 1890 + { skbaddr: ffff8800d62a1900 } hitcount: 1 len: 46 1891 + { skbaddr: ffff8800d2bccb00 } hitcount: 1 len: 468 1892 + { skbaddr: ffff8800d3c69900 } hitcount: 1 len: 46 1893 + { skbaddr: ffff88009ff09100 } hitcount: 1 len: 52 1894 + { skbaddr: ffff88010f13ab00 } hitcount: 1 len: 168 1895 + { skbaddr: ffff88006a54f400 } hitcount: 1 len: 46 1896 + { skbaddr: ffff8800d2bcc500 } hitcount: 1 len: 260 1897 + { skbaddr: ffff880064505000 } hitcount: 1 len: 46 1898 + { skbaddr: ffff8800baf24e00 } hitcount: 1 len: 32 1899 + { skbaddr: ffff88009fe0ad00 } hitcount: 1 len: 46 1900 + { skbaddr: ffff8800d3edff00 } hitcount: 1 len: 44 1901 + { skbaddr: ffff88009fe0b400 } hitcount: 1 len: 168 1902 + { skbaddr: ffff8800a1c55a00 } hitcount: 1 len: 40 1903 + { skbaddr: ffff8800d2bcd100 } hitcount: 1 len: 40 1904 + { skbaddr: ffff880064505f00 } hitcount: 1 len: 174 1905 + { skbaddr: ffff8800a8bff200 } hitcount: 1 len: 160 1906 + { skbaddr: ffff880044e3cc00 } hitcount: 1 len: 76 1907 + { skbaddr: ffff8800a8bfe700 } hitcount: 1 len: 46 1908 + { skbaddr: ffff8800d2bcdc00 } hitcount: 1 len: 32 1909 + { skbaddr: ffff8800a1f64800 } hitcount: 1 len: 46 1910 + { skbaddr: ffff8800d2bcde00 } hitcount: 1 len: 988 1911 + { skbaddr: ffff88006a5dea00 } hitcount: 1 len: 46 1912 + { skbaddr: ffff88002e37a200 } hitcount: 1 len: 44 1913 + { skbaddr: ffff8800a1f32c00 } hitcount: 2 len: 676 1914 + { skbaddr: ffff88000ad52600 } hitcount: 2 len: 107 1915 + { skbaddr: ffff8800a1f91e00 } hitcount: 2 len: 92 1916 + { skbaddr: ffff8800af5a0200 } hitcount: 2 len: 142 1917 + { skbaddr: ffff8800d2bcc600 } hitcount: 2 len: 220 1918 + { skbaddr: ffff8800ba36f500 } hitcount: 2 len: 92 1919 + { skbaddr: ffff8800d021f800 } hitcount: 2 len: 92 1920 + { skbaddr: ffff8800a1f33600 } hitcount: 2 len: 675 1921 + { skbaddr: ffff8800a8bfff00 } hitcount: 3 len: 138 1922 + { skbaddr: ffff8800d62a1300 } hitcount: 3 len: 138 1923 + { skbaddr: ffff88002e37a100 } hitcount: 4 len: 184 1924 + { skbaddr: ffff880064504400 } hitcount: 4 len: 184 1925 + { skbaddr: ffff8800a8bfec00 } hitcount: 4 len: 184 1926 + { skbaddr: ffff88000ad53700 } hitcount: 5 len: 230 1927 + { skbaddr: ffff8800d2bcdb00 } hitcount: 5 len: 196 1928 + { skbaddr: ffff8800a1f90000 } hitcount: 6 len: 276 1929 + { skbaddr: ffff88006a54f900 } hitcount: 6 len: 276 1930 + 1931 + Totals: 1932 + Hits: 81 1933 + Entries: 42 1934 + Dropped: 0 1935 + 1936 + And here's an example that shows how to combine histogram data from 1937 + any two events even if they don't share any 'compatible' fields 1938 + other than 'hitcount' and 'stacktrace'. These commands create a 1939 + couple of triggers named 'bar' using those fields: 1940 + 1941 + # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ 1942 + /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger 1943 + # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ 1944 + /sys/kernel/debug/tracing/events/net/netif_rx/trigger 1945 + 1946 + And displaying the output of either shows some interesting if 1947 + somewhat confusing output: 1948 + 1949 + # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist 1950 + # cat /sys/kernel/debug/tracing/events/net/netif_rx/hist 1951 + 1952 + # event histogram 1953 + # 1954 + # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active] 1955 + # 1956 + 1957 + { stacktrace: 1958 + _do_fork+0x18e/0x330 1959 + kernel_thread+0x29/0x30 1960 + kthreadd+0x154/0x1b0 1961 + ret_from_fork+0x3f/0x70 1962 + } hitcount: 1 1963 + { stacktrace: 1964 + netif_rx_internal+0xb2/0xd0 1965 + netif_rx_ni+0x20/0x70 1966 + dev_loopback_xmit+0xaa/0xd0 1967 + ip_mc_output+0x126/0x240 1968 + ip_local_out_sk+0x31/0x40 1969 + igmp_send_report+0x1e9/0x230 1970 + igmp_timer_expire+0xe9/0x120 1971 + call_timer_fn+0x39/0xf0 1972 + run_timer_softirq+0x1e1/0x290 1973 + __do_softirq+0xfd/0x290 1974 + irq_exit+0x98/0xb0 1975 + smp_apic_timer_interrupt+0x4a/0x60 1976 + apic_timer_interrupt+0x6d/0x80 1977 + cpuidle_enter+0x17/0x20 1978 + call_cpuidle+0x3b/0x60 1979 + cpu_startup_entry+0x22d/0x310 1980 + } hitcount: 1 1981 + { stacktrace: 1982 + netif_rx_internal+0xb2/0xd0 1983 + netif_rx_ni+0x20/0x70 1984 + dev_loopback_xmit+0xaa/0xd0 1985 + ip_mc_output+0x17f/0x240 1986 + ip_local_out_sk+0x31/0x40 1987 + ip_send_skb+0x1a/0x50 1988 + udp_send_skb+0x13e/0x270 1989 + udp_sendmsg+0x2bf/0x980 1990 + inet_sendmsg+0x67/0xa0 1991 + sock_sendmsg+0x38/0x50 1992 + SYSC_sendto+0xef/0x170 1993 + SyS_sendto+0xe/0x10 1994 + entry_SYSCALL_64_fastpath+0x12/0x6a 1995 + } hitcount: 2 1996 + { stacktrace: 1997 + netif_rx_internal+0xb2/0xd0 1998 + netif_rx+0x1c/0x60 1999 + loopback_xmit+0x6c/0xb0 2000 + dev_hard_start_xmit+0x219/0x3a0 2001 + __dev_queue_xmit+0x415/0x4f0 2002 + dev_queue_xmit_sk+0x13/0x20 2003 + ip_finish_output2+0x237/0x340 2004 + ip_finish_output+0x113/0x1d0 2005 + ip_output+0x66/0xc0 2006 + ip_local_out_sk+0x31/0x40 2007 + ip_send_skb+0x1a/0x50 2008 + udp_send_skb+0x16d/0x270 2009 + udp_sendmsg+0x2bf/0x980 2010 + inet_sendmsg+0x67/0xa0 2011 + sock_sendmsg+0x38/0x50 2012 + ___sys_sendmsg+0x14e/0x270 2013 + } hitcount: 76 2014 + { stacktrace: 2015 + netif_rx_internal+0xb2/0xd0 2016 + netif_rx+0x1c/0x60 2017 + loopback_xmit+0x6c/0xb0 2018 + dev_hard_start_xmit+0x219/0x3a0 2019 + __dev_queue_xmit+0x415/0x4f0 2020 + dev_queue_xmit_sk+0x13/0x20 2021 + ip_finish_output2+0x237/0x340 2022 + ip_finish_output+0x113/0x1d0 2023 + ip_output+0x66/0xc0 2024 + ip_local_out_sk+0x31/0x40 2025 + ip_send_skb+0x1a/0x50 2026 + udp_send_skb+0x16d/0x270 2027 + udp_sendmsg+0x2bf/0x980 2028 + inet_sendmsg+0x67/0xa0 2029 + sock_sendmsg+0x38/0x50 2030 + ___sys_sendmsg+0x269/0x270 2031 + } hitcount: 77 2032 + { stacktrace: 2033 + netif_rx_internal+0xb2/0xd0 2034 + netif_rx+0x1c/0x60 2035 + loopback_xmit+0x6c/0xb0 2036 + dev_hard_start_xmit+0x219/0x3a0 2037 + __dev_queue_xmit+0x415/0x4f0 2038 + dev_queue_xmit_sk+0x13/0x20 2039 + ip_finish_output2+0x237/0x340 2040 + ip_finish_output+0x113/0x1d0 2041 + ip_output+0x66/0xc0 2042 + ip_local_out_sk+0x31/0x40 2043 + ip_send_skb+0x1a/0x50 2044 + udp_send_skb+0x16d/0x270 2045 + udp_sendmsg+0x2bf/0x980 2046 + inet_sendmsg+0x67/0xa0 2047 + sock_sendmsg+0x38/0x50 2048 + SYSC_sendto+0xef/0x170 2049 + } hitcount: 88 2050 + { stacktrace: 2051 + _do_fork+0x18e/0x330 2052 + SyS_clone+0x19/0x20 2053 + entry_SYSCALL_64_fastpath+0x12/0x6a 2054 + } hitcount: 244 2055 + 2056 + Totals: 2057 + Hits: 489 2058 + Entries: 7 1821 2059 Dropped: 0
+10 -4
kernel/trace/trace.c
··· 3842 3842 "\t [:sort=<field1[,field2,...]>]\n" 3843 3843 "\t [:size=#entries]\n" 3844 3844 "\t [:pause][:continue][:clear]\n" 3845 + "\t [:name=histname1]\n" 3845 3846 "\t [if <filter>]\n\n" 3846 3847 "\t When a matching event is hit, an entry is added to a hash\n" 3847 3848 "\t table using the key(s) and value(s) named, and the value of a\n" ··· 3855 3854 "\t specified using the 'sort' keyword. The sort direction can\n" 3856 3855 "\t be modified by appending '.descending' or '.ascending' to a\n" 3857 3856 "\t sort field. The 'size' parameter can be used to specify more\n" 3858 - "\t or fewer than the default 2048 entries for the hashtable size.\n\n" 3857 + "\t or fewer than the default 2048 entries for the hashtable size.\n" 3858 + "\t If a hist trigger is given a name using the 'name' parameter,\n" 3859 + "\t its histogram data will be shared with other triggers of the\n" 3860 + "\t same name, and trigger hits will update this common data.\n\n" 3859 3861 "\t Reading the 'hist' file for the event will dump the hash\n" 3860 3862 "\t table in its entirety to stdout. If there are multiple hist\n" 3861 3863 "\t triggers attached to an event, there will be a table for each\n" 3862 - "\t trigger in the output. The default format used to display a\n" 3863 - "\t given field can be modified by appending any of the following\n" 3864 - "\t modifiers to the field name, as applicable:\n\n" 3864 + "\t trigger in the output. The table displayed for a named\n" 3865 + "\t trigger will be the same as any other instance having the\n" 3866 + "\t same name. The default format used to display a given field\n" 3867 + "\t can be modified by appending any of the following modifiers\n" 3868 + "\t to the field name, as applicable:\n\n" 3865 3869 "\t .hex display a number as a hex value\n" 3866 3870 "\t .sym display an address as a symbol\n" 3867 3871 "\t .sym-offset display an address as a symbol and offset\n"
+131 -17
kernel/trace/trace_events_hist.c
··· 117 117 char *keys_str; 118 118 char *vals_str; 119 119 char *sort_key_str; 120 + char *name; 120 121 bool pause; 121 122 bool cont; 122 123 bool clear; ··· 201 200 if (!attrs) 202 201 return; 203 202 203 + kfree(attrs->name); 204 204 kfree(attrs->sort_key_str); 205 205 kfree(attrs->keys_str); 206 206 kfree(attrs->vals_str); ··· 229 227 attrs->vals_str = kstrdup(str, GFP_KERNEL); 230 228 else if (strncmp(str, "sort=", strlen("sort=")) == 0) 231 229 attrs->sort_key_str = kstrdup(str, GFP_KERNEL); 230 + else if (strncmp(str, "name=", strlen("name=")) == 0) 231 + attrs->name = kstrdup(str, GFP_KERNEL); 232 232 else if (strcmp(str, "pause") == 0) 233 233 attrs->pause = true; 234 234 else if ((strcmp(str, "cont") == 0) || ··· 1135 1131 struct hist_field *key_field; 1136 1132 unsigned int i; 1137 1133 1138 - seq_puts(m, "hist:keys="); 1134 + seq_puts(m, "hist:"); 1135 + 1136 + if (data->name) 1137 + seq_printf(m, "%s:", data->name); 1138 + 1139 + seq_puts(m, "keys="); 1139 1140 1140 1141 for_each_hist_key_field(i, hist_data) { 1141 1142 key_field = hist_data->fields[i]; ··· 1205 1196 return 0; 1206 1197 } 1207 1198 1199 + static int event_hist_trigger_init(struct event_trigger_ops *ops, 1200 + struct event_trigger_data *data) 1201 + { 1202 + struct hist_trigger_data *hist_data = data->private_data; 1203 + 1204 + if (!data->ref && hist_data->attrs->name) 1205 + save_named_trigger(hist_data->attrs->name, data); 1206 + 1207 + data->ref++; 1208 + 1209 + return 0; 1210 + } 1211 + 1208 1212 static void event_hist_trigger_free(struct event_trigger_ops *ops, 1209 1213 struct event_trigger_data *data) 1210 1214 { ··· 1228 1206 1229 1207 data->ref--; 1230 1208 if (!data->ref) { 1209 + if (data->name) 1210 + del_named_trigger(data); 1231 1211 trigger_data_free(data); 1232 1212 destroy_hist_data(hist_data); 1233 1213 } ··· 1238 1214 static struct event_trigger_ops event_hist_trigger_ops = { 1239 1215 .func = event_hist_trigger, 1240 1216 .print = event_hist_trigger_print, 1241 - .init = event_trigger_init, 1217 + .init = event_hist_trigger_init, 1242 1218 .free = event_hist_trigger_free, 1219 + }; 1220 + 1221 + static int event_hist_trigger_named_init(struct event_trigger_ops *ops, 1222 + struct event_trigger_data *data) 1223 + { 1224 + data->ref++; 1225 + 1226 + save_named_trigger(data->named_data->name, data); 1227 + 1228 + event_hist_trigger_init(ops, data->named_data); 1229 + 1230 + return 0; 1231 + } 1232 + 1233 + static void event_hist_trigger_named_free(struct event_trigger_ops *ops, 1234 + struct event_trigger_data *data) 1235 + { 1236 + if (WARN_ON_ONCE(data->ref <= 0)) 1237 + return; 1238 + 1239 + event_hist_trigger_free(ops, data->named_data); 1240 + 1241 + data->ref--; 1242 + if (!data->ref) { 1243 + del_named_trigger(data); 1244 + trigger_data_free(data); 1245 + } 1246 + } 1247 + 1248 + static struct event_trigger_ops event_hist_trigger_named_ops = { 1249 + .func = event_hist_trigger, 1250 + .print = event_hist_trigger_print, 1251 + .init = event_hist_trigger_named_init, 1252 + .free = event_hist_trigger_named_free, 1243 1253 }; 1244 1254 1245 1255 static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, ··· 1285 1227 static void hist_clear(struct event_trigger_data *data) 1286 1228 { 1287 1229 struct hist_trigger_data *hist_data = data->private_data; 1288 - bool paused; 1289 1230 1290 - paused = data->paused; 1291 - data->paused = true; 1231 + if (data->name) 1232 + pause_named_trigger(data); 1292 1233 1293 1234 synchronize_sched(); 1294 1235 1295 1236 tracing_map_clear(hist_data->map); 1296 1237 1297 - data->paused = paused; 1238 + if (data->name) 1239 + unpause_named_trigger(data); 1240 + } 1241 + 1242 + static bool compatible_field(struct ftrace_event_field *field, 1243 + struct ftrace_event_field *test_field) 1244 + { 1245 + if (field == test_field) 1246 + return true; 1247 + if (field == NULL || test_field == NULL) 1248 + return false; 1249 + if (strcmp(field->name, test_field->name) != 0) 1250 + return false; 1251 + if (strcmp(field->type, test_field->type) != 0) 1252 + return false; 1253 + if (field->size != test_field->size) 1254 + return false; 1255 + if (field->is_signed != test_field->is_signed) 1256 + return false; 1257 + 1258 + return true; 1298 1259 } 1299 1260 1300 1261 static bool hist_trigger_match(struct event_trigger_data *data, 1301 - struct event_trigger_data *data_test) 1262 + struct event_trigger_data *data_test, 1263 + struct event_trigger_data *named_data, 1264 + bool ignore_filter) 1302 1265 { 1303 1266 struct tracing_map_sort_key *sort_key, *sort_key_test; 1304 1267 struct hist_trigger_data *hist_data, *hist_data_test; 1305 1268 struct hist_field *key_field, *key_field_test; 1306 1269 unsigned int i; 1270 + 1271 + if (named_data && (named_data != data_test) && 1272 + (named_data != data_test->named_data)) 1273 + return false; 1274 + 1275 + if (!named_data && is_named_trigger(data_test)) 1276 + return false; 1307 1277 1308 1278 hist_data = data->private_data; 1309 1279 hist_data_test = data_test->private_data; ··· 1341 1255 hist_data->n_sort_keys != hist_data_test->n_sort_keys) 1342 1256 return false; 1343 1257 1344 - if ((data->filter_str && !data_test->filter_str) || 1345 - (!data->filter_str && data_test->filter_str)) 1346 - return false; 1258 + if (!ignore_filter) { 1259 + if ((data->filter_str && !data_test->filter_str) || 1260 + (!data->filter_str && data_test->filter_str)) 1261 + return false; 1262 + } 1347 1263 1348 1264 for_each_hist_field(i, hist_data) { 1349 1265 key_field = hist_data->fields[i]; ··· 1353 1265 1354 1266 if (key_field->flags != key_field_test->flags) 1355 1267 return false; 1356 - if (key_field->field != key_field_test->field) 1268 + if (!compatible_field(key_field->field, key_field_test->field)) 1357 1269 return false; 1358 1270 if (key_field->offset != key_field_test->offset) 1359 1271 return false; ··· 1368 1280 return false; 1369 1281 } 1370 1282 1371 - if (data->filter_str && 1283 + if (!ignore_filter && data->filter_str && 1372 1284 (strcmp(data->filter_str, data_test->filter_str) != 0)) 1373 1285 return false; 1374 1286 ··· 1380 1292 struct trace_event_file *file) 1381 1293 { 1382 1294 struct hist_trigger_data *hist_data = data->private_data; 1383 - struct event_trigger_data *test; 1295 + struct event_trigger_data *test, *named_data = NULL; 1384 1296 int ret = 0; 1297 + 1298 + if (hist_data->attrs->name) { 1299 + named_data = find_named_trigger(hist_data->attrs->name); 1300 + if (named_data) { 1301 + if (!hist_trigger_match(data, named_data, named_data, 1302 + true)) { 1303 + ret = -EINVAL; 1304 + goto out; 1305 + } 1306 + } 1307 + } 1308 + 1309 + if (hist_data->attrs->name && !named_data) 1310 + goto new; 1385 1311 1386 1312 list_for_each_entry_rcu(test, &file->triggers, list) { 1387 1313 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { 1388 - if (!hist_trigger_match(data, test)) 1314 + if (!hist_trigger_match(data, test, named_data, false)) 1389 1315 continue; 1390 1316 if (hist_data->attrs->pause) 1391 1317 test->paused = true; ··· 1412 1310 goto out; 1413 1311 } 1414 1312 } 1415 - 1313 + new: 1416 1314 if (hist_data->attrs->cont || hist_data->attrs->clear) { 1417 1315 ret = -ENOENT; 1418 1316 goto out; 1317 + } 1318 + 1319 + if (named_data) { 1320 + destroy_hist_data(data->private_data); 1321 + data->private_data = named_data->private_data; 1322 + set_named_trigger_data(data, named_data); 1323 + data->ops = &event_hist_trigger_named_ops; 1419 1324 } 1420 1325 1421 1326 if (hist_data->attrs->pause) ··· 1438 1329 ret++; 1439 1330 1440 1331 update_cond_flag(file); 1332 + 1441 1333 if (trace_event_trigger_enable_disable(file, 1) < 0) { 1442 1334 list_del_rcu(&data->list); 1443 1335 update_cond_flag(file); ··· 1452 1342 struct event_trigger_data *data, 1453 1343 struct trace_event_file *file) 1454 1344 { 1455 - struct event_trigger_data *test; 1345 + struct hist_trigger_data *hist_data = data->private_data; 1346 + struct event_trigger_data *test, *named_data = NULL; 1456 1347 bool unregistered = false; 1348 + 1349 + if (hist_data->attrs->name) 1350 + named_data = find_named_trigger(hist_data->attrs->name); 1457 1351 1458 1352 list_for_each_entry_rcu(test, &file->triggers, list) { 1459 1353 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { 1460 - if (!hist_trigger_match(data, test)) 1354 + if (!hist_trigger_match(data, test, named_data, false)) 1461 1355 continue; 1462 1356 unregistered = true; 1463 1357 list_del_rcu(&test->list);