diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/link.c | 19 | ||||
| -rw-r--r-- | net/tipc/msg.h | 22 | ||||
| -rw-r--r-- | net/tipc/node.c | 11 | ||||
| -rw-r--r-- | net/tipc/socket.c | 21 | ||||
| -rw-r--r-- | net/tipc/topsrv.c | 3 | ||||
| -rw-r--r-- | net/tipc/trace.c | 4 | 
6 files changed, 60 insertions, 20 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 2792a3cae682..341ecd796aa4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1126,7 +1126,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,  			skb_queue_tail(mc_inputq, skb);  			return true;  		} -		/* else: fall through */ +		/* fall through */  	case CONN_MANAGER:  		skb_queue_tail(inputq, skb);  		return true; @@ -1145,7 +1145,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,  	default:  		pr_warn("Dropping received illegal msg type\n");  		kfree_skb(skb); -		return false; +		return true;  	};  } @@ -1425,6 +1425,10 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,  		l->rcv_unacked = 0;  	} else {  		/* RESET_MSG or ACTIVATE_MSG */ +		if (mtyp == ACTIVATE_MSG) { +			msg_set_dest_session_valid(hdr, 1); +			msg_set_dest_session(hdr, l->peer_session); +		}  		msg_set_max_pkt(hdr, l->advertised_mtu);  		strcpy(data, l->if_name);  		msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME); @@ -1642,6 +1646,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,  			rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);  			break;  		} + +		/* If this endpoint was re-created while peer was ESTABLISHING +		 * it doesn't know current session number. Force re-synch. +		 */ +		if (mtyp == ACTIVATE_MSG && msg_dest_session_valid(hdr) && +		    l->session != msg_dest_session(hdr)) { +			if (less(l->session, msg_dest_session(hdr))) +				l->session = msg_dest_session(hdr) + 1; +			break; +		} +  		/* ACTIVATE_MSG serves as PEER_RESET if link is already down */  		if (mtyp == RESET_MSG || !link_is_up(l))  			rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); diff --git a/net/tipc/msg.h b/net/tipc/msg.h index a0924956bb61..d7e4b8b93f9d 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -360,6 +360,28 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)  	msg_set_bits(m, 1, 0, 0xffff, n);  } +/* Note: reusing bits in word 1 for ACTIVATE_MSG only, to re-synch + * link peer session number + */ +static inline bool msg_dest_session_valid(struct tipc_msg *m) +{ +	return msg_bits(m, 1, 16, 0x1); +} + +static inline void msg_set_dest_session_valid(struct tipc_msg *m, bool valid) +{ +	msg_set_bits(m, 1, 16, 0x1, valid); +} + +static inline u16 msg_dest_session(struct tipc_msg *m) +{ +	return msg_bits(m, 1, 0, 0xffff); +} + +static inline void msg_set_dest_session(struct tipc_msg *m, u16 n) +{ +	msg_set_bits(m, 1, 0, 0xffff, n); +}  /*   * Word 2 diff --git a/net/tipc/node.c b/net/tipc/node.c index db2a6c3e0be9..2dc4919ab23c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -830,15 +830,16 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)  	tipc_node_write_lock(n);  	if (!tipc_link_is_establishing(l)) {  		__tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); -		if (delete) { -			kfree(l); -			le->link = NULL; -			n->link_cnt--; -		}  	} else {  		/* Defuse pending tipc_node_link_up() */ +		tipc_link_reset(l);  		tipc_link_fsm_evt(l, LINK_RESET_EVT);  	} +	if (delete) { +		kfree(l); +		le->link = NULL; +		n->link_cnt--; +	}  	trace_tipc_node_link_down(n, true, "node link down or deleted!");  	tipc_node_write_unlock(n);  	if (delete) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1217c90a363b..e482b342bfa8 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -379,16 +379,18 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)  #define tipc_wait_for_cond(sock_, timeo_, condition_)			       \  ({                                                                             \ +	DEFINE_WAIT_FUNC(wait_, woken_wake_function);                          \  	struct sock *sk_;						       \  	int rc_;							       \  									       \  	while ((rc_ = !(condition_))) {					       \ -		DEFINE_WAIT_FUNC(wait_, woken_wake_function);	               \ +		/* coupled with smp_wmb() in tipc_sk_proto_rcv() */            \ +		smp_rmb();                                                     \  		sk_ = (sock_)->sk;					       \  		rc_ = tipc_sk_sock_err((sock_), timeo_);		       \  		if (rc_)						       \  			break;						       \ -		prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \ +		add_wait_queue(sk_sleep(sk_), &wait_);                         \  		release_sock(sk_);					       \  		*(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \  		sched_annotate_sleep();				               \ @@ -735,7 +737,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,  	case TIPC_CONNECTING:  		if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk))  			revents |= EPOLLOUT; -		/* fall thru' */ +		/* fall through */  	case TIPC_LISTEN:  		if (!skb_queue_empty(&sk->sk_receive_queue))  			revents |= EPOLLIN | EPOLLRDNORM; @@ -1677,7 +1679,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk)  static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)  {  	struct sock *sk = sock->sk; -	DEFINE_WAIT(wait); +	DEFINE_WAIT_FUNC(wait, woken_wake_function);  	long timeo = *timeop;  	int err = sock_error(sk); @@ -1685,15 +1687,17 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)  		return err;  	for (;;) { -		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {  			if (sk->sk_shutdown & RCV_SHUTDOWN) {  				err = -ENOTCONN;  				break;  			} +			add_wait_queue(sk_sleep(sk), &wait);  			release_sock(sk); -			timeo = schedule_timeout(timeo); +			timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); +			sched_annotate_sleep();  			lock_sock(sk); +			remove_wait_queue(sk_sleep(sk), &wait);  		}  		err = 0;  		if (!skb_queue_empty(&sk->sk_receive_queue)) @@ -1709,7 +1713,6 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)  		if (err)  			break;  	} -	finish_wait(sk_sleep(sk), &wait);  	*timeop = timeo;  	return err;  } @@ -1982,6 +1985,8 @@ static void tipc_sk_proto_rcv(struct sock *sk,  		return;  	case SOCK_WAKEUP:  		tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0); +		/* coupled with smp_rmb() in tipc_wait_for_cond() */ +		smp_wmb();  		tsk->cong_link_cnt--;  		wakeup = true;  		break; @@ -2416,7 +2421,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,  		 * case is EINPROGRESS, rather than EALREADY.  		 */  		res = -EINPROGRESS; -		/* fall thru' */ +		/* fall through */  	case TIPC_CONNECTING:  		if (!timeout) {  			if (previous == TIPC_CONNECTING) diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index a457c0fbbef1..4a708a4e8583 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -60,7 +60,6 @@   * @awork: accept work item   * @rcv_wq: receive workqueue   * @send_wq: send workqueue - * @max_rcvbuf_size: maximum permitted receive message length   * @listener: topsrv listener socket   * @name: server name   */ @@ -72,7 +71,6 @@ struct tipc_topsrv {  	struct work_struct awork;  	struct workqueue_struct *rcv_wq;  	struct workqueue_struct *send_wq; -	int max_rcvbuf_size;  	struct socket *listener;  	char name[TIPC_SERVER_NAME_LEN];  }; @@ -648,7 +646,6 @@ int tipc_topsrv_start(struct net *net)  		return -ENOMEM;  	srv->net = net; -	srv->max_rcvbuf_size = sizeof(struct tipc_subscr);  	INIT_WORK(&srv->awork, tipc_topsrv_accept);  	strscpy(srv->name, name, sizeof(srv->name)); diff --git a/net/tipc/trace.c b/net/tipc/trace.c index 964823841efe..265f6a26aa3d 100644 --- a/net/tipc/trace.c +++ b/net/tipc/trace.c @@ -111,7 +111,7 @@ int tipc_skb_dump(struct sk_buff *skb, bool more, char *buf)  			break;  		default:  			break; -		}; +		}  		i += scnprintf(buf + i, sz - i, " | %u",  			       msg_src_droppable(hdr));  		i += scnprintf(buf + i, sz - i, " %u", @@ -122,7 +122,7 @@ int tipc_skb_dump(struct sk_buff *skb, bool more, char *buf)  	default:  		/* need more? */  		break; -	}; +	}  	i += scnprintf(buf + i, sz - i, "\n");  	if (!more)  |