Skip to content

Commit

Permalink
tipc: fix failed service subscription deletion
Browse files Browse the repository at this point in the history
When a service subscription is expired or canceled by user, it needs to
be deleted from the subscription list, so that new subscriptions can be
registered (max = 65535 per net). However, there are two issues in code
that can cause such an unused subscription to persist:

1) The 'tipc_conn_delete_sub()' has a loop on the subscription list but
it makes a break shortly when the 1st subscription differs from the one
specified, so the subscription will not be deleted.

2) In case a subscription is canceled, the code to remove the
'TIPC_SUB_CANCEL' flag from the subscription filter does not work if it
is a local subscription (i.e. the little endian isn't involved). So, it
will be no matches when looking for the subscription to delete later.

The subscription(s) will be removed eventually when the user terminates
its topology connection but that could be a long time later. Meanwhile,
the number of available subscriptions may be exhausted.

This commit fixes the two issues above, so as needed a subscription can
be deleted correctly.

Acked-by: Ying Xue <ying.xue@windriver.com>
Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Tuong Lien authored and David S. Miller committed May 13, 2020
1 parent 0771d7d commit 88690b1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
10 changes: 10 additions & 0 deletions net/tipc/subscr.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ void tipc_sub_get(struct tipc_subscription *subscription);
(swap_ ? swab32(val__) : val__); \
})

/* tipc_sub_write - write val_ to field_ of struct sub_ in user endian format
*/
#define tipc_sub_write(sub_, field_, val_) \
({ \
struct tipc_subscr *sub__ = sub_; \
u32 val__ = val_; \
int swap_ = !((sub__)->filter & TIPC_FILTER_MASK); \
(sub__)->field_ = swap_ ? swab32(val__) : val__; \
})

/* tipc_evt_write - write val_ to field_ of struct evt_ in user endian format
*/
#define tipc_evt_write(evt_, field_, val_) \
Expand Down
9 changes: 5 additions & 4 deletions net/tipc/topsrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ static void tipc_conn_delete_sub(struct tipc_conn *con, struct tipc_subscr *s)
if (!s || !memcmp(s, &sub->evt.s, sizeof(*s))) {
tipc_sub_unsubscribe(sub);
atomic_dec(&tn->subscription_count);
} else if (s) {
break;
if (s)
break;
}
}
spin_unlock_bh(&con->sub_lock);
Expand Down Expand Up @@ -362,9 +362,10 @@ static int tipc_conn_rcv_sub(struct tipc_topsrv *srv,
{
struct tipc_net *tn = tipc_net(srv->net);
struct tipc_subscription *sub;
u32 s_filter = tipc_sub_read(s, filter);

if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) {
s->filter &= __constant_ntohl(~TIPC_SUB_CANCEL);
if (s_filter & TIPC_SUB_CANCEL) {
tipc_sub_write(s, filter, s_filter & ~TIPC_SUB_CANCEL);
tipc_conn_delete_sub(con, s);
return 0;
}
Expand Down

0 comments on commit 88690b1

Please sign in to comment.