17
17
#include <linux/errno.h>
18
18
#include <linux/types.h>
19
19
#include <linux/rcupdate.h>
20
+ #include <linux/rcupdate_trace.h>
20
21
#include <linux/tracepoint-defs.h>
21
22
#include <linux/static_call.h>
22
23
@@ -107,6 +108,7 @@ void for_each_tracepoint_in_module(struct module *mod,
107
108
#ifdef CONFIG_TRACEPOINTS
108
109
static inline void tracepoint_synchronize_unregister (void )
109
110
{
111
+ synchronize_rcu_tasks_trace ();
110
112
synchronize_rcu ();
111
113
}
112
114
#else
@@ -196,6 +198,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
196
198
/*
197
199
* it_func[0] is never NULL because there is at least one element in the array
198
200
* when the array itself is non NULL.
201
+ *
202
+ * With @syscall=0, the tracepoint callback array dereference is
203
+ * protected by disabling preemption.
204
+ * With @syscall=1, the tracepoint callback array dereference is
205
+ * protected by Tasks Trace RCU, which allows probes to handle page
206
+ * faults.
199
207
*/
200
208
#define __DO_TRACE (name , args , cond , syscall ) \
201
209
do { \
@@ -204,11 +212,17 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
204
212
if (!(cond)) \
205
213
return; \
206
214
\
207
- preempt_disable_notrace(); \
215
+ if (syscall) \
216
+ rcu_read_lock_trace(); \
217
+ else \
218
+ preempt_disable_notrace(); \
208
219
\
209
220
__DO_TRACE_CALL(name, TP_ARGS(args)); \
210
221
\
211
- preempt_enable_notrace(); \
222
+ if (syscall) \
223
+ rcu_read_unlock_trace(); \
224
+ else \
225
+ preempt_enable_notrace(); \
212
226
} while (0)
213
227
214
228
/*
0 commit comments