@@ -79,20 +79,27 @@ static const struct rhashtable_params fprobe_rht_params = {
7979};
8080
8181/* Node insertion and deletion requires the fprobe_mutex */
82- static int insert_fprobe_node (struct fprobe_hlist_node * node )
82+ static int insert_fprobe_node (struct fprobe_hlist_node * node , struct fprobe * fp )
8383{
84+ int ret ;
85+
8486 lockdep_assert_held (& fprobe_mutex );
8587
86- return rhltable_insert (& fprobe_ip_table , & node -> hlist , fprobe_rht_params );
88+ ret = rhltable_insert (& fprobe_ip_table , & node -> hlist , fprobe_rht_params );
89+ /* Set the fprobe pointer if insertion was successful. */
90+ if (!ret )
91+ WRITE_ONCE (node -> fp , fp );
92+ return ret ;
8793}
8894
8995/* Return true if there are synonims */
9096static bool delete_fprobe_node (struct fprobe_hlist_node * node )
9197{
92- lockdep_assert_held (& fprobe_mutex );
9398 bool ret ;
9499
95- /* Avoid double deleting */
100+ lockdep_assert_held (& fprobe_mutex );
101+
102+ /* Avoid double deleting and non-inserted nodes */
96103 if (READ_ONCE (node -> fp ) != NULL ) {
97104 WRITE_ONCE (node -> fp , NULL );
98105 rhltable_remove (& fprobe_ip_table , & node -> hlist ,
@@ -755,7 +762,6 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
755762 fp -> hlist_array = hlist_array ;
756763 hlist_array -> fp = fp ;
757764 for (i = 0 ; i < num ; i ++ ) {
758- hlist_array -> array [i ].fp = fp ;
759765 addr = ftrace_location (addrs [i ]);
760766 if (!addr ) {
761767 fprobe_fail_cleanup (fp );
@@ -819,6 +825,8 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter
819825}
820826EXPORT_SYMBOL_GPL (register_fprobe );
821827
828+ static int unregister_fprobe_nolock (struct fprobe * fp );
829+
822830/**
823831 * register_fprobe_ips() - Register fprobe to ftrace by address.
824832 * @fp: A fprobe data structure to be registered.
@@ -845,28 +853,25 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
845853 if (ret )
846854 return ret ;
847855
848- hlist_array = fp -> hlist_array ;
849856 if (fprobe_is_ftrace (fp ))
850857 ret = fprobe_ftrace_add_ips (addrs , num );
851858 else
852859 ret = fprobe_graph_add_ips (addrs , num );
853-
854- if (!ret ) {
855- add_fprobe_hash (fp );
856- for (i = 0 ; i < hlist_array -> size ; i ++ ) {
857- ret = insert_fprobe_node (& hlist_array -> array [i ]);
858- if (ret )
859- break ;
860- }
861- /* fallback on insert error */
862- if (ret ) {
863- for (i -- ; i >= 0 ; i -- )
864- delete_fprobe_node (& hlist_array -> array [i ]);
865- }
860+ if (ret ) {
861+ fprobe_fail_cleanup (fp );
862+ return ret ;
866863 }
867864
868- if (ret )
869- fprobe_fail_cleanup (fp );
865+ hlist_array = fp -> hlist_array ;
866+ ret = add_fprobe_hash (fp );
867+ for (i = 0 ; i < hlist_array -> size && !ret ; i ++ )
868+ ret = insert_fprobe_node (& hlist_array -> array [i ], fp );
869+
870+ if (ret ) {
871+ unregister_fprobe_nolock (fp );
872+ /* In error case, wait for clean up safely. */
873+ synchronize_rcu ();
874+ }
870875
871876 return ret ;
872877}
@@ -910,27 +915,12 @@ bool fprobe_is_registered(struct fprobe *fp)
910915 return true;
911916}
912917
913- /**
914- * unregister_fprobe() - Unregister fprobe.
915- * @fp: A fprobe data structure to be unregistered.
916- *
917- * Unregister fprobe (and remove ftrace hooks from the function entries).
918- *
919- * Return 0 if @fp is unregistered successfully, -errno if not.
920- */
921- int unregister_fprobe (struct fprobe * fp )
918+ static int unregister_fprobe_nolock (struct fprobe * fp )
922919{
923- struct fprobe_hlist * hlist_array ;
920+ struct fprobe_hlist * hlist_array = fp -> hlist_array ;
924921 unsigned long * addrs = NULL ;
925- int ret = 0 , i , count ;
922+ int i , count ;
926923
927- mutex_lock (& fprobe_mutex );
928- if (!fp || !fprobe_registered (fp )) {
929- ret = - EINVAL ;
930- goto out ;
931- }
932-
933- hlist_array = fp -> hlist_array ;
934924 addrs = kcalloc (hlist_array -> size , sizeof (unsigned long ), GFP_KERNEL );
935925 if (!addrs ) {
936926 ret = - ENOMEM ; /* TODO: Fallback to one-by-one loop */
@@ -952,12 +942,26 @@ int unregister_fprobe(struct fprobe *fp)
952942
953943 kfree_rcu (hlist_array , rcu );
954944 fp -> hlist_array = NULL ;
945+ kfree (addrs );
955946
956- out :
957- mutex_unlock ( & fprobe_mutex );
947+ return 0 ;
948+ }
958949
959- kfree (addrs );
960- return ret ;
950+ /**
951+ * unregister_fprobe() - Unregister fprobe.
952+ * @fp: A fprobe data structure to be unregistered.
953+ *
954+ * Unregister fprobe (and remove ftrace hooks from the function entries).
955+ *
956+ * Return 0 if @fp is unregistered successfully, -errno if not.
957+ */
958+ int unregister_fprobe (struct fprobe * fp )
959+ {
960+ guard (mutex )(& fprobe_mutex );
961+ if (!fp || !fprobe_registered (fp ))
962+ return - EINVAL ;
963+
964+ return unregister_fprobe_nolock (fp );
961965}
962966EXPORT_SYMBOL_GPL (unregister_fprobe );
963967
0 commit comments