@@ -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 ,
@@ -756,7 +763,6 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
756763 fp -> hlist_array = hlist_array ;
757764 hlist_array -> fp = fp ;
758765 for (i = 0 ; i < num ; i ++ ) {
759- hlist_array -> array [i ].fp = fp ;
760766 addr = ftrace_location (addrs [i ]);
761767 if (!addr ) {
762768 fprobe_fail_cleanup (fp );
@@ -820,6 +826,8 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter
820826}
821827EXPORT_SYMBOL_GPL (register_fprobe );
822828
829+ static int unregister_fprobe_nolock (struct fprobe * fp );
830+
823831/**
824832 * register_fprobe_ips() - Register fprobe to ftrace by address.
825833 * @fp: A fprobe data structure to be registered.
@@ -846,28 +854,25 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
846854 if (ret )
847855 return ret ;
848856
849- hlist_array = fp -> hlist_array ;
850857 if (fprobe_is_ftrace (fp ))
851858 ret = fprobe_ftrace_add_ips (addrs , num );
852859 else
853860 ret = fprobe_graph_add_ips (addrs , num );
854-
855- if (!ret ) {
856- add_fprobe_hash (fp );
857- for (i = 0 ; i < hlist_array -> size ; i ++ ) {
858- ret = insert_fprobe_node (& hlist_array -> array [i ]);
859- if (ret )
860- break ;
861- }
862- /* fallback on insert error */
863- if (ret ) {
864- for (i -- ; i >= 0 ; i -- )
865- delete_fprobe_node (& hlist_array -> array [i ]);
866- }
861+ if (ret ) {
862+ fprobe_fail_cleanup (fp );
863+ return ret ;
867864 }
868865
869- if (ret )
870- fprobe_fail_cleanup (fp );
866+ hlist_array = fp -> hlist_array ;
867+ ret = add_fprobe_hash (fp );
868+ for (i = 0 ; i < hlist_array -> size && !ret ; i ++ )
869+ ret = insert_fprobe_node (& hlist_array -> array [i ], fp );
870+
871+ if (ret ) {
872+ unregister_fprobe_nolock (fp );
873+ /* In error case, wait for clean up safely. */
874+ synchronize_rcu ();
875+ }
871876
872877 return ret ;
873878}
@@ -911,27 +916,12 @@ bool fprobe_is_registered(struct fprobe *fp)
911916 return true;
912917}
913918
914- /**
915- * unregister_fprobe() - Unregister fprobe.
916- * @fp: A fprobe data structure to be unregistered.
917- *
918- * Unregister fprobe (and remove ftrace hooks from the function entries).
919- *
920- * Return 0 if @fp is unregistered successfully, -errno if not.
921- */
922- int unregister_fprobe (struct fprobe * fp )
919+ static int unregister_fprobe_nolock (struct fprobe * fp )
923920{
924- struct fprobe_hlist * hlist_array ;
921+ struct fprobe_hlist * hlist_array = fp -> hlist_array ;
925922 unsigned long * addrs = NULL ;
926- int ret = 0 , i , count ;
923+ int i , count ;
927924
928- mutex_lock (& fprobe_mutex );
929- if (!fp || !fprobe_registered (fp )) {
930- ret = - EINVAL ;
931- goto out ;
932- }
933-
934- hlist_array = fp -> hlist_array ;
935925 addrs = kcalloc (hlist_array -> size , sizeof (unsigned long ), GFP_KERNEL );
936926 /*
937927 * This will remove fprobe_hash_node from the hash table even if
@@ -957,12 +947,26 @@ int unregister_fprobe(struct fprobe *fp)
957947
958948 kfree_rcu (hlist_array , rcu );
959949 fp -> hlist_array = NULL ;
950+ kfree (addrs );
960951
961- out :
962- mutex_unlock ( & fprobe_mutex );
952+ return 0 ;
953+ }
963954
964- kfree (addrs );
965- return ret ;
955+ /**
956+ * unregister_fprobe() - Unregister fprobe.
957+ * @fp: A fprobe data structure to be unregistered.
958+ *
959+ * Unregister fprobe (and remove ftrace hooks from the function entries).
960+ *
961+ * Return 0 if @fp is unregistered successfully, -errno if not.
962+ */
963+ int unregister_fprobe (struct fprobe * fp )
964+ {
965+ guard (mutex )(& fprobe_mutex );
966+ if (!fp || !fprobe_registered (fp ))
967+ return - EINVAL ;
968+
969+ return unregister_fprobe_nolock (fp );
966970}
967971EXPORT_SYMBOL_GPL (unregister_fprobe );
968972
0 commit comments