21
21
#define FPROBE_EVENT_SYSTEM "fprobes"
22
22
#define TRACEPOINT_EVENT_SYSTEM "tracepoints"
23
23
#define RETHOOK_MAXACTIVE_MAX 4096
24
+ #define TRACEPOINT_STUB ERR_PTR(-ENOENT)
24
25
25
26
static int trace_fprobe_create (const char * raw_command );
26
27
static int trace_fprobe_show (struct seq_file * m , struct dyn_event * ev );
@@ -385,6 +386,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
385
386
const char * event ,
386
387
const char * symbol ,
387
388
struct tracepoint * tpoint ,
389
+ struct module * mod ,
388
390
int maxactive ,
389
391
int nargs , bool is_return )
390
392
{
@@ -405,6 +407,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
405
407
tf -> fp .entry_handler = fentry_dispatcher ;
406
408
407
409
tf -> tpoint = tpoint ;
410
+ tf -> mod = mod ;
408
411
tf -> fp .nr_maxactive = maxactive ;
409
412
410
413
ret = trace_probe_init (& tf -> tp , event , group , false, nargs );
@@ -672,6 +675,24 @@ static int unregister_fprobe_event(struct trace_fprobe *tf)
672
675
return trace_probe_unregister_event_call (& tf -> tp );
673
676
}
674
677
678
+ static int __regsiter_tracepoint_fprobe (struct trace_fprobe * tf )
679
+ {
680
+ struct tracepoint * tpoint = tf -> tpoint ;
681
+ unsigned long ip = (unsigned long )tpoint -> probestub ;
682
+ int ret ;
683
+
684
+ /*
685
+ * Here, we do 2 steps to enable fprobe on a tracepoint.
686
+ * At first, put __probestub_##TP function on the tracepoint
687
+ * and put a fprobe on the stub function.
688
+ */
689
+ ret = tracepoint_probe_register_prio_may_exist (tpoint ,
690
+ tpoint -> probestub , NULL , 0 );
691
+ if (ret < 0 )
692
+ return ret ;
693
+ return register_fprobe_ips (& tf -> fp , & ip , 1 );
694
+ }
695
+
675
696
/* Internal register function - just handle fprobe and flags */
676
697
static int __register_trace_fprobe (struct trace_fprobe * tf )
677
698
{
@@ -698,18 +719,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
698
719
tf -> fp .flags |= FPROBE_FL_DISABLED ;
699
720
700
721
if (trace_fprobe_is_tracepoint (tf )) {
701
- struct tracepoint * tpoint = tf -> tpoint ;
702
- unsigned long ip = (unsigned long )tpoint -> probestub ;
703
- /*
704
- * Here, we do 2 steps to enable fprobe on a tracepoint.
705
- * At first, put __probestub_##TP function on the tracepoint
706
- * and put a fprobe on the stub function.
707
- */
708
- ret = tracepoint_probe_register_prio_may_exist (tpoint ,
709
- tpoint -> probestub , NULL , 0 );
710
- if (ret < 0 )
711
- return ret ;
712
- return register_fprobe_ips (& tf -> fp , & ip , 1 );
722
+
723
+ /* This tracepoint is not loaded yet */
724
+ if (tf -> tpoint == TRACEPOINT_STUB )
725
+ return 0 ;
726
+
727
+ return __regsiter_tracepoint_fprobe (tf );
713
728
}
714
729
715
730
/* TODO: handle filter, nofilter or symbol list */
@@ -862,20 +877,106 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
862
877
return ret ;
863
878
}
864
879
880
+ struct __find_tracepoint_cb_data {
881
+ const char * tp_name ;
882
+ struct tracepoint * tpoint ;
883
+ struct module * mod ;
884
+ };
885
+
886
+ static void __find_tracepoint_module_cb (struct tracepoint * tp , struct module * mod , void * priv )
887
+ {
888
+ struct __find_tracepoint_cb_data * data = priv ;
889
+
890
+ if (!data -> tpoint && !strcmp (data -> tp_name , tp -> name )) {
891
+ data -> tpoint = tp ;
892
+ if (!data -> mod ) {
893
+ data -> mod = mod ;
894
+ if (!try_module_get (data -> mod )) {
895
+ data -> tpoint = NULL ;
896
+ data -> mod = NULL ;
897
+ }
898
+ }
899
+ }
900
+ }
901
+
902
+ static void __find_tracepoint_cb (struct tracepoint * tp , void * priv )
903
+ {
904
+ struct __find_tracepoint_cb_data * data = priv ;
905
+
906
+ if (!data -> tpoint && !strcmp (data -> tp_name , tp -> name ))
907
+ data -> tpoint = tp ;
908
+ }
909
+
910
+ /*
911
+ * Find a tracepoint from kernel and module. If the tracepoint is in a module,
912
+ * this increments the module refcount to prevent unloading until the
913
+ * trace_fprobe is registered to the list. After registering the trace_fprobe
914
+ * on the trace_fprobe list, the module refcount is decremented because
915
+ * tracepoint_probe_module_cb will handle it.
916
+ */
917
+ static struct tracepoint * find_tracepoint (const char * tp_name ,
918
+ struct module * * tp_mod )
919
+ {
920
+ struct __find_tracepoint_cb_data data = {
921
+ .tp_name = tp_name ,
922
+ .mod = NULL ,
923
+ };
924
+
925
+ for_each_kernel_tracepoint (__find_tracepoint_cb , & data );
926
+
927
+ if (!data .tpoint && IS_ENABLED (CONFIG_MODULES )) {
928
+ for_each_module_tracepoint (__find_tracepoint_module_cb , & data );
929
+ * tp_mod = data .mod ;
930
+ }
931
+
932
+ return data .tpoint ;
933
+ }
934
+
865
935
#ifdef CONFIG_MODULES
936
+ static void reenable_trace_fprobe (struct trace_fprobe * tf )
937
+ {
938
+ struct trace_probe * tp = & tf -> tp ;
939
+
940
+ list_for_each_entry (tf , trace_probe_probe_list (tp ), tp .list ) {
941
+ __enable_trace_fprobe (tf );
942
+ }
943
+ }
944
+
945
+ static struct tracepoint * find_tracepoint_in_module (struct module * mod ,
946
+ const char * tp_name )
947
+ {
948
+ struct __find_tracepoint_cb_data data = {
949
+ .tp_name = tp_name ,
950
+ .mod = mod ,
951
+ };
952
+
953
+ for_each_tracepoint_in_module (mod , __find_tracepoint_module_cb , & data );
954
+ return data .tpoint ;
955
+ }
956
+
866
957
static int __tracepoint_probe_module_cb (struct notifier_block * self ,
867
958
unsigned long val , void * data )
868
959
{
869
960
struct tp_module * tp_mod = data ;
961
+ struct tracepoint * tpoint ;
870
962
struct trace_fprobe * tf ;
871
963
struct dyn_event * pos ;
872
964
873
- if (val != MODULE_STATE_GOING )
965
+ if (val != MODULE_STATE_GOING && val != MODULE_STATE_COMING )
874
966
return NOTIFY_DONE ;
875
967
876
968
mutex_lock (& event_mutex );
877
969
for_each_trace_fprobe (tf , pos ) {
878
- if (tp_mod -> mod == tf -> mod ) {
970
+ if (val == MODULE_STATE_COMING && tf -> tpoint == TRACEPOINT_STUB ) {
971
+ tpoint = find_tracepoint_in_module (tp_mod -> mod , tf -> symbol );
972
+ if (tpoint ) {
973
+ tf -> tpoint = tpoint ;
974
+ tf -> mod = tp_mod -> mod ;
975
+ if (!WARN_ON_ONCE (__regsiter_tracepoint_fprobe (tf )) &&
976
+ trace_probe_is_enabled (& tf -> tp ))
977
+ reenable_trace_fprobe (tf );
978
+ }
979
+ } else if (val == MODULE_STATE_GOING && tp_mod -> mod == tf -> mod ) {
879
980
tracepoint_probe_unregister (tf -> tpoint ,
880
981
tf -> tpoint -> probestub , NULL );
881
982
tf -> tpoint = NULL ;
@@ -892,30 +993,6 @@ static struct notifier_block tracepoint_module_nb = {
892
993
};
893
994
#endif /* CONFIG_MODULES */
894
995
895
- struct __find_tracepoint_cb_data {
896
- const char * tp_name ;
897
- struct tracepoint * tpoint ;
898
- };
899
-
900
- static void __find_tracepoint_cb (struct tracepoint * tp , void * priv )
901
- {
902
- struct __find_tracepoint_cb_data * data = priv ;
903
-
904
- if (!data -> tpoint && !strcmp (data -> tp_name , tp -> name ))
905
- data -> tpoint = tp ;
906
- }
907
-
908
- static struct tracepoint * find_tracepoint (const char * tp_name )
909
- {
910
- struct __find_tracepoint_cb_data data = {
911
- .tp_name = tp_name ,
912
- };
913
-
914
- for_each_kernel_tracepoint (__find_tracepoint_cb , & data );
915
-
916
- return data .tpoint ;
917
- }
918
-
919
996
static int parse_symbol_and_return (int argc , const char * argv [],
920
997
char * * symbol , bool * is_return ,
921
998
bool is_tracepoint )
@@ -996,6 +1073,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
996
1073
char abuf [MAX_BTF_ARGS_LEN ];
997
1074
char * dbuf = NULL ;
998
1075
bool is_tracepoint = false;
1076
+ struct module * tp_mod = NULL ;
999
1077
struct tracepoint * tpoint = NULL ;
1000
1078
struct traceprobe_parse_context ctx = {
1001
1079
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE ,
@@ -1080,15 +1158,20 @@ static int __trace_fprobe_create(int argc, const char *argv[])
1080
1158
1081
1159
if (is_tracepoint ) {
1082
1160
ctx .flags |= TPARG_FL_TPOINT ;
1083
- tpoint = find_tracepoint (symbol );
1084
- if (!tpoint ) {
1161
+ tpoint = find_tracepoint (symbol , & tp_mod );
1162
+ if (tpoint ) {
1163
+ ctx .funcname = kallsyms_lookup (
1164
+ (unsigned long )tpoint -> probestub ,
1165
+ NULL , NULL , NULL , sbuf );
1166
+ } else if (IS_ENABLED (CONFIG_MODULES )) {
1167
+ /* This *may* be loaded afterwards */
1168
+ tpoint = TRACEPOINT_STUB ;
1169
+ ctx .funcname = symbol ;
1170
+ } else {
1085
1171
trace_probe_log_set_index (1 );
1086
1172
trace_probe_log_err (0 , NO_TRACEPOINT );
1087
1173
goto parse_error ;
1088
1174
}
1089
- ctx .funcname = kallsyms_lookup (
1090
- (unsigned long )tpoint -> probestub ,
1091
- NULL , NULL , NULL , sbuf );
1092
1175
} else
1093
1176
ctx .funcname = symbol ;
1094
1177
@@ -1110,19 +1193,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
1110
1193
goto out ;
1111
1194
1112
1195
/* setup a probe */
1113
- tf = alloc_trace_fprobe (group , event , symbol , tpoint , maxactive ,
1114
- argc , is_return );
1196
+ tf = alloc_trace_fprobe (group , event , symbol , tpoint , tp_mod ,
1197
+ maxactive , argc , is_return );
1115
1198
if (IS_ERR (tf )) {
1116
1199
ret = PTR_ERR (tf );
1117
1200
/* This must return -ENOMEM, else there is a bug */
1118
1201
WARN_ON_ONCE (ret != - ENOMEM );
1119
1202
goto out ; /* We know tf is not allocated */
1120
1203
}
1121
1204
1122
- if (is_tracepoint )
1123
- tf -> mod = __module_text_address (
1124
- (unsigned long )tf -> tpoint -> probestub );
1125
-
1126
1205
/* parse arguments */
1127
1206
for (i = 0 ; i < argc && i < MAX_TRACE_ARGS ; i ++ ) {
1128
1207
trace_probe_log_set_index (i + 2 );
@@ -1155,6 +1234,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
1155
1234
}
1156
1235
1157
1236
out :
1237
+ if (tp_mod )
1238
+ module_put (tp_mod );
1158
1239
traceprobe_finish_parse (& ctx );
1159
1240
trace_probe_log_clear ();
1160
1241
kfree (new_argv );
0 commit comments