@@ -60,7 +60,6 @@ static struct dyn_event_operations trace_uprobe_ops = {
60
60
*/
61
61
struct trace_uprobe {
62
62
struct dyn_event devent ;
63
- struct trace_uprobe_filter filter ;
64
63
struct uprobe_consumer consumer ;
65
64
struct path path ;
66
65
struct inode * inode ;
@@ -264,6 +263,14 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
264
263
}
265
264
NOKPROBE_SYMBOL (process_fetch_insn )
266
265
266
+ static struct trace_uprobe_filter *
267
+ trace_uprobe_get_filter (struct trace_uprobe * tu )
268
+ {
269
+ struct trace_probe_event * event = tu -> tp .event ;
270
+
271
+ return (struct trace_uprobe_filter * )& event -> data [0 ];
272
+ }
273
+
267
274
static inline void init_trace_uprobe_filter (struct trace_uprobe_filter * filter )
268
275
{
269
276
rwlock_init (& filter -> rwlock );
@@ -351,15 +358,16 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
351
358
if (!tu )
352
359
return ERR_PTR (- ENOMEM );
353
360
354
- ret = trace_probe_init (& tu -> tp , event , group );
361
+ ret = trace_probe_init (& tu -> tp , event , group ,
362
+ sizeof (struct trace_uprobe_filter ));
355
363
if (ret < 0 )
356
364
goto error ;
357
365
358
366
dyn_event_init (& tu -> devent , & trace_uprobe_ops );
359
367
tu -> consumer .handler = uprobe_dispatcher ;
360
368
if (is_ret )
361
369
tu -> consumer .ret_handler = uretprobe_dispatcher ;
362
- init_trace_uprobe_filter (& tu -> filter );
370
+ init_trace_uprobe_filter (trace_uprobe_get_filter ( tu ) );
363
371
return tu ;
364
372
365
373
error :
@@ -1067,13 +1075,14 @@ static void __probe_event_disable(struct trace_probe *tp)
1067
1075
struct trace_probe * pos ;
1068
1076
struct trace_uprobe * tu ;
1069
1077
1078
+ tu = container_of (tp , struct trace_uprobe , tp );
1079
+ WARN_ON (!uprobe_filter_is_empty (trace_uprobe_get_filter (tu )));
1080
+
1070
1081
list_for_each_entry (pos , trace_probe_probe_list (tp ), list ) {
1071
1082
tu = container_of (pos , struct trace_uprobe , tp );
1072
1083
if (!tu -> inode )
1073
1084
continue ;
1074
1085
1075
- WARN_ON (!uprobe_filter_is_empty (& tu -> filter ));
1076
-
1077
1086
uprobe_unregister (tu -> inode , tu -> offset , & tu -> consumer );
1078
1087
tu -> inode = NULL ;
1079
1088
}
@@ -1108,7 +1117,7 @@ static int probe_event_enable(struct trace_event_call *call,
1108
1117
}
1109
1118
1110
1119
tu = container_of (tp , struct trace_uprobe , tp );
1111
- WARN_ON (!uprobe_filter_is_empty (& tu -> filter ));
1120
+ WARN_ON (!uprobe_filter_is_empty (trace_uprobe_get_filter ( tu ) ));
1112
1121
1113
1122
if (enabled )
1114
1123
return 0 ;
@@ -1205,39 +1214,39 @@ __uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
1205
1214
}
1206
1215
1207
1216
static inline bool
1208
- uprobe_filter_event (struct trace_uprobe * tu , struct perf_event * event )
1217
+ trace_uprobe_filter_event (struct trace_uprobe_filter * filter ,
1218
+ struct perf_event * event )
1209
1219
{
1210
- return __uprobe_perf_filter (& tu -> filter , event -> hw .target -> mm );
1220
+ return __uprobe_perf_filter (filter , event -> hw .target -> mm );
1211
1221
}
1212
1222
1213
- static int uprobe_perf_close (struct trace_uprobe * tu , struct perf_event * event )
1223
+ static bool trace_uprobe_filter_remove (struct trace_uprobe_filter * filter ,
1224
+ struct perf_event * event )
1214
1225
{
1215
1226
bool done ;
1216
1227
1217
- write_lock (& tu -> filter . rwlock );
1228
+ write_lock (& filter -> rwlock );
1218
1229
if (event -> hw .target ) {
1219
1230
list_del (& event -> hw .tp_list );
1220
- done = tu -> filter . nr_systemwide ||
1231
+ done = filter -> nr_systemwide ||
1221
1232
(event -> hw .target -> flags & PF_EXITING ) ||
1222
- uprobe_filter_event ( tu , event );
1233
+ trace_uprobe_filter_event ( filter , event );
1223
1234
} else {
1224
- tu -> filter . nr_systemwide -- ;
1225
- done = tu -> filter . nr_systemwide ;
1235
+ filter -> nr_systemwide -- ;
1236
+ done = filter -> nr_systemwide ;
1226
1237
}
1227
- write_unlock (& tu -> filter .rwlock );
1228
-
1229
- if (!done )
1230
- return uprobe_apply (tu -> inode , tu -> offset , & tu -> consumer , false);
1238
+ write_unlock (& filter -> rwlock );
1231
1239
1232
- return 0 ;
1240
+ return done ;
1233
1241
}
1234
1242
1235
- static int uprobe_perf_open (struct trace_uprobe * tu , struct perf_event * event )
1243
+ /* This returns true if the filter always covers target mm */
1244
+ static bool trace_uprobe_filter_add (struct trace_uprobe_filter * filter ,
1245
+ struct perf_event * event )
1236
1246
{
1237
1247
bool done ;
1238
- int err ;
1239
1248
1240
- write_lock (& tu -> filter . rwlock );
1249
+ write_lock (& filter -> rwlock );
1241
1250
if (event -> hw .target ) {
1242
1251
/*
1243
1252
* event->parent != NULL means copy_process(), we can avoid
@@ -1247,28 +1256,21 @@ static int uprobe_perf_open(struct trace_uprobe *tu, struct perf_event *event)
1247
1256
* attr.enable_on_exec means that exec/mmap will install the
1248
1257
* breakpoints we need.
1249
1258
*/
1250
- done = tu -> filter . nr_systemwide ||
1259
+ done = filter -> nr_systemwide ||
1251
1260
event -> parent || event -> attr .enable_on_exec ||
1252
- uprobe_filter_event ( tu , event );
1253
- list_add (& event -> hw .tp_list , & tu -> filter . perf_events );
1261
+ trace_uprobe_filter_event ( filter , event );
1262
+ list_add (& event -> hw .tp_list , & filter -> perf_events );
1254
1263
} else {
1255
- done = tu -> filter . nr_systemwide ;
1256
- tu -> filter . nr_systemwide ++ ;
1264
+ done = filter -> nr_systemwide ;
1265
+ filter -> nr_systemwide ++ ;
1257
1266
}
1258
- write_unlock (& tu -> filter . rwlock );
1267
+ write_unlock (& filter -> rwlock );
1259
1268
1260
- err = 0 ;
1261
- if (!done ) {
1262
- err = uprobe_apply (tu -> inode , tu -> offset , & tu -> consumer , true);
1263
- if (err )
1264
- uprobe_perf_close (tu , event );
1265
- }
1266
- return err ;
1269
+ return done ;
1267
1270
}
1268
1271
1269
- static int uprobe_perf_multi_call (struct trace_event_call * call ,
1270
- struct perf_event * event ,
1271
- int (* op )(struct trace_uprobe * tu , struct perf_event * event ))
1272
+ static int uprobe_perf_close (struct trace_event_call * call ,
1273
+ struct perf_event * event )
1272
1274
{
1273
1275
struct trace_probe * pos , * tp ;
1274
1276
struct trace_uprobe * tu ;
@@ -1278,25 +1280,59 @@ static int uprobe_perf_multi_call(struct trace_event_call *call,
1278
1280
if (WARN_ON_ONCE (!tp ))
1279
1281
return - ENODEV ;
1280
1282
1283
+ tu = container_of (tp , struct trace_uprobe , tp );
1284
+ if (trace_uprobe_filter_remove (trace_uprobe_get_filter (tu ), event ))
1285
+ return 0 ;
1286
+
1281
1287
list_for_each_entry (pos , trace_probe_probe_list (tp ), list ) {
1282
1288
tu = container_of (pos , struct trace_uprobe , tp );
1283
- ret = op (tu , event );
1289
+ ret = uprobe_apply (tu -> inode , tu -> offset , & tu -> consumer , false );
1284
1290
if (ret )
1285
1291
break ;
1286
1292
}
1287
1293
1288
1294
return ret ;
1289
1295
}
1296
+
1297
+ static int uprobe_perf_open (struct trace_event_call * call ,
1298
+ struct perf_event * event )
1299
+ {
1300
+ struct trace_probe * pos , * tp ;
1301
+ struct trace_uprobe * tu ;
1302
+ int err = 0 ;
1303
+
1304
+ tp = trace_probe_primary_from_call (call );
1305
+ if (WARN_ON_ONCE (!tp ))
1306
+ return - ENODEV ;
1307
+
1308
+ tu = container_of (tp , struct trace_uprobe , tp );
1309
+ if (trace_uprobe_filter_add (trace_uprobe_get_filter (tu ), event ))
1310
+ return 0 ;
1311
+
1312
+ list_for_each_entry (pos , trace_probe_probe_list (tp ), list ) {
1313
+ err = uprobe_apply (tu -> inode , tu -> offset , & tu -> consumer , true);
1314
+ if (err ) {
1315
+ uprobe_perf_close (call , event );
1316
+ break ;
1317
+ }
1318
+ }
1319
+
1320
+ return err ;
1321
+ }
1322
+
1290
1323
static bool uprobe_perf_filter (struct uprobe_consumer * uc ,
1291
1324
enum uprobe_filter_ctx ctx , struct mm_struct * mm )
1292
1325
{
1326
+ struct trace_uprobe_filter * filter ;
1293
1327
struct trace_uprobe * tu ;
1294
1328
int ret ;
1295
1329
1296
1330
tu = container_of (uc , struct trace_uprobe , consumer );
1297
- read_lock (& tu -> filter .rwlock );
1298
- ret = __uprobe_perf_filter (& tu -> filter , mm );
1299
- read_unlock (& tu -> filter .rwlock );
1331
+ filter = trace_uprobe_get_filter (tu );
1332
+
1333
+ read_lock (& filter -> rwlock );
1334
+ ret = __uprobe_perf_filter (filter , mm );
1335
+ read_unlock (& filter -> rwlock );
1300
1336
1301
1337
return ret ;
1302
1338
}
@@ -1419,10 +1455,10 @@ trace_uprobe_register(struct trace_event_call *event, enum trace_reg type,
1419
1455
return 0 ;
1420
1456
1421
1457
case TRACE_REG_PERF_OPEN :
1422
- return uprobe_perf_multi_call (event , data , uprobe_perf_open );
1458
+ return uprobe_perf_open (event , data );
1423
1459
1424
1460
case TRACE_REG_PERF_CLOSE :
1425
- return uprobe_perf_multi_call (event , data , uprobe_perf_close );
1461
+ return uprobe_perf_close (event , data );
1426
1462
1427
1463
#endif
1428
1464
default :
0 commit comments