Commit 557d054c authored by Ying Xue's avatar Ying Xue Committed by David S. Miller

tipc: fix nametbl deadlock at tipc_nametbl_unsubscribe

Until now, tipc_nametbl_unsubscribe() is called at subscriptions
reference count cleanup. Usually the subscriptions cleanup is
called at subscription timeout or at subscription cancel or at
subscriber delete.

We have ignored the possibility of this being called from other
locations, which causes deadlock as we try to grab the
tn->nametbl_lock while holding it already.

   CPU1:                             CPU2:
----------                     ----------------
tipc_nametbl_publish
spin_lock_bh(&tn->nametbl_lock)
tipc_nametbl_insert_publ
tipc_nameseq_insert_publ
tipc_subscrp_report_overlap
tipc_subscrp_get
tipc_subscrp_send_event
                             tipc_close_conn
                             tipc_subscrb_release_cb
                             tipc_subscrb_delete
                             tipc_subscrp_put
tipc_subscrp_put
tipc_subscrp_kref_release
tipc_nametbl_unsubscribe
spin_lock_bh(&tn->nametbl_lock)
<<grab nametbl_lock again>>

   CPU1:                              CPU2:
----------                     ----------------
tipc_nametbl_stop
spin_lock_bh(&tn->nametbl_lock)
tipc_purge_publications
tipc_nameseq_remove_publ
tipc_subscrp_report_overlap
tipc_subscrp_get
tipc_subscrp_send_event
                             tipc_close_conn
                             tipc_subscrb_release_cb
                             tipc_subscrb_delete
                             tipc_subscrp_put
tipc_subscrp_put
tipc_subscrp_kref_release
tipc_nametbl_unsubscribe
spin_lock_bh(&tn->nametbl_lock)
<<grab nametbl_lock again>>

In this commit, we advance the calling of tipc_nametbl_unsubscribe()
from the refcount cleanup to the intended callers.

Fixes: d094c4d5 ("tipc: add subscription refcount to avoid invalid delete")
Reported-by: default avatarJohn Thompson <thompa.atl@gmail.com>
Acked-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 58194778
...@@ -141,6 +141,11 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, ...@@ -141,6 +141,11 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
static void tipc_subscrp_timeout(unsigned long data) static void tipc_subscrp_timeout(unsigned long data)
{ {
struct tipc_subscription *sub = (struct tipc_subscription *)data; struct tipc_subscription *sub = (struct tipc_subscription *)data;
struct tipc_subscriber *subscriber = sub->subscriber;
spin_lock_bh(&subscriber->lock);
tipc_nametbl_unsubscribe(sub);
spin_unlock_bh(&subscriber->lock);
/* Notify subscriber of timeout */ /* Notify subscriber of timeout */
tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
...@@ -173,7 +178,6 @@ static void tipc_subscrp_kref_release(struct kref *kref) ...@@ -173,7 +178,6 @@ static void tipc_subscrp_kref_release(struct kref *kref)
struct tipc_subscriber *subscriber = sub->subscriber; struct tipc_subscriber *subscriber = sub->subscriber;
spin_lock_bh(&subscriber->lock); spin_lock_bh(&subscriber->lock);
tipc_nametbl_unsubscribe(sub);
list_del(&sub->subscrp_list); list_del(&sub->subscrp_list);
atomic_dec(&tn->subscription_count); atomic_dec(&tn->subscription_count);
spin_unlock_bh(&subscriber->lock); spin_unlock_bh(&subscriber->lock);
...@@ -205,6 +209,7 @@ static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber, ...@@ -205,6 +209,7 @@ static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber,
if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr)))
continue; continue;
tipc_nametbl_unsubscribe(sub);
tipc_subscrp_get(sub); tipc_subscrp_get(sub);
spin_unlock_bh(&subscriber->lock); spin_unlock_bh(&subscriber->lock);
tipc_subscrp_delete(sub); tipc_subscrp_delete(sub);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment