mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									9fd4b070f6
								
							
						
					
					
						commit
						6f00089c73
					
				
					 1 changed files with 52 additions and 80 deletions
				
			
		| 
						 | 
				
			
			@ -442,6 +442,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
 | 
			
		|||
	}
 | 
			
		||||
	msg_set_origport(msg, tsk->portid);
 | 
			
		||||
	setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
 | 
			
		||||
	sk->sk_shutdown = 0;
 | 
			
		||||
	sk->sk_backlog_rcv = tipc_backlog_rcv;
 | 
			
		||||
	sk->sk_rcvbuf = sysctl_tipc_rmem[1];
 | 
			
		||||
	sk->sk_data_ready = tipc_data_ready;
 | 
			
		||||
| 
						 | 
				
			
			@ -470,6 +471,44 @@ static void tipc_sk_callback(struct rcu_head *head)
 | 
			
		|||
	sock_put(&tsk->sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Caller should hold socket lock for the socket. */
 | 
			
		||||
static void __tipc_shutdown(struct socket *sock, int error)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk = sock->sk;
 | 
			
		||||
	struct tipc_sock *tsk = tipc_sk(sk);
 | 
			
		||||
	struct net *net = sock_net(sk);
 | 
			
		||||
	u32 dnode = tsk_peer_node(tsk);
 | 
			
		||||
	struct sk_buff *skb;
 | 
			
		||||
 | 
			
		||||
	/* Reject all unreceived messages, except on an active connection
 | 
			
		||||
	 * (which disconnects locally & sends a 'FIN+' to peer).
 | 
			
		||||
	 */
 | 
			
		||||
	while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 | 
			
		||||
		if (TIPC_SKB_CB(skb)->bytes_read) {
 | 
			
		||||
			kfree_skb(skb);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (!tipc_sk_type_connectionless(sk) &&
 | 
			
		||||
			    sk->sk_state != TIPC_DISCONNECTING) {
 | 
			
		||||
				tipc_set_sk_state(sk, TIPC_DISCONNECTING);
 | 
			
		||||
				tipc_node_remove_conn(net, dnode, tsk->portid);
 | 
			
		||||
			}
 | 
			
		||||
			tipc_sk_respond(sk, skb, error);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (sk->sk_state != TIPC_DISCONNECTING) {
 | 
			
		||||
		skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
 | 
			
		||||
				      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
 | 
			
		||||
				      tsk_own_node(tsk), tsk_peer_port(tsk),
 | 
			
		||||
				      tsk->portid, error);
 | 
			
		||||
		if (skb)
 | 
			
		||||
			tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
 | 
			
		||||
		if (!tipc_sk_type_connectionless(sk)) {
 | 
			
		||||
			tipc_node_remove_conn(net, dnode, tsk->portid);
 | 
			
		||||
			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * tipc_release - destroy a TIPC socket
 | 
			
		||||
 * @sock: socket to destroy
 | 
			
		||||
| 
						 | 
				
			
			@ -489,10 +528,7 @@ static void tipc_sk_callback(struct rcu_head *head)
 | 
			
		|||
static int tipc_release(struct socket *sock)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk = sock->sk;
 | 
			
		||||
	struct net *net;
 | 
			
		||||
	struct tipc_sock *tsk;
 | 
			
		||||
	struct sk_buff *skb;
 | 
			
		||||
	u32 dnode;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Exit if socket isn't fully initialized (occurs when a failed accept()
 | 
			
		||||
| 
						 | 
				
			
			@ -501,46 +537,16 @@ static int tipc_release(struct socket *sock)
 | 
			
		|||
	if (sk == NULL)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	net = sock_net(sk);
 | 
			
		||||
	tsk = tipc_sk(sk);
 | 
			
		||||
	lock_sock(sk);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Reject all unreceived messages, except on an active connection
 | 
			
		||||
	 * (which disconnects locally & sends a 'FIN+' to peer)
 | 
			
		||||
	 */
 | 
			
		||||
	dnode = tsk_peer_node(tsk);
 | 
			
		||||
	while (sock->state != SS_DISCONNECTING) {
 | 
			
		||||
		skb = __skb_dequeue(&sk->sk_receive_queue);
 | 
			
		||||
		if (skb == NULL)
 | 
			
		||||
			break;
 | 
			
		||||
		if (TIPC_SKB_CB(skb)->bytes_read)
 | 
			
		||||
			kfree_skb(skb);
 | 
			
		||||
		else {
 | 
			
		||||
			if ((sock->state == SS_CONNECTING) ||
 | 
			
		||||
			    (sock->state == SS_CONNECTED)) {
 | 
			
		||||
				sock->state = SS_DISCONNECTING;
 | 
			
		||||
				tipc_node_remove_conn(net, dnode, tsk->portid);
 | 
			
		||||
			}
 | 
			
		||||
			tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	__tipc_shutdown(sock, TIPC_ERR_NO_PORT);
 | 
			
		||||
	sk->sk_shutdown = SHUTDOWN_MASK;
 | 
			
		||||
	tipc_sk_withdraw(tsk, 0, NULL);
 | 
			
		||||
	sk_stop_timer(sk, &sk->sk_timer);
 | 
			
		||||
	tipc_sk_remove(tsk);
 | 
			
		||||
	if (tipc_sk_connected(sk)) {
 | 
			
		||||
		skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
 | 
			
		||||
				      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
 | 
			
		||||
				      tsk_own_node(tsk), tsk_peer_port(tsk),
 | 
			
		||||
				      tsk->portid, TIPC_ERR_NO_PORT);
 | 
			
		||||
		if (skb)
 | 
			
		||||
			tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
 | 
			
		||||
		tipc_node_remove_conn(net, dnode, tsk->portid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Reject any messages that accumulated in backlog queue */
 | 
			
		||||
	sock->state = SS_DISCONNECTING;
 | 
			
		||||
	release_sock(sk);
 | 
			
		||||
 | 
			
		||||
	call_rcu(&tsk->rcu, tipc_sk_callback);
 | 
			
		||||
| 
						 | 
				
			
			@ -678,6 +684,11 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
 | 
			
		|||
 | 
			
		||||
	sock_poll_wait(file, sk_sleep(sk), wait);
 | 
			
		||||
 | 
			
		||||
	if (sk->sk_shutdown & RCV_SHUTDOWN)
 | 
			
		||||
		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 | 
			
		||||
	if (sk->sk_shutdown == SHUTDOWN_MASK)
 | 
			
		||||
		mask |= POLLHUP;
 | 
			
		||||
 | 
			
		||||
	switch ((int)sock->state) {
 | 
			
		||||
	case SS_CONNECTED:
 | 
			
		||||
		if (!tsk->link_cong && !tsk_conn_cong(tsk))
 | 
			
		||||
| 
						 | 
				
			
			@ -687,9 +698,6 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
 | 
			
		|||
		if (!skb_queue_empty(&sk->sk_receive_queue))
 | 
			
		||||
			mask |= (POLLIN | POLLRDNORM);
 | 
			
		||||
		break;
 | 
			
		||||
	case SS_DISCONNECTING:
 | 
			
		||||
		mask = (POLLIN | POLLRDNORM | POLLHUP);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		switch (sk->sk_state) {
 | 
			
		||||
		case TIPC_OPEN:
 | 
			
		||||
| 
						 | 
				
			
			@ -882,7 +890,7 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
 | 
			
		|||
		int err = sock_error(sk);
 | 
			
		||||
		if (err)
 | 
			
		||||
			return err;
 | 
			
		||||
		if (sock->state == SS_DISCONNECTING)
 | 
			
		||||
		if (sk->sk_shutdown & SEND_SHUTDOWN)
 | 
			
		||||
			return -EPIPE;
 | 
			
		||||
		if (!*timeo_p)
 | 
			
		||||
			return -EAGAIN;
 | 
			
		||||
| 
						 | 
				
			
			@ -1335,7 +1343,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
 | 
			
		|||
	for (;;) {
 | 
			
		||||
		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 | 
			
		||||
		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
 | 
			
		||||
			if (sock->state == SS_DISCONNECTING) {
 | 
			
		||||
			if (sk->sk_shutdown & RCV_SHUTDOWN) {
 | 
			
		||||
				err = -ENOTCONN;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1676,9 +1684,6 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
 | 
			
		|||
		/* 'ACK-' message is neither accepted nor rejected: */
 | 
			
		||||
		msg_set_dest_droppable(hdr, 1);
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	case SS_DISCONNECTING:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (sk->sk_state) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2191,13 +2196,6 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
 | 
			
		|||
static int tipc_shutdown(struct socket *sock, int how)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk = sock->sk;
 | 
			
		||||
	struct net *net = sock_net(sk);
 | 
			
		||||
	struct tipc_sock *tsk = tipc_sk(sk);
 | 
			
		||||
	struct sk_buff *skb;
 | 
			
		||||
	u32 dnode = tsk_peer_node(tsk);
 | 
			
		||||
	u32 dport = tsk_peer_port(tsk);
 | 
			
		||||
	u32 onode = tipc_own_addr(net);
 | 
			
		||||
	u32 oport = tsk->portid;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	if (how != SHUT_RDWR)
 | 
			
		||||
| 
						 | 
				
			
			@ -2205,43 +2203,17 @@ static int tipc_shutdown(struct socket *sock, int how)
 | 
			
		|||
 | 
			
		||||
	lock_sock(sk);
 | 
			
		||||
 | 
			
		||||
	if (sock->state == SS_CONNECTING || sock->state == SS_CONNECTED) {
 | 
			
		||||
 | 
			
		||||
restart:
 | 
			
		||||
		dnode = tsk_peer_node(tsk);
 | 
			
		||||
 | 
			
		||||
		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
 | 
			
		||||
		skb = __skb_dequeue(&sk->sk_receive_queue);
 | 
			
		||||
		if (skb) {
 | 
			
		||||
			if (TIPC_SKB_CB(skb)->bytes_read) {
 | 
			
		||||
				kfree_skb(skb);
 | 
			
		||||
				goto restart;
 | 
			
		||||
			}
 | 
			
		||||
			tipc_sk_respond(sk, skb, TIPC_CONN_SHUTDOWN);
 | 
			
		||||
		} else {
 | 
			
		||||
			skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
 | 
			
		||||
					      TIPC_CONN_MSG, SHORT_H_SIZE,
 | 
			
		||||
					      0, dnode, onode, dport, oport,
 | 
			
		||||
					      TIPC_CONN_SHUTDOWN);
 | 
			
		||||
			if (skb)
 | 
			
		||||
				tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
 | 
			
		||||
		}
 | 
			
		||||
		tipc_set_sk_state(sk, TIPC_DISCONNECTING);
 | 
			
		||||
		tipc_node_remove_conn(net, dnode, tsk->portid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (sk->sk_state) {
 | 
			
		||||
	case TIPC_DISCONNECTING:
 | 
			
		||||
	__tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
 | 
			
		||||
	sk->sk_shutdown = SEND_SHUTDOWN;
 | 
			
		||||
 | 
			
		||||
	if (sk->sk_state == TIPC_DISCONNECTING) {
 | 
			
		||||
		/* Discard any unreceived messages */
 | 
			
		||||
		__skb_queue_purge(&sk->sk_receive_queue);
 | 
			
		||||
 | 
			
		||||
		/* Wake up anyone sleeping in poll */
 | 
			
		||||
		sk->sk_state_change(sk);
 | 
			
		||||
		res = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
	} else {
 | 
			
		||||
		res = -ENOTCONN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue