aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>2016-11-01 09:02:47 -0400
committerDavid S. Miller <davem@davemloft.net>2016-11-01 11:53:25 -0400
commit6f00089c7372ba9732c046fe242301dfb0a13233 (patch)
tree39064e06ccdb8a69f2bc8cf4da38f2739f42e14e /net/tipc/socket.c
parent9fd4b070f6311faa7ba1ae746e955fedfbe3e045 (diff)
tipc: remove SS_DISCONNECTING state
In this commit, we replace the references to SS_DISCONNECTING with the combination of sk_state TIPC_DISCONNECTING and flags set in sk_shutdown. We introduce a new function _tipc_shutdown(), which provides the common code required by tipc_release() and tipc_shutdown(). Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c132
1 files changed, 52 insertions, 80 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index a48c0c0676cf..e732b1fe7eab 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -442,6 +442,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
442 } 442 }
443 msg_set_origport(msg, tsk->portid); 443 msg_set_origport(msg, tsk->portid);
444 setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk); 444 setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
445 sk->sk_shutdown = 0;
445 sk->sk_backlog_rcv = tipc_backlog_rcv; 446 sk->sk_backlog_rcv = tipc_backlog_rcv;
446 sk->sk_rcvbuf = sysctl_tipc_rmem[1]; 447 sk->sk_rcvbuf = sysctl_tipc_rmem[1];
447 sk->sk_data_ready = tipc_data_ready; 448 sk->sk_data_ready = tipc_data_ready;
@@ -470,6 +471,44 @@ static void tipc_sk_callback(struct rcu_head *head)
470 sock_put(&tsk->sk); 471 sock_put(&tsk->sk);
471} 472}
472 473
474/* Caller should hold socket lock for the socket. */
475static void __tipc_shutdown(struct socket *sock, int error)
476{
477 struct sock *sk = sock->sk;
478 struct tipc_sock *tsk = tipc_sk(sk);
479 struct net *net = sock_net(sk);
480 u32 dnode = tsk_peer_node(tsk);
481 struct sk_buff *skb;
482
483 /* Reject all unreceived messages, except on an active connection
484 * (which disconnects locally & sends a 'FIN+' to peer).
485 */
486 while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
487 if (TIPC_SKB_CB(skb)->bytes_read) {
488 kfree_skb(skb);
489 } else {
490 if (!tipc_sk_type_connectionless(sk) &&
491 sk->sk_state != TIPC_DISCONNECTING) {
492 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
493 tipc_node_remove_conn(net, dnode, tsk->portid);
494 }
495 tipc_sk_respond(sk, skb, error);
496 }
497 }
498 if (sk->sk_state != TIPC_DISCONNECTING) {
499 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
500 TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
501 tsk_own_node(tsk), tsk_peer_port(tsk),
502 tsk->portid, error);
503 if (skb)
504 tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
505 if (!tipc_sk_type_connectionless(sk)) {
506 tipc_node_remove_conn(net, dnode, tsk->portid);
507 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
508 }
509 }
510}
511
473/** 512/**
474 * tipc_release - destroy a TIPC socket 513 * tipc_release - destroy a TIPC socket
475 * @sock: socket to destroy 514 * @sock: socket to destroy
@@ -489,10 +528,7 @@ static void tipc_sk_callback(struct rcu_head *head)
489static int tipc_release(struct socket *sock) 528static int tipc_release(struct socket *sock)
490{ 529{
491 struct sock *sk = sock->sk; 530 struct sock *sk = sock->sk;
492 struct net *net;
493 struct tipc_sock *tsk; 531 struct tipc_sock *tsk;
494 struct sk_buff *skb;
495 u32 dnode;
496 532
497 /* 533 /*
498 * Exit if socket isn't fully initialized (occurs when a failed accept() 534 * Exit if socket isn't fully initialized (occurs when a failed accept()
@@ -501,46 +537,16 @@ static int tipc_release(struct socket *sock)
501 if (sk == NULL) 537 if (sk == NULL)
502 return 0; 538 return 0;
503 539
504 net = sock_net(sk);
505 tsk = tipc_sk(sk); 540 tsk = tipc_sk(sk);
506 lock_sock(sk); 541 lock_sock(sk);
507 542
508 /* 543 __tipc_shutdown(sock, TIPC_ERR_NO_PORT);
509 * Reject all unreceived messages, except on an active connection 544 sk->sk_shutdown = SHUTDOWN_MASK;
510 * (which disconnects locally & sends a 'FIN+' to peer)
511 */
512 dnode = tsk_peer_node(tsk);
513 while (sock->state != SS_DISCONNECTING) {
514 skb = __skb_dequeue(&sk->sk_receive_queue);
515 if (skb == NULL)
516 break;
517 if (TIPC_SKB_CB(skb)->bytes_read)
518 kfree_skb(skb);
519 else {
520 if ((sock->state == SS_CONNECTING) ||
521 (sock->state == SS_CONNECTED)) {
522 sock->state = SS_DISCONNECTING;
523 tipc_node_remove_conn(net, dnode, tsk->portid);
524 }
525 tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
526 }
527 }
528
529 tipc_sk_withdraw(tsk, 0, NULL); 545 tipc_sk_withdraw(tsk, 0, NULL);
530 sk_stop_timer(sk, &sk->sk_timer); 546 sk_stop_timer(sk, &sk->sk_timer);
531 tipc_sk_remove(tsk); 547 tipc_sk_remove(tsk);
532 if (tipc_sk_connected(sk)) {
533 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
534 TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
535 tsk_own_node(tsk), tsk_peer_port(tsk),
536 tsk->portid, TIPC_ERR_NO_PORT);
537 if (skb)
538 tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
539 tipc_node_remove_conn(net, dnode, tsk->portid);
540 }
541 548
542 /* Reject any messages that accumulated in backlog queue */ 549 /* Reject any messages that accumulated in backlog queue */
543 sock->state = SS_DISCONNECTING;
544 release_sock(sk); 550 release_sock(sk);
545 551
546 call_rcu(&tsk->rcu, tipc_sk_callback); 552 call_rcu(&tsk->rcu, tipc_sk_callback);
@@ -678,6 +684,11 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
678 684
679 sock_poll_wait(file, sk_sleep(sk), wait); 685 sock_poll_wait(file, sk_sleep(sk), wait);
680 686
687 if (sk->sk_shutdown & RCV_SHUTDOWN)
688 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
689 if (sk->sk_shutdown == SHUTDOWN_MASK)
690 mask |= POLLHUP;
691
681 switch ((int)sock->state) { 692 switch ((int)sock->state) {
682 case SS_CONNECTED: 693 case SS_CONNECTED:
683 if (!tsk->link_cong && !tsk_conn_cong(tsk)) 694 if (!tsk->link_cong && !tsk_conn_cong(tsk))
@@ -687,9 +698,6 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
687 if (!skb_queue_empty(&sk->sk_receive_queue)) 698 if (!skb_queue_empty(&sk->sk_receive_queue))
688 mask |= (POLLIN | POLLRDNORM); 699 mask |= (POLLIN | POLLRDNORM);
689 break; 700 break;
690 case SS_DISCONNECTING:
691 mask = (POLLIN | POLLRDNORM | POLLHUP);
692 break;
693 default: 701 default:
694 switch (sk->sk_state) { 702 switch (sk->sk_state) {
695 case TIPC_OPEN: 703 case TIPC_OPEN:
@@ -882,7 +890,7 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
882 int err = sock_error(sk); 890 int err = sock_error(sk);
883 if (err) 891 if (err)
884 return err; 892 return err;
885 if (sock->state == SS_DISCONNECTING) 893 if (sk->sk_shutdown & SEND_SHUTDOWN)
886 return -EPIPE; 894 return -EPIPE;
887 if (!*timeo_p) 895 if (!*timeo_p)
888 return -EAGAIN; 896 return -EAGAIN;
@@ -1335,7 +1343,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1335 for (;;) { 1343 for (;;) {
1336 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1344 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1337 if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { 1345 if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
1338 if (sock->state == SS_DISCONNECTING) { 1346 if (sk->sk_shutdown & RCV_SHUTDOWN) {
1339 err = -ENOTCONN; 1347 err = -ENOTCONN;
1340 break; 1348 break;
1341 } 1349 }
@@ -1676,9 +1684,6 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1676 /* 'ACK-' message is neither accepted nor rejected: */ 1684 /* 'ACK-' message is neither accepted nor rejected: */
1677 msg_set_dest_droppable(hdr, 1); 1685 msg_set_dest_droppable(hdr, 1);
1678 return false; 1686 return false;
1679
1680 case SS_DISCONNECTING:
1681 break;
1682 } 1687 }
1683 1688
1684 switch (sk->sk_state) { 1689 switch (sk->sk_state) {
@@ -2191,13 +2196,6 @@ exit:
2191static int tipc_shutdown(struct socket *sock, int how) 2196static int tipc_shutdown(struct socket *sock, int how)
2192{ 2197{
2193 struct sock *sk = sock->sk; 2198 struct sock *sk = sock->sk;
2194 struct net *net = sock_net(sk);
2195 struct tipc_sock *tsk = tipc_sk(sk);
2196 struct sk_buff *skb;
2197 u32 dnode = tsk_peer_node(tsk);
2198 u32 dport = tsk_peer_port(tsk);
2199 u32 onode = tipc_own_addr(net);
2200 u32 oport = tsk->portid;
2201 int res; 2199 int res;
2202 2200
2203 if (how != SHUT_RDWR) 2201 if (how != SHUT_RDWR)
@@ -2205,43 +2203,17 @@ static int tipc_shutdown(struct socket *sock, int how)
2205 2203
2206 lock_sock(sk); 2204 lock_sock(sk);
2207 2205
2208 if (sock->state == SS_CONNECTING || sock->state == SS_CONNECTED) { 2206 __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
2209 2207 sk->sk_shutdown = SEND_SHUTDOWN;
2210restart:
2211 dnode = tsk_peer_node(tsk);
2212
2213 /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
2214 skb = __skb_dequeue(&sk->sk_receive_queue);
2215 if (skb) {
2216 if (TIPC_SKB_CB(skb)->bytes_read) {
2217 kfree_skb(skb);
2218 goto restart;
2219 }
2220 tipc_sk_respond(sk, skb, TIPC_CONN_SHUTDOWN);
2221 } else {
2222 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
2223 TIPC_CONN_MSG, SHORT_H_SIZE,
2224 0, dnode, onode, dport, oport,
2225 TIPC_CONN_SHUTDOWN);
2226 if (skb)
2227 tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
2228 }
2229 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
2230 tipc_node_remove_conn(net, dnode, tsk->portid);
2231 }
2232
2233 switch (sk->sk_state) {
2234 case TIPC_DISCONNECTING:
2235 2208
2209 if (sk->sk_state == TIPC_DISCONNECTING) {
2236 /* Discard any unreceived messages */ 2210 /* Discard any unreceived messages */
2237 __skb_queue_purge(&sk->sk_receive_queue); 2211 __skb_queue_purge(&sk->sk_receive_queue);
2238 2212
2239 /* Wake up anyone sleeping in poll */ 2213 /* Wake up anyone sleeping in poll */
2240 sk->sk_state_change(sk); 2214 sk->sk_state_change(sk);
2241 res = 0; 2215 res = 0;
2242 break; 2216 } else {
2243
2244 default:
2245 res = -ENOTCONN; 2217 res = -ENOTCONN;
2246 } 2218 }
2247 2219