@@ -336,11 +336,10 @@ static bool fprobe_is_ftrace(struct fprobe *fp)
336336}
337337
338338#ifdef CONFIG_MODULES
339- static void fprobe_set_ips (unsigned long * ips , unsigned int cnt , int remove ,
340- int reset )
339+ static void fprobe_remove_ips (unsigned long * ips , unsigned int cnt )
341340{
342- ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , remove , reset );
343- ftrace_set_filter_ips (& fprobe_ftrace_ops , ips , cnt , remove , reset );
341+ ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , 1 , 0 );
342+ ftrace_set_filter_ips (& fprobe_ftrace_ops , ips , cnt , 1 , 0 );
344343}
345344#endif
346345#else
@@ -359,10 +358,9 @@ static bool fprobe_is_ftrace(struct fprobe *fp)
359358}
360359
361360#ifdef CONFIG_MODULES
362- static void fprobe_set_ips (unsigned long * ips , unsigned int cnt , int remove ,
363- int reset )
361+ static void fprobe_remove_ips (unsigned long * ips , unsigned int cnt )
364362{
365- ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , remove , reset );
363+ ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , 1 , 0 );
366364}
367365#endif
368366#endif /* !CONFIG_DYNAMIC_FTRACE_WITH_ARGS && !CONFIG_DYNAMIC_FTRACE_WITH_REGS */
@@ -536,53 +534,32 @@ static void fprobe_graph_remove_ips(unsigned long *addrs, int num)
536534
537535#ifdef CONFIG_MODULES
538536
539- #define FPROBE_IPS_BATCH_INIT 8
537+ #define FPROBE_IPS_BATCH_INIT 128
540538/* instruction pointer address list */
541539struct fprobe_addr_list {
542540 int index ;
543541 int size ;
544542 unsigned long * addrs ;
545543};
546544
547- static int fprobe_addr_list_add (struct fprobe_addr_list * alist , unsigned long addr )
545+ static int fprobe_remove_node_in_module (struct module * mod , struct fprobe_hlist_node * node ,
546+ struct fprobe_addr_list * alist )
548547{
549- unsigned long * addrs ;
550-
551- /* Previously we failed to expand the list. */
552- if (alist -> index == alist -> size )
553- return - ENOSPC ;
554-
555- alist -> addrs [alist -> index ++ ] = addr ;
556- if (alist -> index < alist -> size )
548+ if (!within_module (node -> addr , mod ))
557549 return 0 ;
558550
559- /* Expand the address list */
560- addrs = kcalloc (alist -> size * 2 , sizeof (* addrs ), GFP_KERNEL );
561- if (!addrs )
562- return - ENOMEM ;
563-
564- memcpy (addrs , alist -> addrs , alist -> size * sizeof (* addrs ));
565- alist -> size *= 2 ;
566- kfree (alist -> addrs );
567- alist -> addrs = addrs ;
551+ if (delete_fprobe_node (node ))
552+ return 0 ;
553+ /* If no address list is available, we can't track this address. */
554+ if (!alist -> addrs )
555+ return 0 ;
568556
557+ alist -> addrs [alist -> index ++ ] = node -> addr ;
558+ if (alist -> index == alist -> size )
559+ return - ENOSPC ;
569560 return 0 ;
570561}
571562
572- static void fprobe_remove_node_in_module (struct module * mod , struct fprobe_hlist_node * node ,
573- struct fprobe_addr_list * alist )
574- {
575- if (!within_module (node -> addr , mod ))
576- return ;
577- if (delete_fprobe_node (node ))
578- return ;
579- /*
580- * If failed to update alist, just continue to update hlist.
581- * Therefore, at list user handler will not hit anymore.
582- */
583- fprobe_addr_list_add (alist , node -> addr );
584- }
585-
586563/* Handle module unloading to manage fprobe_ip_table. */
587564static int fprobe_module_callback (struct notifier_block * nb ,
588565 unsigned long val , void * data )
@@ -591,29 +568,50 @@ static int fprobe_module_callback(struct notifier_block *nb,
591568 struct fprobe_hlist_node * node ;
592569 struct rhashtable_iter iter ;
593570 struct module * mod = data ;
571+ bool retry ;
594572
595573 if (val != MODULE_STATE_GOING )
596574 return NOTIFY_DONE ;
597575
598576 alist .addrs = kcalloc (alist .size , sizeof (* alist .addrs ), GFP_KERNEL );
599- /* If failed to alloc memory, we can not remove ips from hash. */
600- if (!alist .addrs )
601- return NOTIFY_DONE ;
577+ /*
578+ * If failed to alloc memory, ftrace_ops will not be able to remove ips from
579+ * hash, but we can still remove nodes from fprobe_ip_table, so we can avoid
580+ * the potential wrong callback. So just print a warning here and try to
581+ * continue without address list.
582+ */
583+ WARN_ONCE (!alist .addrs ,
584+ "Failed to allocate memory for fprobe_addr_list, ftrace_ops will not be updated" );
602585
603586 mutex_lock (& fprobe_mutex );
587+ again :
588+ retry = false;
589+ alist .index = 0 ;
604590 rhltable_walk_enter (& fprobe_ip_table , & iter );
605591 do {
606592 rhashtable_walk_start (& iter );
607593
608594 while ((node = rhashtable_walk_next (& iter )) && !IS_ERR (node ))
609- fprobe_remove_node_in_module (mod , node , & alist );
595+ if (fprobe_remove_node_in_module (mod , node , & alist ) < 0 ) {
596+ retry = true;
597+ break ;
598+ }
610599
611600 rhashtable_walk_stop (& iter );
612- } while (node == ERR_PTR (- EAGAIN ));
601+ } while (node == ERR_PTR (- EAGAIN ) && ! retry );
613602 rhashtable_walk_exit (& iter );
603+ /* Remove any ips from hash table(s) */
604+ if (alist .index > 0 ) {
605+ fprobe_remove_ips (alist .addrs , alist .index );
606+ /*
607+ * If we break rhashtable walk loop except for -EAGAIN, we need
608+ * to restart looping from start for safety. Anyway, this is
609+ * not a hotpath.
610+ */
611+ if (retry )
612+ goto again ;
613+ }
614614
615- if (alist .index > 0 )
616- fprobe_set_ips (alist .addrs , alist .index , 1 , 0 );
617615 mutex_unlock (& fprobe_mutex );
618616
619617 kfree (alist .addrs );
0 commit comments