diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/name_table.c | 6 | ||||
-rw-r--r-- | net/tipc/name_table.h | 3 | ||||
-rw-r--r-- | net/tipc/server.c | 70 | ||||
-rw-r--r-- | net/tipc/server.h | 6 | ||||
-rw-r--r-- | net/tipc/socket.c | 4 | ||||
-rw-r--r-- | net/tipc/subscr.c | 21 |
6 files changed, 56 insertions, 54 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 64cdd3c302b0..ed0457cc99d6 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -680,8 +680,7 @@ exit: | |||
680 | * - Determines if any node local ports overlap | 680 | * - Determines if any node local ports overlap |
681 | */ | 681 | */ |
682 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, | 682 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, |
683 | u32 upper, u32 scope, | 683 | u32 upper, struct tipc_nlist *nodes) |
684 | struct tipc_nlist *nodes) | ||
685 | { | 684 | { |
686 | struct sub_seq *sseq, *stop; | 685 | struct sub_seq *sseq, *stop; |
687 | struct publication *publ; | 686 | struct publication *publ; |
@@ -699,8 +698,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, | |||
699 | for (; sseq != stop && sseq->lower <= upper; sseq++) { | 698 | for (; sseq != stop && sseq->lower <= upper; sseq++) { |
700 | info = sseq->info; | 699 | info = sseq->info; |
701 | list_for_each_entry(publ, &info->zone_list, zone_list) { | 700 | list_for_each_entry(publ, &info->zone_list, zone_list) { |
702 | if (publ->scope == scope) | 701 | tipc_nlist_add(nodes, publ->node); |
703 | tipc_nlist_add(nodes, publ->node); | ||
704 | } | 702 | } |
705 | } | 703 | } |
706 | spin_unlock_bh(&seq->lock); | 704 | spin_unlock_bh(&seq->lock); |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index b595d8aa00f0..f56e7cb3d436 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -105,8 +105,7 @@ int tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper, | |||
105 | void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, | 105 | void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, |
106 | u32 type, u32 domain); | 106 | u32 type, u32 domain); |
107 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, | 107 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, |
108 | u32 upper, u32 domain, | 108 | u32 upper, struct tipc_nlist *nodes); |
109 | struct tipc_nlist *nodes); | ||
110 | bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, | 109 | bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, |
111 | struct list_head *dsts, int *dstcnt, u32 exclude, | 110 | struct list_head *dsts, int *dstcnt, u32 exclude, |
112 | bool all); | 111 | bool all); |
diff --git a/net/tipc/server.c b/net/tipc/server.c index 8ee5e86b7870..c0d331f13eee 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
@@ -132,10 +132,11 @@ static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid) | |||
132 | 132 | ||
133 | spin_lock_bh(&s->idr_lock); | 133 | spin_lock_bh(&s->idr_lock); |
134 | con = idr_find(&s->conn_idr, conid); | 134 | con = idr_find(&s->conn_idr, conid); |
135 | if (con && test_bit(CF_CONNECTED, &con->flags)) | 135 | if (con) { |
136 | conn_get(con); | 136 | if (!test_bit(CF_CONNECTED, &con->flags) || |
137 | else | 137 | !kref_get_unless_zero(&con->kref)) |
138 | con = NULL; | 138 | con = NULL; |
139 | } | ||
139 | spin_unlock_bh(&s->idr_lock); | 140 | spin_unlock_bh(&s->idr_lock); |
140 | return con; | 141 | return con; |
141 | } | 142 | } |
@@ -183,35 +184,28 @@ static void tipc_register_callbacks(struct socket *sock, struct tipc_conn *con) | |||
183 | write_unlock_bh(&sk->sk_callback_lock); | 184 | write_unlock_bh(&sk->sk_callback_lock); |
184 | } | 185 | } |
185 | 186 | ||
186 | static void tipc_unregister_callbacks(struct tipc_conn *con) | ||
187 | { | ||
188 | struct sock *sk = con->sock->sk; | ||
189 | |||
190 | write_lock_bh(&sk->sk_callback_lock); | ||
191 | sk->sk_user_data = NULL; | ||
192 | write_unlock_bh(&sk->sk_callback_lock); | ||
193 | } | ||
194 | |||
195 | static void tipc_close_conn(struct tipc_conn *con) | 187 | static void tipc_close_conn(struct tipc_conn *con) |
196 | { | 188 | { |
197 | struct tipc_server *s = con->server; | 189 | struct tipc_server *s = con->server; |
190 | struct sock *sk = con->sock->sk; | ||
191 | bool disconnect = false; | ||
198 | 192 | ||
199 | if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { | 193 | write_lock_bh(&sk->sk_callback_lock); |
200 | if (con->sock) | 194 | disconnect = test_and_clear_bit(CF_CONNECTED, &con->flags); |
201 | tipc_unregister_callbacks(con); | 195 | if (disconnect) { |
202 | 196 | sk->sk_user_data = NULL; | |
203 | if (con->conid) | 197 | if (con->conid) |
204 | s->tipc_conn_release(con->conid, con->usr_data); | 198 | s->tipc_conn_release(con->conid, con->usr_data); |
205 | |||
206 | /* We shouldn't flush pending works as we may be in the | ||
207 | * thread. In fact the races with pending rx/tx work structs | ||
208 | * are harmless for us here as we have already deleted this | ||
209 | * connection from server connection list. | ||
210 | */ | ||
211 | if (con->sock) | ||
212 | kernel_sock_shutdown(con->sock, SHUT_RDWR); | ||
213 | conn_put(con); | ||
214 | } | 199 | } |
200 | write_unlock_bh(&sk->sk_callback_lock); | ||
201 | |||
202 | /* Handle concurrent calls from sending and receiving threads */ | ||
203 | if (!disconnect) | ||
204 | return; | ||
205 | |||
206 | /* Don't flush pending works, -just let them expire */ | ||
207 | kernel_sock_shutdown(con->sock, SHUT_RDWR); | ||
208 | conn_put(con); | ||
215 | } | 209 | } |
216 | 210 | ||
217 | static struct tipc_conn *tipc_alloc_conn(struct tipc_server *s) | 211 | static struct tipc_conn *tipc_alloc_conn(struct tipc_server *s) |
@@ -248,9 +242,10 @@ static struct tipc_conn *tipc_alloc_conn(struct tipc_server *s) | |||
248 | 242 | ||
249 | static int tipc_receive_from_sock(struct tipc_conn *con) | 243 | static int tipc_receive_from_sock(struct tipc_conn *con) |
250 | { | 244 | { |
251 | struct msghdr msg = {}; | ||
252 | struct tipc_server *s = con->server; | 245 | struct tipc_server *s = con->server; |
246 | struct sock *sk = con->sock->sk; | ||
253 | struct sockaddr_tipc addr; | 247 | struct sockaddr_tipc addr; |
248 | struct msghdr msg = {}; | ||
254 | struct kvec iov; | 249 | struct kvec iov; |
255 | void *buf; | 250 | void *buf; |
256 | int ret; | 251 | int ret; |
@@ -271,12 +266,15 @@ static int tipc_receive_from_sock(struct tipc_conn *con) | |||
271 | goto out_close; | 266 | goto out_close; |
272 | } | 267 | } |
273 | 268 | ||
274 | s->tipc_conn_recvmsg(sock_net(con->sock->sk), con->conid, &addr, | 269 | read_lock_bh(&sk->sk_callback_lock); |
275 | con->usr_data, buf, ret); | 270 | if (test_bit(CF_CONNECTED, &con->flags)) |
276 | 271 | ret = s->tipc_conn_recvmsg(sock_net(con->sock->sk), con->conid, | |
272 | &addr, con->usr_data, buf, ret); | ||
273 | read_unlock_bh(&sk->sk_callback_lock); | ||
277 | kmem_cache_free(s->rcvbuf_cache, buf); | 274 | kmem_cache_free(s->rcvbuf_cache, buf); |
278 | 275 | if (ret < 0) | |
279 | return 0; | 276 | tipc_conn_terminate(s, con->conid); |
277 | return ret; | ||
280 | 278 | ||
281 | out_close: | 279 | out_close: |
282 | if (ret != -EWOULDBLOCK) | 280 | if (ret != -EWOULDBLOCK) |
@@ -525,11 +523,17 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower, | |||
525 | void tipc_topsrv_kern_unsubscr(struct net *net, int conid) | 523 | void tipc_topsrv_kern_unsubscr(struct net *net, int conid) |
526 | { | 524 | { |
527 | struct tipc_conn *con; | 525 | struct tipc_conn *con; |
526 | struct tipc_server *srv; | ||
528 | 527 | ||
529 | con = tipc_conn_lookup(tipc_topsrv(net), conid); | 528 | con = tipc_conn_lookup(tipc_topsrv(net), conid); |
530 | if (!con) | 529 | if (!con) |
531 | return; | 530 | return; |
532 | tipc_close_conn(con); | 531 | |
532 | test_and_clear_bit(CF_CONNECTED, &con->flags); | ||
533 | srv = con->server; | ||
534 | if (con->conid) | ||
535 | srv->tipc_conn_release(con->conid, con->usr_data); | ||
536 | conn_put(con); | ||
533 | conn_put(con); | 537 | conn_put(con); |
534 | } | 538 | } |
535 | 539 | ||
diff --git a/net/tipc/server.h b/net/tipc/server.h index 17f49ee44cfd..64df7513cd70 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h | |||
@@ -74,9 +74,9 @@ struct tipc_server { | |||
74 | int max_rcvbuf_size; | 74 | int max_rcvbuf_size; |
75 | void *(*tipc_conn_new)(int conid); | 75 | void *(*tipc_conn_new)(int conid); |
76 | void (*tipc_conn_release)(int conid, void *usr_data); | 76 | void (*tipc_conn_release)(int conid, void *usr_data); |
77 | void (*tipc_conn_recvmsg)(struct net *net, int conid, | 77 | int (*tipc_conn_recvmsg)(struct net *net, int conid, |
78 | struct sockaddr_tipc *addr, void *usr_data, | 78 | struct sockaddr_tipc *addr, void *usr_data, |
79 | void *buf, size_t len); | 79 | void *buf, size_t len); |
80 | struct sockaddr_tipc *saddr; | 80 | struct sockaddr_tipc *saddr; |
81 | char name[TIPC_SERVER_NAME_LEN]; | 81 | char name[TIPC_SERVER_NAME_LEN]; |
82 | int imp; | 82 | int imp; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1f236271766c..d799e50ff722 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -772,7 +772,6 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
772 | struct net *net = sock_net(sk); | 772 | struct net *net = sock_net(sk); |
773 | int mtu = tipc_bcast_get_mtu(net); | 773 | int mtu = tipc_bcast_get_mtu(net); |
774 | struct tipc_mc_method *method = &tsk->mc_method; | 774 | struct tipc_mc_method *method = &tsk->mc_method; |
775 | u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE); | ||
776 | struct sk_buff_head pkts; | 775 | struct sk_buff_head pkts; |
777 | struct tipc_nlist dsts; | 776 | struct tipc_nlist dsts; |
778 | int rc; | 777 | int rc; |
@@ -788,7 +787,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
788 | /* Lookup destination nodes */ | 787 | /* Lookup destination nodes */ |
789 | tipc_nlist_init(&dsts, tipc_own_addr(net)); | 788 | tipc_nlist_init(&dsts, tipc_own_addr(net)); |
790 | tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower, | 789 | tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower, |
791 | seq->upper, domain, &dsts); | 790 | seq->upper, &dsts); |
792 | if (!dsts.local && !dsts.remote) | 791 | if (!dsts.local && !dsts.remote) |
793 | return -EHOSTUNREACH; | 792 | return -EHOSTUNREACH; |
794 | 793 | ||
@@ -2774,6 +2773,7 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | |||
2774 | if (rc) { | 2773 | if (rc) { |
2775 | tipc_group_delete(net, grp); | 2774 | tipc_group_delete(net, grp); |
2776 | tsk->group = NULL; | 2775 | tsk->group = NULL; |
2776 | return rc; | ||
2777 | } | 2777 | } |
2778 | /* Eliminate any risk that a broadcast overtakes sent JOINs */ | 2778 | /* Eliminate any risk that a broadcast overtakes sent JOINs */ |
2779 | tsk->mc_method.rcast = true; | 2779 | tsk->mc_method.rcast = true; |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 44df528ed6ab..68e26470c516 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -289,17 +289,16 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, | |||
289 | return sub; | 289 | return sub; |
290 | } | 290 | } |
291 | 291 | ||
292 | static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, | 292 | static int tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, |
293 | struct tipc_subscriber *subscriber, int swap, | 293 | struct tipc_subscriber *subscriber, int swap, |
294 | bool status) | 294 | bool status) |
295 | { | 295 | { |
296 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
297 | struct tipc_subscription *sub = NULL; | 296 | struct tipc_subscription *sub = NULL; |
298 | u32 timeout; | 297 | u32 timeout; |
299 | 298 | ||
300 | sub = tipc_subscrp_create(net, s, swap); | 299 | sub = tipc_subscrp_create(net, s, swap); |
301 | if (!sub) | 300 | if (!sub) |
302 | return tipc_conn_terminate(tn->topsrv, subscriber->conid); | 301 | return -1; |
303 | 302 | ||
304 | spin_lock_bh(&subscriber->lock); | 303 | spin_lock_bh(&subscriber->lock); |
305 | list_add(&sub->subscrp_list, &subscriber->subscrp_list); | 304 | list_add(&sub->subscrp_list, &subscriber->subscrp_list); |
@@ -313,6 +312,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, | |||
313 | 312 | ||
314 | if (timeout != TIPC_WAIT_FOREVER) | 313 | if (timeout != TIPC_WAIT_FOREVER) |
315 | mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); | 314 | mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); |
315 | return 0; | ||
316 | } | 316 | } |
317 | 317 | ||
318 | /* Handle one termination request for the subscriber */ | 318 | /* Handle one termination request for the subscriber */ |
@@ -322,9 +322,9 @@ static void tipc_subscrb_release_cb(int conid, void *usr_data) | |||
322 | } | 322 | } |
323 | 323 | ||
324 | /* Handle one request to create a new subscription for the subscriber */ | 324 | /* Handle one request to create a new subscription for the subscriber */ |
325 | static void tipc_subscrb_rcv_cb(struct net *net, int conid, | 325 | static int tipc_subscrb_rcv_cb(struct net *net, int conid, |
326 | struct sockaddr_tipc *addr, void *usr_data, | 326 | struct sockaddr_tipc *addr, void *usr_data, |
327 | void *buf, size_t len) | 327 | void *buf, size_t len) |
328 | { | 328 | { |
329 | struct tipc_subscriber *subscriber = usr_data; | 329 | struct tipc_subscriber *subscriber = usr_data; |
330 | struct tipc_subscr *s = (struct tipc_subscr *)buf; | 330 | struct tipc_subscr *s = (struct tipc_subscr *)buf; |
@@ -338,10 +338,11 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, | |||
338 | /* Detect & process a subscription cancellation request */ | 338 | /* Detect & process a subscription cancellation request */ |
339 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 339 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
340 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | 340 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
341 | return tipc_subscrp_cancel(s, subscriber); | 341 | tipc_subscrp_cancel(s, subscriber); |
342 | return 0; | ||
342 | } | 343 | } |
343 | status = !(s->filter & htohl(TIPC_SUB_NO_STATUS, swap)); | 344 | status = !(s->filter & htohl(TIPC_SUB_NO_STATUS, swap)); |
344 | tipc_subscrp_subscribe(net, s, subscriber, swap, status); | 345 | return tipc_subscrp_subscribe(net, s, subscriber, swap, status); |
345 | } | 346 | } |
346 | 347 | ||
347 | /* Handle one request to establish a new subscriber */ | 348 | /* Handle one request to establish a new subscriber */ |