Re: [PATCH 0/3] tracing: Fix some selftest issues

2024-05-29 Thread Tom Zanussi
Hi Masami,

On Wed, 2024-05-29 at 08:38 +0900, Masami Hiramatsu wrote:
> On Wed, 29 May 2024 01:46:40 +0900
> Masami Hiramatsu (Google)  wrote:
> 
> > On Mon, 27 May 2024 19:29:07 -0400
> > Steven Rostedt  wrote:
> > 
> > > On Sun, 26 May 2024 19:10:57 +0900
> > > "Masami Hiramatsu (Google)"  wrote:
> > > 
> > > > Hi,
> > > > 
> > > > Here is a series of some fixes/improvements for the test
> > > > modules and boot
> > > > time selftest of kprobe events. I found a WARNING message with
> > > > some boot 
> > > > time selftest configuration, which came from the combination of
> > > > embedded
> > > > kprobe generate API tests module and ftrace boot-time selftest.
> > > > So the main
> > > > problem is that the test module should not be built-in. But I
> > > > also think
> > > > this WARNING message is useless (because there are warning
> > > > messages already)
> > > > and the cleanup code is redundant. This series fixes those
> > > > issues.
> > > 
> > > Note, when I enable trace tests as builtin instead of modules, I
> > > just
> > > disable the bootup self tests when it detects this. This helps
> > > with
> > > doing tests via config options than having to add user space code
> > > that
> > > loads modules.
> > > 
> > > Could you do something similar?
> > 
> > OK, in that case, I would like to move the test cleanup code in
> > module_exit function into the end of module_init function. 
> > It looks there is no reason to split those into 2 parts.
> 
> Wait, I would like to hear Tom's opinion. I found following usage
> comments
> in the code.
> 
>  * Following that are a few examples using the created events to test
>  * various ways of tracing a synthetic event.
>  *
>  * To test, select CONFIG_SYNTH_EVENT_GEN_TEST and build the module.
>  * Then:
>  *
>  * # insmod kernel/trace/synth_event_gen_test.ko
>  * # cat /sys/kernel/tracing/trace
>  *
>  * You should see several events in the trace buffer -
>  * "create_synth_test", "empty_synth_test", and several instances of
>  * "gen_synth_test".
>  *
>  * To remove the events, remove the module:
>  *
>  * # rmmod synth_event_gen_test
> 
> Tom, is that intended behavior ? and are you expected to reuse these
> events outside of the module? e.g. load the test module and run some
> test script in user space which uses those events?
> 

Yeah, this module was meant as a sample module showing how to create
and generate synthetic events in-kernel.

So the interested user insmods the module, looks at the trace stream
and sees, ok the events are there as expected, so it does work, great,
let's remove the module to get rid of them and go write our own.

Having both the creation and cleanup in module_init() wouldn't allow
the user the opportunity to do that i.e. verify the results by reading
the trace file.

Tom 

> As far as I can see, those tests are not intended to be embedded in
> the
> kernel because those are expected to be removed.
> 
> Thank you,
> 
> > 
> > Thank you,
> > 
> > > 
> > > -- Steve
> > > 
> > > 
> > > > 
> > > > Thank you,
> > > > 
> > > > ---
> > > > 
> > > > Masami Hiramatsu (Google) (3):
> > > >   tracing: Build event generation tests only as modules
> > > >   tracing/kprobe: Remove unneeded WARN_ON_ONCE() in
> > > > selftests
> > > >   tracing/kprobe: Remove cleanup code unrelated to selftest
> > > > 
> > 
> > 
> > -- 
> > Masami Hiramatsu (Google) 
> 
> 




Re: [PATCH] tracing: Ensure visibility when inserting an element into tracing_map

2024-01-22 Thread Tom Zanussi
 new key. Subsequent updates targeting the same key remain unaffected.
> 
> From the user's perspective, the issue was introduced by commit
> c193707dde77 ("tracing: Remove code which merges duplicates"), which
> followed commit cbf4100efb8f ("tracing: Add support to detect and avoid
> duplicates"). The previous code operated differently; it inherently
> expected potential races which result in duplicates but merged them
> later when they occurred.
> 
> Fixes: c193707dde77 ("tracing: Remove code which merges duplicates")
> Signed-off-by: Petr Pavlu 
> ---
>  kernel/trace/tracing_map.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c
> index c774e560f2f9..a4dcf0f24352 100644
> --- a/kernel/trace/tracing_map.c
> +++ b/kernel/trace/tracing_map.c
> @@ -574,7 +574,12 @@ __tracing_map_insert(struct tracing_map *map, void *key, 
> bool lookup_only)
> }
>  
> memcpy(elt->key, key, map->key_size);
> -   entry->val = elt;
> +       /*
> +    * Ensure the initialization is visible and
> +    * publish the elt.
> +    */
> +   smp_wmb();
> +   WRITE_ONCE(entry->val, elt);
> atomic64_inc(>hits);
>  
> return entry->val;
> 
> base-commit: 9d1694dc91ce7b80bc96d6d8eaf1a1eca668d847

Makes sense, thanks for fixing this!

Acked-by: Tom Zanussi 

Tom






[ANNOUNCE] 5.4.109-rt56

2021-04-17 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 5.4.109-rt56 stable release.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v5.4-rt
  Head SHA1: a84a83ce44cafc96cb9cf419378a713dcdea00ac

Or to build 5.4.109-rt56 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.xz

  https://www.kernel.org/pub/linux/kernel/v5.x/patch-5.4.109.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/patch-5.4.109-rt56.patch.xz


You can also build from 5.4.109-rt55 by applying the incremental patch:

  
https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/incr/patch-5.4.109-rt55-rt56.patch.xz

Enjoy!

   Tom

Changes from v5.4.109-rt55:
---

Sebastian Andrzej Siewior (1):
  mm: slub: Don't resize the location tracking cache on PREEMPT_RT

Tom Zanussi (1):
  Linux 5.4.109-rt56
---
localversion-rt | 2 +-
 mm/slub.c   | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)
---
diff --git a/localversion-rt b/localversion-rt
index 51b05e9abe6f..fdb0f880c7e9 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt55
+-rt56
diff --git a/mm/slub.c b/mm/slub.c
index 1815e28852fe..0d78368d149a 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4647,6 +4647,9 @@ static int alloc_loc_track(struct loc_track *t, unsigned 
long max, gfp_t flags)
struct location *l;
int order;
 
+   if (IS_ENABLED(CONFIG_PREEMPT_RT) && flags == GFP_ATOMIC)
+   return 0;
+
order = get_order(sizeof(struct location) * max);
 
l = (void *)__get_free_pages(flags, order);



[ANNOUNCE] 5.4.109-rt55

2021-04-05 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 5.4.109-rt55 stable release.

This release is just an update to the new stable 5.4.109
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v5.4-rt
  Head SHA1: 209aee2366649eebf5b3881f73199cc78d4700f3

Or to build 5.4.109-rt55 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.xz

  https://www.kernel.org/pub/linux/kernel/v5.x/patch-5.4.109.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/patch-5.4.109-rt55.patch.xz

Enjoy!

   Tom



[PATCH v2 0/1] dmaengine: idxd: IDXD pmu support

2021-04-03 Thread Tom Zanussi
From: Tom Zanussi 

Hi,

This is v2 of the IDXD pmu support patch, which is the same as v1 but
removes a few assigned-but-unused variables reported by kernel test
robot .

Thanks,

Tom


 -- original v1 text --

Hi,

This patchset implements initial pmu support for the Intel DSA (Data
Streaming Accelerator [1]), which I'm hoping can go into 5.13.

I'm also hoping to supply a couple follow-on patches in the near
future, but I'm not yet sure how much sense they make, so I thought
I'd throw a couple ideas out there and maybe get some opinions before
going forward with them:

  - The perf userspace interface for this isn't exactly user-friedly,
in that you currently need to specify numeric values for field
values:

 # perf stat -e dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
filter_eng=0x1,event=0x8,event_category=0x3/

It would be nicer to be able to specify those values symbolically
instead, and the way to do that seems to be via some JSON files in
perf userspace.

  - Some of the DSA pmu support is patterned after existing uncore
code, and there seems to be at least some opportunity to
consolidate some of the things they both do into common code, such
as the cpumask device attributes and related cpu hotplug support.
At this point I'm not sure how much sense it makes to put any
effort into that, but would be willing to try if there would be
some interest in it, especially considering there will probably be
future pmu support added that could benefit from it.

Thanks,

Tom

Tom Zanussi (1):
  dmaengine: idxd: Add IDXD performance monitor support

 drivers/dma/Kconfig  |  13 +
 drivers/dma/idxd/Makefile|   2 +
 drivers/dma/idxd/idxd.h  |  45 +++
 drivers/dma/idxd/init.c  |   9 +
 drivers/dma/idxd/irq.c   |   5 +-
 drivers/dma/idxd/perfmon.c   | 653 +++
 drivers/dma/idxd/perfmon.h   | 119 +++
 drivers/dma/idxd/registers.h | 108 ++
 include/linux/cpuhotplug.h   |   1 +
 9 files changed, 951 insertions(+), 4 deletions(-)
 create mode 100644 drivers/dma/idxd/perfmon.c
 create mode 100644 drivers/dma/idxd/perfmon.h

-- 
2.17.1



[PATCH v2 1/1] dmaengine: idxd: Add IDXD performance monitor support

2021-04-03 Thread Tom Zanussi
  dsa0/event=0x2,event_category=0x1/
19  dsa0/event=0x4,event_category=0x1/
19  dsa0/event=0x8,event_category=0x1/
 0  dsa0/event=0x10,event_category=0x1/
19  dsa0/event=0x20,event_category=0x1/

  21.977436186 seconds time elapsed

The command below illustrates filter usage with a simple example.  It
specifies that MEM_MOVE operations should be counted for the DSA
device dsa0 (event 0x8 corresponds to the EV_MEM_MOVE event - Number
of Memory Move Descriptors, which is part of event category 0x3 -
Operations. The detailed category and event IDs are available in
Appendix D, Performance Monitoring Events, of [1]).  In addition to
the event and event category, a number of filters are also specified
(the detailed filter values are available in Chapter 6.4 (Filter
Support) of [1]), which will restrict counting to only those events
that meet all of the filter criteria.  In this case, the filters
specify that only MEM_MOVE operations that are serviced by work queue
wq0 and specifically engine number engine0 and traffic class tc0
having sizes between 0 and 4k and page size of between 0 and 1G result
in a counter hit; anything else will be filtered out and not appear in
the final count.  Note that filters are optional - any filter not
specified is assumed to be all ones and will pass anything.

 # perf stat -e dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
filter_eng=0x1,event=0x8,event_category=0x3/
  modprobe dmatest channel=dma0chan0 timeout=2000
  iterations=19 run=1 wait=1

 Performance counter stats for 'system wide':

   19  dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
   filter_eng=0x1,event=0x8,event_category=0x3/

  21.865914091 seconds time elapsed

The output above reflects that the unspecified workload resulted in
the counting of 19 MEM_MOVE operation events that met the filter
criteria.

[1]: 
https://software.intel.com/content/www/us/en/develop/download/intel-data-streaming-accelerator-preliminary-architecture-specification.html

[ Based on work originally by Jing Lin. ]

Reviewed-by: Dave Jiang 
Reviewed-by: Kan Liang 
Signed-off-by: Tom Zanussi 
---
 drivers/dma/Kconfig  |  13 +
 drivers/dma/idxd/Makefile|   2 +
 drivers/dma/idxd/idxd.h  |  45 +++
 drivers/dma/idxd/init.c  |   9 +
 drivers/dma/idxd/irq.c   |   5 +-
 drivers/dma/idxd/perfmon.c   | 653 +++
 drivers/dma/idxd/perfmon.h   | 119 +++
 drivers/dma/idxd/registers.h | 108 ++
 include/linux/cpuhotplug.h   |   1 +
 9 files changed, 951 insertions(+), 4 deletions(-)
 create mode 100644 drivers/dma/idxd/perfmon.c
 create mode 100644 drivers/dma/idxd/perfmon.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 0c2827fd8c19..fa945420e346 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -300,6 +300,19 @@ config INTEL_IDXD_SVM
depends on PCI_PASID
depends on PCI_IOV
 
+config INTEL_IDXD_PERFMON
+   bool "Intel Data Accelerators performance monitor support"
+   depends on INTEL_IDXD
+   default y
+   help
+ Enable performance monitor (pmu) support for the Intel(R)
+ data accelerators present in Intel Xeon CPU.  With this
+ enabled, perf can be used to monitor the DSA (Intel Data
+ Streaming Accelerator) events described in the Intel DSA
+ spec.
+
+ If unsure, say N.
+
 config INTEL_IOATDMA
tristate "Intel I/OAT DMA support"
depends on PCI && X86_64
diff --git a/drivers/dma/idxd/Makefile b/drivers/dma/idxd/Makefile
index 8978b898d777..6d11558756f8 100644
--- a/drivers/dma/idxd/Makefile
+++ b/drivers/dma/idxd/Makefile
@@ -1,2 +1,4 @@
 obj-$(CONFIG_INTEL_IDXD) += idxd.o
 idxd-y := init.o irq.o device.o sysfs.o submit.o dma.o cdev.o
+
+idxd-$(CONFIG_INTEL_IDXD_PERFMON) += perfmon.o
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index 81a0e65fd316..bde819f30916 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -8,6 +8,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "registers.h"
 
 #define IDXD_DRIVER_VERSION"1.00"
@@ -25,6 +27,7 @@ enum idxd_type {
 };
 
 #define IDXD_NAME_SIZE 128
+#define IDXD_PMU_EVENT_MAX 64
 
 struct idxd_device_driver {
struct device_driver drv;
@@ -56,6 +59,31 @@ struct idxd_group {
int tc_b;
 };
 
+struct idxd_pmu {
+   struct idxd_device *idxd;
+
+   struct perf_event *event_list[IDXD_PMU_EVENT_MAX];
+   int n_events;
+
+   DECLARE_BITMAP(used_mask, IDXD_PMU_EVENT_MAX);
+
+   struct pmu pmu;
+   char name[IDXD_NAME_SIZE];
+   int cpu;
+
+   int n_counters;
+   int counter_width;
+   int n_event_categories;
+
+   bool per_counter_caps_supported;
+   unsigned long supported_event_categ

[PATCH 1/1] dmaengine: idxd: Add IDXD performance monitor support

2021-04-02 Thread Tom Zanussi
  dsa0/event=0x2,event_category=0x1/
19  dsa0/event=0x4,event_category=0x1/
19  dsa0/event=0x8,event_category=0x1/
 0  dsa0/event=0x10,event_category=0x1/
19  dsa0/event=0x20,event_category=0x1/

  21.977436186 seconds time elapsed

The command below illustrates filter usage with a simple example.  It
specifies that MEM_MOVE operations should be counted for the DSA
device dsa0 (event 0x8 corresponds to the EV_MEM_MOVE event - Number
of Memory Move Descriptors, which is part of event category 0x3 -
Operations. The detailed category and event IDs are available in
Appendix D, Performance Monitoring Events, of [1]).  In addition to
the event and event category, a number of filters are also specified
(the detailed filter values are available in Chapter 6.4 (Filter
Support) of [1]), which will restrict counting to only those events
that meet all of the filter criteria.  In this case, the filters
specify that only MEM_MOVE operations that are serviced by work queue
wq0 and specifically engine number engine0 and traffic class tc0
having sizes between 0 and 4k and page size of between 0 and 1G result
in a counter hit; anything else will be filtered out and not appear in
the final count.  Note that filters are optional - any filter not
specified is assumed to be all ones and will pass anything.

 # perf stat -e dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
filter_eng=0x1,event=0x8,event_category=0x3/
  modprobe dmatest channel=dma0chan0 timeout=2000
  iterations=19 run=1 wait=1

 Performance counter stats for 'system wide':

   19  dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
   filter_eng=0x1,event=0x8,event_category=0x3/

  21.865914091 seconds time elapsed

The output above reflects that the unspecified workload resulted in
the counting of 19 MEM_MOVE operation events that met the filter
criteria.

[1]: 
https://software.intel.com/content/www/us/en/develop/download/intel-data-streaming-accelerator-preliminary-architecture-specification.html

[ Based on work originally by Jing Lin. ]

Reviewed-by: Dave Jiang 
Reviewed-by: Kan Liang 
Signed-off-by: Tom Zanussi 
---
 drivers/dma/Kconfig  |  13 +
 drivers/dma/idxd/Makefile|   2 +
 drivers/dma/idxd/idxd.h  |  45 +++
 drivers/dma/idxd/init.c  |   9 +
 drivers/dma/idxd/irq.c   |   5 +-
 drivers/dma/idxd/perfmon.c   | 661 +++
 drivers/dma/idxd/perfmon.h   | 119 +++
 drivers/dma/idxd/registers.h | 108 ++
 include/linux/cpuhotplug.h   |   1 +
 9 files changed, 959 insertions(+), 4 deletions(-)
 create mode 100644 drivers/dma/idxd/perfmon.c
 create mode 100644 drivers/dma/idxd/perfmon.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 0c2827fd8c19..fa945420e346 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -300,6 +300,19 @@ config INTEL_IDXD_SVM
depends on PCI_PASID
depends on PCI_IOV
 
+config INTEL_IDXD_PERFMON
+   bool "Intel Data Accelerators performance monitor support"
+   depends on INTEL_IDXD
+   default y
+   help
+ Enable performance monitor (pmu) support for the Intel(R)
+ data accelerators present in Intel Xeon CPU.  With this
+ enabled, perf can be used to monitor the DSA (Intel Data
+ Streaming Accelerator) events described in the Intel DSA
+ spec.
+
+ If unsure, say N.
+
 config INTEL_IOATDMA
tristate "Intel I/OAT DMA support"
depends on PCI && X86_64
diff --git a/drivers/dma/idxd/Makefile b/drivers/dma/idxd/Makefile
index 8978b898d777..6d11558756f8 100644
--- a/drivers/dma/idxd/Makefile
+++ b/drivers/dma/idxd/Makefile
@@ -1,2 +1,4 @@
 obj-$(CONFIG_INTEL_IDXD) += idxd.o
 idxd-y := init.o irq.o device.o sysfs.o submit.o dma.o cdev.o
+
+idxd-$(CONFIG_INTEL_IDXD_PERFMON) += perfmon.o
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index 81a0e65fd316..bde819f30916 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -8,6 +8,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "registers.h"
 
 #define IDXD_DRIVER_VERSION"1.00"
@@ -25,6 +27,7 @@ enum idxd_type {
 };
 
 #define IDXD_NAME_SIZE 128
+#define IDXD_PMU_EVENT_MAX 64
 
 struct idxd_device_driver {
struct device_driver drv;
@@ -56,6 +59,31 @@ struct idxd_group {
int tc_b;
 };
 
+struct idxd_pmu {
+   struct idxd_device *idxd;
+
+   struct perf_event *event_list[IDXD_PMU_EVENT_MAX];
+   int n_events;
+
+   DECLARE_BITMAP(used_mask, IDXD_PMU_EVENT_MAX);
+
+   struct pmu pmu;
+   char name[IDXD_NAME_SIZE];
+   int cpu;
+
+   int n_counters;
+   int counter_width;
+   int n_event_categories;
+
+   bool per_counter_caps_supported;
+   unsigned long supported_event_categ

[PATCH 0/1] dmaengine: idxd: IDXD pmu support

2021-04-02 Thread Tom Zanussi
Hi,

This patchset implements initial pmu support for the Intel DSA (Data
Streaming Accelerator [1]), which I'm hoping can go into 5.13.

I'm also hoping to supply a couple follow-on patches in the near
future, but I'm not yet sure how much sense they make, so I thought
I'd throw a couple ideas out there and maybe get some opinions before
going forward with them:

  - The perf userspace interface for this isn't exactly user-friedly,
in that you currently need to specify numeric values for field
values:

 # perf stat -e dsa0/filter_wq=0x1,filter_tc=0x1,filter_sz=0x7,
filter_eng=0x1,event=0x8,event_category=0x3/

It would be nicer to be able to specify those values symbolically
instead, and the way to do that seems to be via some JSON files in
perf userspace.

  - Some of the DSA pmu support is patterned after existing uncore
code, and there seems to be at least some opportunity to
consolidate some of the things they both do into common code, such
as the cpumask device attributes and related cpu hotplug support.
At this point I'm not sure how much sense it makes to put any
effort into that, but would be willing to try if there would be
some interest in it, especially considering there will probably be
future pmu support added that could benefit from it.

Thanks,

Tom

[1]: 
https://software.intel.com/content/www/us/en/develop/download/intel-data-streaming-accelerator-preliminary-architecture-specification.html

Tom Zanussi (1):
  dmaengine: idxd: Add IDXD performance monitor support

 drivers/dma/Kconfig  |  13 +
 drivers/dma/idxd/Makefile|   2 +
 drivers/dma/idxd/idxd.h  |  45 +++
 drivers/dma/idxd/init.c  |   9 +
 drivers/dma/idxd/irq.c   |   5 +-
 drivers/dma/idxd/perfmon.c   | 661 +++
 drivers/dma/idxd/perfmon.h   | 119 +++
 drivers/dma/idxd/registers.h | 108 ++
 include/linux/cpuhotplug.h   |   1 +
 9 files changed, 959 insertions(+), 4 deletions(-)
 create mode 100644 drivers/dma/idxd/perfmon.c
 create mode 100644 drivers/dma/idxd/perfmon.h

-- 
2.17.1



[ANNOUNCE] 4.19.182-rt74

2021-03-23 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.182-rt74 stable release.

This release is just an update to the new stable 4.19.182
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: 973d50c65e7a04ce11a946a0725e22432353a82c

Or to build 4.19.182-rt74 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.182.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.182-rt74.patch.xz

Enjoy!

   Tom



Re: [PATCH 0/7 v2] tracing: Have ring_buffer_event_time_stamp() work for all events

2021-03-16 Thread Tom Zanussi
Hi Steve,

On Tue, 2021-03-16 at 12:41 -0400, Steven Rostedt wrote:
> Yordan has been working on a patch set that will not repeat functions
> in the function tracer but instead show a single event that states
> that
> the previous function repeated X amount of times. I recommended that
> this should also show the time of the last function that repeated.
> To save on space, Yordan suggested to use a 32 bit delta instead of
> a full 64 bit timestamp of the last event. But to create this delta,
> we need a way to extract the time of the repeat event and use that
> to calculate the delta of the last function event.
> 
> But currently the ring_buffer_event_time_stamp() only works if all
> events
> has an absolute time stamp attached to it. That would be counter
> productive
> to make all functions record the full time stamp because we wanted to
> use a 32 bit counter instead of a 64 bit counter for the rare repeat
> event!
> 
> This patch series makes ring_buffer_event_time_stamp() work for all
> non committed events (after reserve and before it is committed).
> The trick is that the per CPU descriptor of the buffer holds the time
> stamp used for the event being processed. It has a nesting of 5
> levels
> to deal with interrupts that add events. Extracting the time for the
> event
> can only be done for the current event being processed and not yet
> committed.
> 
> To achieve this, the buffer that the event is on needs to be passed
> to
> the ring_buffer_event_time_stamp(). That caused a bit of churn for
> the histogram code, because that buffer wasn't available at the time
> the ring_buffer_event_time_stamp() was called. Although the
> hist_field
> contained a pointer to the trace_array that holds the ring buffer,
> if tracing was disabled, then a temporary buffer was used instead,
> and that temporary buffer would need to be passed to the
> ring_buffer_event_time_stamp(). That buffer is exposed to the trace
> event
> logic, but was not passed down into the trigger code. That had to be
> done to take advantage of the new code.
> 
> The second to last patch adds verifier logic (although commented out)
> that was used to debug the issue when a temporary buffer was in use.
> It proved to be very valuable and is kept in, in case this needs to
> be
> debugged again.
> 
> Finally the last patch is for use with Yordan's work, and is needed
> because
> when filtering is enabled, the event being processed may not even be
> on the buffer, and the tracing_event_time_stamp() checks for that and
> will just use the current time stamp if the event is not reserved
> yet.
> This could be used also for the histogram code, but wanted to hold
> off
> on that.
> 
> Changes since v1:
> 
>  - Applied change of last patch to pass buffer not trace_array
>  - Fixed prototype of stack_track_data_snapshot() when snapshot not
> configured
> 
> Steven Rostedt (VMware) (7):
>   ring-buffer: Separate out internal use of
> ring_buffer_event_time_stamp()
>   ring-buffer: Add a event_stamp to cpu_buffer for each level of
> nesting
>   tracing: Pass buffer of event to trigger operations
>   ring-buffer: Allow ring_buffer_event_time_stamp() to return
> time stamp of all events
>   tracing: Use a no_filter_buffering_ref to stop using the filter
> buffer
>   ring-buffer: Add verifier for using
> ring_buffer_event_time_stamp()
>   tracing: Add tracing_event_time_stamp() API
> 
> 
>  include/linux/ring_buffer.h |   3 +-
>  include/linux/trace_events.h|   5 +-
>  kernel/trace/ring_buffer.c  | 138
> ++--
>  kernel/trace/trace.c|  38 +-
>  kernel/trace/trace.h        |   9 +--
>  kernel/trace/trace_events_hist.c| 100 +-
>  kernel/trace/trace_events_trigger.c |  45 +++-
>  7 files changed, 239 insertions(+), 99 deletions(-)

This all looks fine to me.

Reviewed-by: Tom Zanussi 




[ANNOUNCE] 4.19.180-rt73

2021-03-12 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.180-rt73 stable release.

This release is just an update to the new stable 4.19.180
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: fffa72a0bb5b707d7b437cfdbce1a84bae419f2e

Or to build 4.19.180-rt73 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.180.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.180-rt73.patch.xz

Enjoy!

   Tom



Re: linux-next: Fixes tag needs some work in the ftrace tree

2021-02-11 Thread Tom Zanussi
On Thu, 2021-02-11 at 16:21 -0500, Steven Rostedt wrote:
> On Fri, 12 Feb 2021 07:57:28 +1100
> Stephen Rothwell  wrote:
> 
> > Hi all,
> > 
> > In commit
> > 
> >   b5e7014fe1c4 ("selftests/ftrace: Update synthetic event syntax
> > errors")
> > 
> > Fixes tag
> > 
> >   Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for
> > synthetic
> > 
> > has these problem(s):
> > 
> >   - Subject has leading but no trailing parentheses
> > 
> > Please do not split Fixes tags over more than one line.  Also, keep
> > all
> > the commit message tags together at the end of the message.
> > 
> 
> Thanks, I didn't even notice that :-/
> 
> Tom, FYI for next time ;-)
> 

Yep, thanks, Stephen, for pointing that out, didn't realize it until
now either.

Tom


> -- Steve



Re: [PATCH v7 0/6] tracing: More synthetic event error fixes

2021-02-09 Thread Tom Zanussi
Hi Steve,

On Tue, 2021-02-09 at 16:09 -0500, Steven Rostedt wrote:
> On Mon,  1 Feb 2021 13:48:10 -0600
> Tom Zanussi  wrote:
> 
> > Hi,
> > 
> > This is v7 of the synthetic event error fix patchset.  This version
> > addresses the comments from v6:
> > 
> >   - moved check_command() from '[PATCH v6 3/6] tracing: Update
> > synth
> > command errors' to '[PATCH v6 2/6] tracing: Rework synthetic
> > event
> > command parsing'.
> > 
> >   - in __create_synth_event(), moved mutex_lock(_mutex) after
> > is_good_name() check and changed related error handling.
> > 
> >   - simplified check_command() a bit by calling argv_free() sooner
> > as
> > suggested by Steve.
> > 
> >   - added Steve's comment about check_field_version() into that
> > function and added additional comments to the caller.
> > 
> 
> After applying these, the following test fails:
> 
>  test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
> 

Did you apply '[PATCH v7 5/6] selftests/ftrace: Update synthetic event
syntax errors' before you ran the test?  It actually removes the test
that failed.  Here's what I get with all patches applied:

  # ./ftracetest test.d/trigger/inter-event/
=== Ftrace unit tests ===
[1] event trigger - test inter-event histogram trigger expected fail
actions [XFAIL]
[2] event trigger - test field variable support [PASS]
[3] event trigger - test inter-event combined histogram trigger [PASS]
[4] event trigger - test multiple actions on hist trigger   [PASS]
[5] event trigger - test inter-event histogram trigger onchange action  
[PASS]
[6] event trigger - test inter-event histogram trigger onmatch action   
[PASS]
[7] event trigger - test inter-event histogram trigger onmatch-onmax
action  [PASS]
[8] event trigger - test inter-event histogram trigger onmax action 
[PASS]
[9] event trigger - test inter-event histogram trigger snapshot action  
[PASS]
[10] event trigger - test synthetic event create remove [PASS]
[11] event trigger - test inter-event histogram trigger trace action
with dynamic string param   [PASS]
[12] event trigger - test synthetic_events syntax parser errors [PASS]
[13] event trigger - test synthetic_events syntax parser[PASS]
[14] event trigger - test inter-event histogram trigger trace action
[PASS]


# of passed:  13
# of failed:  0
# of unresolved:  0
# of untested:  0
# of unsupported:  0
# of xfailed:  1
# of undefined(test bug):  0

> It appears that:
> 
>   echo 'myevent char str[];; int v' > synthetic_events
> 
> doesn't error after these changes.
> 

Right, it shouldn't fail any more - that was one of the reasons for
reworking the parser, so things like that wouldn't fail.

My assumption, and the reason for adding '[PATCH v7 4/6] tracing: Add a
backward-compatibility check for synthetic event creation', was that we
didn't want previously-working things to suddenly start failing after
the rework, but not that things that used to fail would continue to 
backwards-compatibly fail.

Tom

> -- Steve



[ANNOUNCE] 4.19.173-rt72

2021-02-08 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.173-rt72 stable release.

This release is just an update to the new stable 4.19.173
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: 0f716c5aef71ce6891b78818ba2a8a59d95ac053

Or to build 4.19.173-rt72 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.173.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.173-rt72.patch.xz

Enjoy!

   Tom



[PATCH v7 6/6] selftests/ftrace: Add '!event' synthetic event syntax check

2021-02-01 Thread Tom Zanussi
Add a check confirming that '!event' alone will remove a synthetic
event.

Signed-off-by: Tom Zanussi 
---
 .../trigger/inter-event/trigger-synthetic-event-syntax.tc | 4 
 1 file changed, 4 insertions(+)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
index 59216f3cfb12..2968cdc7df30 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
@@ -32,6 +32,10 @@ grep "myevent[[:space:]]u64 var1" synthetic_events
 # it is not possible to add same name event
 ! echo "myevent u64 var2" >> synthetic_events
 
+# make sure !synthetic event doesn't require a field
+echo "!myevent" >> synthetic_events
+echo "myevent u64 var1" >> synthetic_events
+
 # Non-append open will cleanup all events and add new one
 echo "myevent u64 var2" > synthetic_events
 
-- 
2.17.1



[PATCH v7 5/6] selftests/ftrace: Update synthetic event syntax errors

2021-02-01 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 35 ++-
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..955e3ceea44b 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,38 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v7 3/6] tracing: Update synth command errors

2021-02-01 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 30 +++---
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 4f6c5a104ee2..aace72426e99 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -655,7 +656,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
 
size = synth_field_size(field->type);
if (size < 0) {
-   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1174,7 +1178,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
 */
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
}
 
@@ -1226,7 +1230,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1410,13 +1414,13 @@ static int create_or_delete_synth_event(const char 
*raw_command)
 
ret = check_command(raw_command);
if (ret) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return ret;
}
 
p = strpbrk(raw_command, " \t");
if (!p && raw_command[0] != '!') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto free;
}
@@ -1993,8 +1997,10 @@ static int create_synth_event(const char *raw_command)
last_cmd_set(raw_command);
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
fields = skip_spaces(p);
 
@@ -2007,8 +2013,10 @@ static int create_synth_event(const char *raw_command)
/* This interface accepts group name prefix */
if (strchr(name, '/')) {
len = str_has_prefix(name, SYNTH_SYSTEM "/");
-   if (len == 0)
+   if (len == 0) {
+   synth_err(SYNTH_ERR_INVALID_DYN_CMD, 0);
return -EINVAL;
+   }
name += len;
}
 
@@ -2016,7 +2024,7 @@ static int create_synth_event(const char *raw_command)
 
ret = check_command(raw_command + len);
if (ret) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return ret;
}
 
-- 
2.17.1



[PATCH v7 0/6] tracing: More synthetic event error fixes

2021-02-01 Thread Tom Zanussi
/zanussi/linux-trace.git 
ftrace/synth-fixes-v7

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (5):
  tracing: Rework synthetic event command parsing
  tracing: Update synth command errors
  tracing: Add a backward-compatibility check for synthetic event
creation
  selftests/ftrace: Update synthetic event syntax errors
  selftests/ftrace: Add '!event' synthetic event syntax check

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 +-
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 320 +-
 kernel/trace/trace_kprobe.c   |  33 +-
 kernel/trace/trace_probe.c|  17 +
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 +-
 .../trigger-synthetic-event-syntax.tc |   4 +
 .../trigger-synthetic_event_syntax_errors.tc  |  35 +-
 11 files changed, 333 insertions(+), 159 deletions(-)

-- 
2.17.1



[PATCH v7 1/6] tracing/dynevent: Delegate parsing to create function

2021-02-01 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

This requires changes to the kprobe/uprobe/synthetic event handling,
which are also included here.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 23 ++--
 kernel/trace/trace.h  |  3 +-
 kernel/trace/trace_dynevent.c | 35 +++---
 kernel/trace/trace_dynevent.h |  4 +--
 kernel/trace/trace_events_synth.c | 60 +++
 kernel/trace/trace_kprobe.c   | 33 +
 kernel/trace/trace_probe.c| 17 +
 kernel/trace/trace_probe.h|  1 +
 kernel/trace/trace_uprobe.c   | 17 +
 9 files changed, 120 insertions(+), 73 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index eb5205e48733..e9cde7a3e0a6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9426,30 +9426,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9497,7 +9478,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e448d2da0b99..98211637e545 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1830,10 +1830,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 4f967d5cd917..dc971a68dda4 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
retur

[PATCH v7 2/6] tracing: Rework synthetic event command parsing

2021-02-01 Thread Tom Zanussi
Now that command parsing has been delegated to the create functions
and we're no longer constrained by argv_split(), we can modify the
synthetic event command parser to better match the higher-level
structure of the synthetic event commands, which is basically an event
name followed by a set of semicolon-separated fields.

Since we're also now passed the raw command, we can also save it
directly and can get rid of save_cmdstr().

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 245 +-
 1 file changed, 143 insertions(+), 102 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b2588a5650c9..4f6c5a104ee2 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -579,18 +579,14 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, const char **argv,
-int *consumed)
+static struct synth_field *parse_synth_field(int argc, char **argv)
 {
-   struct synth_field *field;
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
-   int len, ret = -ENOMEM;
+   int len, consumed, ret = -ENOMEM;
+   struct synth_field *field;
struct seq_buf s;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -599,10 +595,20 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
-   *consumed = 3;
+   consumed = 3;
} else {
field_name = argv[1];
-   *consumed = 2;
+   consumed = 2;
+   }
+
+   if (consumed < argc) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
+   }
+
+   if (!field_name) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
}
 
field = kzalloc(sizeof(*field), GFP_KERNEL);
@@ -613,8 +619,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name)
@@ -626,8 +630,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
if (array)
@@ -644,11 +646,8 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
seq_buf_puts(, prefix);
seq_buf_puts(, field_type);
-   if (array) {
+   if (array)
seq_buf_puts(, array);
-   if (s.buffer[s.len - 1] == ';')
-   s.len--;
-   }
if (WARN_ON_ONCE(!seq_buf_buffer_left()))
goto free;
 
@@ -1160,46 +1159,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
-static int __create_synth_event(int argc, const char *name, const char **argv)
+static int __create_synth_event(const char *name, const char *raw_fields)
 {
+   char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   int i, argc, n_fields = 0, ret = 0;
struct synth_event *event = NULL;
-   int i, consumed = 0, n_fields = 0, ret = 0;
-
-  

[PATCH v7 4/6] tracing: Add a backward-compatibility check for synthetic event creation

2021-02-01 Thread Tom Zanussi
The synthetic event parsing rework now requires semicolons between
synthetic event fields.  That requirement breaks existing users who
might already have used the old synthetic event command format, so
this adds an inner loop that can parse more than one field, if
present, between semicolons.  For each field, parse_synth_field()
checks in which version that field was introduced, using
check_field_version().  The caller, __create_synth_event() can then use
that version information to determine whether or not to enforce the
requirement on the command as a whole.

In the future, if/when new features are added, the requirement will be
that any field/string containing the new feature must use semicolons,
and the check_field_version() check can then check for those and
enforce it.  Using a version number allows this scheme to be extended
if necessary.

[ zanussi: added check_field_version() comment from rost...@goodmis.org ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 93 ---
 1 file changed, 74 insertions(+), 19 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index aace72426e99..2979a96595b4 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -580,11 +580,29 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, char **argv)
+static int check_field_version(const char *prefix, const char *field_type,
+  const char *field_name)
+{
+   /*
+* For backward compatibility, the old synthetic event command
+* format did not require semicolons, and in order to not
+* break user space, that old format must still work. If a new
+* feature is added, then the format that uses the new feature
+* will be required to have semicolons, as nothing that uses
+* the old format would be using the new, yet to be created,
+* feature. When a new feature is added, this will detect it,
+* and return a number greater than 1, and require the format
+* to use semicolons.
+*/
+   return 1;
+}
+
+static struct synth_field *parse_synth_field(int argc, char **argv,
+int *consumed, int *field_version)
 {
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
-   int len, consumed, ret = -ENOMEM;
struct synth_field *field;
+   int len, ret = -ENOMEM;
struct seq_buf s;
ssize_t size;
 
@@ -596,15 +614,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
-   consumed = 3;
+   *consumed += 3;
} else {
field_name = argv[1];
-   consumed = 2;
-   }
-
-   if (consumed < argc) {
-   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
-   return ERR_PTR(-EINVAL);
+   *consumed += 2;
}
 
if (!field_name) {
@@ -612,6 +625,8 @@ static struct synth_field *parse_synth_field(int argc, char 
**argv)
return ERR_PTR(-EINVAL);
}
 
+   *field_version = check_field_version(prefix, field_type, field_name);
+
field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field)
return ERR_PTR(-ENOMEM);
@@ -1167,6 +1182,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
 {
char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   int consumed, cmd_version = 1, n_fields_this_loop;
int i, argc, n_fields = 0, ret = 0;
struct synth_event *event = NULL;
 
@@ -1212,21 +1228,60 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
if (!argc)
continue;
 
-   field = parse_synth_field(argc, argv);
-   if (IS_ERR(field)) {
-   argv_free(argv);
-   ret = PTR_ERR(field);
-   goto err;
-   }
+   n_fields_this_loop = 0;
+   consumed = 0;
+   while (argc > consumed) {
+   int field_version;
+
+   field = parse_synth_field(argc - consumed,
+ argv + consumed, ,
+ _version);
+   if (IS_ERR(field)) {
+   argv_free(argv);
+   ret = PTR_ERR(field);
+   goto err;
+   }
 
-   argv_free(argv);
+   /*
+* Track the

Re: [PATCH v6 4/6] tracing: Add a backward-compatibility check for synthetic event creation

2021-01-25 Thread Tom Zanussi
Hi Steve,

On Fri, 2021-01-22 at 16:12 -0500, Steven Rostedt wrote:
> On Thu, 21 Jan 2021 11:01:07 -0600
> Tom Zanussi  wrote:
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -580,11 +580,18 @@ static void free_synth_field(struct
> > synth_field *field)
> > kfree(field);
> >  }
> >  
> > -static struct synth_field *parse_synth_field(int argc, char
> > **argv)
> > +static int check_field_version(const char *prefix, const char
> > *field_type,
> > +  const char *field_name)
> > +{
> 
> This needs a comment:
> 
>   /*
>* For backward compatibility, the old format did not require
>* semicolons, and not to break user space, that old format
> must
>* still work. If a new feature is added, then the format that
> uses
>* the new feature will be required to have semicolons, as
> nothing
>* that uses the old format would be using the new, yet to be
>* created, feature. When a new feature is added, this will
> detect
>* it, and return a number greater than 1, and require the
> format
>* to use semicolons.
>*/
> 
> Or something to that effect.
> 

OK, will add better comments in the code about how this is meant to
work.

Thanks,

Tom

> > +   return 1;
> > +}
> > +
> > +static struct synth_field *parse_synth_field(int argc, char
> > **argv,
> > +int *consumed, int
> > *field_version)
> >  {
> > const char *prefix = NULL, *field_type = argv[0], *field_name,
> > *array;
> > -   int len, consumed, ret = -ENOMEM;
> > struct synth_field *field;
> > +   int len, ret = -ENOMEM;
> > struct seq_buf s;
> > ssize_t size;
> >  
> > @@ -596,15 +603,10 @@ static struct synth_field
> > *parse_synth_field(int argc, char **argv)
> > prefix = "unsigned ";
> > field_type = argv[1];
> > field_name = argv[2];
> > -   consumed = 3;
> > +   *consumed += 3;
> > } else {
> > field_name = argv[1];
> > -   consumed = 2;
> > -   }
> > -
> > -   if (consumed < argc) {
> > -   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
> > -   return ERR_PTR(-EINVAL);
> > +   *consumed += 2;
> > }
> >  
> > if (!field_name) {
> > @@ -612,6 +614,8 @@ static struct synth_field
> > *parse_synth_field(int argc, char **argv)
> > return ERR_PTR(-EINVAL);
> > }
> >  
> > +   *field_version = check_field_version(prefix, field_type,
> > field_name);
> > +
> > field = kzalloc(sizeof(*field), GFP_KERNEL);
> > if (!field)
> > return ERR_PTR(-ENOMEM);
> > @@ -1167,6 +1171,7 @@ static int __create_synth_event(const char
> > *name, const char *raw_fields)
> >  {
> > char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
> > struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
> > +   int consumed, cmd_version = 1, n_fields_this_loop;
> > int i, argc, n_fields = 0, ret = 0;
> > struct synth_event *event = NULL;
> >  
> > @@ -1214,21 +1219,46 @@ static int __create_synth_event(const char
> > *name, const char *raw_fields)
> > if (!argc)
> > continue;
> >  
> > -   field = parse_synth_field(argc, argv);
> > -   if (IS_ERR(field)) {
> > -   argv_free(argv);
> > -   ret = PTR_ERR(field);
> > -   goto err;
> > -   }
> > +   n_fields_this_loop = 0;
> > +   consumed = 0;
> > +   while (argc > consumed) {
> > +   int field_version;
> > +
> > +   field = parse_synth_field(argc - consumed,
> > + argv + consumed,
> > ,
> > + _version);
> > +   if (IS_ERR(field)) {
> > +   argv_free(argv);
> > +   ret = PTR_ERR(field);
> > +   goto err;
> > +   }
> >  
> > -   argv_free(argv);
> > +   if (field_version > cmd_version)
> > +   cmd_version = field_version;
> > +
> 
> There needs to be some comments here to explain what th

Re: [PATCH v6 2/6] tracing: Rework synthetic event command parsing

2021-01-25 Thread Tom Zanussi
Hi Steve,

On Fri, 2021-01-22 at 16:00 -0500, Steven Rostedt wrote:
> On Thu, 21 Jan 2021 11:01:05 -0600
> Tom Zanussi  wrote:
> 
> > @@ -1208,13 +1173,14 @@ static int __create_synth_event(int argc,
> > const char *name, const char **argv)
> >  *  where 'field' = type field_name
> >  */
> >  
> > -   if (name[0] == '\0' || argc < 1) {
> > +   mutex_lock(_mutex);
> 
> I'm curious, why is the event_mutex taken here? I'm guessing it is
> first
> needed for the find_synth_event() call, in which case, it can be
> moved
> after the is_good_name() check. I don't see why the goto out is
> required
> here or for the is_good_name() check.
> 

Yes, it's for the find_synth_event() call, and yes, it should come
after the is_good_name() check.  I'll move it and fix up the goto
changes as a result.

Thanks,

Tom

> -- Steve
> 
> > +
> > +   if (name[0] == '\0') {
> > synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
> > -   return -EINVAL;
> > +   ret = -EINVAL;
> > +   goto out;
> > }
> >  
> > -   mutex_lock(_mutex);
> > -
> > if (!is_good_name(name)) {
> > synth_err(SYNTH_ERR_BAD_NAME, errpos(name));
> > ret = -EINVAL;



Re: [PATCH v6 3/6] tracing: Update synth command errors

2021-01-25 Thread Tom Zanussi
On Fri, 2021-01-22 at 22:23 +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> On Thu, 21 Jan 2021 11:01:06 -0600
> Tom Zanussi  wrote:
> 
> > Since array types are handled differently, errors referencing them
> > also need to be handled differently.  Add and use a new
> > INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD
> > to
> > catch and display the correct form for badly-formed commands, which
> > can also be used in place of CMD_INCOMPLETE, which is removed, and
> > remove CMD_TOO_LONG, since it's no longer used.
> 
> OK, so this will add new errors for precise error logging.
> 
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> >  kernel/trace/trace_events_synth.c | 72
> > +++
> >  1 file changed, 63 insertions(+), 9 deletions(-)
> > 
> > diff --git a/kernel/trace/trace_events_synth.c
> > b/kernel/trace/trace_events_synth.c
> > index a79c17b97add..dd141ee6b3fc 100644
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -23,13 +23,14 @@
> >  #undef ERRORS
> >  #define ERRORS \
> > C(BAD_NAME, "Illegal name"),\
> > -   C(CMD_INCOMPLETE,   "Incomplete command"),  \
> > +   C(INVALID_CMD,  "Command must be of the form:
> >  field[;field] ..."),\
> > +   C(INVALID_DYN_CMD,  "Command must be of the form: s or
> > -:[synthetic/] field[;field] ..."),\
> > C(EVENT_EXISTS, "Event already exists"),\
> > C(TOO_MANY_FIELDS,  "Too many fields"), \
> > C(INCOMPLETE_TYPE,  "Incomplete type"), \
> > C(INVALID_TYPE, "Invalid type"),\
> > -   C(INVALID_FIELD,"Invalid field"),   \
> > -   C(CMD_TOO_LONG, "Command too long"),
> > +   C(INVALID_FIELD,"Invalid field"),   \
> > +   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
> >  
> >  #undef C
> >  #define C(a, b)SYNTH_ERR_##a
> > @@ -655,7 +656,10 @@ static struct synth_field
> > *parse_synth_field(int argc, char **argv)
> >  
> > size = synth_field_size(field->type);
> > if (size < 0) {
> > -   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
> > +   if (array)
> > +   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC,
> > errpos(field_name));
> > +   else
> > +   synth_err(SYNTH_ERR_INVALID_TYPE,
> > errpos(field_type));
> > ret = -EINVAL;
> > goto free;
> > } else if (size == 0) {
> > @@ -1176,7 +1180,7 @@ static int __create_synth_event(const char
> > *name, const char *raw_fields)
> > mutex_lock(_mutex);
> >  
> > if (name[0] == '\0') {
> > -   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
> > +   synth_err(SYNTH_ERR_INVALID_CMD, 0);
> > ret = -EINVAL;
> > goto out;
> > }
> > @@ -1228,7 +1232,7 @@ static int __create_synth_event(const char
> > *name, const char *raw_fields)
> > }
> >  
> > if (n_fields == 0) {
> > -   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
> > +   synth_err(SYNTH_ERR_INVALID_CMD, 0);
> > ret = -EINVAL;
> > goto err;
> > }
> > @@ -1366,6 +1370,40 @@ int synth_event_delete(const char
> > *event_name)
> >  }
> >  EXPORT_SYMBOL_GPL(synth_event_delete);
> >  
> > +static int check_command(const char *raw_command)
> > +{
> > +   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
> > +   int argc, ret = 0;
> > +
> > +   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
> > +   if (!cmd)
> > +   return -ENOMEM;
> > +
> > +   name_and_field = strsep(, ";");
> > +   if (!name_and_field) {
> > +   ret = -EINVAL;
> > +   goto free;
> > +   }
> > +
> > +   if (name_and_field[0] == '!')
> > +   goto free;
> > +
> > +   argv = argv_split(GFP_KERNEL, name_and_field, );
> > +   if (!argv) {
> > +   ret = -ENOMEM;
> > +   goto free;
> > +   }
> > +
> > +   if (argc < 3)
> > +   ret = -EINVAL;
> > +free:
> > +   kfree(saved_cmd);
> > +   if (argv)
> > +   argv_free(argv);
> > +
> > +   return ret;
> > +}
> 
> But I'm not sure why this (yet another parser) is needed. What you
> are expecting
> for this check_command()? Could you tell me some examples?
> 

This is just a common function to check we even have the possibility of
a valid command.  It will catch things right off the top like

  # echo 'myevent' >> synthetic_events

or

  # echo 'myevent int'  >> synthetic events

You're right, it's confusing to have it in this patch, since it really
belongs in the rework patch - I'll move it there.

Thanks,

Tom


> Thank you,
> 
> 
> 



Re: [PATCH v6 2/6] tracing: Rework synthetic event command parsing

2021-01-25 Thread Tom Zanussi
On Fri, 2021-01-22 at 22:16 +0900, Masami Hiramatsu wrote:
> On Thu, 21 Jan 2021 11:01:05 -0600
> Tom Zanussi  wrote:
> 
> > Now that command parsing has been delegated to the create functions
> > and we're no longer constrained by argv_split(), we can modify the
> > synthetic event command parser to better match the higher-level
> > structure of the synthetic event commands, which is basically an
> > event
> > name followed by a set of semicolon-separated fields.
> > 
> > Since we're also now passed the raw command, we can also save it
> > directly and can get rid of save_cmdstr().
> > 
> 
> This looks good to me.
> 
> Reviewed-by: Masami Hiramatsu 
> 
> Thank you,
> 

Thanks, Masami.

Tom

> > Signed-off-by: Tom Zanussi 
> > ---
> >  kernel/trace/trace_events_synth.c | 198 +++---
> > 
> >  1 file changed, 98 insertions(+), 100 deletions(-)
> > 
> > diff --git a/kernel/trace/trace_events_synth.c
> > b/kernel/trace/trace_events_synth.c
> > index b2588a5650c9..a79c17b97add 100644
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -48,7 +48,7 @@ static int errpos(const char *str)
> > return err_pos(last_cmd, str);
> >  }
> >  
> > -static void last_cmd_set(char *str)
> > +static void last_cmd_set(const char *str)
> >  {
> > if (!str)
> > return;
> > @@ -579,18 +579,14 @@ static void free_synth_field(struct
> > synth_field *field)
> > kfree(field);
> >  }
> >  
> > -static struct synth_field *parse_synth_field(int argc, const char
> > **argv,
> > -int *consumed)
> > +static struct synth_field *parse_synth_field(int argc, char
> > **argv)
> >  {
> > -   struct synth_field *field;
> > const char *prefix = NULL, *field_type = argv[0], *field_name,
> > *array;
> > -   int len, ret = -ENOMEM;
> > +   int len, consumed, ret = -ENOMEM;
> > +   struct synth_field *field;
> > struct seq_buf s;
> > ssize_t size;
> >  
> > -   if (field_type[0] == ';')
> > -   field_type++;
> > -
> > if (!strcmp(field_type, "unsigned")) {
> > if (argc < 3) {
> > synth_err(SYNTH_ERR_INCOMPLETE_TYPE,
> > errpos(field_type));
> > @@ -599,10 +595,20 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > prefix = "unsigned ";
> > field_type = argv[1];
> > field_name = argv[2];
> > -   *consumed = 3;
> > +   consumed = 3;
> > } else {
> > field_name = argv[1];
> > -   *consumed = 2;
> > +   consumed = 2;
> > +   }
> > +
> > +   if (consumed < argc) {
> > +   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
> > +   return ERR_PTR(-EINVAL);
> > +   }
> > +
> > +   if (!field_name) {
> > +   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
> > +   return ERR_PTR(-EINVAL);
> > }
> >  
> > field = kzalloc(sizeof(*field), GFP_KERNEL);
> > @@ -613,8 +619,6 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > array = strchr(field_name, '[');
> > if (array)
> > len -= strlen(array);
> > -   else if (field_name[len - 1] == ';')
> > -   len--;
> >  
> > field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
> > if (!field->name)
> > @@ -626,8 +630,6 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > goto free;
> > }
> >  
> > -   if (field_type[0] == ';')
> > -   field_type++;
> > len = strlen(field_type) + 1;
> >  
> > if (array)
> > @@ -644,11 +646,8 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > if (prefix)
> > seq_buf_puts(, prefix);
> > seq_buf_puts(, field_type);
> > -   if (array) {
> > +   if (array)
> > seq_buf_puts(, array);
> > -   if (s.buffer[s.len - 1] == ';')
> > -   s.len--;
> > -   }
> > if (WARN_ON_ONCE(!seq_buf_buffer_left()))
> > goto free;
> >  
> > @@ -1160,46 +1159,12 @@ int synth_event_gen_cmd_array_start(struct
> > dynevent_cmd *cmd, const char *name,
> >  }
> >  EXPORT_

[PATCH v6 0/6] tracing: More synthetic event error fixes

2021-01-21 Thread Tom Zanussi
Hi,

This is v6 of the synthetic event error fix patchset.  This version
removes the semicolon-adding pass and instead adds an inner loop as
suggested by Masami.  A different mechanism adding per-version field
checks was also added in place of the previous whole-string audit.

Also, moved the parse_synth_field() error message back into patch 2/6
(tracing: Rework synthetic event command parsing) and fixed the
problem with the !name problem as also noted by Masami, and added a
new patch (selftests/ftrace: Add '!event' synthetic event syntax
check) to check for that and prevent future changes from breaking it
again.

Tom


v5 text:

Hi,

This is v5 of the sythetic event error fix patchset.  This version is
the same as v4 but with a few variable-initialization fixes flagged by
Dan Carpenter and the kernel test robot.

Tom

v4 text:

Hi,

This is v4 of the sythetic event error fix patchset.  As suggested by
Steve, I added a new pass that adds semicolons to 'old' commands that
may be missing them, in order to maintain backward compatibility.  All
commands are handled by the new and improved parsing code, but
commands missing the semicolons have them added before processing and
are therefore still valid.  At some point in the future, as new
features are added and we can require any command containing them to
require semicolons, this pass can be completely skipped by detecting
those features in the currently empty audit_old_buffer() hook.

Also, as a result, the patch adding semicolons to the selftests is no
longer necessary (selftests/ftrace: Add synthetic event field
separators) and has been dropped in this series.

Tom


v3 text:

Hi,

This is v3 of the sythetic event error fix patchset.  As suggested by
Masami, I split the 'tracing/dynevent: Delegate parsing to create
function' into two - one containing just the interface changes and the
second with the synthetic event parsing changes the first enabled.

I also replaced a couple argv_split() with strpbrk() as suggested by
Masami, along with removing the no-longer-used consume lines and
another line that tested ECANCELED that was no longer needed.

Also, removed a test case that was no longer needed since the commands
are now stripped of whitespace first.

Thanks, Masami, for the suggestions.

Tom

v2 text:

This is v2 of the previous sythetic event error fix patchset.

This version drops the original ([PATCH 1/4] tracing: Make
trace_*_run_command() more flexible) and (tracing: Use new
trace_run_command() options) patches and replaces them with Masami's
patch (tracing/dynevent: Delegate parsing to create function) [1].
The new version adds in all the synthetic event changes needed to
compile and use the new interface.

A new patch was also added (selftests/ftrace: Add synthetic event
field separators) that fixes more invalid synthetic event syntax I
found while testing.

I also added some more new checks to the synthetic event sytax error
testcase.

As before, I didn't see any problems running the entire ftrace
testsuite or the test modules that also use the things that were
touched here.

[1] 
https://lore.kernel.org/lkml/20201019001504.70dc3ec608277ed22060d...@kernel.org/

Thanks,

Tom


v1 text:

Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit f6a694665f132cbf6edd2f173dc35330a8aa:

  tracing: Offload eval map updates to a work queue (2020-12-15 09:29:14 -0500)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v6

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (5):
  tracing: Rework synthetic event command parsing
  tracing: Update synth command errors
  tracing: Add a backward-compatibility check for synthetic event
creation
  selftests/ftrace: Update synthetic event syntax errors
  selftests/ftrace: Add '!event' synthetic event syntax check

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 ++-
 kernel/trace/trace_dynevent.h

[PATCH v6 2/6] tracing: Rework synthetic event command parsing

2021-01-21 Thread Tom Zanussi
Now that command parsing has been delegated to the create functions
and we're no longer constrained by argv_split(), we can modify the
synthetic event command parser to better match the higher-level
structure of the synthetic event commands, which is basically an event
name followed by a set of semicolon-separated fields.

Since we're also now passed the raw command, we can also save it
directly and can get rid of save_cmdstr().

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 198 +++---
 1 file changed, 98 insertions(+), 100 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b2588a5650c9..a79c17b97add 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -579,18 +579,14 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, const char **argv,
-int *consumed)
+static struct synth_field *parse_synth_field(int argc, char **argv)
 {
-   struct synth_field *field;
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
-   int len, ret = -ENOMEM;
+   int len, consumed, ret = -ENOMEM;
+   struct synth_field *field;
struct seq_buf s;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -599,10 +595,20 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
-   *consumed = 3;
+   consumed = 3;
} else {
field_name = argv[1];
-   *consumed = 2;
+   consumed = 2;
+   }
+
+   if (consumed < argc) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
+   }
+
+   if (!field_name) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
}
 
field = kzalloc(sizeof(*field), GFP_KERNEL);
@@ -613,8 +619,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name)
@@ -626,8 +630,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
if (array)
@@ -644,11 +646,8 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
seq_buf_puts(, prefix);
seq_buf_puts(, field_type);
-   if (array) {
+   if (array)
seq_buf_puts(, array);
-   if (s.buffer[s.len - 1] == ';')
-   s.len--;
-   }
if (WARN_ON_ONCE(!seq_buf_buffer_left()))
goto free;
 
@@ -1160,46 +1159,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
-static int __create_synth_event(int argc, const char *name, const char **argv)
+static int __create_synth_event(const char *name, const char *raw_fields)
 {
+   char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   int i, argc, n_fields = 0, ret = 0;
struct synth_event *event = NULL;
-   int i, consumed = 0, n_fields = 0, ret = 0;
-
-  

[PATCH v6 3/6] tracing: Update synth command errors

2021-01-21 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 72 +++
 1 file changed, 63 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index a79c17b97add..dd141ee6b3fc 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -655,7 +656,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
 
size = synth_field_size(field->type);
if (size < 0) {
-   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1176,7 +1180,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
mutex_lock(_mutex);
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto out;
}
@@ -1228,7 +1232,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1366,6 +1370,40 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int check_command(const char *raw_command)
+{
+   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
+   int argc, ret = 0;
+
+   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   name_and_field = strsep(, ";");
+   if (!name_and_field) {
+   ret = -EINVAL;
+   goto free;
+   }
+
+   if (name_and_field[0] == '!')
+   goto free;
+
+   argv = argv_split(GFP_KERNEL, name_and_field, );
+   if (!argv) {
+   ret = -ENOMEM;
+   goto free;
+   }
+
+   if (argc < 3)
+   ret = -EINVAL;
+free:
+   kfree(saved_cmd);
+   if (argv)
+   argv_free(argv);
+
+   return ret;
+}
+
 static int create_or_delete_synth_event(const char *raw_command)
 {
char *name = NULL, *fields, *p;
@@ -1377,9 +1415,15 @@ static int create_or_delete_synth_event(const char 
*raw_command)
 
last_cmd_set(raw_command);
 
+   ret = check_command(raw_command);
+   if (ret) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
+   return ret;
+   }
+
p = strpbrk(raw_command, " \t");
if (!p && raw_command[0] != '!') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto free;
}
@@ -1956,8 +2000,10 @@ static int create_synth_event(const char *raw_command)
last_cmd_set(raw_command);
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
fields = skip_spaces(p);
 
@@ -1970,13 +2016,21 @@ static int create_synth_event(const char *raw_command)
/* 

[PATCH v6 4/6] tracing: Add a backward-compatibility check for synthetic event creation

2021-01-21 Thread Tom Zanussi
The synthetic event parsing rework now requires semicolons between
synthetic event fields.  That requirement breaks existing users who
might already have used the old synthetic event command format, so
this adds an inner loop that can parse more than one field, if
present, between semicolons.  For each field, parse_synth_field()
checks in which version that field was introduced, using
check_field_version().  The caller, __create_synth_event() can then use
that version information to determine whether or not to enforce the
requirement on the command as a whole.

In the future, if/when new features are added, the requirement will be
that any field/string containing the new feature must use semicolons,
and the check_field_version() check can then check for those and
enforce it.  Using a version number allows this scheme to be extended
if necessary.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 68 ++-
 1 file changed, 49 insertions(+), 19 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index dd141ee6b3fc..1b7d1ff68140 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -580,11 +580,18 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, char **argv)
+static int check_field_version(const char *prefix, const char *field_type,
+  const char *field_name)
+{
+   return 1;
+}
+
+static struct synth_field *parse_synth_field(int argc, char **argv,
+int *consumed, int *field_version)
 {
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
-   int len, consumed, ret = -ENOMEM;
struct synth_field *field;
+   int len, ret = -ENOMEM;
struct seq_buf s;
ssize_t size;
 
@@ -596,15 +603,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
-   consumed = 3;
+   *consumed += 3;
} else {
field_name = argv[1];
-   consumed = 2;
-   }
-
-   if (consumed < argc) {
-   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
-   return ERR_PTR(-EINVAL);
+   *consumed += 2;
}
 
if (!field_name) {
@@ -612,6 +614,8 @@ static struct synth_field *parse_synth_field(int argc, char 
**argv)
return ERR_PTR(-EINVAL);
}
 
+   *field_version = check_field_version(prefix, field_type, field_name);
+
field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field)
return ERR_PTR(-ENOMEM);
@@ -1167,6 +1171,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
 {
char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   int consumed, cmd_version = 1, n_fields_this_loop;
int i, argc, n_fields = 0, ret = 0;
struct synth_event *event = NULL;
 
@@ -1214,21 +1219,46 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
if (!argc)
continue;
 
-   field = parse_synth_field(argc, argv);
-   if (IS_ERR(field)) {
-   argv_free(argv);
-   ret = PTR_ERR(field);
-   goto err;
-   }
+   n_fields_this_loop = 0;
+   consumed = 0;
+   while (argc > consumed) {
+   int field_version;
+
+   field = parse_synth_field(argc - consumed,
+ argv + consumed, ,
+ _version);
+   if (IS_ERR(field)) {
+   argv_free(argv);
+   ret = PTR_ERR(field);
+   goto err;
+   }
 
-   argv_free(argv);
+   if (field_version > cmd_version)
+   cmd_version = field_version;
+
+   if (cmd_version > 1 && n_fields_this_loop >= 1) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 
errpos(field_str));
+   ret = -EINVAL;
+   goto err;
+   }
+
+   fields[n_fields++] = field;
+   if (n_fields == SYNTH_FIELDS_MAX) {
+   synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
+   ret = -EINVAL;
+   goto err;
+   }
+
+

[PATCH v6 6/6] selftests/ftrace: Add '!event' synthetic event syntax check

2021-01-21 Thread Tom Zanussi
Add a check confirming that '!event' alone will remove a synthetic
event.

Signed-off-by: Tom Zanussi 
---
 .../trigger/inter-event/trigger-synthetic-event-syntax.tc | 4 
 1 file changed, 4 insertions(+)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
index 59216f3cfb12..2968cdc7df30 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc
@@ -32,6 +32,10 @@ grep "myevent[[:space:]]u64 var1" synthetic_events
 # it is not possible to add same name event
 ! echo "myevent u64 var2" >> synthetic_events
 
+# make sure !synthetic event doesn't require a field
+echo "!myevent" >> synthetic_events
+echo "myevent u64 var1" >> synthetic_events
+
 # Non-append open will cleanup all events and add new one
 echo "myevent u64 var2" > synthetic_events
 
-- 
2.17.1



[PATCH v6 5/6] selftests/ftrace: Update synthetic event syntax errors

2021-01-21 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 35 ++-
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..955e3ceea44b 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,38 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v6 1/6] tracing/dynevent: Delegate parsing to create function

2021-01-21 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

This requires changes to the kprobe/uprobe/synthetic event handling,
which are also included here.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 23 ++--
 kernel/trace/trace.h  |  3 +-
 kernel/trace/trace_dynevent.c | 35 +++---
 kernel/trace/trace_dynevent.h |  4 +--
 kernel/trace/trace_events_synth.c | 60 +++
 kernel/trace/trace_kprobe.c   | 33 +
 kernel/trace/trace_probe.c| 17 +
 kernel/trace/trace_probe.h|  1 +
 kernel/trace/trace_uprobe.c   | 17 +
 9 files changed, 120 insertions(+), 73 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index eb5205e48733..e9cde7a3e0a6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9426,30 +9426,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9497,7 +9478,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e448d2da0b99..98211637e545 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1830,10 +1830,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 4f967d5cd917..dc971a68dda4 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
retur

[ANNOUNCE] 4.19.165-rt70

2021-01-08 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.165-rt70 stable release.

This release is just an update to the new stable 4.19.165
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: 443f65a6dbad1e4b9184f81675c1d62e27c0ccee

Or to build 4.19.165-rt70 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.165.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.165-rt70.patch.xz

Enjoy!

   Tom



Re: [PATCH v5 2/5] tracing: Rework synthetic event command parsing

2020-12-23 Thread Tom Zanussi
Hi Masami,

On Tue, 2020-12-22 at 21:42 +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> On Mon, 21 Dec 2020 15:44:28 -0600
> Tom Zanussi  wrote:
> 
> 
> > @@ -656,7 +651,6 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> >  
> > size = synth_field_size(field->type);
> > if (size < 0) {
> > -   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
> 
> Why did you remove this error message?

It wasn't actually removed - it was just moved into the next patch, so
is still there.  I'll move it back here to avoid confusion.

> 
> [..]
> > @@ -1228,26 +1189,47 @@ static int __create_synth_event(int argc,
> > const char *name, const char **argv)
> > goto out;
> > }
> >  
> > -   for (i = 0; i < argc - 1; i++) {
> > -   if (strcmp(argv[i], ";") == 0)
> > -   continue;
> > +   tmp_fields = saved_fields = kstrdup(raw_fields, GFP_KERNEL);
> > +   if (!tmp_fields) {
> > +   ret = -ENOMEM;
> > +   goto out;
> > +   }
> > +
> > +   while ((field_str = strsep(_fields, ";")) != NULL) {
> > if (n_fields == SYNTH_FIELDS_MAX) {
> > synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
> > ret = -EINVAL;
> > goto err;
> > }
> >  
> > -   field = parse_synth_field(argc - i, [i],
> > );
> > +   argv = argv_split(GFP_KERNEL, field_str, );
> > +   if (!argv) {
> > +   ret = -ENOMEM;
> > +   goto err;
> > +   }
> > +
> > +   if (!argc)
> > +   continue;
> > +
> > +   field = parse_synth_field(argc, argv, );
> > if (IS_ERR(field)) {
> > +   argv_free(argv);
> > ret = PTR_ERR(field);
> > goto err;
> > }
> > +
> > +   argv_free(argv);
> > +
> > +   if (consumed < argc) {
> > +   ret = -EINVAL;
> > +   goto err;
> > +   }
> 
> You can check the consumed < argc in parse_synth_field(), unless
> you keep the backward compatibility - I think you can add an
> inner loop for it, something like
> 
> while ((field_str = strsep(_fields, ";")) != NULL) {
> argv = argv_split(...);
> consumed = 0;
> while (argc > consumed) {
> // increment consumed in parse_synth_field()
> field = parse_synth_field(argc - consumed, argv + consumed,
> );
> if (IS_ERR(field)) {...}
> 
> fields[n_fields++] = field;
> if (n_fields == SYNTH_FIELDS_MAX) {...}
>  }
> 
> argv_free(argv);
> }
> 
> what would you think?

Hmm, not sure this helps - there's only supposed to be one field per
field_str and consumed returns either 2 or 3 depending on the field. 
consumed is only used to detect whether there were unused words and if
so flag an error, rather than loop around to try to get another field.

> 
> > +
> > fields[n_fields++] = field;
> > -   i += consumed - 1;
> > }
> >  
> > -   if (i < argc && strcmp(argv[i], ";") != 0) {
> > -   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i]));
> > +   if (n_fields == 0) {
> > +   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
> > ret = -EINVAL;
> > goto err;
> > }
> > @@ -1266,6 +1248,8 @@ static int __create_synth_event(int argc,
> > const char *name, const char **argv)
> >   out:
> > mutex_unlock(_mutex);
> >  
> > +   kfree(saved_fields);
> > +
> > return ret;
> >   err:
> > for (i = 0; i < n_fields; i++)
> > @@ -1385,29 +1369,35 @@ EXPORT_SYMBOL_GPL(synth_event_delete);
> >  
> >  static int create_or_delete_synth_event(const char *raw_command)
> >  {
> > -   char **argv, *name = NULL;
> > -   int argc = 0, ret = 0;
> > +   char *name = NULL, *fields, *p;
> > +   int ret = 0;
> >  
> > -   argv = argv_split(GFP_KERNEL, raw_command, );
> > -   if (!argv)
> > -   return -ENOMEM;
> > +   raw_command = skip_spaces(raw_command);
> > +   if (raw_command[0] == '\0')
> > +   return ret;
> >  
> > -   if (!argc)
> > -   goto free;
> > +   last_cmd_set(raw_command);
> >  
> > -   name = argv[0];
> > +   p = strpbrk(raw_command, " \t");
> > +   if (!p)
> > +   return -EINVAL;
> 
> Hmm, this may drop the ability to delete an event with "!name",
> it always requires some spaces after the name.
> 

Yes, good point, will fix that and also add a test case for just !name.

Thanks,

Tom

> Thank you,
> 
> 



[PATCH v5 1/5] tracing/dynevent: Delegate parsing to create function

2020-12-21 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

This requires changes to the kprobe/uprobe/synthetic event handling,
which are also included here.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 23 ++--
 kernel/trace/trace.h  |  3 +-
 kernel/trace/trace_dynevent.c | 35 +++---
 kernel/trace/trace_dynevent.h |  4 +--
 kernel/trace/trace_events_synth.c | 60 +++
 kernel/trace/trace_kprobe.c   | 33 +
 kernel/trace/trace_probe.c| 17 +
 kernel/trace/trace_probe.h|  1 +
 kernel/trace/trace_uprobe.c   | 17 +
 9 files changed, 120 insertions(+), 73 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index eb5205e48733..e9cde7a3e0a6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9426,30 +9426,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9497,7 +9478,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e448d2da0b99..98211637e545 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1830,10 +1830,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 4f967d5cd917..dc971a68dda4 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
retur

[PATCH v5 5/5] selftests/ftrace: Update synthetic event syntax errors

2020-12-21 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 35 ++-
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..955e3ceea44b 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,38 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v5 2/5] tracing: Rework synthetic event command parsing

2020-12-21 Thread Tom Zanussi
Now that command parsing has been delegated to the create functions
and we're no longer constrained by argv_split(), we can modify the
synthetic event command parser to better match the higher-level
structure of the synthetic event commands, which is basically an event
name followed by a set of semicolon-separated fields.

Since we're also now passed the raw command, we can also save it
directly and can get rid of save_cmdstr().

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 184 +++---
 1 file changed, 90 insertions(+), 94 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b2588a5650c9..66ccbab3483b 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -579,7 +579,7 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, const char **argv,
+static struct synth_field *parse_synth_field(int argc, char **argv,
 int *consumed)
 {
struct synth_field *field;
@@ -588,9 +588,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
struct seq_buf s;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -605,6 +602,11 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
*consumed = 2;
}
 
+   if (!field_name) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
+   }
+
field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field)
return ERR_PTR(-ENOMEM);
@@ -613,8 +615,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name)
@@ -626,8 +626,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
if (array)
@@ -644,11 +642,8 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
seq_buf_puts(, prefix);
seq_buf_puts(, field_type);
-   if (array) {
+   if (array)
seq_buf_puts(, array);
-   if (s.buffer[s.len - 1] == ';')
-   s.len--;
-   }
if (WARN_ON_ONCE(!seq_buf_buffer_left()))
goto free;
 
@@ -656,7 +651,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
-   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1160,46 +1154,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
-static int __create_synth_event(int argc, const char *name, const char **argv)
+static int __create_synth_event(const char *name, const char *raw_fields)
 {
+   int i, argc, n_fields = 0, ret = 0, consumed;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_event *event = NULL;
-   int i, consumed = 0, n_fields = 0, ret = 0;
-
-   ret = save_cmdstr(argc, name, argv);
-   if (ret)
-   return ret;
 
/*
 * Argument syntax:
@@

[PATCH v5 3/5] tracing: Update synth command errors

2020-12-21 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 71 +++
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 66ccbab3483b..2a9c8bf74bb2 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -651,6 +652,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1171,7 +1176,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
mutex_lock(_mutex);
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto out;
}
@@ -1221,6 +1226,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
argv_free(argv);
 
if (consumed < argc) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1229,7 +1235,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1367,6 +1373,37 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int check_command(const char *raw_command)
+{
+   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
+   int argc, ret = 0;
+
+   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   name_and_field = strsep(, ";");
+   if (!name_and_field) {
+   ret = -EINVAL;
+   goto free;
+   }
+
+   argv = argv_split(GFP_KERNEL, name_and_field, );
+   if (!argv) {
+   ret = -ENOMEM;
+   goto free;
+   }
+
+   if (argc < 3)
+   ret = -EINVAL;
+free:
+   kfree(saved_cmd);
+   if (argv)
+   argv_free(argv);
+
+   return ret;
+}
+
 static int create_or_delete_synth_event(const char *raw_command)
 {
char *name = NULL, *fields, *p;
@@ -1378,9 +1415,17 @@ static int create_or_delete_synth_event(const char 
*raw_command)
 
last_cmd_set(raw_command);
 
+   ret = check_command(raw_command);
+   if (ret) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
+   return ret;
+   }
+
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
name = kmemdup_nul(raw_command, p - raw_command, GFP_KERNEL);
if (!name)
@@ -1954,8 +1999,10 @@ static int create_synth_event(const char *raw_command)
last_cmd_set(raw_command);
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD

[PATCH v5 4/5] tracing: Add a backward-compatibility check for synthetic event creation

2020-12-21 Thread Tom Zanussi
The synthetic event parsing rework requiring semicolons between
synthetic event fields.  That requirement breaks existing users who
might already have used the old form, so this adds a pre-parsing pass
that adds semicolons between fields to any string missing them.  If
none are required, the original string is used.

In the future, if/when new features are added, the requirement will be
that any string containing the new feature will be required to use
semicolons, and the audit_old_buffer() check can check for those and
avoid the pre-parsing semicolon pass altogether.

As it stands, the pre-parsing pass creates a new string with
semicolons only if one or more semicolons were actually needed and
only if no errors were found in pre-parsing.  The assumption is that
the real parsing pass will find and flag any errors and the user
should see them in reference to the original unmodified string.

[ zanussi: Added missing variable initializations reported by Dan
  Carpenter  and kernel test robot
   ]

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 292 --
 1 file changed, 272 insertions(+), 20 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 2a9c8bf74bb2..2aaa1a202beb 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1373,6 +1373,243 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int save_synth_field(int argc, char **argv, int *consumed,
+   struct seq_buf *s, bool *added_semi)
+{
+   const char *prefix = NULL, *field_name, *field_type = argv[0];
+   const char *save_field_type, *array, *next_tok;
+   int len, ret = -EINVAL;
+   struct seq_buf f;
+   ssize_t size;
+   char *tmp;
+
+   *added_semi = false;
+
+   if (field_type[0] == ';')
+   field_type++;
+
+   if (!strcmp(field_type, "unsigned")) {
+   if (argc < 3)
+   goto out;
+   prefix = "unsigned";
+   field_type = argv[1];
+   field_name = argv[2];
+   *consumed = 3;
+   } else {
+   field_type = argv[0];
+   field_name = argv[1];
+   *consumed = 2;
+   }
+
+   len = strlen(field_name);
+   array = strchr(field_name, '[');
+   if (array)
+   len -= strlen(array);
+   else if (field_name[len - 1] == ';')
+   len--;
+
+   tmp = kmemdup_nul(field_name, len, GFP_KERNEL);
+   if (!tmp) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   if (!is_good_name(tmp)) {
+   kfree(tmp);
+   goto out;
+   }
+
+   kfree(tmp);
+
+   save_field_type = field_type;
+   if (field_type[0] == ';')
+   field_type++;
+   len = strlen(field_type) + 1;
+
+   if (array)
+   len += strlen(array);
+
+   if (prefix)
+   len += strlen(prefix) + 1;
+
+   tmp = kzalloc(len, GFP_KERNEL);
+   if (!tmp) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   seq_buf_init(, tmp, len);
+   if (prefix) {
+   seq_buf_puts(, prefix);
+   seq_buf_putc(, ' ');
+   }
+   seq_buf_puts(, field_type);
+   if (array) {
+   seq_buf_puts(, array);
+   if (f.buffer[f.len - 1] == ';')
+   f.len--;
+   }
+   if (WARN_ON_ONCE(!seq_buf_buffer_left())) {
+   kfree(tmp);
+   goto out;
+   }
+
+   f.buffer[f.len] = '\0';
+
+   field_type = save_field_type;
+
+   size = synth_field_size(tmp);
+   if (size < 0 || ((size == 0) && (!synth_field_is_string(tmp {
+   kfree(tmp);
+   goto out;
+   }
+
+   kfree(tmp);
+
+   if (prefix) {
+   seq_buf_puts(s, prefix);
+   seq_buf_putc(s, ' ');
+   }
+   seq_buf_puts(s, field_type);
+   seq_buf_putc(s, ' ');
+   seq_buf_puts(s, field_name);
+   if (field_name[strlen(field_name) - 1] == ';')
+   seq_buf_putc(s, ' ');
+
+   if (*consumed < argc) {
+   next_tok = argv[*consumed];
+   if (field_name[strlen(field_name) - 1] != ';' &&
+   next_tok[0] != ';') {
+   seq_buf_puts(s, "; ");
+   *added_semi = true;
+   }
+   }
+
+   ret = 0;
+ out:
+   return ret;
+}
+
+static char *insert_semicolons(const char *raw_command)
+{
+   int i, argc = 0, consumed = 0, n_fields = 0, semis_added = 0;
+   char *name, **argv, **save_argv = NULL, *buf = NULL;
+   int ret = -EINVAL;
+   struct seq_buf s;
+   bool added_semi;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (

[PATCH v5 0/5] tracing: More synthetic event error fixes

2020-12-21 Thread Tom Zanussi
Hi,

This is v5 of the sythetic event error fix patchset.  This version is
the same as v4 but with a few variable-initialization fixes flagged by
Dan Carpenter and the kernel test robot.

Tom

v4 text:

Hi,

This is v4 of the sythetic event error fix patchset.  As suggested by
Steve, I added a new pass that adds semicolons to 'old' commands that
may be missing them, in order to maintain backward compatibility.  All
commands are handled by the new and improved parsing code, but
commands missing the semicolons have them added before processing and
are therefore still valid.  At some point in the future, as new
features are added and we can require any command containing them to
require semicolons, this pass can be completely skipped by detecting
those features in the currently empty audit_old_buffer() hook.

Also, as a result, the patch adding semicolons to the selftests is no
longer necessary (selftests/ftrace: Add synthetic event field
separators) and has been dropped in this series.

Tom


v3 text:

Hi,

This is v3 of the sythetic event error fix patchset.  As suggested by
Masami, I split the 'tracing/dynevent: Delegate parsing to create
function' into two - one containing just the interface changes and the
second with the synthetic event parsing changes the first enabled.

I also replaced a couple argv_split() with strpbrk() as suggested by
Masami, along with removing the no-longer-used consume lines and
another line that tested ECANCELED that was no longer needed.

Also, removed a test case that was no longer needed since the commands
are now stripped of whitespace first.

Thanks, Masami, for the suggestions.

Tom

v2 text:

This is v2 of the previous sythetic event error fix patchset.

This version drops the original ([PATCH 1/4] tracing: Make
trace_*_run_command() more flexible) and (tracing: Use new
trace_run_command() options) patches and replaces them with Masami's
patch (tracing/dynevent: Delegate parsing to create function) [1].
The new version adds in all the synthetic event changes needed to
compile and use the new interface.

A new patch was also added (selftests/ftrace: Add synthetic event
field separators) that fixes more invalid synthetic event syntax I
found while testing.

I also added some more new checks to the synthetic event sytax error
testcase.

As before, I didn't see any problems running the entire ftrace
testsuite or the test modules that also use the things that were
touched here.

[1] 
https://lore.kernel.org/lkml/20201019001504.70dc3ec608277ed22060d...@kernel.org/

Thanks,

Tom


v1 text:

Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit f6a694665f132cbf6edd2f173dc35330a8aa:

  tracing: Offload eval map updates to a work queue (2020-12-15 09:29:14 -0500)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v5

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (4):
  tracing: Rework synthetic event command parsing
  tracing: Update synth command errors
  tracing: Add a backward-compatibility check for synthetic event
creation
  selftests/ftrace: Update synthetic event syntax errors

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 +-
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 501 +++---
 kernel/trace/trace_kprobe.c   |  33 +-
 kernel/trace/trace_probe.c|  17 +
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  35 +-
 10 files changed, 519 insertions(+), 150 deletions(-)

-- 
2.17.1



[PATCH v4 5/5] selftests/ftrace: Update synthetic event syntax errors

2020-12-17 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 35 ++-
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..955e3ceea44b 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,38 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v4 1/5] tracing/dynevent: Delegate parsing to create function

2020-12-17 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

This requires changes to the kprobe/uprobe/synthetic event handling,
which are also included here.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 23 ++--
 kernel/trace/trace.h  |  3 +-
 kernel/trace/trace_dynevent.c | 35 +++---
 kernel/trace/trace_dynevent.h |  4 +--
 kernel/trace/trace_events_synth.c | 60 +++
 kernel/trace/trace_kprobe.c   | 33 +
 kernel/trace/trace_probe.c| 17 +
 kernel/trace/trace_probe.h|  1 +
 kernel/trace/trace_uprobe.c   | 17 +
 9 files changed, 120 insertions(+), 73 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index eb5205e48733..e9cde7a3e0a6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9426,30 +9426,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9497,7 +9478,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e448d2da0b99..98211637e545 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1830,10 +1830,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 4f967d5cd917..dc971a68dda4 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
retur

[PATCH v4 4/5] tracing: Add a backward-compatibility check for synthetic event creation

2020-12-17 Thread Tom Zanussi
The synthetic event parsing rework requiring semicolons between
synthetic event fields.  That requirement breaks existing users who
might already have used the old form, so this adds a pre-parsing pass
that adds semicolons between fields to any string missing them.  If
none are required, the original string is used.

In the future, if/when new features are added, the requirement will be
that any string containing the new feature will be required to use
semicolons, and the audit_old_buffer() check can check for those and
avoid the pre-parsing semicolon pass altogether.

As it stands, the pre-parsing pass creates a new string with
semicolons only if one or more semicolons were actually needed and
only if no errors were found in pre-parsing.  The assumption is that
the real parsing pass will find and flag any errors and the user
should see them in reference to the original unmodified string.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 294 --
 1 file changed, 274 insertions(+), 20 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 2a9c8bf74bb2..6bff54ed31ce 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1373,6 +1373,245 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int save_synth_field(int argc, char **argv, int *consumed,
+   struct seq_buf *s, bool *added_semi)
+{
+   const char *prefix = NULL, *field_name, *field_type = argv[0];
+   const char *save_field_type, *array, *next_tok;
+   int len, ret = -EINVAL;
+   struct seq_buf f;
+   ssize_t size;
+   char *tmp;
+
+   *added_semi = false;
+
+   if (field_type[0] == ';')
+   field_type++;
+
+   if (!strcmp(field_type, "unsigned")) {
+   if (argc < 3)
+   goto out;
+   prefix = "unsigned";
+   field_type = argv[1];
+   field_name = argv[2];
+   *consumed = 3;
+   } else {
+   field_type = argv[0];
+   field_name = argv[1];
+   *consumed = 2;
+   }
+
+   len = strlen(field_name);
+   array = strchr(field_name, '[');
+   if (array)
+   len -= strlen(array);
+   else if (field_name[len - 1] == ';')
+   len--;
+
+   tmp = kmemdup_nul(field_name, len, GFP_KERNEL);
+   if (!tmp) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   if (!is_good_name(tmp)) {
+   kfree(tmp);
+   goto out;
+   }
+
+   kfree(tmp);
+
+   save_field_type = field_type;
+   if (field_type[0] == ';')
+   field_type++;
+   len = strlen(field_type) + 1;
+
+   if (array)
+   len += strlen(array);
+
+   if (prefix)
+   len += strlen(prefix) + 1;
+
+   tmp = kzalloc(len, GFP_KERNEL);
+   if (!tmp) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   seq_buf_init(, tmp, len);
+   if (prefix) {
+   seq_buf_puts(, prefix);
+   seq_buf_putc(, ' ');
+   }
+   seq_buf_puts(, field_type);
+   if (array) {
+   seq_buf_puts(, array);
+   if (f.buffer[f.len - 1] == ';')
+   f.len--;
+   }
+   if (WARN_ON_ONCE(!seq_buf_buffer_left())) {
+   kfree(tmp);
+   goto out;
+   }
+
+   f.buffer[f.len] = '\0';
+
+   field_type = save_field_type;
+
+   size = synth_field_size(tmp);
+   if (size < 0 || ((size == 0) && (!synth_field_is_string(tmp {
+   kfree(tmp);
+   goto out;
+   }
+
+   kfree(tmp);
+
+   if (prefix) {
+   seq_buf_puts(s, prefix);
+   seq_buf_putc(s, ' ');
+   }
+   seq_buf_puts(s, field_type);
+   seq_buf_putc(s, ' ');
+   seq_buf_puts(s, field_name);
+   if (field_name[strlen(field_name) - 1] == ';')
+   seq_buf_putc(s, ' ');
+
+   if (*consumed < argc) {
+   next_tok = argv[*consumed];
+   if (field_name[strlen(field_name) - 1] != ';' &&
+   next_tok[0] != ';') {
+   seq_buf_puts(s, "; ");
+   *added_semi = true;
+   }
+   }
+
+   ret = 0;
+ out:
+   return ret;
+}
+
+static char *insert_semicolons(const char *raw_command)
+{
+   int i, argc, consumed = 0, n_fields = 0, semis_added = 0;
+   char *name, **argv, **save_argv;
+   int ret = -EINVAL;
+   struct seq_buf s;
+   bool added_semi;
+   char *buf;
+
+   argc = 0;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return NULL;
+
+   if (!argc)
+   goto out;
+
+   name = argv[0];

[PATCH v4 3/5] tracing: Update synth command errors

2020-12-17 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 71 +++
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 66ccbab3483b..2a9c8bf74bb2 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -651,6 +652,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1171,7 +1176,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
mutex_lock(_mutex);
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto out;
}
@@ -1221,6 +1226,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
argv_free(argv);
 
if (consumed < argc) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1229,7 +1235,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1367,6 +1373,37 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int check_command(const char *raw_command)
+{
+   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
+   int argc, ret = 0;
+
+   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   name_and_field = strsep(, ";");
+   if (!name_and_field) {
+   ret = -EINVAL;
+   goto free;
+   }
+
+   argv = argv_split(GFP_KERNEL, name_and_field, );
+   if (!argv) {
+   ret = -ENOMEM;
+   goto free;
+   }
+
+   if (argc < 3)
+   ret = -EINVAL;
+free:
+   kfree(saved_cmd);
+   if (argv)
+   argv_free(argv);
+
+   return ret;
+}
+
 static int create_or_delete_synth_event(const char *raw_command)
 {
char *name = NULL, *fields, *p;
@@ -1378,9 +1415,17 @@ static int create_or_delete_synth_event(const char 
*raw_command)
 
last_cmd_set(raw_command);
 
+   ret = check_command(raw_command);
+   if (ret) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
+   return ret;
+   }
+
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
name = kmemdup_nul(raw_command, p - raw_command, GFP_KERNEL);
if (!name)
@@ -1954,8 +1999,10 @@ static int create_synth_event(const char *raw_command)
last_cmd_set(raw_command);
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD

[PATCH v4 2/5] tracing: Rework synthetic event command parsing

2020-12-17 Thread Tom Zanussi
Now that command parsing has been delegated to the create functions
and we're no longer constrained by argv_split(), we can modify the
synthetic event command parser to better match the higher-level
structure of the synthetic event commands, which is basically an event
name followed by a set of semicolon-separated fields.

Since we're also now passed the raw command, we can also save it
directly and can get rid of save_cmdstr().

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 184 +++---
 1 file changed, 90 insertions(+), 94 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b2588a5650c9..66ccbab3483b 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -579,7 +579,7 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, const char **argv,
+static struct synth_field *parse_synth_field(int argc, char **argv,
 int *consumed)
 {
struct synth_field *field;
@@ -588,9 +588,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
struct seq_buf s;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -605,6 +602,11 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
*consumed = 2;
}
 
+   if (!field_name) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
+   }
+
field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field)
return ERR_PTR(-ENOMEM);
@@ -613,8 +615,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name)
@@ -626,8 +626,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
if (array)
@@ -644,11 +642,8 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
seq_buf_puts(, prefix);
seq_buf_puts(, field_type);
-   if (array) {
+   if (array)
seq_buf_puts(, array);
-   if (s.buffer[s.len - 1] == ';')
-   s.len--;
-   }
if (WARN_ON_ONCE(!seq_buf_buffer_left()))
goto free;
 
@@ -656,7 +651,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
-   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1160,46 +1154,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
-static int __create_synth_event(int argc, const char *name, const char **argv)
+static int __create_synth_event(const char *name, const char *raw_fields)
 {
+   int i, argc, n_fields = 0, ret = 0, consumed;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_event *event = NULL;
-   int i, consumed = 0, n_fields = 0, ret = 0;
-
-   ret = save_cmdstr(argc, name, argv);
-   if (ret)
-   return ret;
 
/*
 * Argument syntax:
@@

[PATCH v4 0/5] tracing: More synthetic event error fixes

2020-12-17 Thread Tom Zanussi
Hi,

This is v4 of the sythetic event error fix patchset.  As suggested by
Steve, I added a new pass that adds semicolons to 'old' commands that
may be missing them, in order to maintain backward compatibility.  All
commands are handled by the new and improved parsing code, but
commands missing the semicolons have them added before processing and
are therefore still valid.  At some point in the future, as new
features are added and we can require any command containing them to
require semicolons, this pass can be completely skipped by detecting
those features in the currently empty audit_old_buffer() hook.

Also, as a result, the patch adding semicolons to the selftests is no
longer necessary (selftests/ftrace: Add synthetic event field
separators) and has been dropped in this series.

Tom


v3 text:

Hi,

This is v3 of the sythetic event error fix patchset.  As suggested by
Masami, I split the 'tracing/dynevent: Delegate parsing to create
function' into two - one containing just the interface changes and the
second with the synthetic event parsing changes the first enabled.

I also replaced a couple argv_split() with strpbrk() as suggested by
Masami, along with removing the no-longer-used consume lines and
another line that tested ECANCELED that was no longer needed.

Also, removed a test case that was no longer needed since the commands
are now stripped of whitespace first.

Thanks, Masami, for the suggestions.

Tom

v2 text:

This is v2 of the previous sythetic event error fix patchset.

This version drops the original ([PATCH 1/4] tracing: Make
trace_*_run_command() more flexible) and (tracing: Use new
trace_run_command() options) patches and replaces them with Masami's
patch (tracing/dynevent: Delegate parsing to create function) [1].
The new version adds in all the synthetic event changes needed to
compile and use the new interface.

A new patch was also added (selftests/ftrace: Add synthetic event
field separators) that fixes more invalid synthetic event syntax I
found while testing.

I also added some more new checks to the synthetic event sytax error
testcase.

As before, I didn't see any problems running the entire ftrace
testsuite or the test modules that also use the things that were
touched here.

[1] 
https://lore.kernel.org/lkml/20201019001504.70dc3ec608277ed22060d...@kernel.org/

Thanks,

Tom


v1 text:

Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit f6a694665f132cbf6edd2f173dc35330a8aa:

  tracing: Offload eval map updates to a work queue (2020-12-15 09:29:14 -0500)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v4

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (4):
  tracing: Rework synthetic event command parsing
  tracing: Update synth command errors
  tracing: Add a backward-compatibility check for synthetic event
creation
  selftests/ftrace: Update synthetic event syntax errors

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 +-
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 503 +++---
 kernel/trace/trace_kprobe.c   |  33 +-
 kernel/trace/trace_probe.c|  17 +
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  35 +-
 10 files changed, 521 insertions(+), 150 deletions(-)

-- 
2.17.1



Re: [PATCH v3 3/5] tracing: Update synth command errors

2020-12-08 Thread Tom Zanussi
Hi Steve,

On Tue, 2020-12-08 at 12:53 -0500, Steven Rostedt wrote:
> On Tue, 08 Dec 2020 11:34:41 -0600
> Tom Zanussi  wrote:
> 
> > Unfortunately, you're correct, if you have a script that creates a
> > synthetic event without semicolons, this patchset will break it, as
> > I
> > myself found out and fixed in patch 4 ([PATCH v3 4/5]
> > selftests/ftrace:
> > Add synthetic event field separators) [4].
> > 
> > So whereas before this would work, even though it shouldn't have in
> > the
> > first place:
> > 
> >   # echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' >
> > synthetic_events
> > 
> > it now has to be:
> > 
> >   # echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' >
> > synthetic_events
> > 
> > So yeah, this patchset fixes a set of parsing bugs for things that
> > shouldn't have been accepted as valid, but shouldn't break things
> > that
> > are obviously valid.
> > 
> > If it's too late to fix them, though, I guess we'll just have to
> > live
> > with them, or some other option?
> 
> 
> I would suggest allowing the old interface work (with no new
> features, for
> backward compatibility), but new things like "char comm[16]" we
> require
> semicolons.
> 
> One method to do this is to add to the start of reading the string,
> and
> checking if it has semicolons. If it does not, we create a new string
> with
> them, but make sure that the string does not include new changes.
> 
>   strncpy_from_user(buffer, user_buff, sizeof(buffer));
> 
>   if (!strstr(buffer, ";")) {
>   if (!audit_old_buffer(buffer))
>   goto error;
>   insert_colons(buffer);
>   }
> 
> 
> That is, if the buffer does not have semicolons, then check if it is
> a
> valid "old format", and if not, we error out. Otherwise, we insert
> the
> colons into the buffer, and process that as if the user put in
> colons:
> 
> That is:
> 
>   echo 'wakeup_latency u64 lat pid_t pid' > synthetic_events
> 
> would change the buffer to:
> 
>   "wakeup_latency u64 lat; pid_t pid;"
> 
> And then put it through the normal processing. I think its OK that if
> the
> user were to cat out the synthetic events, it would see the
> semicolons even
> if it did not add them. As I don't think that will break userspace.
> 
> Does that make sense?
> 

Yeah, that should work, I'll try adding that.

Thanks,

Tom

> -- Steve



Re: [PATCH v3 2/5] tracing: Rework synthetic event command parsing

2020-12-08 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-12-07 at 19:16 -0500, Steven Rostedt wrote:
> On Mon, 26 Oct 2020 10:06:10 -0500
> Tom Zanussi  wrote:
> 
> > Now that command parsing has been delegated to the create functions
> > and we're no longer constrained by argv_split(), we can modify the
> > synthetic event command parser to better match the higher-level
> > structure of the synthetic event commands, which is basically an
> > event
> > name followed by a set of semicolon-separated fields.
> > 
> > Since we're also now passed the raw command, we can also save it
> > directly and can get rid of save_cmdstr().
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> > 
> 
> This patch fails to build with:
> 
>   CC  kernel/trace/trace_events_synth.o
> /work/git/linux-trace.git/kernel/trace/trace_events_synth.c: In
> function ‘create_or_delete_synth_event’:
> /work/git/linux-trace.git/kernel/trace/trace_events_synth.c:1372:8:
> error: implicit declaration of function ‘check_command’ [-
> Werror=implicit-function-declaration]
>  1372 |  ret = check_command(raw_command);
>   |^
> cc1: some warnings being treated as errors
> make[3]: *** [/work/git/linux-trace.git/scripts/Makefile.build:283:
> kernel/trace/trace_events_synth.o] Error 1
> make[2]: *** [/work/git/linux-trace.git/scripts/Makefile.build:500:
> kernel/trace] Error 2
> make[1]: *** [/work/git/linux-trace.git/Makefile:1799: kernel] Error
> 2
> make[1]: Leaving directory '/work/git/nobackup/bxtest/trace'
> make: *** [Makefile:185: __sub-make] Error 2
> 

Oops, yeah, a stray check_command() call got left behind in that patch
when refactoring, should be moved to the next patch.

Tom

> -- Steve



Re: [PATCH v3 3/5] tracing: Update synth command errors

2020-12-08 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-12-07 at 20:13 -0500, Steven Rostedt wrote:
> On Mon, 26 Oct 2020 10:06:11 -0500
> Tom Zanussi  wrote:
> 
> > Since array types are handled differently, errors referencing them
> > also need to be handled differently.  Add and use a new
> > INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD
> > to
> > catch and display the correct form for badly-formed commands, which
> > can also be used in place of CMD_INCOMPLETE, which is removed, and
> > remove CMD_TOO_LONG, since it's no longer used.
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> 
> Unfortunately, this patch series breaks user space.
> 
> I already have scripts that do the histograms, and I'm sure others
> may
> have that too, and if we change how synthetic events are created, it
> will break them.
> 
> What's the rationale for the new delimiters?
> 

The overall problem this is trying to fix is that it was probably a
mistake to try to shoehorn the synthetic event parsing into what was
available from  trace_run_command() and trace_parse_run_command(),
which use argv_split() to do the command splitting, and which only
splits on whitespace.  Whereas the synthetic events have a bit of a
higher-level structure which is 'event field; field; field;...'

So this patchset tries to remedy that - the first patch,
(tracing/dynevent: Delegate parsing to create function) is from Masami,
and makes it possible to share code between kprobe/uprobe and synthetic
evnents, and to allow synthetic events to have their own higher-level
parsing, which the next 2 patches do.

The history in more detail:

Initially the problem was to fix the errors mentioned by Masami in
[1]. 

Things like:

  # echo myevent char str[];; int v >> synthetic_events

which was identified as INVALID_TYPE where it should just be a void arg
and

  # echo mye;vent char str[] >> synthetic_events

which was identified as BAD_NAME where it should have been an invalid
command, etc.

I suggested that the way to fix them was to consider semicolon as
additional whitespace and the result was the patchset containing [2],
which also explains the reasons for wanting to enforce semicolon
grouping.

Masami pointed out that it really wasn't correct to do it that way,
and  the commands should be split out first at the higher level by
semicolon and then further processed [3].

Unfortunately, you're correct, if you have a script that creates a
synthetic event without semicolons, this patchset will break it, as I
myself found out and fixed in patch 4 ([PATCH v3 4/5] selftests/ftrace:
Add synthetic event field separators) [4].

So whereas before this would work, even though it shouldn't have in the
first place:

  # echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' >
synthetic_events

it now has to be:

  # echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' >
synthetic_events

So yeah, this patchset fixes a set of parsing bugs for things that
shouldn't have been accepted as valid, but shouldn't break things that
are obviously valid.

If it's too late to fix them, though, I guess we'll just have to live
with them, or some other option?

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/
[2] 
https://lore.kernel.org/lkml/e29c3ae1fc46892ec792d6f6f910f75d0e12584c.1602883818.git.zanu...@kernel.org/
[3] 
https://lore.kernel.org/lkml/20201018232011.38e5da51f5cd8e73e6f52...@kernel.org/
[4] 
https://lore.kernel.org/lkml/75a2816b4001e04e7d60bcc87aa91477ad5d90b3.1603723933.git.zanu...@kernel.org/



> -- Steve



[ANNOUNCE] 4.19.160-rt69

2020-11-25 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.160-rt69 stable release.

This release is just an update to the new stable 4.19.160
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: de0586f55c33891d912bd4ce3e9f76163c4c05a3

Or to build 4.19.160-rt69 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.160.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.160-rt69.patch.xz

Enjoy!

   Tom



Re: [FEATURE REQUEST] tracing: Have event filters handle dynamic arrays

2020-11-25 Thread Tom Zanussi
Hi Steve, Daniel,

On Tue, 2020-11-24 at 11:37 -0500, Steven Rostedt wrote:
> Hi Tom,
> 
> Daniel asked about filtering bitmasks, something like:
> 
>cpumask != 0xff
> 
> Looking into the code, I realized that bitmasks are dynamic arrays,
> and
> there's no logic in the filter code to handle dynamic arrays of
> anything
> other than 'char' type (which are dynamic strings).
> 
> If you have any cycles to spare, do you think you can add code to
> process
> dynamic arrays other than char?
> 
> The compare logic may be complex though. I think the above example
> should
> work, but we would need to define how that happens.
> 
> I guess we should follow the cpumask logic, and break all non string
> dynamic arrays up into 32 bit words. Even if something is defined as
> u8, it
> will be converted to the local endian of the machine. Basically, we
> should
> follow the function bitmap_string() defined in lib/vsnprintf.c
> 
> If we have a u8 dynamic array of:
> 
>  0x12 0x34 0x56 0x78 0x9a 0xbc 0xde 0xf0
> 
> On a little endian machine it would match:
> 
>   0xf0debca9,0x78563412
> 
> This way, if we have a machine with 64 CPUS, and we want to match
> cpus 0-7,
> then we only need to do:
> 
>   cpumask & 0xff
> 
> The above would be equivalent to:
> 
>  cpumask & 0,0xff
> 
> in such a case.
> 
> That's because, if I'm reading the code correctly, a cpumask for CPUs
> 0-7
> bits set for 64 CPU machine in raw format would be:
> 
>  0x00 0x00 0x00 0xff 0x00 0x00 0x00 0x00
> 
> The dynamic arrays will allow comma separated 4 byte words to match.
> 
> Daniel brought this up, and he said he'd be willing to help out
> making a
> patch if he has spare cycles to spare. Perhaps, between the two of
> you, you
> could come up with the cycles to produce such a patch :-)
> 

Sure, I can take a look - luckily holidays are coming up so should be
able to find some time for this.

Tom

> Cheers,
> 
> -- Steve



[ANNOUNCE] 4.19.152-rt66

2020-11-20 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.152-rt66 stable release.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: 3b515711216822e708490d1c686813c819e237b1

Or to build 4.19.152-rt66 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.152.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.152-rt66.patch.xz


You can also build from 4.19.152-rt65 by applying the incremental patch:

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/incr/patch-4.19.152-rt65-rt66.patch.xz

Enjoy!

   Tom

Changes from v4.19.152-rt65:
---

Oleg Nesterov (1):
  ptrace: fix ptrace_unfreeze_traced() race with rt-lock

Sebastian Andrzej Siewior (1):
  mm/memcontrol: Disable preemption in __mod_memcg_lruvec_state()

Tom Zanussi (1):
  Linux 4.19.152-rt66
---
include/linux/memcontrol.h |  2 ++
 kernel/ptrace.c| 23 +++
 localversion-rt|  2 +-
 3 files changed, 18 insertions(+), 9 deletions(-)
---
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index cc6b6532eb56..dbb2c4e27277 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -665,6 +665,7 @@ static inline void __mod_lruvec_state(struct lruvec *lruvec,
 
pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
 
+   preempt_disable_rt();
/* Update memcg */
__mod_memcg_state(pn->memcg, idx, val);
 
@@ -675,6 +676,7 @@ static inline void __mod_lruvec_state(struct lruvec *lruvec,
x = 0;
}
__this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
+   preempt_enable_rt();
 }
 
 static inline void mod_lruvec_state(struct lruvec *lruvec,
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index a38b304fb9fd..cbefb0234be3 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -191,8 +191,8 @@ static bool ptrace_freeze_traced(struct task_struct *task)
 
 static void ptrace_unfreeze_traced(struct task_struct *task)
 {
-   if (task->state != __TASK_TRACED)
-   return;
+   unsigned long flags;
+   bool frozen = true;
 
WARN_ON(!task->ptrace || task->parent != current);
 
@@ -201,12 +201,19 @@ static void ptrace_unfreeze_traced(struct task_struct 
*task)
 * Recheck state under the lock to close this race.
 */
spin_lock_irq(>sighand->siglock);
-   if (task->state == __TASK_TRACED) {
-   if (__fatal_signal_pending(task))
-   wake_up_state(task, __TASK_TRACED);
-   else
-   task->state = TASK_TRACED;
-   }
+
+   raw_spin_lock_irqsave(>pi_lock, flags);
+   if (task->state == __TASK_TRACED)
+   task->state = TASK_TRACED;
+   else if (task->saved_state == __TASK_TRACED)
+   task->saved_state = TASK_TRACED;
+   else
+   frozen = false;
+   raw_spin_unlock_irqrestore(>pi_lock, flags);
+
+   if (frozen && __fatal_signal_pending(task))
+   wake_up_state(task, __TASK_TRACED);
+
spin_unlock_irq(>sighand->siglock);
 }
 
diff --git a/localversion-rt b/localversion-rt
index e2eb19782d4c..d42c0971b041 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt65
+-rt66



Re: [PATCH RT 1/5] net: Properly annotate the try-lock for the seqlock

2020-11-14 Thread Tom Zanussi
On Sat, 2020-11-14 at 20:00 +0100, Mike Galbraith wrote:
> On Fri, 2020-11-13 at 14:14 -0600, Tom Zanussi wrote:
> > 
> > This patch seems to fix it for me:
> 
> If there was any discussion about this patch, I missed it.

There wasn't, just this thread.

> 
> > From 4855377d0cb34b1b67a5c6d84cc8609c9da0bc3e Mon Sep 17 00:00:00
> > 2001
> > Message-Id: <
> > 4855377d0cb34b1b67a5c6d84cc8609c9da0bc3e.1605297603.git.zanu...@kernel.org
> > >
> > From: Tom Zanussi 
> > Date: Fri, 13 Nov 2020 13:04:15 -0600
> > Subject: [PATCH] net: Add missing __raw_write_seqcount_end() and
> >  seqcount_release()
> > 
> > The patch ('net: Properly annotate the try-lock for the seqlock")
> > adds
> > __raw_write_seqcount_begin() in qdisc_run_begin() but omits the
> > corresponding __raw_write_seqcount_end() and seqcount_release() in
> > qdisc_run_end().
> > 
> > Add it unconditionally, since qdisc_run_end() is never called
> > unless
> > qdisc_run_begin() succeeds, and if it succeeds,
> > __raw_write_seqcount_begin() seqcount_acquire() will have been
> > called.
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> >  include/net/sch_generic.h | 4 
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> > index 112d2dca8b08..c5ccce4f8f62 100644
> > --- a/include/net/sch_generic.h
> > +++ b/include/net/sch_generic.h
> > @@ -192,7 +192,11 @@ static inline bool qdisc_run_begin(struct
> > Qdisc *qdisc)
> >  static inline void qdisc_run_end(struct Qdisc *qdisc)
> >  {
> >  #ifdef CONFIG_PREEMPT_RT
> > +   seqcount_t *s = >running.seqcount;
> > +
> > write_sequnlock(>running);
> > +   __raw_write_seqcount_end(s);
> > +   seqcount_release(>dep_map, 1, _RET_IP_);
> >  #else
> > write_seqcount_end(>running);
> >  #endif
> 
> __raw_write_seqcount_end() is an integral part of write_sequnlock(),
> but we do seem to be missing a seqcount_release() in 5.4-rt.
> 

Yep, you're right, it's just the missing seqcount_release() - I'll
resubmit with just that.

Thanks,

Tom

>   -Mike
> 



Re: [PATCH RT 1/5] net: Properly annotate the try-lock for the seqlock

2020-11-13 Thread Tom Zanussi
Hi Steve,

On Fri, 2020-11-13 at 11:06 -0600, Tom Zanussi wrote:
> Hi Steve,
> 
> On Tue, 2020-11-10 at 10:38 -0500, Steven Rostedt wrote:
> > 5.4.74-rt42-rc2 stable review patch.
> > If anyone has any objections, please let me know.
> > 
> > --
> > 
> > From: Sebastian Andrzej Siewior 
> > 
> > In patch
> >("net/Qdisc: use a seqlock instead seqcount")
> > 
> > the seqcount has been replaced with a seqlock to allow to reader to
> > boost the preempted writer.
> > The try_write_seqlock() acquired the lock with a try-lock but the
> > seqcount annotation was "lock".
> > 
> > Opencode write_seqcount_t_begin() and use the try-lock annotation
> > for
> > lockdep.
> > 
> > Reported-by: Mike Galbraith 
> > Cc: stable...@vger.kernel.org
> > Signed-off-by: Sebastian Andrzej Siewior 
> > Signed-off-by: Steven Rostedt (VMware) 
> > ---
> >  include/linux/seqlock.h   |  9 -
> >  include/net/sch_generic.h | 10 +-
> >  2 files changed, 9 insertions(+), 10 deletions(-)
> > 
> > diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
> > index e5207897c33e..f390293974ea 100644
> > --- a/include/linux/seqlock.h
> > +++ b/include/linux/seqlock.h
> > @@ -489,15 +489,6 @@ static inline void write_seqlock(seqlock_t
> > *sl)
> > __raw_write_seqcount_begin(>seqcount);
> >  }
> >  
> > -static inline int try_write_seqlock(seqlock_t *sl)
> > -{
> > -   if (spin_trylock(>lock)) {
> > -   __raw_write_seqcount_begin(>seqcount);
> > -   return 1;
> > -   }
> > -   return 0;
> > -}
> > -
> >  static inline void write_sequnlock(seqlock_t *sl)
> >  {
> > __raw_write_seqcount_end(>seqcount);
> > diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> > index e6afb4b9cede..112d2dca8b08 100644
> > --- a/include/net/sch_generic.h
> > +++ b/include/net/sch_generic.h
> > @@ -168,8 +168,16 @@ static inline bool qdisc_run_begin(struct
> > Qdisc
> > *qdisc)
> > return false;
> > }
> >  #ifdef CONFIG_PREEMPT_RT
> > -   if (try_write_seqlock(>running))
> > +   if (spin_trylock(>running.lock)) {
> > +   seqcount_t *s = >running.seqcount;
> > +   /*
> > +* Variant of write_seqcount_t_begin() telling lockdep
> > that a
> > +* trylock was attempted.
> > +*/
> > +   __raw_write_seqcount_begin(s);
> > +   seqcount_acquire(>dep_map, 0, 1, _RET_IP_);
> > return true;
> > +   }
> > return false;
> >  #else
> > /* Variant of write_seqcount_begin() telling lockdep a trylock
> 
> I applied this to 4.19 and saw some splat with my 'debug-full'
> configuration, so tried 5.4 and saw the same thing:
> 
> [   30.573698] BUG: workqueue leaked lock or atomic:
> kworker/1:4/0x/143
> last function: wireless_nlevent_process
> [   30.573707] 1 lock held by kworker/1:4/143:
> [   30.573708]  #0: 8e981d80 (noop_qdisc.running#2){+.+.},
> at: __do_softirq+0xca/0x561
> [   30.573715] CPU: 1 PID: 143 Comm: kworker/1:4 Not tainted 5.4.74-
> rt42-rt-test-full-debug #1
> [   30.573716] Hardware name: LENOVO 4236L51/4236L51, BIOS 83ET59WW
> (1.29 ) 06/01/2011
> [   30.573720] Workqueue: events wireless_nlevent_process
> [   30.573721] Call Trace:
> [   30.573724]  dump_stack+0x71/0x9b
> [   30.573728]  process_one_work+0x533/0x760
> [   30.573731]  worker_thread+0x39/0x3f0
> [   30.573733]  ? process_one_work+0x760/0x760
> [   30.573734]  kthread+0x165/0x180
> [   30.573736]  ? __kthread_create_on_node+0x180/0x180
> [   30.573737]  ret_from_fork+0x3a/0x50
> [   30.629329] wlp3s0: authenticate with 84:1b:5e:41:5e:4d
> [   30.634864] wlp3s0: send auth to 84:1b:5e:41:5e:4d (try 1/3)
> [   30.638433] wlp3s0: authenticated
> [   30.642250] wlp3s0: associate with 84:1b:5e:41:5e:4d (try 1/3)
> [   30.645704] wlp3s0: RX AssocResp from 84:1b:5e:41:5e:4d
> (capab=0x411 status=0 aid=6)
> [   30.650803] wlp3s0: associated
> 
> [   30.656764] 
> [   30.656765] WARNING: lock held when returning to user space!
> [   30.656766] 5.4.74-rt42-rt-test-full-debug #1 Not tainted
> [   30.656767] --------
> [   30.656768] wpa_supplicant/836 is leaving the kernel with locks
> still held!
> [   30.656769] 1 lock held by wpa_supplicant/836:
> [   30.656770]  #0: 98f1c9622280 (>qdi

Re: [PATCH RT 1/5] net: Properly annotate the try-lock for the seqlock

2020-11-13 Thread Tom Zanussi
Hi Steve,

On Tue, 2020-11-10 at 10:38 -0500, Steven Rostedt wrote:
> 5.4.74-rt42-rc2 stable review patch.
> If anyone has any objections, please let me know.
> 
> --
> 
> From: Sebastian Andrzej Siewior 
> 
> In patch
>("net/Qdisc: use a seqlock instead seqcount")
> 
> the seqcount has been replaced with a seqlock to allow to reader to
> boost the preempted writer.
> The try_write_seqlock() acquired the lock with a try-lock but the
> seqcount annotation was "lock".
> 
> Opencode write_seqcount_t_begin() and use the try-lock annotation for
> lockdep.
> 
> Reported-by: Mike Galbraith 
> Cc: stable...@vger.kernel.org
> Signed-off-by: Sebastian Andrzej Siewior 
> Signed-off-by: Steven Rostedt (VMware) 
> ---
>  include/linux/seqlock.h   |  9 -
>  include/net/sch_generic.h | 10 +-
>  2 files changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
> index e5207897c33e..f390293974ea 100644
> --- a/include/linux/seqlock.h
> +++ b/include/linux/seqlock.h
> @@ -489,15 +489,6 @@ static inline void write_seqlock(seqlock_t *sl)
>   __raw_write_seqcount_begin(>seqcount);
>  }
>  
> -static inline int try_write_seqlock(seqlock_t *sl)
> -{
> - if (spin_trylock(>lock)) {
> - __raw_write_seqcount_begin(>seqcount);
> - return 1;
> - }
> - return 0;
> -}
> -
>  static inline void write_sequnlock(seqlock_t *sl)
>  {
>   __raw_write_seqcount_end(>seqcount);
> diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> index e6afb4b9cede..112d2dca8b08 100644
> --- a/include/net/sch_generic.h
> +++ b/include/net/sch_generic.h
> @@ -168,8 +168,16 @@ static inline bool qdisc_run_begin(struct Qdisc
> *qdisc)
>   return false;
>   }
>  #ifdef CONFIG_PREEMPT_RT
> - if (try_write_seqlock(>running))
> + if (spin_trylock(>running.lock)) {
> + seqcount_t *s = >running.seqcount;
> + /*
> +  * Variant of write_seqcount_t_begin() telling lockdep
> that a
> +  * trylock was attempted.
> +  */
> + __raw_write_seqcount_begin(s);
> + seqcount_acquire(>dep_map, 0, 1, _RET_IP_);
>   return true;
> + }
>   return false;
>  #else
>   /* Variant of write_seqcount_begin() telling lockdep a trylock

I applied this to 4.19 and saw some splat with my 'debug-full'
configuration, so tried 5.4 and saw the same thing:

[   30.573698] BUG: workqueue leaked lock or atomic: kworker/1:4/0x/143
last function: wireless_nlevent_process
[   30.573707] 1 lock held by kworker/1:4/143:
[   30.573708]  #0: 8e981d80 (noop_qdisc.running#2){+.+.}, at: 
__do_softirq+0xca/0x561
[   30.573715] CPU: 1 PID: 143 Comm: kworker/1:4 Not tainted 
5.4.74-rt42-rt-test-full-debug #1
[   30.573716] Hardware name: LENOVO 4236L51/4236L51, BIOS 83ET59WW (1.29 ) 
06/01/2011
[   30.573720] Workqueue: events wireless_nlevent_process
[   30.573721] Call Trace:
[   30.573724]  dump_stack+0x71/0x9b
[   30.573728]  process_one_work+0x533/0x760
[   30.573731]  worker_thread+0x39/0x3f0
[   30.573733]  ? process_one_work+0x760/0x760
[   30.573734]  kthread+0x165/0x180
[   30.573736]  ? __kthread_create_on_node+0x180/0x180
[   30.573737]  ret_from_fork+0x3a/0x50
[   30.629329] wlp3s0: authenticate with 84:1b:5e:41:5e:4d
[   30.634864] wlp3s0: send auth to 84:1b:5e:41:5e:4d (try 1/3)
[   30.638433] wlp3s0: authenticated
[   30.642250] wlp3s0: associate with 84:1b:5e:41:5e:4d (try 1/3)
[   30.645704] wlp3s0: RX AssocResp from 84:1b:5e:41:5e:4d (capab=0x411 
status=0 aid=6)
[   30.650803] wlp3s0: associated

[   30.656764] 
[   30.656765] WARNING: lock held when returning to user space!
[   30.656766] 5.4.74-rt42-rt-test-full-debug #1 Not tainted
[   30.656767] 
[   30.656768] wpa_supplicant/836 is leaving the kernel with locks still held!
[   30.656769] 1 lock held by wpa_supplicant/836:
[   30.656770]  #0: 98f1c9622280 (>qdisc_running_key){+.+.}, at: 
packet_sendmsg+0xec1/0x1ad0

Let me know if you want me to send you my .config or the full output (a
bunch more of the above).

Thanks,

Tom



Re: [PATCH] docs: trace: fix event state structure name

2020-11-06 Thread Tom Zanussi
Hi Artem,

On Wed, 2020-11-04 at 14:21 +0200, Artem Bityutskiy wrote:
> From: Artem Bityutskiy 
> 
> The documentation refers to a non-existent 'struct synth_trace_state'
> structure. The correct name is 'struct synth_event_trace_state'.
> 
> In other words, this patch is a mechanical substitution:
> s/synth_trace_state/synth_event_trace_state/g
> 
> Signed-off-by: Artem Bityutskiy 

Thanks for fixing this!

Reviewed-by: Tom Zanussi 


> ---
>  Documentation/trace/events.rst | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/trace/events.rst
> b/Documentation/trace/events.rst
> index f792b1959a33..bdba7b0e19ef 100644
> --- a/Documentation/trace/events.rst
> +++ b/Documentation/trace/events.rst
> @@ -787,13 +787,13 @@ To trace a synthetic using the piecewise method
> described above, the
>  synth_event_trace_start() function is used to 'open' the synthetic
>  event trace::
>  
> -   struct synth_trace_state trace_state;
> +   struct synth_event_trace_state trace_state;
>  
> ret = synth_event_trace_start(schedtest_event_file,
> _state);
>  
>  It's passed the trace_event_file representing the synthetic event
>  using the same methods as described above, along with a pointer to a
> -struct synth_trace_state object, which will be zeroed before use and
> +struct synth_event_trace_state object, which will be zeroed before
> use and
>  used to maintain state between this and following calls.
>  
>  Once the event has been opened, which means space for it has been
> @@ -805,7 +805,7 @@ lookup per field.
>  
>  To assign the values one after the other without lookups,
>  synth_event_add_next_val() should be used.  Each call is passed the
> -same synth_trace_state object used in the synth_event_trace_start(),
> +same synth_event_trace_state object used in the
> synth_event_trace_start(),
>  along with the value to set the next field in the event.  After each
>  field is set, the 'cursor' points to the next field, which will be
> set
>  by the subsequent call, continuing until all the fields have been
> set
> @@ -834,7 +834,7 @@ this method would be (without error-handling
> code)::
> ret = synth_event_add_next_val(395, _state);
>  
>  To assign the values in any order, synth_event_add_val() should be
> -used.  Each call is passed the same synth_trace_state object used in
> +used.  Each call is passed the same synth_event_trace_state object
> used in
>  the synth_event_trace_start(), along with the field name of the
> field
>  to set and the value to set it to.  The same sequence of calls as in
>  the above examples using this method would be (without error-
> handling
> @@ -856,7 +856,7 @@ can be used but not both at the same time.
>  
>  Finally, the event won't be actually traced until it's 'closed',
>  which is done using synth_event_trace_end(), which takes only the
> -struct synth_trace_state object used in the previous calls::
> +struct synth_event_trace_state object used in the previous calls::
>  
> ret = synth_event_trace_end(_state);
>  



[ANNOUNCE] 4.19.152-rt65

2020-10-30 Thread Tom Zanussi
Hello RT Folks!

I'm pleased to announce the 4.19.152-rt65 stable release.

This release is just an update to the new stable 4.19.152
version and no RT specific changes have been made.

You can get this release via the git tree at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git

  branch: v4.19-rt
  Head SHA1: 007d95624000d3baa5c70c0710c3f52683929f02

Or to build 4.19.152-rt65 directly, the following patches should be applied:

  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz

  https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.152.xz

  
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/patch-4.19.152-rt65.patch.xz

Enjoy!

   Tom



Re: [PATCH v2] tracing, synthetic events: Replace buggy strcat() with seq_buf operations

2020-10-26 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-10-26 at 12:53 -0400, Steven Rostedt wrote:
> From: "Steven Rostedt (VMware)" 
> 
> There was a memory corruption bug happening while running the
> synthetic
> event selftests:
> 
>  kmemleak: Cannot insert 0x8c196fa2afe5 into the object search
> tree (overlaps existing)
>  CPU: 5 PID: 6866 Comm: ftracetest Tainted: GW 5.9.0-
> rc5-test+ #577
>  Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01
> v03.03 07/14/2016
>  Call Trace:
>   dump_stack+0x8d/0xc0
>   create_object.cold+0x3b/0x60
>   slab_post_alloc_hook+0x57/0x510
>   ? tracing_map_init+0x178/0x340
>   __kmalloc+0x1b1/0x390
>   tracing_map_init+0x178/0x340
>   event_hist_trigger_func+0x523/0xa40
>   trigger_process_regex+0xc5/0x110
>   event_trigger_write+0x71/0xd0
>   vfs_write+0xca/0x210
>   ksys_write+0x70/0xf0
>   do_syscall_64+0x33/0x40
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
>  RIP: 0033:0x7fef0a63a487
>  Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f
> 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48>
> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
>  RSP: 002b:7fff76f18398 EFLAGS: 0246 ORIG_RAX:
> 0001
>  RAX: ffda RBX: 0039 RCX: 7fef0a63a487
>  RDX: 0039 RSI: 55eb3b26d690 RDI: 0001
>  RBP: 55eb3b26d690 R08: 000a R09: 0038
>  R10: 55eb3b2cdb80 R11: 0246 R12: 0039
>  R13: 7fef0a70b500 R14: 0039 R15: 7fef0a70b700
>  kmemleak: Kernel memory leak detector disabled
>  kmemleak: Object 0x8c196fa2afe0 (size 8):
>  kmemleak:   comm "ftracetest", pid 6866, jiffies 4295082531
>  kmemleak:   min_count = 1
>  kmemleak:   count = 0
>  kmemleak:   flags = 0x1
>  kmemleak:   checksum = 0
>  kmemleak:   backtrace:
>   __kmalloc+0x1b1/0x390
>   tracing_map_init+0x1be/0x340
>   event_hist_trigger_func+0x523/0xa40
>   trigger_process_regex+0xc5/0x110
>   event_trigger_write+0x71/0xd0
>   vfs_write+0xca/0x210
>   ksys_write+0x70/0xf0
>   do_syscall_64+0x33/0x40
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> The cause came down to a use of strcat() that was adding an string
> that was
> shorten, but the strcat() did not take that into account.
> 
> strcat() is extremely dangerous as it does not care how big the
> buffer is.
> Replace it with seq_buf operations that prevent the buffer from being
> overwritten if what is being written is bigger than the buffer.
> 
> Fixes: 10819e25799a ("tracing: Handle synthetic event array field
> type checking correctly")
> Signed-off-by: Steven Rostedt (VMware) 
> ---
> 
> Changes since v1, Dan's scripts detected a double free.
>Just needed to move, the freeing after the error branch
>to freeing.
> 

Looks fine to me, thanks for fixing this.

Reviewed-by: Tom Zanussi 
Tested-by: Tom Zanussi 



>  kernel/trace/trace_events_synth.c | 36 +++
> 
>  1 file changed, 22 insertions(+), 14 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_synth.c
> b/kernel/trace/trace_events_synth.c
> index 3212e2c653b3..84b7cab55291 100644
> --- a/kernel/trace/trace_events_synth.c
> +++ b/kernel/trace/trace_events_synth.c
> @@ -585,6 +585,7 @@ static struct synth_field *parse_synth_field(int
> argc, const char **argv,
>   struct synth_field *field;
>   const char *prefix = NULL, *field_type = argv[0], *field_name,
> *array;
>   int len, ret = 0;
> + struct seq_buf s;
>   ssize_t size;
>  
>   if (field_type[0] == ';')
> @@ -630,13 +631,9 @@ static struct synth_field *parse_synth_field(int
> argc, const char **argv,
>   field_type++;
>   len = strlen(field_type) + 1;
>  
> -if (array) {
> -int l = strlen(array);
> + if (array)
> + len += strlen(array);
>  
> -if (l && array[l - 1] == ';')
> -l--;
> -len += l;
> -}
>   if (prefix)
>   len += strlen(prefix);
>  
> @@ -645,14 +642,18 @@ static struct synth_field
> *parse_synth_field(int argc, const char **argv,
>   ret = -ENOMEM;
>   goto free;
>   }
> + seq_buf_init(, field->type, len);
>   if (prefix)
> - strcat(field->type, prefix);
> - strcat(field->type, field_type);
> + seq_buf_puts(, prefix);
> + seq_buf_puts(, field_type);
>   if (array) {
> - strcat(field->type, array);
> -   

[PATCH v3 1/5] tracing/dynevent: Delegate parsing to create function

2020-10-26 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

This requires changes to the kprobe/uprobe/synthetic event handling,
which are also included here.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 23 ++--
 kernel/trace/trace.h  |  3 +-
 kernel/trace/trace_dynevent.c | 35 +++---
 kernel/trace/trace_dynevent.h |  4 +--
 kernel/trace/trace_events_synth.c | 60 +++
 kernel/trace/trace_kprobe.c   | 33 +
 kernel/trace/trace_probe.c| 17 +
 kernel/trace/trace_probe.h|  1 +
 kernel/trace/trace_uprobe.c   | 17 +
 9 files changed, 120 insertions(+), 73 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 63c97012ed39..277d97220971 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9367,30 +9367,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9438,7 +9419,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 34e0c4d5a6e7..02d7c487a30b 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1982,10 +1982,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 5fa49cfd2bb6..af83bc5447fe 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
retur

[PATCH v3 5/5] selftests/ftrace: Update synthetic event syntax errors

2020-10-26 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 35 ++-
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..955e3ceea44b 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,38 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v3 4/5] selftests/ftrace: Add synthetic event field separators

2020-10-26 Thread Tom Zanussi
These tests omit field separators from the synthetic event definitions
so don't follow the syntax ' field[;field] ...' required
for synthetic events.

Fixes: f06eec4d0f2c (selftests: ftrace: Add inter-event hist triggers testcases)
Signed-off-by: Tom Zanussi 
---
 .../trigger/inter-event/trigger-inter-event-combined-hist.tc  | 4 ++--
 .../test.d/trigger/inter-event/trigger-onmatch-action-hist.tc | 2 +-
 .../trigger/inter-event/trigger-onmatch-onmax-action-hist.tc  | 2 +-
 .../test.d/trigger/inter-event/trigger-trace-action-hist.tc   | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
index 9098f1e7433f..29a03ed3377d 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'waking_latency  u64 lat pid_t pid' > synthetic_events
+echo 'waking_latency  u64 lat; pid_t pid' > synthetic_events
 if [ ! -d events/synthetic/waking_latency ]; then
 fail "Failed to create waking_latency synthetic event"
 fi
@@ -21,7 +21,7 @@ echo 'hist:keys=pid:ts0=common_timestamp.usecs if 
comm=="ping"' > events/sched/s
 echo 
'hist:keys=pid:waking_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).waking_latency($waking_lat,pid)
 if comm=="ping"' > events/sched/sched_wakeup/trigger
 echo 'hist:keys=pid,lat:sort=pid,lat' > events/synthetic/waking_latency/trigger
 
-echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events
+echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events
 echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> 
events/sched/sched_wakeup/trigger
 echo 
'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid)
 if next_comm=="ping"' > events/sched/sched_switch/trigger
 
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
index 20e39471052e..5015d0d74de8 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
index f4b03ab7c287..ac7ba2bbce47 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
index c126d2350a6d..76a213f197a0 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
-- 
2.17.1



[PATCH v3 3/5] tracing: Update synth command errors

2020-10-26 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 68 +++
 1 file changed, 59 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 0d2fe4b6bd94..fdf0e85c0b8a 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -648,6 +649,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
 
size = synth_field_size(field->type);
if (size < 0) {
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1169,7 +1174,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
mutex_lock(_mutex);
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto out;
}
@@ -1222,7 +1227,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1360,6 +1365,37 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int check_command(const char *raw_command)
+{
+   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
+   int argc, ret = 0;
+
+   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   name_and_field = strsep(, ";");
+   if (!name_and_field) {
+   ret = -EINVAL;
+   goto free;
+   }
+
+   argv = argv_split(GFP_KERNEL, name_and_field, );
+   if (!argv) {
+   ret = -ENOMEM;
+   goto free;
+   }
+
+   if (argc < 3)
+   ret = -EINVAL;
+free:
+   kfree(saved_cmd);
+   if (argv)
+   argv_free(argv);
+
+   return ret;
+}
+
 static int create_or_delete_synth_event(const char *raw_command)
 {
char *name = NULL, *fields, *p;
@@ -1372,12 +1408,16 @@ static int create_or_delete_synth_event(const char 
*raw_command)
last_cmd_set(raw_command);
 
ret = check_command(raw_command);
-   if (ret)
+   if (ret) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return ret;
+   }
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
name = kmemdup_nul(raw_command, p - raw_command, GFP_KERNEL);
fields = skip_spaces(p);
@@ -1948,8 +1988,10 @@ static int create_synth_event(const char *raw_command)
last_cmd_set(raw_command);
 
p = strpbrk(raw_command, " \t");
-   if (!p)
+   if (!p) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
return -EINVAL;
+   }
 
fields = skip_spaces(p);
 
@@ -1962,13 +2004,21 @@ static int create_synth_event(const char *raw_command)
/* This interface accepts group name prefix */
if (strchr(name, '/')) {
len = str_h

[PATCH v3 2/5] tracing: Rework synthetic event command parsing

2020-10-26 Thread Tom Zanussi
Now that command parsing has been delegated to the create functions
and we're no longer constrained by argv_split(), we can modify the
synthetic event command parser to better match the higher-level
structure of the synthetic event commands, which is basically an event
name followed by a set of semicolon-separated fields.

Since we're also now passed the raw command, we can also save it
directly and can get rid of save_cmdstr().

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 181 ++
 1 file changed, 83 insertions(+), 98 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 271811fbf8fb..0d2fe4b6bd94 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -579,8 +579,7 @@ static void free_synth_field(struct synth_field *field)
kfree(field);
 }
 
-static struct synth_field *parse_synth_field(int argc, const char **argv,
-int *consumed)
+static struct synth_field *parse_synth_field(int argc, char **argv)
 {
struct synth_field *field;
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
@@ -588,9 +587,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
struct seq_buf s;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -599,10 +595,12 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
-   *consumed = 3;
-   } else {
+   } else
field_name = argv[1];
-   *consumed = 2;
+
+   if (!field_name) {
+   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
+   return ERR_PTR(-EINVAL);
}
 
field = kzalloc(sizeof(*field), GFP_KERNEL);
@@ -613,8 +611,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name) {
@@ -627,8 +623,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
if (array)
@@ -646,18 +640,14 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
seq_buf_puts(, prefix);
seq_buf_puts(, field_type);
-   if (array) {
+   if (array)
seq_buf_puts(, array);
-   if (s.buffer[s.len - 1] == ';')
-   s.len--;
-   }
if (WARN_ON_ONCE(!seq_buf_buffer_left()))
goto free;
s.buffer[s.len] = '\0';
 
size = synth_field_size(field->type);
if (size < 0) {
-   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1162,46 +1152,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
-static int __create_synth_event(int argc, const char *name, const char **argv)
+static int __create_synth_event(const char *name, const char *raw_fields)
 {
+   int i, argc, n_fields = 0, ret = 0;
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
+   char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
struct synth_event *event = NULL;
-   int i, consumed = 0

[PATCH v3 0/5] tracing: More synthetic event error fixes

2020-10-26 Thread Tom Zanussi
Hi,

This is v3 of the sythetic event error fix patchset.  As suggested by
Masami, I split the 'tracing/dynevent: Delegate parsing to create
function' into two - one containing just the interface changes and the
second with the synthetic event parsing changes the first enabled.

I also replaced a couple argv_split() with strpbrk() as suggested by
Masami, along with removing the no-longer-used consume lines and
another line that tested ECANCELED that was no longer needed.

Also, removed a test case that was no longer needed since the commands
are now stripped of whitespace first.

Thanks, Masami, for the suggestions.

Tom

v2 text:

This is v2 of the previous sythetic event error fix patchset.

This version drops the original ([PATCH 1/4] tracing: Make
trace_*_run_command() more flexible) and (tracing: Use new
trace_run_command() options) patches and replaces them with Masami's
patch (tracing/dynevent: Delegate parsing to create function) [1].
The new version adds in all the synthetic event changes needed to
compile and use the new interface.

A new patch was also added (selftests/ftrace: Add synthetic event
field separators) that fixes more invalid synthetic event syntax I
found while testing.

I also added some more new checks to the synthetic event sytax error
testcase.

As before, I didn't see any problems running the entire ftrace
testsuite or the test modules that also use the things that were
touched here.

[1] 
https://lore.kernel.org/lkml/20201019001504.70dc3ec608277ed22060d...@kernel.org/

Thanks,

Tom


v1 text:

Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit b37b1f9a6311469937aae1c039db00e5b75b9fcb:

  tracing, synthetic events: Replace buggy strcat() with seq_buf operations 
(2020-10-23 19:05:12 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v3

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (4):
  tracing: Rework synthetic event command parsing
  tracing: Update synth command errors
  selftests/ftrace: Add synthetic event field separators
  selftests/ftrace: Update synthetic event syntax errors

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 ++-
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 235 +++---
 kernel/trace/trace_kprobe.c   |  33 +--
 kernel/trace/trace_probe.c|  17 ++
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 +-
 .../trigger-inter-event-combined-hist.tc  |   4 +-
 .../trigger-onmatch-action-hist.tc|   2 +-
 .../trigger-onmatch-onmax-action-hist.tc  |   2 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  35 ++-
 .../inter-event/trigger-trace-action-hist.tc  |   2 +-
 14 files changed, 257 insertions(+), 156 deletions(-)

-- 
2.17.1



[PATCH v2 2/4] tracing: Update synth command errors

2020-10-23 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also add INVALID_CMD and INVALID_DYN_CMD to
catch and display the correct form for badly-formed commands, which
can also be used in place of CMD_INCOMPLETE, which is removed, and
remove CMD_TOO_LONG, since it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 66 +++
 1 file changed, 58 insertions(+), 8 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 90c1790ed1d6..1aa808791f56 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -23,13 +23,14 @@
 #undef ERRORS
 #define ERRORS \
C(BAD_NAME, "Illegal name"),\
-   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(INVALID_CMD,  "Command must be of the form:  
field[;field] ..."),\
+   C(INVALID_DYN_CMD,  "Command must be of the form: s or 
-:[synthetic/] field[;field] ..."),\
C(EVENT_EXISTS, "Event already exists"),\
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -643,6 +644,10 @@ static struct synth_field *parse_synth_field(int argc, 
char **argv)
 
size = synth_field_size(field->type);
if (size < 0) {
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1158,7 +1163,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
mutex_lock(_mutex);
 
if (name[0] == '\0') {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto out;
}
@@ -1212,7 +1217,7 @@ static int __create_synth_event(const char *name, const 
char *raw_fields)
}
 
if (n_fields == 0) {
-   synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
ret = -EINVAL;
goto err;
}
@@ -1350,13 +1355,42 @@ int synth_event_delete(const char *event_name)
 }
 EXPORT_SYMBOL_GPL(synth_event_delete);
 
+static int check_command(const char *raw_command)
+{
+   char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
+   int argc, ret = 0;
+
+   cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   name_and_field = strsep(, ";");
+   if (!name_and_field) {
+   ret = -EINVAL;
+   goto free;
+   }
+
+   argv = argv_split(GFP_KERNEL, name_and_field, );
+   if (!argv) {
+   ret = -ENOMEM;
+   goto free;
+   }
+
+   if (argc < 3)
+   ret = -EINVAL;
+free:
+   kfree(saved_cmd);
+   if (argv)
+   argv_free(argv);
+
+   return ret;
+}
+
 static int create_or_delete_synth_event(const char *raw_command)
 {
char **argv, *name = NULL, *fields;
int argc = 0, ret = 0;
 
-   last_cmd_set(raw_command);
-
argv = argv_split(GFP_KERNEL, raw_command, );
if (!argv)
return -ENOMEM;
@@ -1364,9 +1398,16 @@ static int create_or_delete_synth_event(const char 
*raw_command)
if (!argc)
goto free;
 
+   last_cmd_set(raw_command);
+
+   ret = check_command(raw_command);
+   if (ret) {
+   synth_err(SYNTH_ERR_INVALID_CMD, 0);
+   goto free;
+   }
+
name = argv[0];
 
-   /* trace_run_command() ensures argc != 0 */
if (name[0] == '!') {
ret = synth_event_delete(name + 1);
goto free;
@@ -1951,12 +1992,21 @@ static int create_synth_event(const char *raw_command)
if (strchr(name, '/')) {
len = str_has_prefix(name, SYNTH_SYSTEM "/");
if (len == 0) {
+   synth_err(SYNTH_ERR_INVALID_DYN_CMD, 0);
ret = -EINVAL;
goto free;
}
name += len;
}
 

[PATCH v2 3/4] selftests/ftrace: Add synthetic event field separators

2020-10-23 Thread Tom Zanussi
These tests omit field separators from the synthetic event definitions
so don't follow the syntax ' field[;field] ...' required
for synthetic events.

Fixes: f06eec4d0f2c (selftests: ftrace: Add inter-event hist triggers testcases)
Signed-off-by: Tom Zanussi 
---
 .../trigger/inter-event/trigger-inter-event-combined-hist.tc  | 4 ++--
 .../test.d/trigger/inter-event/trigger-onmatch-action-hist.tc | 2 +-
 .../trigger/inter-event/trigger-onmatch-onmax-action-hist.tc  | 2 +-
 .../test.d/trigger/inter-event/trigger-trace-action-hist.tc   | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
index 9098f1e7433f..29a03ed3377d 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'waking_latency  u64 lat pid_t pid' > synthetic_events
+echo 'waking_latency  u64 lat; pid_t pid' > synthetic_events
 if [ ! -d events/synthetic/waking_latency ]; then
 fail "Failed to create waking_latency synthetic event"
 fi
@@ -21,7 +21,7 @@ echo 'hist:keys=pid:ts0=common_timestamp.usecs if 
comm=="ping"' > events/sched/s
 echo 
'hist:keys=pid:waking_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).waking_latency($waking_lat,pid)
 if comm=="ping"' > events/sched/sched_wakeup/trigger
 echo 'hist:keys=pid,lat:sort=pid,lat' > events/synthetic/waking_latency/trigger
 
-echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events
+echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events
 echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> 
events/sched/sched_wakeup/trigger
 echo 
'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid)
 if next_comm=="ping"' > events/sched/sched_switch/trigger
 
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
index 20e39471052e..5015d0d74de8 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
index f4b03ab7c287..ac7ba2bbce47 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
index c126d2350a6d..76a213f197a0 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc
@@ -10,7 +10,7 @@ fail() { #msg
 
 echo "Test create synthetic event"
 
-echo 'wakeup_latency  u64 lat pid_t pid char comm[16]' > synthetic_events
+echo 'wakeup_latency  u64 lat; pid_t pid; char comm[16]' > synthetic_events
 if [ ! -d events/synthetic/wakeup_latency ]; then
 fail "Failed to create wakeup_latency synthetic event"
 fi
-- 
2.17.1



[PATCH v2 4/4] selftests/ftrace: Update synthetic event syntax errors

2020-10-23 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 36 ++-
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..9b2f47f7eb07 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,39 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
+check_dyn_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events'
+}
+
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
-check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent ^unsigned arg'# INCOMPLETE_TYPE
+
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+
+check_error 'myevent char str;^[]' # INVALID_FIELD
+check_error 'myevent char str; ^int'   # INVALID_FIELD
+
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
+check_error '  myevent char ^str[' # INVALID_ARRAY_SPEC
+
+check_error '^mye;vent char str[]' # INVALID_CMD
+check_error '^myevent ; char str[]'# INVALID_CMD
+check_error '^myevent; char str[]' # INVALID_CMD
+check_error '^myevent ;char str[]' # INVALID_CMD
+check_error '^; char str[]'# INVALID_CMD
+check_error '^;myevent char str[]' # INVALID_CMD
+check_error '^myevent' # INVALID_CMD
+
+check_dyn_error '^s:junk/myevent char str['# INVALID_DYN_CMD
 
 exit 0
-- 
2.17.1



[PATCH v2 0/4] tracing: More synthetic event error fixes

2020-10-23 Thread Tom Zanussi
This is v2 of the previous sythetic event error fix patchset.

This version drops the original ([PATCH 1/4] tracing: Make
trace_*_run_command() more flexible) and (tracing: Use new
trace_run_command() options) patches and replaces them with Masami's
patch (tracing/dynevent: Delegate parsing to create function) [1].
The new version adds in all the synthetic event changes needed to
compile and use the new interface.

A new patch was also added (selftests/ftrace: Add synthetic event
field separators) that fixes more invalid synthetic event syntax I
found while testing.

I also added some more new checks to the synthetic event sytax error
testcase.

As before, I didn't see any problems running the entire ftrace
testsuite or the test modules that also use the things that were
touched here.

[1] 
https://lore.kernel.org/lkml/20201019001504.70dc3ec608277ed22060d...@kernel.org/

Thanks,

Tom


v1 text:

Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit ce66f6136460a51acfc32de4481fe8fd69dfd50b:

  tracing: Remove __init from __trace_early_add_new_event() (2020-10-16 
09:43:36 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v2

Masami Hiramatsu (1):
  tracing/dynevent: Delegate parsing to create function

Tom Zanussi (3):
  tracing: Update synth command errors
  selftests/ftrace: Add synthetic event field separators
  selftests/ftrace: Update synthetic event syntax errors

 kernel/trace/trace.c  |  23 +-
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 ++-
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 246 +++---
 kernel/trace/trace_kprobe.c   |  33 +--
 kernel/trace/trace_probe.c|  17 ++
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 +-
 .../trigger-inter-event-combined-hist.tc  |   4 +-
 .../trigger-onmatch-action-hist.tc|   2 +-
 .../trigger-onmatch-onmax-action-hist.tc  |   2 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  36 ++-
 .../inter-event/trigger-trace-action-hist.tc  |   2 +-
 14 files changed, 262 insertions(+), 163 deletions(-)

-- 
2.17.1



[PATCH v2 1/4] tracing/dynevent: Delegate parsing to create function

2020-10-23 Thread Tom Zanussi
From: Masami Hiramatsu 

Delegate command parsing to each create function so that the
command syntax can be customized.

Signed-off-by: Masami Hiramatsu 
[ zanu...@kernel.org: added synthetic event modifications ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  |  23 +---
 kernel/trace/trace.h  |   3 +-
 kernel/trace/trace_dynevent.c |  35 +++---
 kernel/trace/trace_dynevent.h |   4 +-
 kernel/trace/trace_events_synth.c | 186 --
 kernel/trace/trace_kprobe.c   |  33 +++---
 kernel/trace/trace_probe.c|  17 +++
 kernel/trace/trace_probe.h|   1 +
 kernel/trace/trace_uprobe.c   |  17 ++-
 9 files changed, 174 insertions(+), 145 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 63c97012ed39..277d97220971 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9367,30 +9367,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
-{
-   char **argv;
-   int argc, ret;
-
-   argc = 0;
-   ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
-   return -ENOMEM;
-
-   if (argc)
-   ret = createfn(argc, argv);
-
-   argv_free(argv);
-
-   return ret;
-}
-
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(const char *))
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9438,7 +9419,7 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = createfn(buf);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 34e0c4d5a6e7..02d7c487a30b 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1982,10 +1982,9 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NAME_LEN 64
 
-extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
 extern ssize_t trace_parse_run_command(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos,
-   int (*createfn)(int, char**));
+   int (*createfn)(const char *));
 
 extern unsigned int err_pos(char *cmd, const char *str);
 extern void tracing_log_err(struct trace_array *tr,
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 5fa49cfd2bb6..af83bc5447fe 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -31,23 +31,31 @@ int dyn_event_register(struct dyn_event_operations *ops)
return 0;
 }
 
-int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)
+int dyn_event_release(const char *raw_command, struct dyn_event_operations 
*type)
 {
struct dyn_event *pos, *n;
char *system = NULL, *event, *p;
-   int ret = -ENOENT;
+   int argc, ret = -ENOENT;
+   char **argv;
+
+   argv = argv_split(GFP_KERNEL, raw_command, );
+   if (!argv)
+   return -ENOMEM;
 
if (argv[0][0] == '-') {
-   if (argv[0][1] != ':')
-   return -EINVAL;
+   if (argv[0][1] != ':') {
+   ret = -EINVAL;
+   goto out;
+   }
event = [0][2];
} else {
event = strchr(argv[0], ':');
-   if (!event)
-   return -EINVAL;
+   if (!event) {
+   ret = -EINVAL;
+   goto out;
+   }
event++;
}
-   argc--; argv++;
 
p = strchr(event, '/');
if (p) {
@@ -63,7 +71,7 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
if (type && type != pos->ops)
continue;
if (!pos->ops->match(system, event,
-   argc, (const char **)argv, pos))
+   argc - 1, (const char **)argv + 1, pos))
continue;
 
ret = pos->ops->free(pos);
@@ -71,21 +79,22 @@ int dyn_event_release(int argc, char **argv, struct 
dyn_event_operations *type)
break;
}
mutex_unlock(_mutex);
-
+out:
+   argv_free(argv);
return ret;
 }
 
-static int create_dyn_event(int argc, char **argv)
+static int create_dyn_event(const char *raw_command)
 {
struct dy

Re: [PATCH 1/4] tracing: Make trace_*_run_command() more flexible

2020-10-19 Thread Tom Zanussi
Hi Masami,

On Mon, 2020-10-19 at 00:15 +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> On Sun, 18 Oct 2020 23:20:11 +0900
> Masami Hiramatsu  wrote:
> 
> > Hi Tom,
> > 
> > On Fri, 16 Oct 2020 16:48:22 -0500
> > Tom Zanussi  wrote:
> > 
> > > trace_run_command() and therefore functions that use it, such as
> > > trace_parse_run_command(), uses argv_split() to split the command
> > > into
> > > an array of args then passed to the callback to handle.
> > > 
> > > This works fine for most commands but some commands would like to
> > > allow the user to use and additional separator to visually group
> > > items
> > > in the command.  One example would be synthetic event commands,
> > > which
> > > use semicolons to group fields:
> > > 
> > >   echo 'event_name int a; char b[]; u64 lat' >> synthetic_events
> > > 
> > > What gets passed as an args array to the command for a command
> > > like
> > > this include tokens that have semicolons included with the token,
> > > which the callback then needs to strip out, since argv_split()
> > > only
> > > looks at whitespace as a separator.
> > > 
> > > It would be nicer to just have trace_run_command() strip out the
> > > semicolons at its level rather than passing that task onto the
> > > callback. To accomplish that, this change adds an
> > > 'additional_sep'
> > > arg to a new __trace_run_command() function that allows a caller
> > > to
> > > pass an additional separator char that if non-zero simply
> > > replaces
> > > that character with whitespace before splitting the command into
> > > args.
> > > The original trace_run_command() remains as-is in this regard,
> > > simply
> > > calling __trace_run_command() with 0 for the separator, while
> > > making a
> > > new trace_run_command_add_sep() version that can be used to pass
> > > in a
> > > separator.
> > 
> > No, I don't like to tweak trace_run_command() that way, I'm OK to
> > delegate the argv_split() totally to the callback function (pass
> > the raw command string to the callback), OR __create_synth_event()
> > concatinate the fields argv and parse it by itself (I think the
> > latter is better and simpler).
> > 
> > The ";" separator is not an additinal separator but that is higher
> > level separator for synthetic event. Suppose that you get the
> > following input;
> >  "myevent int c ; char b"
> >  "myevent int;c;char;b;"
> > These should not be same for the synthetic events. The fields must
> > be
> > splitted by ';' at first, and then each field should be parsed.
> > 
> > So, I recommend you not to pass the additional separator to the
> > generic function, but (since it is only for synthetic event) to
> > reconstruct the raw command from argv, and parse it again with
> > ";" inside synthetic event parser. Then each fields parser can
> > check that is a wrong input or not.
> > 
> > It will be something like
> > 
> > __create_synth_event(argc, argv)
> > {
> > 
> > argc--; argv++;
> > 
> > raw_fields = concat_argv(argc, argv);// you can assume argv is
> > generated by argv_split().
> > vfields = split_fields(raw_fields, );// similar to
> > argv_split()
> > for (i = 0; i < nfields; i++)
> > parse_synth_field(vfields[i]);
> > }
> > 
> > Then, you don't need to change the generic functions, and also
> > you will get the correct parser routines.
> 
> If you think the split->concat->split process is redundant, I think
> we
> can remove trace_run_command() and just pass a raw command string to
> each
> event command parser as I said above.
> 
> In this way, each event create function can parse the command by
> themselves.
> So you can parse the command as you like.
> 
> Here is the patch which modifies trace-{k,u}probe and trace-dynevent
> side, but not changing synthetic event side yet. Will this help you?
> 

Yeah, it was probably a mistake to try to shoehorn synthetic events
into the unmodified trace_run_command() in the first place.

This should work for me - I'll build on it.  Thanks for supplying it!

Tom


> From 5aed03a8df0926d92f6585b3932fdc96324cb82d Mon Sep 17 00:00:00
> 2001
> From: Masami Hiramatsu 
> Date: Sat, 17 Oct 2020 23:11:29 +0900
> Subject: [PATCH] tracing/dynevent: Delegate parsing to create
> function
> 
> Delegate command pa

[PATCH 1/4] tracing: Make trace_*_run_command() more flexible

2020-10-16 Thread Tom Zanussi
trace_run_command() and therefore functions that use it, such as
trace_parse_run_command(), uses argv_split() to split the command into
an array of args then passed to the callback to handle.

This works fine for most commands but some commands would like to
allow the user to use and additional separator to visually group items
in the command.  One example would be synthetic event commands, which
use semicolons to group fields:

  echo 'event_name int a; char b[]; u64 lat' >> synthetic_events

What gets passed as an args array to the command for a command like
this include tokens that have semicolons included with the token,
which the callback then needs to strip out, since argv_split() only
looks at whitespace as a separator.

It would be nicer to just have trace_run_command() strip out the
semicolons at its level rather than passing that task onto the
callback.  To accomplish that, this change adds an 'additional_sep'
arg to a new __trace_run_command() function that allows a caller to
pass an additional separator char that if non-zero simply replaces
that character with whitespace before splitting the command into args.
The original trace_run_command() remains as-is in this regard, simply
calling __trace_run_command() with 0 for the separator, while making a
new trace_run_command_add_sep() version that can be used to pass in a
separator.

The other change here simply has __trace_run_command() make a copy of
the original command to work on, while leaving the original command
string untouched.  This untouched string is now passed into the
callback as well - this allows the callback to use the original string
for error processing and caret placement rather than forcing the
callback to recreate the original string from the args, which isn't
always possible.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.c  | 41 +--
 kernel/trace/trace.h  | 12 ++---
 kernel/trace/trace_dynevent.c |  4 +--
 kernel/trace/trace_events_synth.c |  5 ++--
 kernel/trace/trace_kprobe.c   |  5 ++--
 kernel/trace/trace_uprobe.c   |  5 ++--
 6 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 63c97012ed39..afa526414b25 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9367,30 +9367,56 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 }
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
-int trace_run_command(const char *buf, int (*createfn)(int, char **))
+static int __trace_run_command(const char *buf,
+  int (*createfn)(int, char **, const char *),
+  char additional_sep)
 {
-   char **argv;
int argc, ret;
+   char **argv, *cmd;
+
+   cmd = kstrdup(buf, GFP_KERNEL);
+   if (!cmd)
+   return -ENOMEM;
+
+   if (additional_sep)
+   strreplace(cmd, additional_sep, ' ');
 
argc = 0;
ret = 0;
-   argv = argv_split(GFP_KERNEL, buf, );
-   if (!argv)
+   argv = argv_split(GFP_KERNEL, cmd, );
+   if (!argv) {
+   kfree(cmd);
return -ENOMEM;
+   }
 
if (argc)
-   ret = createfn(argc, argv);
+   ret = createfn(argc, argv, buf);
 
argv_free(argv);
+   kfree(cmd);
 
return ret;
 }
 
+int trace_run_command(const char *buf, int (*createfn)(int, char **,
+  const char *))
+{
+   return __trace_run_command(buf, createfn, 0);
+}
+
+int trace_run_command_add_sep(const char *buf,
+ int (*createfn)(int, char **, const char *),
+ char additional_sep)
+{
+   return __trace_run_command(buf, createfn, additional_sep);
+}
+
 #define WRITE_BUFSIZE  4096
 
 ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos,
-   int (*createfn)(int, char **))
+   int (*createfn)(int, char **, const char *),
+   char additional_sep)
 {
char *kbuf, *buf, *tmp;
int ret = 0;
@@ -9438,7 +9464,8 @@ ssize_t trace_parse_run_command(struct file *file, const 
char __user *buffer,
if (tmp)
*tmp = '\0';
 
-   ret = trace_run_command(buf, createfn);
+   ret = trace_run_command_add_sep(buf, createfn,
+   additional_sep);
if (ret)
goto out;
buf += size;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 34e0c4d5a6e7..ae6e0c2ec028 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1982,10 +1982,16 @@ extern int tracing_set_cpumask(struct trace_array *tr,
 
 #define MAX_EVENT_NA

[PATCH 4/4] selftests/ftrace: Update synthetic event syntax errors

2020-10-16 Thread Tom Zanussi
Some of the synthetic event errors and positions have changed in the
code - update those and add several more tests.

Also add a runtime check to ensure that the kernel supports dynamic
strings in synthetic events, which these tests require.

Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic
event syntax errors)

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc| 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
index ada594fe16cb..ebdc7c0a75a1 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -1,19 +1,22 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log
+# requires: synthetic_events error_log "char name[]' >> 
synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
 ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
 }
 
 check_error 'myevent ^chr arg' # INVALID_TYPE
-check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
-check_error 'myevent char ^str]; int v'# INVALID_NAME
-check_error 'myevent char ^str;[]' # INVALID_NAME
-check_error 'myevent ^char str[; int v'# INVALID_TYPE
-check_error '^mye;vent char str[]' # BAD_NAME
-check_error 'myevent char str[]; ^int' # INVALID_FIELD
+check_error 'mye;^vent char str[]' # INVALID_TYPE
+check_error 'myevent char ^str]; int v'# BAD_NAME
+check_error '^mye-vent char str[]' # BAD_NAME
+check_error 'myevent char ^st-r[]' # BAD_NAME
+check_error 'myevent char str;^[]' # INCOMPLETE_CMD
+check_error 'myevent char str[]; ^int' # INCOMPLETE_CMD
 check_error '^myevent' # INCOMPLETE_CMD
+check_error 'myevent char ^str[; int v'# INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC
+check_error 'myevent char ^str[257]'   # INVALID_ARRAY_SPEC
 
 exit 0
-- 
2.17.1



[PATCH 2/4] tracing: Use new trace_run_command() options

2020-10-16 Thread Tom Zanussi
Now that the synthetic event command passes in ';' as an additional
separator to trace_parse_run_command(), all of the parsing related to
semicolon can be removed.

Additionally, the since create_or_delete_synth_event() now receives
the raw command string, it doesn't need save_cmdstr(), which can also
be removed.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 65 ---
 1 file changed, 8 insertions(+), 57 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index e6659bb9a500..2333025ef31e 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -48,7 +48,7 @@ static int errpos(const char *str)
return err_pos(last_cmd, str);
 }
 
-static void last_cmd_set(char *str)
+static void last_cmd_set(const char *str)
 {
if (!str)
return;
@@ -587,9 +587,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
int len, ret = 0;
ssize_t size;
 
-   if (field_type[0] == ';')
-   field_type++;
-
if (!strcmp(field_type, "unsigned")) {
if (argc < 3) {
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
@@ -612,8 +609,6 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
array = strchr(field_name, '[');
if (array)
len -= strlen(array);
-   else if (field_name[len - 1] == ';')
-   len--;
 
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
if (!field->name) {
@@ -626,17 +621,11 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
 
-   if (field_type[0] == ';')
-   field_type++;
len = strlen(field_type) + 1;
 
-if (array) {
-int l = strlen(array);
+if (array)
+len += strlen(array);
 
-if (l && array[l - 1] == ';')
-l--;
-len += l;
-}
if (prefix)
len += strlen(prefix);
 
@@ -648,11 +637,8 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (prefix)
strcat(field->type, prefix);
strcat(field->type, field_type);
-   if (array) {
+   if (array)
strcat(field->type, array);
-   if (field->type[len - 1] == ';')
-   field->type[len - 1] = '\0';
-   }
 
size = synth_field_size(field->type);
if (size < 0) {
@@ -1155,47 +1141,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
-static int save_cmdstr(int argc, const char *name, const char **argv)
-{
-   struct seq_buf s;
-   char *buf;
-   int i;
-
-   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-
-   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
-
-   seq_buf_puts(, name);
-
-   for (i = 0; i < argc; i++) {
-   seq_buf_putc(, ' ');
-   seq_buf_puts(, argv[i]);
-   }
-
-   if (!seq_buf_buffer_left()) {
-   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
-   kfree(buf);
-   return -EINVAL;
-   }
-   buf[s.len] = 0;
-   last_cmd_set(buf);
-
-   kfree(buf);
-   return 0;
-}
-
 static int __create_synth_event(int argc, const char *name, const char **argv)
 {
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
struct synth_event *event = NULL;
int i, consumed = 0, n_fields = 0, ret = 0;
 
-   ret = save_cmdstr(argc, name, argv);
-   if (ret)
-   return ret;
-
/*
 * Argument syntax:
 *  - Add synthetic event:  field[;field] ...
@@ -1224,8 +1175,6 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
}
 
for (i = 0; i < argc - 1; i++) {
-   if (strcmp(argv[i], ";") == 0)
-   continue;
if (n_fields == SYNTH_FIELDS_MAX) {
synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
ret = -EINVAL;
@@ -1241,7 +1190,7 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
i += consumed - 1;
}
 
-   if (i < argc && strcmp(argv[i], ";") != 0) {
+   if (i < argc) {
synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i]));
ret = -EINVAL;
goto err;
@@ -1384,6 +1333,8 @@ static int create_or_delete_synth_event(int argc, char 
**argv,
const char *name = argv[0];
int ret;
 
+   last_cmd_set(raw_cmd);
+
/* trace_run_command() ensures argc

[PATCH 3/4] tracing: Update synth command errors

2020-10-16 Thread Tom Zanussi
Since array types are handled differently, errors referencing them
also need to be handled differently.  Add and use a new
INVALID_ARRAY_SPEC error.  Also remove INVALID_FIELD since it can
better be handled using CMD_INCOMPLETE, and remove CMD_TOO_LONG, since
it's no longer used.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 2333025ef31e..f48964bdd66e 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -28,8 +28,7 @@
C(TOO_MANY_FIELDS,  "Too many fields"), \
C(INCOMPLETE_TYPE,  "Incomplete type"), \
C(INVALID_TYPE, "Invalid type"),\
-   C(INVALID_FIELD,"Invalid field"),   \
-   C(CMD_TOO_LONG, "Command too long"),
+   C(INVALID_ARRAY_SPEC,   "Invalid array specification"),
 
 #undef C
 #define C(a, b)SYNTH_ERR_##a
@@ -643,6 +642,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
size = synth_field_size(field->type);
if (size < 0) {
synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
+   if (array)
+   synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, 
errpos(field_name));
+   else
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -1191,7 +1194,7 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
}
 
if (i < argc) {
-   synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i]));
+   synth_err(SYNTH_ERR_CMD_INCOMPLETE, errpos(argv[i]));
ret = -EINVAL;
goto err;
}
-- 
2.17.1



[PATCH 0/4] tracing: More synthetic event error fixes

2020-10-16 Thread Tom Zanussi
Hi,

This patchset addresses the synthetic event error anomalies reported
by Masami in the last patchset [1].

It turns out that most of the problems boil down to clunky separator
parsing; adding a couple new abilities to trace_run_command() and then
adapting the existing users seemed to me the best way to fix these
things, and also gets rid of some code.

Also, to make things easier for error display, I changed these to
preserve the original command string and pass it through the callback
instead of rebuilding it for error display.

I added some new error strings and removed unused ones as well, and
added a bunch of new test cases to the synthetic parser error test
case.

I didn't see any problems running the entire ftrace testsuite or the
test modules that also use the things that were touched here.

Thanks,

Tom

[1] 
https://lore.kernel.org/lkml/20201014110636.139df7be275d40a23b523...@kernel.org/

The following changes since commit 6107742d15832011cd0396d821f3225b52551f1f:

  tracing: support "bool" type in synthetic trace events (2020-10-15 12:01:14 
-0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/synth-fixes-v1

Tom Zanussi (4):
  tracing: Make trace_*_run_command() more flexible
  tracing: Use new trace_run_command() options
  tracing: Update synth command errors
  selftests/ftrace: Update synthetic event syntax errors

 kernel/trace/trace.c  | 41 --
 kernel/trace/trace.h  | 12 ++-
 kernel/trace/trace_dynevent.c |  4 +-
 kernel/trace/trace_events_synth.c | 79 ---
 kernel/trace/trace_kprobe.c   |  5 +-
 kernel/trace/trace_uprobe.c   |  5 +-
 .../trigger-synthetic_event_syntax_errors.tc  | 17 ++--
 7 files changed, 78 insertions(+), 85 deletions(-)

-- 
2.17.1



Re: [PATCH v3 7/7] selftests/ftrace: Add test case for synthetic event syntax errors

2020-10-15 Thread Tom Zanussi
Hi Masami,

On Wed, 2020-10-14 at 11:06 +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> On Tue, 13 Oct 2020 09:17:58 -0500
> Tom Zanussi  wrote:
> 
> > Add a selftest that verifies that the syntax error messages and
> > caret
> > positions are correct for most of the possible synthetic event
> > syntax
> > error cases.
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> >  .../trigger-synthetic_event_syntax_errors.tc  | 19
> > +++
> >  1 file changed, 19 insertions(+)
> >  create mode 100644
> > tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-
> > synthetic_event_syntax_errors.tc
> > 
> > diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-
> > event/trigger-synthetic_event_syntax_errors.tc
> > b/tools/testing/selftests/ftrace/test.d/trigger/inter-
> > event/trigger-synthetic_event_syntax_errors.tc
> > new file mode 100644
> > index ..ada594fe16cb
> > --- /dev/null
> > +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-
> > event/trigger-synthetic_event_syntax_errors.tc
> > @@ -0,0 +1,19 @@
> > +#!/bin/sh
> > +# SPDX-License-Identifier: GPL-2.0
> > +# description: event trigger - test synthetic_events syntax parser
> > errors
> > +# requires: synthetic_events error_log
> 
> This also requires dynamic strings support. So, its "requires" line
> should be
> 
> # requires: synthetic_events error_log "char name[]' >>
> synthetic_events":README
> 

Yes, thanks for reminding me. ;-)

> > +
> > +check_error() { # command-with-error-pos-by-^
> > +ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
> > +}
> > +
> 
> BTW, some errors looks a bit odd.
> 
> > +check_error 'myevent ^chr arg' # INVALID_TYPE
> > +check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
> 
> I think there is a wrong "void" argument between ";", instead of
> invalid type.

Yes, you're right.  I think the solution overall is to just treat
semicolons as whitespace.

> 
> > +check_error 'myevent char ^str]; int v'# INVALID_NAME
> > +check_error 'myevent char ^str;[]' # INVALID_NAME
> 
> This is also not an invalid name but '[]' is an invalid type. 
> 
> > +check_error 'myevent ^char str[; int v'# INVALID_TYPE
> > +check_error '^mye;vent char str[]' # BAD_NAME
> > +check_error 'myevent char str[]; ^int' # INVALID_FIELD
> 
> Isn't it an incomplete command?

Yes, but also an invalid field.  I'll try to refine these errors a bit
and make these more consistent.

Tom

> 
> > +check_error '^myevent' #
> > INCOMPLETE_CMD
> > +
> > +exit 0
> 
> Thank you,
> 
> > -- 
> > 2.17.1
> > 
> 
> 



Re: [PATCH] tracing: Check return value of __create_val_fields() before using its result

2020-10-15 Thread Tom Zanussi
Hi Steve,

On Tue, 2020-10-13 at 15:48 -0400, Steven Rostedt wrote:
> From: "Steven Rostedt (VMware)" 
> 
> After having a typo for writing a histogram trigger.
> 
> Wrote:
>   echo 'hist:key=pid:ts=common_timestamp.usec' >
> events/sched/sched_waking/trigger
> 
> Instead of:
>   echo 'hist:key=pid:ts=common_timestamp.usecs' >
> events/sched/sched_waking/trigger
> 
> and the following crash happened:
> 
>  BUG: kernel NULL pointer dereference, address: 0008
>  #PF: supervisor read access in kernel mode
>  #PF: error_code(0x) - not-present page
>  PGD 0 P4D 0
>  Oops:  [#1] PREEMPT SMP PTI
>  CPU: 4 PID: 1641 Comm: sh Not tainted 5.9.0-rc5-test+ #549
>  Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01
> v03.03 07/14/2016
>  RIP: 0010:event_hist_trigger_func+0x70b/0x1ee0
>  Code: 24 08 89 d5 49 89 cc e9 8c 00 00 00 4c 89 f2 41 b9 00 10 00 00
> 4c 89 e1 44 89 ee 4c 89 ff e8 dc d3 ff ff 45 89 ea 4b 8b 14 d7 
> 42 08 04 74 17 41 8b 8f c0 00 00 00 8d 71 01 41 89 b7 c0 00 00
>  RSP: 0018:959213d53db0 EFLAGS: 00010202
>  RAX: ffea RBX:  RCX: 00084c04
>  RDX:  RSI: df7326aefebd174c RDI: 00031080
>  RBP: 0002 R08: 0001 R09: 0001
>  R10: 0001 R11: 0046 R12: 959211dcf690
>  R13: 0001 R14: 95925a36e370 R15: 959251c89800
>  FS:  7fb9ea934740() GS:95925ab0()
> knlGS:
>  CS:  0010 DS:  ES:  CR0: 80050033
>  CR2: 0008 CR3: c976c005 CR4: 001706e0
>  Call Trace:
>   ? trigger_process_regex+0x78/0x110
>   trigger_process_regex+0xc5/0x110
>   event_trigger_write+0x71/0xd0
>   vfs_write+0xca/0x210
>   ksys_write+0x70/0xf0
>   do_syscall_64+0x33/0x40
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
>  RIP: 0033:0x7fb9eaa29487
>  Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f
> 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48>
> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
> 
> This was caused by accessing the hlist_data fields after the call to
> __create_val_fields() without checking if the creation succeed.
> 
> Fixes: 63a1e5de3006 ("tracing: Save normal string variables")

Yes, this fixes the fix, sigh.

Reviewed-by: Tom Zanussi 

Thanks,

Tom


> Signed-off-by: Steven Rostedt (VMware) 
> ---
>  kernel/trace/trace_events_hist.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/kernel/trace/trace_events_hist.c
> b/kernel/trace/trace_events_hist.c
> index c74a7d157306..96c3f86b81c5 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -3687,7 +3687,7 @@ static int create_var_field(struct
> hist_trigger_data *hist_data,
>  
>   ret = __create_val_field(hist_data, val_idx, file, var_name,
> expr_str, flags);
>  
> - if (hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING)
> + if (!ret && hist_data->fields[val_idx]->flags &
> HIST_FIELD_FL_STRING)
>   hist_data->fields[val_idx]->var_str_idx = hist_data-
> >n_var_str++;
>  
>   return ret;



[PATCH v3 6/7] tracing: Handle synthetic event array field type checking correctly

2020-10-13 Thread Tom Zanussi
Since synthetic event array types are derived from the field name,
there may be a semicolon at the end of the type which should be
stripped off.

If there are more characters following that, normal type string
checking will result in an invalid type.

Without this patch, you can end up with an invalid field type string
that gets displayed in both the synthetic event description and the
event format:

Before:

  # echo 'myevent char str[16]; int v' >> synthetic_events
  # cat synthetic_events
myevent char[16]; str; int v

  name: myevent
  ID: 1936
  format:
field:unsigned short common_type;   offset:0;   size:2; 
signed:0;
field:unsigned char common_flags;   offset:2;   size:1; 
signed:0;
field:unsigned char common_preempt_count;   offset:3;   size:1; 
signed:0;
field:int common_pid;   offset:4;   size:4; signed:1;

field:char str[16];;offset:8;   size:16;signed:1;
field:int v;offset:40;  size:4; signed:1;

  print fmt: "str=%s, v=%d", REC->str, REC->v

After:

  # echo 'myevent char str[16]; int v' >> synthetic_events
  # cat synthetic_events
myevent char[16] str; int v

  # cat events/synthetic/myevent/format
  name: myevent
  ID: 1936
  format:
field:unsigned short common_type;   offset:0;   size:2; 
signed:0;
field:unsigned char common_flags;   offset:2;   size:1; 
signed:0;
field:unsigned char common_preempt_count;   offset:3;   size:1; 
signed:0;
field:int common_pid;   offset:4;   size:4; signed:1;

field:char str[16]; offset:8;   size:16;signed:1;
field:int v;offset:40;  size:4; signed:1;

  print fmt: "str=%s, v=%d", REC->str, REC->v

[ : wrote parse_synth_field() snippet. ]
Fixes: 4b147936fa50 (tracing: Add support for 'synthetic' events)
Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 7efe39be6576..ac3d112268ed 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -174,7 +174,7 @@ static int synth_field_string_size(char *type)
start += sizeof("char[") - 1;
 
end = strchr(type, ']');
-   if (!end || end < start)
+   if (!end || end < start || type + strlen(type) > end + 1)
return -EINVAL;
 
len = end - start;
@@ -625,8 +625,14 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (field_type[0] == ';')
field_type++;
len = strlen(field_type) + 1;
-   if (array)
-   len += strlen(array);
+
+if (array) {
+int l = strlen(array);
+
+if (l && array[l - 1] == ';')
+l--;
+len += l;
+}
if (prefix)
len += strlen(prefix);
 
-- 
2.17.1



[PATCH v3 7/7] selftests/ftrace: Add test case for synthetic event syntax errors

2020-10-13 Thread Tom Zanussi
Add a selftest that verifies that the syntax error messages and caret
positions are correct for most of the possible synthetic event syntax
error cases.

Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
new file mode 100644
index ..ada594fe16cb
--- /dev/null
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -0,0 +1,19 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event trigger - test synthetic_events syntax parser errors
+# requires: synthetic_events error_log
+
+check_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
+}
+
+check_error 'myevent ^chr arg' # INVALID_TYPE
+check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
+check_error 'myevent char ^str]; int v'# INVALID_NAME
+check_error 'myevent char ^str;[]' # INVALID_NAME
+check_error 'myevent ^char str[; int v'# INVALID_TYPE
+check_error '^mye;vent char str[]' # BAD_NAME
+check_error 'myevent char str[]; ^int' # INVALID_FIELD
+check_error '^myevent' # INCOMPLETE_CMD
+
+exit 0
-- 
2.17.1



[PATCH v3 2/7] tracing: Move is_good_name() from trace_probe.h to trace.h

2020-10-13 Thread Tom Zanussi
is_good_name() is useful for other trace infrastructure, such as
synthetic events, so make it available via trace.h.

Acked-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.h   | 13 +
 kernel/trace/trace_probe.h | 13 -
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 5b0e797cacdd..a94852838491 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 #include /* For NR_SYSCALLS   */
@@ -2090,4 +2091,16 @@ static __always_inline void trace_iterator_reset(struct 
trace_iterator *iter)
iter->pos = -1;
 }
 
+/* Check the name is good for event/group/fields */
+static inline bool is_good_name(const char *name)
+{
+   if (!isalpha(*name) && *name != '_')
+   return false;
+   while (*++name != '\0') {
+   if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+   return false;
+   }
+   return true;
+}
+
 #endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 04d00987da69..2f703a20c724 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -348,18 +347,6 @@ bool trace_probe_match_command_args(struct trace_probe *tp,
 #define trace_probe_for_each_link_rcu(pos, tp) \
list_for_each_entry_rcu(pos, &(tp)->event->files, list)
 
-/* Check the name is good for event/group/fields */
-static inline bool is_good_name(const char *name)
-{
-   if (!isalpha(*name) && *name != '_')
-   return false;
-   while (*++name != '\0') {
-   if (!isalpha(*name) && !isdigit(*name) && *name != '_')
-   return false;
-   }
-   return true;
-}
-
 #define TPARG_FL_RETURN BIT(0)
 #define TPARG_FL_KERNEL BIT(1)
 #define TPARG_FL_FENTRY BIT(2)
-- 
2.17.1



[PATCH v3 4/7] tracing: Add synthetic event error logging

2020-10-13 Thread Tom Zanussi
Add support for synthetic event error logging, which entails adding a
logging function for it, a way to save the synthetic event command,
and a set of specific synthetic event parse error strings and
handling.

[ : wrote save_cmdstr() seq_buf implementation. ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 92 ++-
 1 file changed, 90 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 8c9d6e464da0..7efe39be6576 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -20,6 +20,48 @@
 
 #include "trace_synth.h"
 
+#undef ERRORS
+#define ERRORS \
+   C(BAD_NAME, "Illegal name"),\
+   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(EVENT_EXISTS, "Event already exists"),\
+   C(TOO_MANY_FIELDS,  "Too many fields"), \
+   C(INCOMPLETE_TYPE,  "Incomplete type"), \
+   C(INVALID_TYPE, "Invalid type"),\
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(CMD_TOO_LONG, "Command too long"),
+
+#undef C
+#define C(a, b)SYNTH_ERR_##a
+
+enum { ERRORS };
+
+#undef C
+#define C(a, b)b
+
+static const char *err_text[] = { ERRORS };
+
+static char last_cmd[MAX_FILTER_STR_VAL];
+
+static int errpos(const char *str)
+{
+   return err_pos(last_cmd, str);
+}
+
+static void last_cmd_set(char *str)
+{
+   if (!str)
+   return;
+
+   strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);
+}
+
+static void synth_err(u8 err_type, u8 err_pos)
+{
+   tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
+   err_type, err_pos);
+}
+
 static int create_synth_event(int argc, const char **argv);
 static int synth_event_show(struct seq_file *m, struct dyn_event *ev);
 static int synth_event_release(struct dyn_event *ev);
@@ -545,8 +587,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field_type++;
 
if (!strcmp(field_type, "unsigned")) {
-   if (argc < 3)
+   if (argc < 3) {
+   synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
return ERR_PTR(-EINVAL);
+   }
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
@@ -573,6 +617,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
if (!is_good_name(field->name)) {
+   synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
ret = -EINVAL;
goto free;
}
@@ -601,6 +646,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -621,6 +667,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field->is_dynamic = true;
size = sizeof(u64);
} else {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
}
@@ -1098,12 +1145,47 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
+static int save_cmdstr(int argc, const char *name, const char **argv)
+{
+struct seq_buf s;
+   char *buf;
+   int i;
+
+buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
+if (!buf)
+return -ENOMEM;
+
+seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
+
+seq_buf_puts(, name);
+
+for (i = 0; i < argc; i++) {
+seq_buf_putc(, ' ');
+seq_buf_puts(, argv[i]);
+}
+
+if (!seq_buf_buffer_left()) {
+synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
+kfree(buf);
+return -EINVAL;
+}
+buf[s.len] = 0;
+last_cmd_set(buf);
+
+kfree(buf);
+return 0;
+}
+
 static int __create_synth_event(int argc, const char *name, const char **argv)
 {
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
struct synth_event *event = NULL;
int i, consumed = 0, n_fields = 0, ret = 0;
 
+   ret = save_cmdstr(argc, name, argv);
+   if (ret)
+   return ret;
+
/*
 * Argument syntax:
 *  - Add synthetic event:  fi

[PATCH v3 0/7] tracing: Synthetic event dynamic string fixes

2020-10-13 Thread Tom Zanussi
This updates v2 to replace some of the v2 code with improved code from
Steve (tracing: Add synthetic event error logging) and (tracing:
Handle synthetic event array field type checking correctly) and remove
the synth_error_clear() function and change last_cmd_set() to use
strncpy.

Thanks,

Tom

v2 text:

This updates v1 to fix a couple of additional things that Masami
pointed out:

 - The error logging for the BAD_TYPE error was actually pointing to
   the name - it now points to the type as it should.

 - Added a new test case that verifies most of the synthetic event
   error messages and caret positions.
 
 - Added a new patch that correctly strips off trailing semicolons and
   everything else from array types, which wasn't happening before,
   even before the dynamic array patches.

Original v1 text:

These patches provide fixes for the problems observed by Masami in the
new synthetic event dynamic string patchset.

The first patch (tracing: Don't show dynamic string internals in
synthetic event description) removes the __data_loc from the event
description but leaves it in the format.

The patch (tracing: Add synthetic event error logging) addresses the
lack of error messages when parse errors occur.

The remaining three patches address the other problems Masami noted
which result from allowing illegal characters in synthetic event and
field names when defining an event.  The is_good_name() function is
used to check that's not possible for the probe events, but should
also be used for the synthetic events as well.

(tracing: Move is_good_name() from trace_probe.h to trace.h) makes
that function available to other trace subsystems by putting it in
trace.h.  (tracing: Check that the synthetic event and field names are
legal) applies it to the synthetic events, and (selftests/ftrace:
Change synthetic event name for inter-event-combined test) changes a
testcase that now fails because it uses an illegal name.

The following changes since commit 848183553e431e6e9c2ea2f72421a7a1bbc6532e:

  tracing: Fix synthetic print fmt check for use of __get_str() (2020-10-08 
15:29:07 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/dynstring-fixes-v3

Tom Zanussi (7):
  tracing: Don't show dynamic string internals in synthetic event
description
  tracing: Move is_good_name() from trace_probe.h to trace.h
  tracing: Check that the synthetic event and field names are legal
  tracing: Add synthetic event error logging
  selftests/ftrace: Change synthetic event name for inter-event-combined
test
  tracing: Handle synthetic event array field type checking correctly
  selftests/ftrace: Add test case for synthetic event syntax errors

 kernel/trace/trace.h  |  13 ++
 kernel/trace/trace_events_synth.c | 123 +-
 kernel/trace/trace_probe.h|  13 --
 .../trigger-inter-event-combined-hist.tc  |   8 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  19 +++
 5 files changed, 153 insertions(+), 23 deletions(-)
 create mode 100644 
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc

-- 
2.17.1



[PATCH v3 1/7] tracing: Don't show dynamic string internals in synthetic event description

2020-10-13 Thread Tom Zanussi
For synthetic event dynamic fields, the type contains "__data_loc",
which is basically an internal part of the type which is only meant to
be displayed in the format, not in the event description itself, which
is confusing to users since they can't use __data_loc on the
command-line to define an event field, which printing it would lead
them to believe.

So filter it out from the description, while leaving it in the type.

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 3b2dcc42b8ee..b19e2f4159ab 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1867,14 +1867,22 @@ static int __synth_event_show(struct seq_file *m, 
struct synth_event *event)
 {
struct synth_field *field;
unsigned int i;
+   char *type, *t;
 
seq_printf(m, "%s\t", event->name);
 
for (i = 0; i < event->n_fields; i++) {
field = event->fields[i];
 
+   type = field->type;
+   t = strstr(type, "__data_loc");
+   if (t) { /* __data_loc belongs in format but not event desc */
+   t += sizeof("__data_loc");
+   type = t;
+   }
+
/* parameter values */
-   seq_printf(m, "%s %s%s", field->type, field->name,
+   seq_printf(m, "%s %s%s", type, field->name,
   i == event->n_fields - 1 ? "" : "; ");
}
 
-- 
2.17.1



[PATCH v3 3/7] tracing: Check that the synthetic event and field names are legal

2020-10-13 Thread Tom Zanussi
Call the is_good_name() function used by probe events to make sure
synthetic event and field names don't contain illegal characters and
cause unexpected parsing of synthetic event commands.

Fixes: 4b147936fa50 (tracing: Add support for 'synthetic' events)
Reported-by: Masami Hiramatsu 
Reviewed-by: Masami Hiramatsu 
Tested-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b19e2f4159ab..8c9d6e464da0 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -572,6 +572,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
ret = -ENOMEM;
goto free;
}
+   if (!is_good_name(field->name)) {
+   ret = -EINVAL;
+   goto free;
+   }
 
if (field_type[0] == ';')
field_type++;
@@ -1112,6 +1116,11 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
 
mutex_lock(_mutex);
 
+   if (!is_good_name(name)) {
+   ret = -EINVAL;
+   goto out;
+   }
+
event = find_synth_event(name);
if (event) {
ret = -EEXIST;
-- 
2.17.1



[PATCH v3 5/7] selftests/ftrace: Change synthetic event name for inter-event-combined test

2020-10-13 Thread Tom Zanussi
This test uses waking+wakeup_latency as an event name, which doesn't
make sense since it includes an operator.  Illegal names are now
detected by the synthetic event command parsing, which causes this
test to fail.  Change the name to 'waking_plus_wakeup_latency' to
prevent this.

Fixes: f06eec4d0f2c (selftests: ftrace: Add inter-event hist triggers testcases)
Acked-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../inter-event/trigger-inter-event-combined-hist.tc  | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
index 7449a4b8f1f9..9098f1e7433f 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
@@ -25,12 +25,12 @@ echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events
 echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> 
events/sched/sched_wakeup/trigger
 echo 
'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid)
 if next_comm=="ping"' > events/sched/sched_switch/trigger
 
-echo 'waking+wakeup_latency u64 lat; pid_t pid' >> synthetic_events
-echo 
'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking+wakeup_latency($ww_lat,pid)'
 >> events/synthetic/wakeup_latency/trigger
-echo 'hist:keys=pid,lat:sort=pid,lat' >> 
events/synthetic/waking+wakeup_latency/trigger
+echo 'waking_plus_wakeup_latency u64 lat; pid_t pid' >> synthetic_events
+echo 
'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking_plus_wakeup_latency($ww_lat,pid)'
 >> events/synthetic/wakeup_latency/trigger
+echo 'hist:keys=pid,lat:sort=pid,lat' >> 
events/synthetic/waking_plus_wakeup_latency/trigger
 
 ping $LOCALHOST -c 3
-if ! grep -q "pid:" events/synthetic/waking+wakeup_latency/hist; then
+if ! grep -q "pid:" events/synthetic/waking_plus_wakeup_latency/hist; then
 fail "Failed to create combined histogram"
 fi
 
-- 
2.17.1



Re: [PATCH v2 6/7] tracing: Handle synthetic event array field type checking correctly

2020-10-12 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-10-12 at 18:14 -0400, Steven Rostedt wrote:
> On Mon, 12 Oct 2020 15:18:08 -0500
> Tom Zanussi  wrote:
> 
> > @@ -630,8 +630,11 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > if (field_type[0] == ';')
> > field_type++;
> > len = strlen(field_type) + 1;
> > -   if (array)
> > +   if (array) {
> > len += strlen(array);
> > +   if (array[strlen(array) - 1] == ';')
> > +   len--;
> > +   }
> 
> Why not:
> 
>   if (array) {
>   int l = strlen(array);
> 
>   if (l && array[l - 1] == ';')
>   l--;
>   len += l;
>   }
> 

Yeah, I think that's better, will change it.

Thanks,

Tom

> -- Steve



Re: [PATCH v2 4/7] tracing: Add synthetic event error logging

2020-10-12 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-10-12 at 18:04 -0400, Steven Rostedt wrote:
> On Mon, 12 Oct 2020 15:18:06 -0500
> Tom Zanussi  wrote:
> 
> > +static int cmdstr_append(char *buf, const char *str, int
> > *remaining)
> > +{
> > +   int len = strlen(str);
> > +
> > +   if (len + 1 >= *remaining) {
> > +   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
> > +   return -EINVAL;
> > +   }
> > +
> > +   strcat(buf, str);
> > +   strcat(buf, " ");
> > +   *remaining -= len + 1;
> > +
> > +   return 0;
> > +}
> > +
> > +static int save_cmdstr(int argc, const char *name, const char
> > **argv)
> > +{
> > +   int i, ret, remaining = MAX_DYNEVENT_CMD_LEN;
> > +   char *buf;
> > +
> > +   synth_err_clear();
> > +
> > +   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
> > +   if (!buf)
> > +   return -ENOMEM;
> > +
> > +   ret = cmdstr_append(buf, name, );
> > +   if (ret) {
> > +   kfree(buf);
> > +   return ret;
> > +   }
> > +
> > +   for (i = 0; i < argc; i++) {
> > +   ret = cmdstr_append(buf, argv[i], );
> > +   if (ret) {
> > +   kfree(buf);
> > +   return ret;
> > +   }
> > +   }
> > +
> > +   last_cmd_set(buf);
> > +
> > +   kfree(buf);
> > +
> > +   return ret;
> > +}
> > +
> 
> Hmm, the above could easily be replaced with:
> 
>   struct seq_buf s;
> 
>   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
>   if (!buf)
>   return -ENOMEM;
> 
>   seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
> 
>   seq_buf_puts(, name);
> 
>   for (i = 0; i < argc; i++) {
>   seq_buf_putc(, ' ');
>   seq_buf_puts(, argv[i]);
>   }
> 
>   if (!seq_buf_buffer_left()) {
>   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
>   kfree(buf);
>   return -EINVAL;
>   }
>   buf[s.len] = 0;
>   last_cmd_set(buf);
> 
>   kfree(buf);
>   return 0;
> 

Yeah, that makes sense, will change it.

Thanks,

Tom

> 
> -- Steve



Re: [PATCH v2 4/7] tracing: Add synthetic event error logging

2020-10-12 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-10-12 at 17:49 -0400, Steven Rostedt wrote:
> On Mon, 12 Oct 2020 17:42:40 -0400
> Steven Rostedt  wrote:
> 
> > On Mon, 12 Oct 2020 15:18:06 -0500
> > Tom Zanussi  wrote:
> > 
> > > +static char last_cmd[MAX_FILTER_STR_VAL];
> > > +
> > > +static int errpos(const char *str)
> > > +{
> > > + return err_pos(last_cmd, str);
> > > +}
> > > +
> > > +static void last_cmd_set(char *str)
> > > +{
> > > + if (!str)
> > > + return;
> > > +
> > > + strncat(last_cmd, str, MAX_FILTER_STR_VAL - 1);  
> > 
> > If I understand strncat() correctly, it will add 'n' + 1 bytes from
> > str
> > to last_cmd. That is, I think you want:
> > 
> > strncat(last_cmd, str, MAX_FILTER_STR_VAL - (strlen(last_cmd) +
> > 1));
> > 
> 
> Looking at the patch more, it only has one caller to last_cmd_set(),
> and one caller to synth_err_clear().
> 
> Why not just clear on set?

Yeah, that would make sense, or just remove the clear and use strncpy
in last_cmd_set() instead.

Tom

> 
> -- Steve
> 
> 
> 
> > 
> > > +}
> > > +
> > > +static void synth_err(u8 err_type, u8 err_pos)
> > > +{
> > > + tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
> > > + err_type, err_pos);
> > > +}
> > > +
> > > +static void synth_err_clear(void)
> > > +{
> > > + last_cmd[0] = '\0';
> > > +}
> > > +  
> 
> 



[PATCH v2 3/7] tracing: Check that the synthetic event and field names are legal

2020-10-12 Thread Tom Zanussi
Call the is_good_name() function used by probe events to make sure
synthetic event and field names don't contain illegal characters and
cause unexpected parsing of synthetic event commands.

Fixes: 4b147936fa50 (tracing: Add support for 'synthetic' events)
Reported-by: Masami Hiramatsu 
Reviewed-by: Masami Hiramatsu 
Tested-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index b19e2f4159ab..8c9d6e464da0 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -572,6 +572,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
ret = -ENOMEM;
goto free;
}
+   if (!is_good_name(field->name)) {
+   ret = -EINVAL;
+   goto free;
+   }
 
if (field_type[0] == ';')
field_type++;
@@ -1112,6 +1116,11 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
 
mutex_lock(_mutex);
 
+   if (!is_good_name(name)) {
+   ret = -EINVAL;
+   goto out;
+   }
+
event = find_synth_event(name);
if (event) {
ret = -EEXIST;
-- 
2.17.1



[PATCH v2 6/7] tracing: Handle synthetic event array field type checking correctly

2020-10-12 Thread Tom Zanussi
Since synthetic event array types are derived from the field name,
there may be a semicolon at the end of the type which should be
stripped off.

If there are more characters following that, normal type string
checking will result in an invalid type.

Without this patch, you can end up with an invalid field type string
that gets displayed in both the synthetic event description and the
event format:

Before:

  # echo 'myevent char str[16]; int v' >> synthetic_events
  # cat synthetic_events
myevent char[16]; str; int v

  name: myevent
  ID: 1936
  format:
field:unsigned short common_type;   offset:0;   size:2; 
signed:0;
field:unsigned char common_flags;   offset:2;   size:1; 
signed:0;
field:unsigned char common_preempt_count;   offset:3;   size:1; 
signed:0;
field:int common_pid;   offset:4;   size:4; signed:1;

field:char str[16];;offset:8;   size:16;signed:1;
field:int v;offset:40;  size:4; signed:1;

  print fmt: "str=%s, v=%d", REC->str, REC->v

After:

  # echo 'myevent char str[16]; int v' >> synthetic_events
  # cat synthetic_events
myevent char[16] str; int v

  # cat events/synthetic/myevent/format
  name: myevent
  ID: 1936
  format:
field:unsigned short common_type;   offset:0;   size:2; 
signed:0;
field:unsigned char common_flags;   offset:2;   size:1; 
signed:0;
field:unsigned char common_preempt_count;   offset:3;   size:1; 
signed:0;
field:int common_pid;   offset:4;   size:4; signed:1;

field:char str[16]; offset:8;   size:16;signed:1;
field:int v;offset:40;  size:4; signed:1;

  print fmt: "str=%s, v=%d", REC->str, REC->v

Fixes: 4b147936fa50 (tracing: Add support for 'synthetic' events)
Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 64c65be62dfe..5c3f5ae6f0bd 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -179,7 +179,7 @@ static int synth_field_string_size(char *type)
start += sizeof("char[") - 1;
 
end = strchr(type, ']');
-   if (!end || end < start)
+   if (!end || end < start || type + strlen(type) > end + 1)
return -EINVAL;
 
len = end - start;
@@ -630,8 +630,11 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
if (field_type[0] == ';')
field_type++;
len = strlen(field_type) + 1;
-   if (array)
+   if (array) {
len += strlen(array);
+   if (array[strlen(array) - 1] == ';')
+   len--;
+   }
if (prefix)
len += strlen(prefix);
 
-- 
2.17.1



[PATCH v2 2/7] tracing: Move is_good_name() from trace_probe.h to trace.h

2020-10-12 Thread Tom Zanussi
is_good_name() is useful for other trace infrastructure, such as
synthetic events, so make it available via trace.h.

Acked-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace.h   | 13 +
 kernel/trace/trace_probe.h | 13 -
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 5b0e797cacdd..a94852838491 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 #include /* For NR_SYSCALLS   */
@@ -2090,4 +2091,16 @@ static __always_inline void trace_iterator_reset(struct 
trace_iterator *iter)
iter->pos = -1;
 }
 
+/* Check the name is good for event/group/fields */
+static inline bool is_good_name(const char *name)
+{
+   if (!isalpha(*name) && *name != '_')
+   return false;
+   while (*++name != '\0') {
+   if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+   return false;
+   }
+   return true;
+}
+
 #endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 04d00987da69..2f703a20c724 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -348,18 +347,6 @@ bool trace_probe_match_command_args(struct trace_probe *tp,
 #define trace_probe_for_each_link_rcu(pos, tp) \
list_for_each_entry_rcu(pos, &(tp)->event->files, list)
 
-/* Check the name is good for event/group/fields */
-static inline bool is_good_name(const char *name)
-{
-   if (!isalpha(*name) && *name != '_')
-   return false;
-   while (*++name != '\0') {
-   if (!isalpha(*name) && !isdigit(*name) && *name != '_')
-   return false;
-   }
-   return true;
-}
-
 #define TPARG_FL_RETURN BIT(0)
 #define TPARG_FL_KERNEL BIT(1)
 #define TPARG_FL_FENTRY BIT(2)
-- 
2.17.1



[PATCH v2 1/7] tracing: Don't show dynamic string internals in synthetic event description

2020-10-12 Thread Tom Zanussi
For synthetic event dynamic fields, the type contains "__data_loc",
which is basically an internal part of the type which is only meant to
be displayed in the format, not in the event description itself, which
is confusing to users since they can't use __data_loc on the
command-line to define an event field, which printing it would lead
them to believe.

So filter it out from the description, while leaving it in the type.

Reported-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 3b2dcc42b8ee..b19e2f4159ab 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1867,14 +1867,22 @@ static int __synth_event_show(struct seq_file *m, 
struct synth_event *event)
 {
struct synth_field *field;
unsigned int i;
+   char *type, *t;
 
seq_printf(m, "%s\t", event->name);
 
for (i = 0; i < event->n_fields; i++) {
field = event->fields[i];
 
+   type = field->type;
+   t = strstr(type, "__data_loc");
+   if (t) { /* __data_loc belongs in format but not event desc */
+   t += sizeof("__data_loc");
+   type = t;
+   }
+
/* parameter values */
-   seq_printf(m, "%s %s%s", field->type, field->name,
+   seq_printf(m, "%s %s%s", type, field->name,
   i == event->n_fields - 1 ? "" : "; ");
}
 
-- 
2.17.1



[PATCH v2 5/7] selftests/ftrace: Change synthetic event name for inter-event-combined test

2020-10-12 Thread Tom Zanussi
This test uses waking+wakeup_latency as an event name, which doesn't
make sense since it includes an operator.  Illegal names are now
detected by the synthetic event command parsing, which causes this
test to fail.  Change the name to 'waking_plus_wakeup_latency' to
prevent this.

Fixes: f06eec4d0f2c (selftests: ftrace: Add inter-event hist triggers testcases)
Acked-by: Masami Hiramatsu 
Signed-off-by: Tom Zanussi 
---
 .../inter-event/trigger-inter-event-combined-hist.tc  | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
index 7449a4b8f1f9..9098f1e7433f 100644
--- 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
@@ -25,12 +25,12 @@ echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events
 echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> 
events/sched/sched_wakeup/trigger
 echo 
'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid)
 if next_comm=="ping"' > events/sched/sched_switch/trigger
 
-echo 'waking+wakeup_latency u64 lat; pid_t pid' >> synthetic_events
-echo 
'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking+wakeup_latency($ww_lat,pid)'
 >> events/synthetic/wakeup_latency/trigger
-echo 'hist:keys=pid,lat:sort=pid,lat' >> 
events/synthetic/waking+wakeup_latency/trigger
+echo 'waking_plus_wakeup_latency u64 lat; pid_t pid' >> synthetic_events
+echo 
'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking_plus_wakeup_latency($ww_lat,pid)'
 >> events/synthetic/wakeup_latency/trigger
+echo 'hist:keys=pid,lat:sort=pid,lat' >> 
events/synthetic/waking_plus_wakeup_latency/trigger
 
 ping $LOCALHOST -c 3
-if ! grep -q "pid:" events/synthetic/waking+wakeup_latency/hist; then
+if ! grep -q "pid:" events/synthetic/waking_plus_wakeup_latency/hist; then
 fail "Failed to create combined histogram"
 fi
 
-- 
2.17.1



[PATCH v2 4/7] tracing: Add synthetic event error logging

2020-10-12 Thread Tom Zanussi
Add support for synthetic event error logging, which entails adding a
logging function for it, a way to save the synthetic event command,
and a set of specific synthetic event parse error strings and
handling.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 114 +-
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 8c9d6e464da0..64c65be62dfe 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -20,6 +20,53 @@
 
 #include "trace_synth.h"
 
+#undef ERRORS
+#define ERRORS \
+   C(BAD_NAME, "Illegal name"),\
+   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   C(EVENT_EXISTS, "Event already exists"),\
+   C(TOO_MANY_FIELDS,  "Too many fields"), \
+   C(INCOMPLETE_TYPE,  "Incomplete type"), \
+   C(INVALID_TYPE, "Invalid type"),\
+   C(INVALID_FIELD,"Invalid field"),   \
+   C(CMD_TOO_LONG, "Command too long"),
+
+#undef C
+#define C(a, b)SYNTH_ERR_##a
+
+enum { ERRORS };
+
+#undef C
+#define C(a, b)b
+
+static const char *err_text[] = { ERRORS };
+
+static char last_cmd[MAX_FILTER_STR_VAL];
+
+static int errpos(const char *str)
+{
+   return err_pos(last_cmd, str);
+}
+
+static void last_cmd_set(char *str)
+{
+   if (!str)
+   return;
+
+   strncat(last_cmd, str, MAX_FILTER_STR_VAL - 1);
+}
+
+static void synth_err(u8 err_type, u8 err_pos)
+{
+   tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
+   err_type, err_pos);
+}
+
+static void synth_err_clear(void)
+{
+   last_cmd[0] = '\0';
+}
+
 static int create_synth_event(int argc, const char **argv);
 static int synth_event_show(struct seq_file *m, struct dyn_event *ev);
 static int synth_event_release(struct dyn_event *ev);
@@ -545,8 +592,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field_type++;
 
if (!strcmp(field_type, "unsigned")) {
-   if (argc < 3)
+   if (argc < 3) {
+   synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
return ERR_PTR(-EINVAL);
+   }
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
@@ -573,6 +622,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
if (!is_good_name(field->name)) {
+   synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
ret = -EINVAL;
goto free;
}
@@ -601,6 +651,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -621,6 +672,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field->is_dynamic = true;
size = sizeof(u64);
} else {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
}
@@ -1098,12 +1150,64 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
+static int cmdstr_append(char *buf, const char *str, int *remaining)
+{
+   int len = strlen(str);
+
+   if (len + 1 >= *remaining) {
+   synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
+   return -EINVAL;
+   }
+
+   strcat(buf, str);
+   strcat(buf, " ");
+   *remaining -= len + 1;
+
+   return 0;
+}
+
+static int save_cmdstr(int argc, const char *name, const char **argv)
+{
+   int i, ret, remaining = MAX_DYNEVENT_CMD_LEN;
+   char *buf;
+
+   synth_err_clear();
+
+   buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   ret = cmdstr_append(buf, name, );
+   if (ret) {
+   kfree(buf);
+   return ret;
+   }
+
+   for (i = 0; i < argc; i++) {
+   ret = cmdstr_append(buf, argv[i], );
+   if (ret) {
+   kfree(buf);
+   return ret;
+   }
+   }
+
+   last_cmd_set(buf);
+
+   kfree(buf);
+
+   return ret;
+}
+
 static int __create_synth_event(int argc, con

[PATCH v2 7/7] selftests/ftrace: Add test case for synthetic event syntax errors

2020-10-12 Thread Tom Zanussi
Add a selftest that verifies that the syntax error messages and caret
positions are correct for most of the possible synthetic event syntax
error cases.

Signed-off-by: Tom Zanussi 
---
 .../trigger-synthetic_event_syntax_errors.tc  | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc

diff --git 
a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
new file mode 100644
index ..136276b11386
--- /dev/null
+++ 
b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
@@ -0,0 +1,19 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Synthetic event parser error log check
+# requires: synthetic_events error_log
+
+check_error() { # command-with-error-pos-by-^
+ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
+}
+
+check_error 'myevent ^chr arg' # INVALID_TYPE
+check_error 'myevent ^char str[];; int v'  # INVALID_TYPE
+check_error 'myevent char ^str]; int v'# INVALID_NAME
+check_error 'myevent char ^str;[]' # INVALID_NAME
+check_error 'myevent ^char str[; int v'# INVALID_TYPE
+check_error '^mye;vent char str[]' # BAD_NAME
+check_error 'myevent char str[]; ^int' # INVALID_FIELD
+check_error '^myevent' # INCOMPLETE_CMD
+
+exit 0
-- 
2.17.1



[PATCH v2 0/7] tracing: Synthetic event dynamic string fixes

2020-10-12 Thread Tom Zanussi
This updates v1 to fix a couple of additional things that Masami
pointed out:

 - The error logging for the BAD_TYPE error was actually pointing to
   the name - it now points to the type as it should.

 - Added a new test case that verifies most of the synthetic event
   error messages and caret positions.
 
 - Added a new patch that correctly strips off trailing semicolons and
   everything else from array types, which wasn't happening before,
   even before the dynamic array patches.

Thanks,

Tom

Original v1 text:

These patches provide fixes for the problems observed by Masami in the
new synthetic event dynamic string patchset.

The first patch (tracing: Don't show dynamic string internals in
synthetic event description) removes the __data_loc from the event
description but leaves it in the format.

The patch (tracing: Add synthetic event error logging) addresses the
lack of error messages when parse errors occur.

The remaining three patches address the other problems Masami noted
which result from allowing illegal characters in synthetic event and
field names when defining an event.  The is_good_name() function is
used to check that's not possible for the probe events, but should
also be used for the synthetic events as well.

(tracing: Move is_good_name() from trace_probe.h to trace.h) makes
that function available to other trace subsystems by putting it in
trace.h.  (tracing: Check that the synthetic event and field names are
legal) applies it to the synthetic events, and (selftests/ftrace:
Change synthetic event name for inter-event-combined test) changes a
testcase that now fails because it uses an illegal name.

The following changes since commit 848183553e431e6e9c2ea2f72421a7a1bbc6532e:

  tracing: Fix synthetic print fmt check for use of __get_str() (2020-10-08 
15:29:07 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/zanussi/linux-trace.git 
ftrace/dynstring-fixes-v2

Tom Zanussi (7):
  tracing: Don't show dynamic string internals in synthetic event
description
  tracing: Move is_good_name() from trace_probe.h to trace.h
  tracing: Check that the synthetic event and field names are legal
  tracing: Add synthetic event error logging
  selftests/ftrace: Change synthetic event name for inter-event-combined
test
  tracing: Handle synthetic event array field type checking correctly
  selftests/ftrace: Add test case for synthetic event syntax errors

 kernel/trace/trace.h  |  13 ++
 kernel/trace/trace_events_synth.c | 140 +-
 kernel/trace/trace_probe.h|  13 --
 .../trigger-inter-event-combined-hist.tc  |   8 +-
 .../trigger-synthetic_event_syntax_errors.tc  |  19 +++
 5 files changed, 171 insertions(+), 22 deletions(-)
 create mode 100644 
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc

-- 
2.17.1



Re: [PATCH 0/5] tracing: Synthetic event dynamic string fixes

2020-10-12 Thread Tom Zanussi
Hi Steve,

On Mon, 2020-10-12 at 11:13 -0400, Steven Rostedt wrote:
> On Fri,  9 Oct 2020 10:17:06 -0500
> Tom Zanussi  wrote:
> 
> > These patches provide fixes for the problems observed by Masami in
> > the
> > new synthetic event dynamic string patchset.
> > 
> > The first patch (tracing: Don't show dynamic string internals in
> > synthetic event description) removes the __data_loc from the event
> > description but leaves it in the format.
> > 
> > The patch (tracing: Add synthetic event error logging) addresses
> > the
> > lack of error messages when parse errors occur.
> > 
> > The remaining three patches address the other problems Masami noted
> > which result from allowing illegal characters in synthetic event
> > and
> > field names when defining an event.  The is_good_name() function is
> > used to check that's not possible for the probe events, but should
> > also be used for the synthetic events as well.
> > 
> > (tracing: Move is_good_name() from trace_probe.h to trace.h) makes
> > that function available to other trace subsystems by putting it in
> > trace.h.  (tracing: Check that the synthetic event and field names
> > are
> > legal) applies it to the synthetic events, and (selftests/ftrace:
> > Change synthetic event name for inter-event-combined test) changes
> > a
> > testcase that now fails because it uses an illegal name.
> > 
> 
> 
> Hi Tom,
> 
> Would you be able to address Masami's concerns on patches 1 and 4?

Yes, I'll submit a v2 fixing those soon (today).

Thanks,

Tom

> 
> -- Steve



Re: [PATCH 1/5] tracing: Don't show dynamic string internals in synthetic event description

2020-10-12 Thread Tom Zanussi
Hi Masami,

On Sun, 2020-10-11 at 00:03 +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> On Fri,  9 Oct 2020 10:17:07 -0500
> Tom Zanussi  wrote:
> 
> > For synthetic event dynamic fields, the type contains "__data_loc",
> > which is basically an internal part of the type which is only meant
> > to
> > be displayed in the format, not in the event description itself,
> > which
> > is confusing to users since they can't use __data_loc on the
> > command-line to define an event field, which printing it would lead
> > them to believe.
> > 
> > So filter it out from the description, while leaving it in the
> > type.
> > 
> 
> OK, I confirmed this removes __data_loc from synth_events interface.
> However, I also found another issue.
> 
>   /sys/kernel/debug/tracing # echo "myevent char str[]; int v" >>
> synthetic_events  
>   /sys/kernel/debug/tracing # cat synthetic_events 
>   myevent char[]; str; int v
> 
> It seems that the type "char[]" includes ";" as a type, this results
> 

Yeah, this isn't a result of this patchset - it's a different bug which
I'll submit a new fix for.  Basically in the array case it doesn't
effectively strip off trailing characters when creating the array type.

Thanks,

Tom

> 
>   /sys/kernel/debug/tracing # cat events/synthetic/myevent/format 
>   name: myevent
>   ID: 1220
>   format:
>   field:unsigned short common_type;   offset:0;   size:2; signe
> d:0;
>   field:unsigned char common_flags;   offset:2;   size:1; signe
> d:0;
>   field:unsigned char common_preempt_count;   offset:3;   size:
> 1;signed:0;
>   field:int common_pid;   offset:4;   size:4; signed:1;
> 
>   field:__data_loc char[]; str;   offset:8;   size:8; signe
> d:1;
>   field:int v;offset:16;  size:4; signed:1;
> 
>   print fmt: "str=%.*s, v=%d", __get_str(str), REC->v
> 
> 
> As you can see, the field type has ";" in format file too. This will
> prevent
> parsing event information correctly.
> I also try to remove ";" as below, it seems to work correctly.
> 
>   /sys/kernel/debug/tracing # echo "myevent char[] str; int v" >>
> synthetic_events 
>   /sys/kernel/debug/tracing # cat events/synthetic/myevent/format 
>   name: myevent
>   ID: 1221
>   format:
>   field:unsigned short common_type;   offset:0;   size:2; signe
> d:0;
>   field:unsigned char common_flags;   offset:2;   size:1; signe
> d:0;
>   field:unsigned char common_preempt_count;   offset:3;   size:
> 1;signed:0;
>   field:int common_pid;   offset:4;   size:4; signed:1;
> 
>   field:__data_loc char[] str;offset:8;   size:8; signe
> d:1;
>   field:int v;offset:16;  size:4; signed:1;
> 
>   print fmt: "str=%.*s, v=%d", __get_str(str), REC->v
> 
> 
> Thank you,
> 
> > Reported-by: Masami Hiramatsu 
> > Signed-off-by: Tom Zanussi 
> > ---
> >  kernel/trace/trace_events_synth.c | 10 +-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/kernel/trace/trace_events_synth.c
> > b/kernel/trace/trace_events_synth.c
> > index 3b2dcc42b8ee..b19e2f4159ab 100644
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -1867,14 +1867,22 @@ static int __synth_event_show(struct
> > seq_file *m, struct synth_event *event)
> >  {
> > struct synth_field *field;
> > unsigned int i;
> > +   char *type, *t;
> >  
> > seq_printf(m, "%s\t", event->name);
> >  
> > for (i = 0; i < event->n_fields; i++) {
> > field = event->fields[i];
> >  
> > +   type = field->type;
> > +   t = strstr(type, "__data_loc");
> > +   if (t) { /* __data_loc belongs in format but not event
> > desc */
> > +   t += sizeof("__data_loc");
> > +   type = t;
> > +   }
> > +
> > /* parameter values */
> > -   seq_printf(m, "%s %s%s", field->type, field->name,
> > +   seq_printf(m, "%s %s%s", type, field->name,
> >i == event->n_fields - 1 ? "" : "; ");
> > }
> >  
> > -- 
> > 2.17.1
> > 
> 
> 



Re: [PATCH 4/5] tracing: Add synthetic event error logging

2020-10-12 Thread Tom Zanussi
Hi Masami,

On Sat, 2020-10-10 at 23:57 +0900, Masami Hiramatsu wrote:
> On Fri,  9 Oct 2020 10:17:10 -0500
> Tom Zanussi  wrote:
> 
> > Add support for synthetic event error logging, which entails adding
> > a
> > logging function for it, a way to save the synthetic event command,
> > and a set of specific synthetic event parse error strings and
> > handling.
> 
> Thanks for fixing this. But it seems that the INVALID_TYPE error
> position is not correct.
> 
> /sys/kernel/debug/tracing # echo "myevent chr arg" >>
> synthetic_events 
> sh: write error: Invalid argument
> /sys/kernel/debug/tracing # cat error_log 
> [ 1354.611660] synthetic_events: error: Invalid type
>   Command: myevent chr arg 
>^
> 
> If the type is invalid, it should point "chr" instead of "arg".
> If you add a syntax error testcase as same as kprobe_events, you can
> check the error position too.
> 

Right, it's using name where it should be using type.  Will fix in the
next version.

Thanks,

Tom

> Thank you,
> 
> > 
> > Signed-off-by: Tom Zanussi 
> > ---
> >  kernel/trace/trace_events_synth.c | 114
> > +-
> >  1 file changed, 112 insertions(+), 2 deletions(-)
> > 
> > diff --git a/kernel/trace/trace_events_synth.c
> > b/kernel/trace/trace_events_synth.c
> > index 8c9d6e464da0..ce4cae5cfd47 100644
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -20,6 +20,53 @@
> >  
> >  #include "trace_synth.h"
> >  
> > +#undef ERRORS
> > +#define ERRORS \
> > +   C(BAD_NAME, "Illegal name"),\
> > +   C(CMD_INCOMPLETE,   "Incomplete command"),  \
> > +   C(EVENT_EXISTS, "Event already exists"),\
> > +   C(TOO_MANY_FIELDS,  "Too many fields"), \
> > +   C(INCOMPLETE_TYPE,  "Incomplete type"), \
> > +   C(INVALID_TYPE, "Invalid type"),\
> > +   C(INVALID_FIELD,"Invalid field"),   \
> > +   C(CMD_TOO_LONG, "Command too long"),
> > +
> > +#undef C
> > +#define C(a, b)SYNTH_ERR_##a
> > +
> > +enum { ERRORS };
> > +
> > +#undef C
> > +#define C(a, b)b
> > +
> > +static const char *err_text[] = { ERRORS };
> > +
> > +static char last_cmd[MAX_FILTER_STR_VAL];
> > +
> > +static int errpos(const char *str)
> > +{
> > +   return err_pos(last_cmd, str);
> > +}
> > +
> > +static void last_cmd_set(char *str)
> > +{
> > +   if (!str)
> > +   return;
> > +
> > +   strncat(last_cmd, str, MAX_FILTER_STR_VAL - 1);
> > +}
> > +
> > +static void synth_err(u8 err_type, u8 err_pos)
> > +{
> > +   tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
> > +   err_type, err_pos);
> > +}
> > +
> > +static void synth_err_clear(void)
> > +{
> > +   last_cmd[0] = '\0';
> > +}
> > +
> >  static int create_synth_event(int argc, const char **argv);
> >  static int synth_event_show(struct seq_file *m, struct dyn_event
> > *ev);
> >  static int synth_event_release(struct dyn_event *ev);
> > @@ -545,8 +592,10 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > field_type++;
> >  
> > if (!strcmp(field_type, "unsigned")) {
> > -   if (argc < 3)
> > +   if (argc < 3) {
> > +   synth_err(SYNTH_ERR_INCOMPLETE_TYPE,
> > errpos(field_type));
> > return ERR_PTR(-EINVAL);
> > +   }
> > prefix = "unsigned ";
> > field_type = argv[1];
> > field_name = argv[2];
> > @@ -573,6 +622,7 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> > goto free;
> > }
> > if (!is_good_name(field->name)) {
> > +   synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
> > ret = -EINVAL;
> > goto free;
> > }
> > @@ -601,6 +651,7 @@ static struct synth_field
> > *parse_synth_field(int argc, const char **argv,
> >  
> > size = synth_field_size(field->type);
> > if (size < 0) {
> > +   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field->name));
> >  

Re: [PATCH v3 1/2] tracing: support "bool" type in synthetic trace events

2020-10-12 Thread Tom Zanussi
Hi Steve,

Looks ok to me.

Acked-by: Tom Zanussi 

Thanks,

Tom


On Mon, 2020-10-12 at 10:15 -0400, Steven Rostedt wrote:
> Tom,
> 
> Can you ack this patch for me?
> 
> -- Steve
> 
> 
> On Fri,  9 Oct 2020 15:05:23 -0700
> Axel Rasmussen  wrote:
> 
> > It's common [1] to define tracepoint fields as "bool" when they
> > contain
> > a true / false value. Currently, defining a synthetic event with a
> > "bool" field yields EINVAL. It's possible to work around this by
> > using
> > e.g. u8 (assuming sizeof(bool) is 1, and bool is unsigned; if
> > either of
> > these properties don't match, you get EINVAL [2]).
> > 
> > Supporting "bool" explicitly makes hooking this up easier and more
> > portable for userspace.
> > 
> > [1]: grep -r "bool" include/trace/events/
> > [2]: check_synth_field() in kernel/trace/trace_events_hist.c
> > 
> > Acked-by: Michel Lespinasse 
> > Signed-off-by: Axel Rasmussen 
> > ---
> >  kernel/trace/trace_events_synth.c | 4 
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/kernel/trace/trace_events_synth.c
> > b/kernel/trace/trace_events_synth.c
> > index 8e1974fbad0e..8f94c84349a6 100644
> > --- a/kernel/trace/trace_events_synth.c
> > +++ b/kernel/trace/trace_events_synth.c
> > @@ -234,6 +234,8 @@ static int synth_field_size(char *type)
> > size = sizeof(long);
> > else if (strcmp(type, "unsigned long") == 0)
> > size = sizeof(unsigned long);
> > +   else if (strcmp(type, "bool") == 0)
> > +   size = sizeof(bool);
> > else if (strcmp(type, "pid_t") == 0)
> > size = sizeof(pid_t);
> > else if (strcmp(type, "gfp_t") == 0)
> > @@ -276,6 +278,8 @@ static const char *synth_field_fmt(char *type)
> > fmt = "%ld";
> > else if (strcmp(type, "unsigned long") == 0)
> > fmt = "%lu";
> > +   else if (strcmp(type, "bool") == 0)
> > +   fmt = "%d";
> > else if (strcmp(type, "pid_t") == 0)
> > fmt = "%d";
> > else if (strcmp(type, "gfp_t") == 0)
> > --
> > 2.28.0.1011.ga647a8990f-goog
> 
> 



  1   2   3   4   5   6   7   8   9   10   >