@@ -136,12 +136,12 @@ static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd)
136136}
137137
138138/**
139- * tipc_service_find_range - find service range matching a service instance
139+ * tipc_service_first_range - find first service range in tree matching instance
140140 *
141141 * Very time-critical, so binary search through range rb tree
142142 */
143- static struct service_range * tipc_service_find_range (struct tipc_service * sc ,
144- u32 instance )
143+ static struct service_range * tipc_service_first_range (struct tipc_service * sc ,
144+ u32 instance )
145145{
146146 struct rb_node * n = sc -> ranges .rb_node ;
147147 struct service_range * sr ;
@@ -158,6 +158,30 @@ static struct service_range *tipc_service_find_range(struct tipc_service *sc,
158158 return NULL ;
159159}
160160
161+ /* tipc_service_find_range - find service range matching publication parameters
162+ */
163+ static struct service_range * tipc_service_find_range (struct tipc_service * sc ,
164+ u32 lower , u32 upper )
165+ {
166+ struct rb_node * n = sc -> ranges .rb_node ;
167+ struct service_range * sr ;
168+
169+ sr = tipc_service_first_range (sc , lower );
170+ if (!sr )
171+ return NULL ;
172+
173+ /* Look for exact match */
174+ for (n = & sr -> tree_node ; n ; n = rb_next (n )) {
175+ sr = container_of (n , struct service_range , tree_node );
176+ if (sr -> upper == upper )
177+ break ;
178+ }
179+ if (!n || sr -> lower != lower || sr -> upper != upper )
180+ return NULL ;
181+
182+ return sr ;
183+ }
184+
161185static struct service_range * tipc_service_create_range (struct tipc_service * sc ,
162186 u32 lower , u32 upper )
163187{
@@ -238,54 +262,19 @@ static struct publication *tipc_service_insert_publ(struct net *net,
238262/**
239263 * tipc_service_remove_publ - remove a publication from a service
240264 */
241- static struct publication * tipc_service_remove_publ (struct net * net ,
242- struct tipc_service * sc ,
243- u32 lower , u32 upper ,
244- u32 node , u32 key ,
245- struct service_range * * rng )
265+ static struct publication * tipc_service_remove_publ (struct service_range * sr ,
266+ u32 node , u32 key )
246267{
247- struct tipc_subscription * sub , * tmp ;
248- struct service_range * sr ;
249268 struct publication * p ;
250- bool found = false;
251- bool last = false;
252- struct rb_node * n ;
253-
254- sr = tipc_service_find_range (sc , lower );
255- if (!sr )
256- return NULL ;
257269
258- /* Find exact matching service range */
259- for (n = & sr -> tree_node ; n ; n = rb_next (n )) {
260- sr = container_of (n , struct service_range , tree_node );
261- if (sr -> upper == upper )
262- break ;
263- }
264- if (!n || sr -> lower != lower || sr -> upper != upper )
265- return NULL ;
266-
267- /* Find publication, if it exists */
268270 list_for_each_entry (p , & sr -> all_publ , all_publ ) {
269271 if (p -> key != key || (node && node != p -> node ))
270272 continue ;
271- found = true;
272- break ;
273+ list_del (& p -> all_publ );
274+ list_del (& p -> local_publ );
275+ return p ;
273276 }
274- if (!found )
275- return NULL ;
276-
277- list_del (& p -> all_publ );
278- list_del (& p -> local_publ );
279- if (list_empty (& sr -> all_publ ))
280- last = true;
281-
282- /* Notify any waiting subscriptions */
283- list_for_each_entry_safe (sub , tmp , & sc -> subscriptions , service_list ) {
284- tipc_sub_report_overlap (sub , p -> lower , p -> upper , TIPC_WITHDRAWN ,
285- p -> port , p -> node , p -> scope , last );
286- }
287- * rng = sr ;
288- return p ;
277+ return NULL ;
289278}
290279
291280/**
@@ -376,17 +365,31 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
376365 u32 node , u32 key )
377366{
378367 struct tipc_service * sc = tipc_service_find (net , type );
368+ struct tipc_subscription * sub , * tmp ;
379369 struct service_range * sr = NULL ;
380370 struct publication * p = NULL ;
371+ bool last ;
381372
382373 if (!sc )
383374 return NULL ;
384375
385376 spin_lock_bh (& sc -> lock );
386- p = tipc_service_remove_publ (net , sc , lower , upper , node , key , & sr );
377+ sr = tipc_service_find_range (sc , lower , upper );
378+ if (!sr )
379+ goto exit ;
380+ p = tipc_service_remove_publ (sr , node , key );
381+ if (!p )
382+ goto exit ;
383+
384+ /* Notify any waiting subscriptions */
385+ last = list_empty (& sr -> all_publ );
386+ list_for_each_entry_safe (sub , tmp , & sc -> subscriptions , service_list ) {
387+ tipc_sub_report_overlap (sub , lower , upper , TIPC_WITHDRAWN ,
388+ p -> port , node , p -> scope , last );
389+ }
387390
388391 /* Remove service range item if this was its last publication */
389- if (sr && list_empty (& sr -> all_publ )) {
392+ if (list_empty (& sr -> all_publ )) {
390393 rb_erase (& sr -> tree_node , & sc -> ranges );
391394 kfree (sr );
392395 }
@@ -396,6 +399,7 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
396399 hlist_del_init_rcu (& sc -> service_list );
397400 kfree_rcu (sc , rcu );
398401 }
402+ exit :
399403 spin_unlock_bh (& sc -> lock );
400404 return p ;
401405}
@@ -437,7 +441,7 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode)
437441 goto not_found ;
438442
439443 spin_lock_bh (& sc -> lock );
440- sr = tipc_service_find_range (sc , instance );
444+ sr = tipc_service_first_range (sc , instance );
441445 if (unlikely (!sr ))
442446 goto no_match ;
443447
@@ -484,7 +488,7 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope,
484488
485489 spin_lock_bh (& sc -> lock );
486490
487- sr = tipc_service_find_range (sc , instance );
491+ sr = tipc_service_first_range (sc , instance );
488492 if (!sr )
489493 goto no_match ;
490494
@@ -756,8 +760,7 @@ static void tipc_service_delete(struct net *net, struct tipc_service *sc)
756760 spin_lock_bh (& sc -> lock );
757761 rbtree_postorder_for_each_entry_safe (sr , tmpr , & sc -> ranges , tree_node ) {
758762 list_for_each_entry_safe (p , tmp , & sr -> all_publ , all_publ ) {
759- tipc_service_remove_publ (net , sc , p -> lower , p -> upper ,
760- p -> node , p -> key , & sr );
763+ tipc_service_remove_publ (sr , p -> node , p -> key );
761764 kfree_rcu (p , rcu );
762765 }
763766 rb_erase (& sr -> tree_node , & sc -> ranges );
0 commit comments