2121#define FPROBE_EVENT_SYSTEM "fprobes"
2222#define TRACEPOINT_EVENT_SYSTEM "tracepoints"
2323#define RETHOOK_MAXACTIVE_MAX 4096
24+ #define TRACEPOINT_STUB ERR_PTR(-ENOENT)
2425
2526static int trace_fprobe_create (const char * raw_command );
2627static 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,
385386 const char * event ,
386387 const char * symbol ,
387388 struct tracepoint * tpoint ,
389+ struct module * mod ,
388390 int maxactive ,
389391 int nargs , bool is_return )
390392{
@@ -405,6 +407,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
405407 tf -> fp .entry_handler = fentry_dispatcher ;
406408
407409 tf -> tpoint = tpoint ;
410+ tf -> mod = mod ;
408411 tf -> fp .nr_maxactive = maxactive ;
409412
410413 ret = trace_probe_init (& tf -> tp , event , group , false, nargs );
@@ -672,6 +675,24 @@ static int unregister_fprobe_event(struct trace_fprobe *tf)
672675 return trace_probe_unregister_event_call (& tf -> tp );
673676}
674677
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+
675696/* Internal register function - just handle fprobe and flags */
676697static int __register_trace_fprobe (struct trace_fprobe * tf )
677698{
@@ -698,18 +719,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
698719 tf -> fp .flags |= FPROBE_FL_DISABLED ;
699720
700721 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 );
713728 }
714729
715730 /* TODO: handle filter, nofilter or symbol list */
@@ -862,20 +877,106 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
862877 return ret ;
863878}
864879
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+
865935#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+
866957static int __tracepoint_probe_module_cb (struct notifier_block * self ,
867958 unsigned long val , void * data )
868959{
869960 struct tp_module * tp_mod = data ;
961+ struct tracepoint * tpoint ;
870962 struct trace_fprobe * tf ;
871963 struct dyn_event * pos ;
872964
873- if (val != MODULE_STATE_GOING )
965+ if (val != MODULE_STATE_GOING && val != MODULE_STATE_COMING )
874966 return NOTIFY_DONE ;
875967
876968 mutex_lock (& event_mutex );
877969 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 ) {
879980 tracepoint_probe_unregister (tf -> tpoint ,
880981 tf -> tpoint -> probestub , NULL );
881982 tf -> tpoint = NULL ;
@@ -892,30 +993,6 @@ static struct notifier_block tracepoint_module_nb = {
892993};
893994#endif /* CONFIG_MODULES */
894995
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-
919996static int parse_symbol_and_return (int argc , const char * argv [],
920997 char * * symbol , bool * is_return ,
921998 bool is_tracepoint )
@@ -996,6 +1073,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
9961073 char abuf [MAX_BTF_ARGS_LEN ];
9971074 char * dbuf = NULL ;
9981075 bool is_tracepoint = false;
1076+ struct module * tp_mod = NULL ;
9991077 struct tracepoint * tpoint = NULL ;
10001078 struct traceprobe_parse_context ctx = {
10011079 .flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE ,
@@ -1080,15 +1158,20 @@ static int __trace_fprobe_create(int argc, const char *argv[])
10801158
10811159 if (is_tracepoint ) {
10821160 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 {
10851171 trace_probe_log_set_index (1 );
10861172 trace_probe_log_err (0 , NO_TRACEPOINT );
10871173 goto parse_error ;
10881174 }
1089- ctx .funcname = kallsyms_lookup (
1090- (unsigned long )tpoint -> probestub ,
1091- NULL , NULL , NULL , sbuf );
10921175 } else
10931176 ctx .funcname = symbol ;
10941177
@@ -1110,19 +1193,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11101193 goto out ;
11111194
11121195 /* 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 );
11151198 if (IS_ERR (tf )) {
11161199 ret = PTR_ERR (tf );
11171200 /* This must return -ENOMEM, else there is a bug */
11181201 WARN_ON_ONCE (ret != - ENOMEM );
11191202 goto out ; /* We know tf is not allocated */
11201203 }
11211204
1122- if (is_tracepoint )
1123- tf -> mod = __module_text_address (
1124- (unsigned long )tf -> tpoint -> probestub );
1125-
11261205 /* parse arguments */
11271206 for (i = 0 ; i < argc && i < MAX_TRACE_ARGS ; i ++ ) {
11281207 trace_probe_log_set_index (i + 2 );
@@ -1155,6 +1234,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11551234 }
11561235
11571236out :
1237+ if (tp_mod )
1238+ module_put (tp_mod );
11581239 traceprobe_finish_parse (& ctx );
11591240 trace_probe_log_clear ();
11601241 kfree (new_argv );
0 commit comments