@@ -344,11 +344,10 @@ static bool fprobe_is_ftrace(struct fprobe *fp)
344344}
345345
346346#ifdef CONFIG_MODULES
347- static void fprobe_set_ips (unsigned long * ips , unsigned int cnt , int remove ,
348- int reset )
347+ static void fprobe_remove_ips (unsigned long * ips , unsigned int cnt )
349348{
350- ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , remove , reset );
351- ftrace_set_filter_ips (& fprobe_ftrace_ops , ips , cnt , remove , reset );
349+ ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , 1 , 0 );
350+ ftrace_set_filter_ips (& fprobe_ftrace_ops , ips , cnt , 1 , 0 );
352351}
353352#endif
354353#else
@@ -367,10 +366,9 @@ static bool fprobe_is_ftrace(struct fprobe *fp)
367366}
368367
369368#ifdef CONFIG_MODULES
370- static void fprobe_set_ips (unsigned long * ips , unsigned int cnt , int remove ,
371- int reset )
369+ static void fprobe_remove_ips (unsigned long * ips , unsigned int cnt )
372370{
373- ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , remove , reset );
371+ ftrace_set_filter_ips (& fprobe_graph_ops .ops , ips , cnt , 1 , 0 );
374372}
375373#endif
376374#endif /* !CONFIG_DYNAMIC_FTRACE_WITH_ARGS && !CONFIG_DYNAMIC_FTRACE_WITH_REGS */
@@ -542,53 +540,32 @@ static void fprobe_graph_remove_ips(unsigned long *addrs, int num)
542540
543541#ifdef CONFIG_MODULES
544542
545- #define FPROBE_IPS_BATCH_INIT 8
543+ #define FPROBE_IPS_BATCH_INIT 128
546544/* instruction pointer address list */
547545struct fprobe_addr_list {
548546 int index ;
549547 int size ;
550548 unsigned long * addrs ;
551549};
552550
553- static int fprobe_addr_list_add (struct fprobe_addr_list * alist , unsigned long addr )
551+ static int fprobe_remove_node_in_module (struct module * mod , struct fprobe_hlist_node * node ,
552+ struct fprobe_addr_list * alist )
554553{
555- unsigned long * addrs ;
556-
557- /* Previously we failed to expand the list. */
558- if (alist -> index == alist -> size )
559- return - ENOSPC ;
560-
561- alist -> addrs [alist -> index ++ ] = addr ;
562- if (alist -> index < alist -> size )
554+ if (!within_module (node -> addr , mod ))
563555 return 0 ;
564556
565- /* Expand the address list */
566- addrs = kcalloc (alist -> size * 2 , sizeof (* addrs ), GFP_KERNEL );
567- if (!addrs )
568- return - ENOMEM ;
569-
570- memcpy (addrs , alist -> addrs , alist -> size * sizeof (* addrs ));
571- alist -> size *= 2 ;
572- kfree (alist -> addrs );
573- alist -> addrs = addrs ;
557+ if (delete_fprobe_node (node ))
558+ return 0 ;
559+ /* If no address list is available, we can't track this address. */
560+ if (!alist -> addrs )
561+ return 0 ;
574562
563+ alist -> addrs [alist -> index ++ ] = node -> addr ;
564+ if (alist -> index == alist -> size )
565+ return - ENOSPC ;
575566 return 0 ;
576567}
577568
578- static void fprobe_remove_node_in_module (struct module * mod , struct fprobe_hlist_node * node ,
579- struct fprobe_addr_list * alist )
580- {
581- if (!within_module (node -> addr , mod ))
582- return ;
583- if (delete_fprobe_node (node ))
584- return ;
585- /*
586- * If failed to update alist, just continue to update hlist.
587- * Therefore, at list user handler will not hit anymore.
588- */
589- fprobe_addr_list_add (alist , node -> addr );
590- }
591-
592569/* Handle module unloading to manage fprobe_ip_table. */
593570static int fprobe_module_callback (struct notifier_block * nb ,
594571 unsigned long val , void * data )
@@ -597,29 +574,50 @@ static int fprobe_module_callback(struct notifier_block *nb,
597574 struct fprobe_hlist_node * node ;
598575 struct rhashtable_iter iter ;
599576 struct module * mod = data ;
577+ bool retry ;
600578
601579 if (val != MODULE_STATE_GOING )
602580 return NOTIFY_DONE ;
603581
604582 alist .addrs = kcalloc (alist .size , sizeof (* alist .addrs ), GFP_KERNEL );
605- /* If failed to alloc memory, we can not remove ips from hash. */
606- if (!alist .addrs )
607- return NOTIFY_DONE ;
583+ /*
584+ * If failed to alloc memory, ftrace_ops will not be able to remove ips from
585+ * hash, but we can still remove nodes from fprobe_ip_table, so we can avoid
586+ * the potential wrong callback. So just print a warning here and try to
587+ * continue without address list.
588+ */
589+ WARN_ONCE (!alist .addrs ,
590+ "Failed to allocate memory for fprobe_addr_list, ftrace_ops will not be updated" );
608591
609592 mutex_lock (& fprobe_mutex );
593+ again :
594+ retry = false;
595+ alist .index = 0 ;
610596 rhltable_walk_enter (& fprobe_ip_table , & iter );
611597 do {
612598 rhashtable_walk_start (& iter );
613599
614600 while ((node = rhashtable_walk_next (& iter )) && !IS_ERR (node ))
615- fprobe_remove_node_in_module (mod , node , & alist );
601+ if (fprobe_remove_node_in_module (mod , node , & alist ) < 0 ) {
602+ retry = true;
603+ break ;
604+ }
616605
617606 rhashtable_walk_stop (& iter );
618- } while (node == ERR_PTR (- EAGAIN ));
607+ } while (node == ERR_PTR (- EAGAIN ) && ! retry );
619608 rhashtable_walk_exit (& iter );
609+ /* Remove any ips from hash table(s) */
610+ if (alist .index > 0 ) {
611+ fprobe_remove_ips (alist .addrs , alist .index );
612+ /*
613+ * If we break rhashtable walk loop except for -EAGAIN, we need
614+ * to restart looping from start for safety. Anyway, this is
615+ * not a hotpath.
616+ */
617+ if (retry )
618+ goto again ;
619+ }
620620
621- if (alist .index > 0 )
622- fprobe_set_ips (alist .addrs , alist .index , 1 , 0 );
623621 mutex_unlock (& fprobe_mutex );
624622
625623 kfree (alist .addrs );
0 commit comments