diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/bearer.c | 7 | ||||
| -rw-r--r-- | net/tipc/config.c | 11 | ||||
| -rw-r--r-- | net/tipc/core.c | 109 | ||||
| -rw-r--r-- | net/tipc/core.h | 2 | ||||
| -rw-r--r-- | net/tipc/handler.c | 1 | ||||
| -rw-r--r-- | net/tipc/link.c | 7 | ||||
| -rw-r--r-- | net/tipc/name_table.c | 40 | ||||
| -rw-r--r-- | net/tipc/netlink.c | 8 | ||||
| -rw-r--r-- | net/tipc/ref.c | 3 | ||||
| -rw-r--r-- | net/tipc/server.c | 19 | ||||
| -rw-r--r-- | net/tipc/server.h | 2 | ||||
| -rw-r--r-- | net/tipc/socket.c | 12 | ||||
| -rw-r--r-- | net/tipc/subscr.c | 48 | 
13 files changed, 136 insertions, 133 deletions
| diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a38c89969c68..574b86193b15 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -610,8 +610,13 @@ static struct notifier_block notifier = {  int tipc_bearer_setup(void)  { +	int err; + +	err = register_netdevice_notifier(¬ifier); +	if (err) +		return err;  	dev_add_pack(&tipc_packet_type); -	return register_netdevice_notifier(¬ifier); +	return 0;  }  void tipc_bearer_cleanup(void) diff --git a/net/tipc/config.c b/net/tipc/config.c index c301a9a592d8..e6d721692ae0 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void)  	if (tipc_own_addr)  		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED  						   " (cannot change node address once assigned)"); -	tipc_core_start_net(addr); +	tipc_net_start(addr);  	return tipc_cfg_reply_none();  } @@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,  	struct tipc_cfg_msg_hdr *req_hdr;  	struct tipc_cfg_msg_hdr *rep_hdr;  	struct sk_buff *rep_buf; -	int ret;  	/* Validate configuration message header (ignore invalid message) */  	req_hdr = (struct tipc_cfg_msg_hdr *)buf; @@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,  		memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));  		rep_hdr->tcm_len = htonl(rep_buf->len);  		rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); - -		ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, -					rep_buf->len); -		if (ret < 0) -			pr_err("Sending cfg reply message failed, no memory\n"); - +		tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, +				  rep_buf->len);  		kfree_skb(rep_buf);  	}  } diff --git a/net/tipc/core.c b/net/tipc/core.c index f9e88d8b04ca..80c20647b3d2 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -77,37 +77,13 @@ struct sk_buff *tipc_buf_acquire(u32 size)  }  /** - * tipc_core_stop_net - shut down TIPC networking sub-systems - */ -static void tipc_core_stop_net(void) -{ -	tipc_net_stop(); -	tipc_bearer_cleanup(); -} - -/** - * start_net - start TIPC networking sub-systems - */ -int tipc_core_start_net(unsigned long addr) -{ -	int res; - -	tipc_net_start(addr); -	res = tipc_bearer_setup(); -	if (res < 0) -		goto err; -	return res; - -err: -	tipc_core_stop_net(); -	return res; -} - -/**   * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode   */  static void tipc_core_stop(void)  { +	tipc_handler_stop(); +	tipc_net_stop(); +	tipc_bearer_cleanup();  	tipc_netlink_stop();  	tipc_cfg_stop();  	tipc_subscr_stop(); @@ -122,30 +98,65 @@ static void tipc_core_stop(void)   */  static int tipc_core_start(void)  { -	int res; +	int err;  	get_random_bytes(&tipc_random, sizeof(tipc_random)); -	res = tipc_handler_start(); -	if (!res) -		res = tipc_ref_table_init(tipc_max_ports, tipc_random); -	if (!res) -		res = tipc_nametbl_init(); -	if (!res) -		res = tipc_netlink_start(); -	if (!res) -		res = tipc_socket_init(); -	if (!res) -		res = tipc_register_sysctl(); -	if (!res) -		res = tipc_subscr_start(); -	if (!res) -		res = tipc_cfg_init(); -	if (res) { -		tipc_handler_stop(); -		tipc_core_stop(); -	} -	return res; +	err = tipc_handler_start(); +	if (err) +		goto out_handler; + +	err = tipc_ref_table_init(tipc_max_ports, tipc_random); +	if (err) +		goto out_reftbl; + +	err = tipc_nametbl_init(); +	if (err) +		goto out_nametbl; + +	err = tipc_netlink_start(); +	if (err) +		goto out_netlink; + +	err = tipc_socket_init(); +	if (err) +		goto out_socket; + +	err = tipc_register_sysctl(); +	if (err) +		goto out_sysctl; + +	err = tipc_subscr_start(); +	if (err) +		goto out_subscr; + +	err = tipc_cfg_init(); +	if (err) +		goto out_cfg; + +	err = tipc_bearer_setup(); +	if (err) +		goto out_bearer; + +	return 0; +out_bearer: +	tipc_cfg_stop(); +out_cfg: +	tipc_subscr_stop(); +out_subscr: +	tipc_unregister_sysctl(); +out_sysctl: +	tipc_socket_stop(); +out_socket: +	tipc_netlink_stop(); +out_netlink: +	tipc_nametbl_stop(); +out_nametbl: +	tipc_ref_table_stop(); +out_reftbl: +	tipc_handler_stop(); +out_handler: +	return err;  }  static int __init tipc_init(void) @@ -174,8 +185,6 @@ static int __init tipc_init(void)  static void __exit tipc_exit(void)  { -	tipc_handler_stop(); -	tipc_core_stop_net();  	tipc_core_stop();  	pr_info("Deactivated\n");  } diff --git a/net/tipc/core.h b/net/tipc/core.h index 1ff477b0450d..4dfe137587bb 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -90,7 +90,6 @@ extern int tipc_random __read_mostly;  /*   * Routines available to privileged subsystems   */ -int tipc_core_start_net(unsigned long);  int tipc_handler_start(void);  void tipc_handler_stop(void);  int tipc_netlink_start(void); @@ -192,6 +191,7 @@ static inline void k_term_timer(struct timer_list *timer)  struct tipc_skb_cb {  	void *handle; +	bool deferred;  };  #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) diff --git a/net/tipc/handler.c b/net/tipc/handler.c index e4bc8a296744..1fabf160501f 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)  	spin_lock_bh(&qitem_lock);  	if (!handler_enabled) { -		pr_err("Signal request ignored by handler\n");  		spin_unlock_bh(&qitem_lock);  		return -ENOPROTOOPT;  	} diff --git a/net/tipc/link.c b/net/tipc/link.c index d4b5de41b682..da6018beb6eb 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf)  	u32 hdr_size;  	u32 min_hdr_size; +	/* If this packet comes from the defer queue, the skb has already +	 * been validated +	 */ +	if (unlikely(TIPC_SKB_CB(buf)->deferred)) +		return 1; +  	if (unlikely(buf->len < MIN_H_SIZE))  		return 0; @@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,  				&l_ptr->newest_deferred_in, buf)) {  		l_ptr->deferred_inqueue_sz++;  		l_ptr->stats.deferred_recv++; +		TIPC_SKB_CB(buf)->deferred = true;  		if ((l_ptr->deferred_inqueue_sz % 16) == 1)  			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);  	} else diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 92a1533af4e0..042e8e3cabc0 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -941,20 +941,48 @@ int tipc_nametbl_init(void)  	return 0;  } -void tipc_nametbl_stop(void) +/** + * tipc_purge_publications - remove all publications for a given type + * + * tipc_nametbl_lock must be held when calling this function + */ +static void tipc_purge_publications(struct name_seq *seq)  { -	u32 i; +	struct publication *publ, *safe; +	struct sub_seq *sseq; +	struct name_info *info; -	if (!table.types) +	if (!seq->sseqs) { +		nameseq_delete_empty(seq);  		return; +	} +	sseq = seq->sseqs; +	info = sseq->info; +	list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { +		tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, +					 publ->ref, publ->key); +	} +} + +void tipc_nametbl_stop(void) +{ +	u32 i; +	struct name_seq *seq; +	struct hlist_head *seq_head; +	struct hlist_node *safe; -	/* Verify name table is empty, then release it */ +	/* Verify name table is empty and purge any lingering +	 * publications, then release the name table +	 */  	write_lock_bh(&tipc_nametbl_lock);  	for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {  		if (hlist_empty(&table.types[i]))  			continue; -		pr_err("nametbl_stop(): orphaned hash chain detected\n"); -		break; +		seq_head = &table.types[i]; +		hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { +			tipc_purge_publications(seq); +		} +		continue;  	}  	kfree(table.types);  	table.types = NULL; diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 9f72a6376362..3aaf73de9e2d 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = {  	},  }; -static int tipc_genl_family_registered; -  int tipc_netlink_start(void)  {  	int res; @@ -94,16 +92,10 @@ int tipc_netlink_start(void)  		pr_err("Failed to register netlink interface\n");  		return res;  	} - -	tipc_genl_family_registered = 1;  	return 0;  }  void tipc_netlink_stop(void)  { -	if (!tipc_genl_family_registered) -		return; -  	genl_unregister_family(&tipc_genl_family); -	tipc_genl_family_registered = 0;  } diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 2a2a938dc22c..de3d593e2fee 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start)   */  void tipc_ref_table_stop(void)  { -	if (!tipc_ref_table.entries) -		return; -  	vfree(tipc_ref_table.entries);  	tipc_ref_table.entries = NULL;  } diff --git a/net/tipc/server.c b/net/tipc/server.c index b635ca347a87..646a930eefbf 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con);  static void tipc_conn_kref_release(struct kref *kref)  {  	struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); -	struct tipc_server *s = con->server;  	if (con->sock) {  		tipc_sock_release_local(con->sock); @@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref)  	}  	tipc_clean_outqueues(con); - -	if (con->conid) -		s->tipc_conn_shutdown(con->conid, con->usr_data); -  	kfree(con);  } @@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con)  	struct tipc_server *s = con->server;  	if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { +		if (con->conid) +			s->tipc_conn_shutdown(con->conid, con->usr_data); +  		spin_lock_bh(&s->idr_lock);  		idr_remove(&s->conn_idr, con->conid);  		s->idr_in_use--; @@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,  	list_add_tail(&e->list, &con->outqueue);  	spin_unlock_bh(&con->outqueue_lock); -	if (test_bit(CF_CONNECTED, &con->flags)) +	if (test_bit(CF_CONNECTED, &con->flags)) {  		if (!queue_work(s->send_wq, &con->swork))  			conn_put(con); - +	} else { +		conn_put(con); +	}  	return 0;  } @@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s)  		kmem_cache_destroy(s->rcvbuf_cache);  		return ret;  	} -	s->enabled = 1;  	return ret;  } @@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s)  	int total = 0;  	int id; -	if (!s->enabled) -		return; - -	s->enabled = 0;  	spin_lock_bh(&s->idr_lock);  	for (id = 0; total < s->idr_in_use; id++) {  		con = idr_find(&s->conn_idr, id); diff --git a/net/tipc/server.h b/net/tipc/server.h index 98b23f20bc0f..be817b0b547e 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -56,7 +56,6 @@   * @name: server name   * @imp: message importance   * @type: socket type - * @enabled: identify whether server is launched or not   */  struct tipc_server {  	struct idr conn_idr; @@ -74,7 +73,6 @@ struct tipc_server {  	const char name[TIPC_SERVER_NAME_LEN];  	int imp;  	int type; -	int enabled;  };  int tipc_conn_sendmsg(struct tipc_server *s, int conid, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index aab4948f0aff..0ed0eaa62f29 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -70,8 +70,6 @@ static const struct proto_ops msg_ops;  static struct proto tipc_proto;  static struct proto tipc_proto_kern; -static int sockets_enabled; -  /*   * Revised TIPC socket locking policy:   * @@ -999,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo)  	for (;;) {  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); -		if (skb_queue_empty(&sk->sk_receive_queue)) { +		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {  			if (sock->state == SS_DISCONNECTING) {  				err = -ENOTCONN;  				break; @@ -1625,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)  	for (;;) {  		prepare_to_wait_exclusive(sk_sleep(sk), &wait,  					  TASK_INTERRUPTIBLE); -		if (skb_queue_empty(&sk->sk_receive_queue)) { +		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {  			release_sock(sk);  			timeo = schedule_timeout(timeo);  			lock_sock(sk); @@ -2027,8 +2025,6 @@ int tipc_socket_init(void)  		proto_unregister(&tipc_proto);  		goto out;  	} - -	sockets_enabled = 1;   out:  	return res;  } @@ -2038,10 +2034,6 @@ int tipc_socket_init(void)   */  void tipc_socket_stop(void)  { -	if (!sockets_enabled) -		return; - -	sockets_enabled = 0;  	sock_unregister(tipc_family_ops.family);  	proto_unregister(&tipc_proto);  } diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7cb0bd5b1176..642437231ad5 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower,  {  	struct tipc_subscriber *subscriber = sub->subscriber;  	struct kvec msg_sect; -	int ret;  	msg_sect.iov_base = (void *)&sub->evt;  	msg_sect.iov_len = sizeof(struct tipc_event); -  	sub->evt.event = htohl(event, sub->swap);  	sub->evt.found_lower = htohl(found_lower, sub->swap);  	sub->evt.found_upper = htohl(found_upper, sub->swap);  	sub->evt.port.ref = htohl(port_ref, sub->swap);  	sub->evt.port.node = htohl(node, sub->swap); -	ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, -				msg_sect.iov_base, msg_sect.iov_len); -	if (ret < 0) -		pr_err("Sending subscription event failed, no memory\n"); +	tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, +			  msg_sect.iov_len);  }  /** @@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub)  	/* The spin lock per subscriber is used to protect its members */  	spin_lock_bh(&subscriber->lock); -	/* Validate if the connection related to the subscriber is -	 * closed (in case subscriber is terminating) -	 */ -	if (subscriber->conid == 0) { -		spin_unlock_bh(&subscriber->lock); -		return; -	} -  	/* Validate timeout (in case subscription is being cancelled) */  	if (sub->timeout == TIPC_WAIT_FOREVER) {  		spin_unlock_bh(&subscriber->lock); @@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber)  	spin_lock_bh(&subscriber->lock); -	/* Invalidate subscriber reference */ -	subscriber->conid = 0; -  	/* Destroy any existing subscriptions for subscriber */  	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,  				 subscription_list) { @@ -278,9 +263,9 @@ static void subscr_cancel(struct tipc_subscr *s,   *   * Called with subscriber lock held.   */ -static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, -					     struct tipc_subscriber *subscriber) -{ +static int subscr_subscribe(struct tipc_subscr *s, +			    struct tipc_subscriber *subscriber, +			    struct tipc_subscription **sub_p) {  	struct tipc_subscription *sub;  	int swap; @@ -291,23 +276,21 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,  	if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {  		s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);  		subscr_cancel(s, subscriber); -		return NULL; +		return 0;  	}  	/* Refuse subscription if global limit exceeded */  	if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {  		pr_warn("Subscription rejected, limit reached (%u)\n",  			TIPC_MAX_SUBSCRIPTIONS); -		subscr_terminate(subscriber); -		return NULL; +		return -EINVAL;  	}  	/* Allocate subscription object */  	sub = kmalloc(sizeof(*sub), GFP_ATOMIC);  	if (!sub) {  		pr_warn("Subscription rejected, no memory\n"); -		subscr_terminate(subscriber); -		return NULL; +		return -ENOMEM;  	}  	/* Initialize subscription object */ @@ -321,8 +304,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,  	    (sub->seq.lower > sub->seq.upper)) {  		pr_warn("Subscription rejected, illegal request\n");  		kfree(sub); -		subscr_terminate(subscriber); -		return NULL; +		return -EINVAL;  	}  	INIT_LIST_HEAD(&sub->nameseq_list);  	list_add(&sub->subscription_list, &subscriber->subscription_list); @@ -335,8 +317,8 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,  			     (Handler)subscr_timeout, (unsigned long)sub);  		k_start_timer(&sub->timer, sub->timeout);  	} - -	return sub; +	*sub_p = sub; +	return 0;  }  /* Handle one termination request for the subscriber */ @@ -350,10 +332,14 @@ static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr,  				  void *usr_data, void *buf, size_t len)  {  	struct tipc_subscriber *subscriber = usr_data; -	struct tipc_subscription *sub; +	struct tipc_subscription *sub = NULL;  	spin_lock_bh(&subscriber->lock); -	sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber); +	if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) { +		spin_unlock_bh(&subscriber->lock); +		subscr_terminate(subscriber); +		return; +	}  	if (sub)  		tipc_nametbl_subscribe(sub);  	spin_unlock_bh(&subscriber->lock); |