diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/name_table.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 4068eaad61a6..dd1c4fa2eb78 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -241,7 +241,8 @@ err: | |||
241 | static struct publication *tipc_service_remove_publ(struct net *net, | 241 | static struct publication *tipc_service_remove_publ(struct net *net, |
242 | struct tipc_service *sc, | 242 | struct tipc_service *sc, |
243 | u32 lower, u32 upper, | 243 | u32 lower, u32 upper, |
244 | u32 node, u32 key) | 244 | u32 node, u32 key, |
245 | struct service_range **rng) | ||
245 | { | 246 | { |
246 | struct tipc_subscription *sub, *tmp; | 247 | struct tipc_subscription *sub, *tmp; |
247 | struct service_range *sr; | 248 | struct service_range *sr; |
@@ -275,19 +276,15 @@ static struct publication *tipc_service_remove_publ(struct net *net, | |||
275 | 276 | ||
276 | list_del(&p->all_publ); | 277 | list_del(&p->all_publ); |
277 | list_del(&p->local_publ); | 278 | list_del(&p->local_publ); |
278 | 279 | if (list_empty(&sr->all_publ)) | |
279 | /* Remove service range item if this was its last publication */ | ||
280 | if (list_empty(&sr->all_publ)) { | ||
281 | last = true; | 280 | last = true; |
282 | rb_erase(&sr->tree_node, &sc->ranges); | ||
283 | kfree(sr); | ||
284 | } | ||
285 | 281 | ||
286 | /* Notify any waiting subscriptions */ | 282 | /* Notify any waiting subscriptions */ |
287 | list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { | 283 | list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { |
288 | tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_WITHDRAWN, | 284 | tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_WITHDRAWN, |
289 | p->port, p->node, p->scope, last); | 285 | p->port, p->node, p->scope, last); |
290 | } | 286 | } |
287 | *rng = sr; | ||
291 | return p; | 288 | return p; |
292 | } | 289 | } |
293 | 290 | ||
@@ -379,13 +376,20 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, | |||
379 | u32 node, u32 key) | 376 | u32 node, u32 key) |
380 | { | 377 | { |
381 | struct tipc_service *sc = tipc_service_find(net, type); | 378 | struct tipc_service *sc = tipc_service_find(net, type); |
379 | struct service_range *sr = NULL; | ||
382 | struct publication *p = NULL; | 380 | struct publication *p = NULL; |
383 | 381 | ||
384 | if (!sc) | 382 | if (!sc) |
385 | return NULL; | 383 | return NULL; |
386 | 384 | ||
387 | spin_lock_bh(&sc->lock); | 385 | spin_lock_bh(&sc->lock); |
388 | p = tipc_service_remove_publ(net, sc, lower, upper, node, key); | 386 | p = tipc_service_remove_publ(net, sc, lower, upper, node, key, &sr); |
387 | |||
388 | /* Remove service range item if this was its last publication */ | ||
389 | if (sr && list_empty(&sr->all_publ)) { | ||
390 | rb_erase(&sr->tree_node, &sc->ranges); | ||
391 | kfree(sr); | ||
392 | } | ||
389 | 393 | ||
390 | /* Delete service item if this no more publications and subscriptions */ | 394 | /* Delete service item if this no more publications and subscriptions */ |
391 | if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { | 395 | if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { |
@@ -747,16 +751,17 @@ int tipc_nametbl_init(struct net *net) | |||
747 | static void tipc_service_delete(struct net *net, struct tipc_service *sc) | 751 | static void tipc_service_delete(struct net *net, struct tipc_service *sc) |
748 | { | 752 | { |
749 | struct service_range *sr, *tmpr; | 753 | struct service_range *sr, *tmpr; |
750 | struct publication *p, *tmpb; | 754 | struct publication *p, *tmp; |
751 | 755 | ||
752 | spin_lock_bh(&sc->lock); | 756 | spin_lock_bh(&sc->lock); |
753 | rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) { | 757 | rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) { |
754 | list_for_each_entry_safe(p, tmpb, | 758 | list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) { |
755 | &sr->all_publ, all_publ) { | ||
756 | tipc_service_remove_publ(net, sc, p->lower, p->upper, | 759 | tipc_service_remove_publ(net, sc, p->lower, p->upper, |
757 | p->node, p->key); | 760 | p->node, p->key, &sr); |
758 | kfree_rcu(p, rcu); | 761 | kfree_rcu(p, rcu); |
759 | } | 762 | } |
763 | rb_erase(&sr->tree_node, &sc->ranges); | ||
764 | kfree(sr); | ||
760 | } | 765 | } |
761 | hlist_del_init_rcu(&sc->service_list); | 766 | hlist_del_init_rcu(&sc->service_list); |
762 | spin_unlock_bh(&sc->lock); | 767 | spin_unlock_bh(&sc->lock); |