Commit 
fa2c3254d7cf (sched/tracing: Don't re-read p->state when emitting
sched_switch event, 2022-01-20) added a new prev_state argument to the
sched_switch tracepoint, before the prev task_struct pointer.
This reordering of arguments broke BPF programs that use the raw
tracepoint (e.g. tp_btf programs). The type of the second argument has
changed and existing programs that assume a task_struct* argument
(e.g. for bpf_task_storage access) will now fail to verify.
If we instead append the new argument to the end, all existing programs
would continue to work and can conditionally extract the prev_state
argument on supported kernel versions.
Fixes: fa2c3254d7cf (sched/tracing: Don't re-read p->state when emitting sched_switch event, 2022-01-20)
Signed-off-by: Delyan Kratunov <delyank@fb.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Link: https://lkml.kernel.org/r/c8a6930dfdd58a4a5755fc01732675472979732b.camel@fb.com
 TRACE_EVENT(sched_switch,
 
        TP_PROTO(bool preempt,
-                unsigned int prev_state,
                 struct task_struct *prev,
-                struct task_struct *next),
+                struct task_struct *next,
+                unsigned int prev_state),
 
-       TP_ARGS(preempt, prev_state, prev, next),
+       TP_ARGS(preempt, prev, next, prev_state),
 
        TP_STRUCT__entry(
                __array(        char,   prev_comm,      TASK_COMM_LEN   )
 
                migrate_disable_switch(rq, prev);
                psi_sched_switch(prev, next, !task_on_rq_queued(prev));
 
-               trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev_state, prev, next);
+               trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
 
                /* Also unlocks the rq: */
                rq = context_switch(rq, prev, next, &rf);
 
 
 static void
 ftrace_graph_probe_sched_switch(void *ignore, bool preempt,
-                               unsigned int prev_state,
                                struct task_struct *prev,
-                               struct task_struct *next)
+                               struct task_struct *next,
+                               unsigned int prev_state)
 {
        unsigned long long timestamp;
        int index;
 
 
 static void
 ftrace_filter_pid_sched_switch_probe(void *data, bool preempt,
-                                    unsigned int prev_state,
                                     struct task_struct *prev,
-                                    struct task_struct *next)
+                                    struct task_struct *next,
+                                    unsigned int prev_state)
 {
        struct trace_array *tr = data;
        struct trace_pid_list *pid_list;
 
 
 static void
 event_filter_pid_sched_switch_probe_pre(void *data, bool preempt,
-                                       unsigned int prev_state,
                                        struct task_struct *prev,
-                                       struct task_struct *next)
+                                       struct task_struct *next,
+                                       unsigned int prev_state)
 {
        struct trace_array *tr = data;
        struct trace_pid_list *no_pid_list;
 
 static void
 event_filter_pid_sched_switch_probe_post(void *data, bool preempt,
-                                        unsigned int prev_state,
                                         struct task_struct *prev,
-                                        struct task_struct *next)
+                                        struct task_struct *next,
+                                        unsigned int prev_state)
 {
        struct trace_array *tr = data;
        struct trace_pid_list *no_pid_list;
 
  */
 static void
 trace_sched_switch_callback(void *data, bool preempt,
-                           unsigned int prev_state,
                            struct task_struct *p,
-                           struct task_struct *n)
+                           struct task_struct *n,
+                           unsigned int prev_state)
 {
        struct osnoise_variables *osn_var = this_cpu_osn_var();
 
 
 
 static void
 probe_sched_switch(void *ignore, bool preempt,
-                  unsigned int prev_state,
-                  struct task_struct *prev, struct task_struct *next)
+                  struct task_struct *prev, struct task_struct *next,
+                  unsigned int prev_state)
 {
        int flags;
 
 
 
 static void notrace
 probe_wakeup_sched_switch(void *ignore, bool preempt,
-                         unsigned int prev_state,
-                         struct task_struct *prev, struct task_struct *next)
+                         struct task_struct *prev, struct task_struct *next,
+                         unsigned int prev_state)
 {
        struct trace_array_cpu *data;
        u64 T0, T1, delta;
 
         * that the custom event is using.
         */
        TP_PROTO(bool preempt,
-                unsigned int prev_state,
                 struct task_struct *prev,
-                struct task_struct *next),
+                struct task_struct *next,
+                unsigned int prev_state),
 
-       TP_ARGS(preempt, prev_state, prev, next),
+       TP_ARGS(preempt, prev, next, prev_state),
 
        /*
         * The next fields are where the customization happens.