Skip to content

Commit 2db832e

Browse files
committed
tracing: fprobe-events: Register fprobe-events only when it is enabled
Currently fprobe events are registered when it is defined. Thus it will give some overhead even if it is disabled. This changes it to register the fprobe only when it is enabled. Link: https://lore.kernel.org/all/174343537128.843280.16131300052837035043.stgit@devnote2/ Suggested-by: Steven Rostedt <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent e3d6e1b commit 2db832e

File tree

3 files changed

+126
-121
lines changed

3 files changed

+126
-121
lines changed

include/linux/fprobe.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num);
9494
int register_fprobe_syms(struct fprobe *fp, const char **syms, int num);
9595
int unregister_fprobe(struct fprobe *fp);
9696
bool fprobe_is_registered(struct fprobe *fp);
97+
int fprobe_count_ips_from_filter(const char *filter, const char *notfilter);
9798
#else
9899
static inline int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter)
99100
{
@@ -115,6 +116,10 @@ static inline bool fprobe_is_registered(struct fprobe *fp)
115116
{
116117
return false;
117118
}
119+
static inline int fprobe_count_ips_from_filter(const char *filter, const char *notfilter)
120+
{
121+
return -EOPNOTSUPP;
122+
}
118123
#endif
119124

120125
/**

kernel/trace/fprobe.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,11 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
648648

649649
#define FPROBE_IPS_MAX INT_MAX
650650

651+
int fprobe_count_ips_from_filter(const char *filter, const char *notfilter)
652+
{
653+
return get_ips_from_filter(filter, notfilter, NULL, NULL, FPROBE_IPS_MAX);
654+
}
655+
651656
/**
652657
* register_fprobe() - Register fprobe to ftrace by pattern.
653658
* @fp: A fprobe data structure to be registered.

kernel/trace/trace_fprobe.c

Lines changed: 116 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -600,98 +600,6 @@ static struct trace_fprobe *find_trace_fprobe(const char *event,
600600
return NULL;
601601
}
602602

603-
static inline int __enable_trace_fprobe(struct trace_fprobe *tf)
604-
{
605-
if (trace_fprobe_is_registered(tf))
606-
enable_fprobe(&tf->fp);
607-
608-
return 0;
609-
}
610-
611-
static void __disable_trace_fprobe(struct trace_probe *tp)
612-
{
613-
struct trace_fprobe *tf;
614-
615-
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
616-
if (!trace_fprobe_is_registered(tf))
617-
continue;
618-
disable_fprobe(&tf->fp);
619-
}
620-
}
621-
622-
/*
623-
* Enable trace_probe
624-
* if the file is NULL, enable "perf" handler, or enable "trace" handler.
625-
*/
626-
static int enable_trace_fprobe(struct trace_event_call *call,
627-
struct trace_event_file *file)
628-
{
629-
struct trace_probe *tp;
630-
struct trace_fprobe *tf;
631-
bool enabled;
632-
int ret = 0;
633-
634-
tp = trace_probe_primary_from_call(call);
635-
if (WARN_ON_ONCE(!tp))
636-
return -ENODEV;
637-
enabled = trace_probe_is_enabled(tp);
638-
639-
/* This also changes "enabled" state */
640-
if (file) {
641-
ret = trace_probe_add_file(tp, file);
642-
if (ret)
643-
return ret;
644-
} else
645-
trace_probe_set_flag(tp, TP_FLAG_PROFILE);
646-
647-
if (!enabled) {
648-
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
649-
/* TODO: check the fprobe is gone */
650-
__enable_trace_fprobe(tf);
651-
}
652-
}
653-
654-
return 0;
655-
}
656-
657-
/*
658-
* Disable trace_probe
659-
* if the file is NULL, disable "perf" handler, or disable "trace" handler.
660-
*/
661-
static int disable_trace_fprobe(struct trace_event_call *call,
662-
struct trace_event_file *file)
663-
{
664-
struct trace_probe *tp;
665-
666-
tp = trace_probe_primary_from_call(call);
667-
if (WARN_ON_ONCE(!tp))
668-
return -ENODEV;
669-
670-
if (file) {
671-
if (!trace_probe_get_file_link(tp, file))
672-
return -ENOENT;
673-
if (!trace_probe_has_single_file(tp))
674-
goto out;
675-
trace_probe_clear_flag(tp, TP_FLAG_TRACE);
676-
} else
677-
trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
678-
679-
if (!trace_probe_is_enabled(tp))
680-
__disable_trace_fprobe(tp);
681-
682-
out:
683-
if (file)
684-
/*
685-
* Synchronization is done in below function. For perf event,
686-
* file == NULL and perf_trace_event_unreg() calls
687-
* tracepoint_synchronize_unregister() to ensure synchronize
688-
* event. We don't need to care about it.
689-
*/
690-
trace_probe_remove_file(tp, file);
691-
692-
return 0;
693-
}
694-
695603
/* Event entry printers */
696604
static enum print_line_t
697605
print_fentry_event(struct trace_iterator *iter, int flags,
@@ -851,6 +759,29 @@ static int __regsiter_tracepoint_fprobe(struct trace_fprobe *tf)
851759
return register_fprobe_ips(&tf->fp, &ip, 1);
852760
}
853761

762+
/* Returns an error if the target function is not available, or 0 */
763+
static int trace_fprobe_verify_target(struct trace_fprobe *tf)
764+
{
765+
int ret;
766+
767+
if (trace_fprobe_is_tracepoint(tf)) {
768+
769+
/* This tracepoint is not loaded yet */
770+
if (!tracepoint_user_is_registered(tf->tuser))
771+
return 0;
772+
773+
/* We assume all stab function is tracable. */
774+
return tracepoint_user_ip(tf->tuser) ? 0 : -ENOENT;
775+
}
776+
777+
/*
778+
* Note: since we don't lock the module, even if this succeeded,
779+
* register_fprobe() later can fail.
780+
*/
781+
ret = fprobe_count_ips_from_filter(tf->symbol, NULL);
782+
return (ret < 0) ? ret : 0;
783+
}
784+
854785
/* Internal register function - just handle fprobe and flags */
855786
static int __register_trace_fprobe(struct trace_fprobe *tf)
856787
{
@@ -870,11 +801,7 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
870801
return ret;
871802
}
872803

873-
/* Set/clear disabled flag according to tp->flag */
874-
if (trace_probe_is_enabled(&tf->tp))
875-
tf->fp.flags &= ~FPROBE_FL_DISABLED;
876-
else
877-
tf->fp.flags |= FPROBE_FL_DISABLED;
804+
tf->fp.flags &= ~FPROBE_FL_DISABLED;
878805

879806
if (trace_fprobe_is_tracepoint(tf)) {
880807

@@ -895,10 +822,10 @@ static void __unregister_trace_fprobe(struct trace_fprobe *tf)
895822
if (trace_fprobe_is_registered(tf)) {
896823
unregister_fprobe(&tf->fp);
897824
memset(&tf->fp, 0, sizeof(tf->fp));
898-
if (trace_fprobe_is_tracepoint(tf)) {
899-
tracepoint_user_put(tf->tuser);
900-
tf->tuser = NULL;
901-
}
825+
}
826+
if (trace_fprobe_is_tracepoint(tf)) {
827+
tracepoint_user_put(tf->tuser);
828+
tf->tuser = NULL;
902829
}
903830
}
904831

@@ -958,7 +885,7 @@ static bool trace_fprobe_has_same_fprobe(struct trace_fprobe *orig,
958885
return false;
959886
}
960887

961-
static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to)
888+
static int append_trace_fprobe_event(struct trace_fprobe *tf, struct trace_fprobe *to)
962889
{
963890
int ret;
964891

@@ -986,7 +913,7 @@ static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to)
986913
if (ret)
987914
return ret;
988915

989-
ret = __register_trace_fprobe(tf);
916+
ret = trace_fprobe_verify_target(tf);
990917
if (ret)
991918
trace_probe_unlink(&tf->tp);
992919
else
@@ -995,8 +922,8 @@ static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to)
995922
return ret;
996923
}
997924

998-
/* Register a trace_probe and probe_event */
999-
static int register_trace_fprobe(struct trace_fprobe *tf)
925+
/* Register a trace_probe and probe_event, and check the fprobe is available. */
926+
static int register_trace_fprobe_event(struct trace_fprobe *tf)
1000927
{
1001928
struct trace_fprobe *old_tf;
1002929
int ret;
@@ -1006,7 +933,7 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
1006933
old_tf = find_trace_fprobe(trace_probe_name(&tf->tp),
1007934
trace_probe_group_name(&tf->tp));
1008935
if (old_tf)
1009-
return append_trace_fprobe(tf, old_tf);
936+
return append_trace_fprobe_event(tf, old_tf);
1010937

1011938
/* Register new event */
1012939
ret = register_fprobe_event(tf);
@@ -1019,8 +946,8 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
1019946
return ret;
1020947
}
1021948

1022-
/* Register fprobe */
1023-
ret = __register_trace_fprobe(tf);
949+
/* Verify fprobe is sane. */
950+
ret = trace_fprobe_verify_target(tf);
1024951
if (ret < 0)
1025952
unregister_fprobe_event(tf);
1026953
else
@@ -1084,15 +1011,6 @@ static struct tracepoint *find_tracepoint(const char *tp_name,
10841011
}
10851012

10861013
#ifdef CONFIG_MODULES
1087-
static void reenable_trace_fprobe(struct trace_fprobe *tf)
1088-
{
1089-
struct trace_probe *tp = &tf->tp;
1090-
1091-
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
1092-
__enable_trace_fprobe(tf);
1093-
}
1094-
}
1095-
10961014
/*
10971015
* Find a tracepoint from specified module. In this case, this does not get the
10981016
* module's refcount. The caller must ensure the module is not freed.
@@ -1146,9 +1064,8 @@ static int __tracepoint_probe_module_cb(struct notifier_block *self,
11461064
}
11471065

11481066
/* Finally enable fprobe on this module. */
1149-
if (!WARN_ON_ONCE(__regsiter_tracepoint_fprobe(tf)) &&
1150-
trace_probe_is_enabled(&tf->tp))
1151-
reenable_trace_fprobe(tf);
1067+
if (trace_probe_is_enabled(&tf->tp) && !trace_fprobe_is_registered(tf))
1068+
WARN_ON_ONCE(__regsiter_tracepoint_fprobe(tf));
11521069
} else if (val == MODULE_STATE_GOING) {
11531070
tuser = tf->tuser;
11541071
/* Unregister all tracepoint_user in this module. */
@@ -1397,7 +1314,7 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
13971314
if (ret < 0)
13981315
return ret;
13991316

1400-
ret = register_trace_fprobe(tf);
1317+
ret = register_trace_fprobe_event(tf);
14011318
if (ret) {
14021319
trace_probe_log_set_index(1);
14031320
if (ret == -EILSEQ)
@@ -1466,6 +1383,84 @@ static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev)
14661383
return 0;
14671384
}
14681385

1386+
/*
1387+
* Enable trace_probe
1388+
* if the file is NULL, enable "perf" handler, or enable "trace" handler.
1389+
*/
1390+
static int enable_trace_fprobe(struct trace_event_call *call,
1391+
struct trace_event_file *file)
1392+
{
1393+
struct trace_probe *tp;
1394+
struct trace_fprobe *tf;
1395+
bool enabled;
1396+
int ret = 0;
1397+
1398+
tp = trace_probe_primary_from_call(call);
1399+
if (WARN_ON_ONCE(!tp))
1400+
return -ENODEV;
1401+
enabled = trace_probe_is_enabled(tp);
1402+
1403+
/* This also changes "enabled" state */
1404+
if (file) {
1405+
ret = trace_probe_add_file(tp, file);
1406+
if (ret)
1407+
return ret;
1408+
} else
1409+
trace_probe_set_flag(tp, TP_FLAG_PROFILE);
1410+
1411+
if (!enabled) {
1412+
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
1413+
ret = __register_trace_fprobe(tf);
1414+
if (ret < 0)
1415+
return ret;
1416+
}
1417+
}
1418+
1419+
return 0;
1420+
}
1421+
1422+
/*
1423+
* Disable trace_probe
1424+
* if the file is NULL, disable "perf" handler, or disable "trace" handler.
1425+
*/
1426+
static int disable_trace_fprobe(struct trace_event_call *call,
1427+
struct trace_event_file *file)
1428+
{
1429+
struct trace_fprobe *tf;
1430+
struct trace_probe *tp;
1431+
1432+
tp = trace_probe_primary_from_call(call);
1433+
if (WARN_ON_ONCE(!tp))
1434+
return -ENODEV;
1435+
1436+
if (file) {
1437+
if (!trace_probe_get_file_link(tp, file))
1438+
return -ENOENT;
1439+
if (!trace_probe_has_single_file(tp))
1440+
goto out;
1441+
trace_probe_clear_flag(tp, TP_FLAG_TRACE);
1442+
} else
1443+
trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
1444+
1445+
if (!trace_probe_is_enabled(tp)) {
1446+
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
1447+
unregister_fprobe(&tf->fp);
1448+
}
1449+
}
1450+
1451+
out:
1452+
if (file)
1453+
/*
1454+
* Synchronization is done in below function. For perf event,
1455+
* file == NULL and perf_trace_event_unreg() calls
1456+
* tracepoint_synchronize_unregister() to ensure synchronize
1457+
* event. We don't need to care about it.
1458+
*/
1459+
trace_probe_remove_file(tp, file);
1460+
1461+
return 0;
1462+
}
1463+
14691464
/*
14701465
* called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
14711466
*/

0 commit comments

Comments
 (0)