diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 18:13:54 +0100 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-06 18:13:54 +0100 | 
| commit | 11e4afb49b7fa1fc8e1ffd850c1806dd86a08204 (patch) | |
| tree | 9e57efcb106ae912f7bec718feb3f8ec607559bb /net/tipc | |
| parent | 162500b3a3ff39d941d29db49b41a16667ae44f0 (diff) | |
| parent | 9b2a606d3898fcb2eedb6faded3bb37549590ac4 (diff) | |
Merge branches 'gemini' and 'misc' into devel
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/addr.c | 32 | ||||
| -rw-r--r-- | net/tipc/addr.h | 37 | ||||
| -rw-r--r-- | net/tipc/bcast.c | 149 | ||||
| -rw-r--r-- | net/tipc/bcast.h | 117 | ||||
| -rw-r--r-- | net/tipc/bearer.c | 16 | ||||
| -rw-r--r-- | net/tipc/bearer.h | 16 | ||||
| -rw-r--r-- | net/tipc/cluster.c | 2 | ||||
| -rw-r--r-- | net/tipc/config.c | 68 | ||||
| -rw-r--r-- | net/tipc/core.c | 26 | ||||
| -rw-r--r-- | net/tipc/core.h | 28 | ||||
| -rw-r--r-- | net/tipc/discover.c | 8 | ||||
| -rw-r--r-- | net/tipc/eth_media.c | 1 | ||||
| -rw-r--r-- | net/tipc/link.c | 102 | ||||
| -rw-r--r-- | net/tipc/link.h | 35 | ||||
| -rw-r--r-- | net/tipc/msg.c | 94 | ||||
| -rw-r--r-- | net/tipc/msg.h | 99 | ||||
| -rw-r--r-- | net/tipc/name_distr.c | 2 | ||||
| -rw-r--r-- | net/tipc/name_table.c | 2 | ||||
| -rw-r--r-- | net/tipc/net.c | 8 | ||||
| -rw-r--r-- | net/tipc/node.c | 14 | ||||
| -rw-r--r-- | net/tipc/port.c | 27 | ||||
| -rw-r--r-- | net/tipc/port.h | 2 | ||||
| -rw-r--r-- | net/tipc/socket.c | 28 | ||||
| -rw-r--r-- | net/tipc/subscr.c | 15 | 
24 files changed, 489 insertions, 439 deletions
| diff --git a/net/tipc/addr.c b/net/tipc/addr.c index e5207a11edf..c048543ffbe 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -92,3 +92,35 @@ int tipc_addr_node_valid(u32 addr)  	return (tipc_addr_domain_valid(addr) && tipc_node(addr));  } +int tipc_in_scope(u32 domain, u32 addr) +{ +	if (!domain || (domain == addr)) +		return 1; +	if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ +		return 1; +	if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ +		return 1; +	return 0; +} + +/** + * tipc_addr_scope - convert message lookup domain to a 2-bit scope value + */ + +int tipc_addr_scope(u32 domain) +{ +	if (likely(!domain)) +		return TIPC_ZONE_SCOPE; +	if (tipc_node(domain)) +		return TIPC_NODE_SCOPE; +	if (tipc_cluster(domain)) +		return TIPC_CLUSTER_SCOPE; +	return TIPC_ZONE_SCOPE; +} + +char *tipc_addr_string_fill(char *string, u32 addr) +{ +	snprintf(string, 16, "<%u.%u.%u>", +		 tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); +	return string; +} diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 3ba67e6ce03..c1cc5724d8c 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -67,32 +67,6 @@ static inline int may_route(u32 addr)  	return(addr ^ tipc_own_addr) >> 11;  } -static inline int in_scope(u32 domain, u32 addr) -{ -	if (!domain || (domain == addr)) -		return 1; -	if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ -		return 1; -	if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ -		return 1; -	return 0; -} - -/** - * addr_scope - convert message lookup domain to equivalent 2-bit scope value - */ - -static inline int addr_scope(u32 domain) -{ -	if (likely(!domain)) -		return TIPC_ZONE_SCOPE; -	if (tipc_node(domain)) -		return TIPC_NODE_SCOPE; -	if (tipc_cluster(domain)) -		return TIPC_CLUSTER_SCOPE; -	return TIPC_ZONE_SCOPE; -} -  /**   * addr_domain - convert 2-bit scope value to equivalent message lookup domain   * @@ -110,14 +84,9 @@ static inline int addr_domain(int sc)  	return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);  } -static inline char *addr_string_fill(char *string, u32 addr) -{ -	snprintf(string, 16, "<%u.%u.%u>", -		 tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); -	return string; -} -  int tipc_addr_domain_valid(u32);  int tipc_addr_node_valid(u32 addr); - +int tipc_in_scope(u32 domain, u32 addr); +int tipc_addr_scope(u32 domain); +char *tipc_addr_string_fill(char *string, u32 addr);  #endif diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index a3bfd406491..a008c668930 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -119,7 +119,7 @@ static struct bclink *bclink = NULL;  static struct link *bcl = NULL;  static DEFINE_SPINLOCK(bc_lock); -const char tipc_bclink_name[] = "multicast-link"; +const char tipc_bclink_name[] = "broadcast-link";  static u32 buf_seqno(struct sk_buff *buf) @@ -275,7 +275,7 @@ static void bclink_send_nack(struct tipc_node *n_ptr)  	buf = buf_acquire(INT_H_SIZE);  	if (buf) {  		msg = buf_msg(buf); -		msg_init(msg, BCAST_PROTOCOL, STATE_MSG, +		tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG,  			 INT_H_SIZE, n_ptr->addr);  		msg_set_mc_netid(msg, tipc_net_id);  		msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); @@ -558,10 +558,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf,  			      struct tipc_bearer *unused1,  			      struct tipc_media_addr *unused2)  { -	static int send_count = 0; -  	int bp_index; -	int swap_time;  	/* Prepare buffer for broadcasting (if first time trying to send it) */ @@ -575,11 +572,6 @@ static int tipc_bcbearer_send(struct sk_buff *buf,  		msg_set_mc_netid(msg, tipc_net_id);  	} -	/* Determine if bearer pairs should be swapped following this attempt */ - -	if ((swap_time = (++send_count >= 10))) -		send_count = 0; -  	/* Send buffer over bearers until all targets reached */  	bcbearer->remains = tipc_cltr_bcast_nodes; @@ -595,21 +587,22 @@ static int tipc_bcbearer_send(struct sk_buff *buf,  		if (bcbearer->remains_new.count == bcbearer->remains.count)  			continue;	/* bearer pair doesn't add anything */ -		if (!p->publ.blocked && -		    !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { -			if (swap_time && s && !s->publ.blocked) -				goto swap; -			else -				goto update; +		if (p->publ.blocked || +		    p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { +			/* unable to send on primary bearer */ +			if (!s || s->publ.blocked || +			    s->media->send_msg(buf, &s->publ, +					       &s->media->bcast_addr)) { +				/* unable to send on either bearer */ +				continue; +			} +		} + +		if (s) { +			bcbearer->bpairs[bp_index].primary = s; +			bcbearer->bpairs[bp_index].secondary = p;  		} -		if (!s || s->publ.blocked || -		    s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) -			continue;	/* unable to send using bearer pair */ -swap: -		bcbearer->bpairs[bp_index].primary = s; -		bcbearer->bpairs[bp_index].secondary = p; -update:  		if (bcbearer->remains_new.count == 0)  			return 0; @@ -829,3 +822,113 @@ void tipc_bclink_stop(void)  	spin_unlock_bh(&bc_lock);  } + +/** + * tipc_nmap_add - add a node to a node map + */ + +void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node) +{ +	int n = tipc_node(node); +	int w = n / WSIZE; +	u32 mask = (1 << (n % WSIZE)); + +	if ((nm_ptr->map[w] & mask) == 0) { +		nm_ptr->count++; +		nm_ptr->map[w] |= mask; +	} +} + +/** + * tipc_nmap_remove - remove a node from a node map + */ + +void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node) +{ +	int n = tipc_node(node); +	int w = n / WSIZE; +	u32 mask = (1 << (n % WSIZE)); + +	if ((nm_ptr->map[w] & mask) != 0) { +		nm_ptr->map[w] &= ~mask; +		nm_ptr->count--; +	} +} + +/** + * tipc_nmap_diff - find differences between node maps + * @nm_a: input node map A + * @nm_b: input node map B + * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) + */ + +void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, +				  struct tipc_node_map *nm_diff) +{ +	int stop = ARRAY_SIZE(nm_a->map); +	int w; +	int b; +	u32 map; + +	memset(nm_diff, 0, sizeof(*nm_diff)); +	for (w = 0; w < stop; w++) { +		map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); +		nm_diff->map[w] = map; +		if (map != 0) { +			for (b = 0 ; b < WSIZE; b++) { +				if (map & (1 << b)) +					nm_diff->count++; +			} +		} +	} +} + +/** + * tipc_port_list_add - add a port to a port list, ensuring no duplicates + */ + +void tipc_port_list_add(struct port_list *pl_ptr, u32 port) +{ +	struct port_list *item = pl_ptr; +	int i; +	int item_sz = PLSIZE; +	int cnt = pl_ptr->count; + +	for (; ; cnt -= item_sz, item = item->next) { +		if (cnt < PLSIZE) +			item_sz = cnt; +		for (i = 0; i < item_sz; i++) +			if (item->ports[i] == port) +				return; +		if (i < PLSIZE) { +			item->ports[i] = port; +			pl_ptr->count++; +			return; +		} +		if (!item->next) { +			item->next = kmalloc(sizeof(*item), GFP_ATOMIC); +			if (!item->next) { +				warn("Incomplete multicast delivery, no memory\n"); +				return; +			} +			item->next->next = NULL; +		} +	} +} + +/** + * tipc_port_list_free - free dynamically created entries in port_list chain + * + */ + +void tipc_port_list_free(struct port_list *pl_ptr) +{ +	struct port_list *item; +	struct port_list *next; + +	for (item = pl_ptr->next; item; item = next) { +		next = item->next; +		kfree(item); +	} +} + diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 4c1771e95c9..e8c2b81658c 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -72,41 +72,11 @@ struct tipc_node;  extern const char tipc_bclink_name[]; +void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node); +void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node);  /** - * nmap_add - add a node to a node map - */ - -static inline void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node) -{ -	int n = tipc_node(node); -	int w = n / WSIZE; -	u32 mask = (1 << (n % WSIZE)); - -	if ((nm_ptr->map[w] & mask) == 0) { -		nm_ptr->count++; -		nm_ptr->map[w] |= mask; -	} -} - -/** - * nmap_remove - remove a node from a node map - */ - -static inline void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node) -{ -	int n = tipc_node(node); -	int w = n / WSIZE; -	u32 mask = (1 << (n % WSIZE)); - -	if ((nm_ptr->map[w] & mask) != 0) { -		nm_ptr->map[w] &= ~mask; -		nm_ptr->count--; -	} -} - -/** - * nmap_equal - test for equality of node maps + * tipc_nmap_equal - test for equality of node maps   */  static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b) @@ -114,84 +84,11 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_m  	return !memcmp(nm_a, nm_b, sizeof(*nm_a));  } -/** - * nmap_diff - find differences between node maps - * @nm_a: input node map A - * @nm_b: input node map B - * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) - */ - -static inline void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, -				  struct tipc_node_map *nm_diff) -{ -	int stop = ARRAY_SIZE(nm_a->map); -	int w; -	int b; -	u32 map; - -	memset(nm_diff, 0, sizeof(*nm_diff)); -	for (w = 0; w < stop; w++) { -		map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); -		nm_diff->map[w] = map; -		if (map != 0) { -			for (b = 0 ; b < WSIZE; b++) { -				if (map & (1 << b)) -					nm_diff->count++; -			} -		} -	} -} - -/** - * port_list_add - add a port to a port list, ensuring no duplicates - */ - -static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port) -{ -	struct port_list *item = pl_ptr; -	int i; -	int item_sz = PLSIZE; -	int cnt = pl_ptr->count; - -	for (; ; cnt -= item_sz, item = item->next) { -		if (cnt < PLSIZE) -			item_sz = cnt; -		for (i = 0; i < item_sz; i++) -			if (item->ports[i] == port) -				return; -		if (i < PLSIZE) { -			item->ports[i] = port; -			pl_ptr->count++; -			return; -		} -		if (!item->next) { -			item->next = kmalloc(sizeof(*item), GFP_ATOMIC); -			if (!item->next) { -				warn("Incomplete multicast delivery, no memory\n"); -				return; -			} -			item->next->next = NULL; -		} -	} -} - -/** - * port_list_free - free dynamically created entries in port_list chain - * - * Note: First item is on stack, so it doesn't need to be released - */ - -static inline void tipc_port_list_free(struct port_list *pl_ptr) -{ -	struct port_list *item; -	struct port_list *next; - -	for (item = pl_ptr->next; item; item = next) { -		next = item->next; -		kfree(item); -	} -} +void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, +				  struct tipc_node_map *nm_diff); +void tipc_port_list_add(struct port_list *pl_ptr, u32 port); +void tipc_port_list_free(struct port_list *pl_ptr);  int  tipc_bclink_init(void);  void tipc_bclink_stop(void); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 78091375ca1..52ae17b2583 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -467,6 +467,18 @@ int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)  	return res;  } +/** + * tipc_bearer_congested - determines if bearer is currently congested + */ + +int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) +{ +	if (unlikely(b_ptr->publ.blocked)) +		return 1; +	if (likely(list_empty(&b_ptr->cong_links))) +		return 0; +	return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); +}  /**   * tipc_enable_bearer - enable bearer with the given name @@ -493,7 +505,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)  		return -EINVAL;  	}  	if (!tipc_addr_domain_valid(bcast_scope) || -	    !in_scope(bcast_scope, tipc_own_addr)) { +	    !tipc_in_scope(bcast_scope, tipc_own_addr)) {  		warn("Bearer <%s> rejected, illegal broadcast scope\n", name);  		return -EINVAL;  	} @@ -571,7 +583,7 @@ restart:  	spin_lock_init(&b_ptr->publ.lock);  	write_unlock_bh(&tipc_net_lock);  	info("Enabled bearer <%s>, discovery domain %s, priority %u\n", -	     name, addr_string_fill(addr_string, bcast_scope), priority); +	     name, tipc_addr_string_fill(addr_string, bcast_scope), priority);  	return 0;  failed:  	write_unlock_bh(&tipc_net_lock); diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 000228e93f9..a850b389663 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -125,6 +125,7 @@ void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest);  void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);  struct bearer *tipc_bearer_find_interface(const char *if_name);  int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); +int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr);  int tipc_bearer_init(void);  void tipc_bearer_stop(void);  void tipc_bearer_lock_push(struct bearer *b_ptr); @@ -154,17 +155,4 @@ static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf,  	return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);  } -/** - * tipc_bearer_congested - determines if bearer is currently congested - */ - -static inline int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) -{ -	if (unlikely(b_ptr->publ.blocked)) -		return 1; -	if (likely(list_empty(&b_ptr->cong_links))) -		return 0; -	return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); -} - -#endif +#endif	/* _TIPC_BEARER_H */ diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index a7eac00cd36..e68f705381b 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c @@ -238,7 +238,7 @@ static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)  	if (buf) {  		msg = buf_msg(buf);  		memset((char *)msg, 0, size); -		msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest); +		tipc_msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest);  	}  	return buf;  } diff --git a/net/tipc/config.c b/net/tipc/config.c index ca3544d030c..961d1b09714 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -56,9 +56,6 @@ struct subscr_data {  struct manager {  	u32 user_ref;  	u32 port_ref; -	u32 subscr_ref; -	u32 link_subscriptions; -	struct list_head link_subscribers;  };  static struct manager mng = { 0}; @@ -70,12 +67,6 @@ static int req_tlv_space;		/* request message TLV area size */  static int rep_headroom;		/* reply message headroom to use */ -void tipc_cfg_link_event(u32 addr, char *name, int up) -{ -	/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ -} - -  struct sk_buff *tipc_cfg_reply_alloc(int payload_size)  {  	struct sk_buff *buf; @@ -130,12 +121,24 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)  } - -  #if 0  /* Now obsolete code for handling commands not yet implemented the new way */ +/* + * Some of this code assumed that the manager structure contains two added + * fields: + *	u32 link_subscriptions; + *	struct list_head link_subscribers; + * which are currently not present.  These fields may need to be re-introduced + * if and when support for link subscriptions is added. + */ + +void tipc_cfg_link_event(u32 addr, char *name, int up) +{ +	/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ +} +  int tipc_cfg_cmd(const struct tipc_cmd_msg * msg,  		 char *data,  		 u32 sz, @@ -243,13 +246,48 @@ static void cfg_cmd_event(struct tipc_cmd_msg *msg,  	default:  		rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig);  	} -	exit: +exit:  	rmsg.result_len = htonl(msg_sect[1].iov_len);  	rmsg.retval = htonl(rv);  	tipc_cfg_respond(msg_sect, 2u, orig);  }  #endif +#define MAX_STATS_INFO 2000 + +static struct sk_buff *tipc_show_stats(void) +{ +	struct sk_buff *buf; +	struct tlv_desc *rep_tlv; +	struct print_buf pb; +	int str_len; +	u32 value; + +	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) +		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + +	value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); +	if (value != 0) +		return tipc_cfg_reply_error_string("unsupported argument"); + +	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); +	if (buf == NULL) +		return NULL; + +	rep_tlv = (struct tlv_desc *)buf->data; +	tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); + +	tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); + +	/* Use additional tipc_printf()'s to return more info ... */ + +	str_len = tipc_printbuf_validate(&pb); +	skb_put(buf, TLV_SPACE(str_len)); +	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + +	return buf; +} +  static struct sk_buff *cfg_enable_bearer(void)  {  	struct tipc_bearer_config *args; @@ -533,6 +571,9 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area  	case TIPC_CMD_DUMP_LOG:  		rep_tlv_buf = tipc_log_dump();  		break; +	case TIPC_CMD_SHOW_STATS: +		rep_tlv_buf = tipc_show_stats(); +		break;  	case TIPC_CMD_SET_LINK_TOL:  	case TIPC_CMD_SET_LINK_PRI:  	case TIPC_CMD_SET_LINK_WINDOW: @@ -667,9 +708,6 @@ int tipc_cfg_init(void)  	struct tipc_name_seq seq;  	int res; -	memset(&mng, 0, sizeof(mng)); -	INIT_LIST_HEAD(&mng.link_subscribers); -  	res = tipc_attach(&mng.user_ref, NULL, NULL);  	if (res)  		goto failed; diff --git a/net/tipc/core.c b/net/tipc/core.c index 52c571fedbe..69646811798 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -49,8 +49,6 @@  #include "config.h" -#define TIPC_MOD_VER "1.6.4" -  #ifndef CONFIG_TIPC_ZONES  #define CONFIG_TIPC_ZONES 3  #endif @@ -104,6 +102,30 @@ int tipc_get_mode(void)  }  /** + * buf_acquire - creates a TIPC message buffer + * @size: message size (including TIPC header) + * + * Returns a new buffer with data pointers set to the specified size. + * + * NOTE: Headroom is reserved to allow prepending of a data link header. + *       There may also be unrequested tailroom present at the buffer's end. + */ + +struct sk_buff *buf_acquire(u32 size) +{ +	struct sk_buff *skb; +	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; + +	skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); +	if (skb) { +		skb_reserve(skb, BUF_HEADROOM); +		skb_put(skb, size); +		skb->next = NULL; +	} +	return skb; +} + +/**   * tipc_core_stop_net - shut down TIPC networking sub-systems   */ diff --git a/net/tipc/core.h b/net/tipc/core.h index a881f92a853..188799017ab 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -56,8 +56,12 @@  #include <linux/netdevice.h>  #include <linux/in.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/vmalloc.h> + +#define TIPC_MOD_VER "2.0.0" +  /*   * TIPC sanity test macros   */ @@ -324,29 +328,7 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb)  	return (struct tipc_msg *)skb->data;  } -/** - * buf_acquire - creates a TIPC message buffer - * @size: message size (including TIPC header) - * - * Returns a new buffer with data pointers set to the specified size. - * - * NOTE: Headroom is reserved to allow prepending of a data link header. - *       There may also be unrequested tailroom present at the buffer's end. - */ - -static inline struct sk_buff *buf_acquire(u32 size) -{ -	struct sk_buff *skb; -	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; - -	skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); -	if (skb) { -		skb_reserve(skb, BUF_HEADROOM); -		skb_put(skb, size); -		skb->next = NULL; -	} -	return skb; -} +extern struct sk_buff *buf_acquire(u32 size);  /**   * buf_discard - frees a TIPC message buffer diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 74b7d1e28ae..fc1fcf5e6b5 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -120,7 +120,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,  	if (buf) {  		msg = buf_msg(buf); -		msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); +		tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain);  		msg_set_non_seq(msg, 1);  		msg_set_req_links(msg, req_links);  		msg_set_dest_domain(msg, dest_domain); @@ -144,7 +144,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,  	char media_addr_str[64];  	struct print_buf pb; -	addr_string_fill(node_addr_str, node_addr); +	tipc_addr_string_fill(node_addr_str, node_addr);  	tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));  	tipc_media_addr_printf(&pb, media_addr);  	tipc_printbuf_validate(&pb); @@ -183,7 +183,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)  			disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);  		return;  	} -	if (!in_scope(dest, tipc_own_addr)) +	if (!tipc_in_scope(dest, tipc_own_addr))  		return;  	if (is_slave(tipc_own_addr) && is_slave(orig))  		return; @@ -224,7 +224,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)  			memcpy(addr, &media_addr, sizeof(*addr));  			tipc_link_reset(link);  		} -		link_fully_up = (link->state == WORKING_WORKING); +		link_fully_up = link_working_working(link);  		spin_unlock_bh(&n_ptr->lock);  		if ((type == DSC_RESP_MSG) || link_fully_up)  			return; diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 524ba5696d4..6230d16020c 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -38,6 +38,7 @@  #include <net/tipc/tipc_bearer.h>  #include <net/tipc/tipc_msg.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #define MAX_ETH_BEARERS		2 diff --git a/net/tipc/link.c b/net/tipc/link.c index 1a7e4665af8..a3616b99529 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -202,41 +202,6 @@ static unsigned int align(unsigned int i)  	return (i + 3) & ~3u;  } -static int link_working_working(struct link *l_ptr) -{ -	return (l_ptr->state == WORKING_WORKING); -} - -static int link_working_unknown(struct link *l_ptr) -{ -	return (l_ptr->state == WORKING_UNKNOWN); -} - -static int link_reset_unknown(struct link *l_ptr) -{ -	return (l_ptr->state == RESET_UNKNOWN); -} - -static int link_reset_reset(struct link *l_ptr) -{ -	return (l_ptr->state == RESET_RESET); -} - -static int link_blocked(struct link *l_ptr) -{ -	return (l_ptr->exp_msg_count || l_ptr->blocked); -} - -static int link_congested(struct link *l_ptr) -{ -	return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); -} - -static u32 link_max_pkt(struct link *l_ptr) -{ -	return l_ptr->max_pkt; -} -  static void link_init_max_pkt(struct link *l_ptr)  {  	u32 max_pkt; @@ -468,7 +433,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,  	l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;  	msg = l_ptr->pmsg; -	msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr); +	tipc_msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr);  	msg_set_size(msg, sizeof(l_ptr->proto_msg));  	msg_set_session(msg, (tipc_random & 0xffff));  	msg_set_bearer_id(msg, b_ptr->identity); @@ -561,9 +526,8 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)  			goto exit;  		if (!list_empty(&p_ptr->wait_list))  			goto exit; -		p_ptr->congested_link = l_ptr;  		p_ptr->publ.congested = 1; -		p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr)); +		p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt);  		list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);  		l_ptr->stats.link_congs++;  exit: @@ -592,7 +556,6 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all)  		if (win <= 0)  			break;  		list_del_init(&p_ptr->wait_list); -		p_ptr->congested_link = NULL;  		spin_lock_bh(p_ptr->publ.lock);  		p_ptr->publ.congested = 0;  		p_ptr->wakeup(&p_ptr->publ); @@ -877,7 +840,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)  		case TIMEOUT_EVT:  			dbg_link("TIM ");  			if (l_ptr->next_in_no != l_ptr->checkpoint) { -				dbg_link("-> WW \n"); +				dbg_link("-> WW\n");  				l_ptr->state = WORKING_WORKING;  				l_ptr->fsm_msg_cnt = 0;  				l_ptr->checkpoint = l_ptr->next_in_no; @@ -934,7 +897,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)  			link_set_timer(l_ptr, cont_intv);  			break;  		case RESET_MSG: -			dbg_link("RES \n"); +			dbg_link("RES\n");  			dbg_link(" -> RR\n");  			l_ptr->state = RESET_RESET;  			l_ptr->fsm_msg_cnt = 0; @@ -947,7 +910,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)  			l_ptr->started = 1;  			/* fall through */  		case TIMEOUT_EVT: -			dbg_link("TIM \n"); +			dbg_link("TIM\n");  			tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);  			l_ptr->fsm_msg_cnt++;  			link_set_timer(l_ptr, cont_intv); @@ -1017,7 +980,7 @@ static int link_bundle_buf(struct link *l_ptr,  		return 0;  	if (skb_tailroom(bundler) < (pad + size))  		return 0; -	if (link_max_pkt(l_ptr) < (to_pos + size)) +	if (l_ptr->max_pkt < (to_pos + size))  		return 0;  	skb_put(bundler, pad + size); @@ -1062,9 +1025,9 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)  	u32 size = msg_size(msg);  	u32 dsz = msg_data_sz(msg);  	u32 queue_size = l_ptr->out_queue_size; -	u32 imp = msg_tot_importance(msg); +	u32 imp = tipc_msg_tot_importance(msg);  	u32 queue_limit = l_ptr->queue_limit[imp]; -	u32 max_packet = link_max_pkt(l_ptr); +	u32 max_packet = l_ptr->max_pkt;  	msg_set_prevnode(msg, tipc_own_addr);	/* If routed message */ @@ -1127,7 +1090,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)  			struct tipc_msg bundler_hdr;  			if (bundler) { -				msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, +				tipc_msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,  					 INT_H_SIZE, l_ptr->addr);  				skb_copy_to_linear_data(bundler, &bundler_hdr,  							INT_H_SIZE); @@ -1195,7 +1158,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,  	int res = msg_data_sz(msg);  	if (likely(!link_congested(l_ptr))) { -		if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { +		if (likely(msg_size(msg) <= l_ptr->max_pkt)) {  			if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {  				link_add_to_outqueue(l_ptr, buf, msg);  				if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, @@ -1212,7 +1175,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,  			}  		}  		else -			*used_max_pkt = link_max_pkt(l_ptr); +			*used_max_pkt = l_ptr->max_pkt;  	}  	return tipc_link_send_buf(l_ptr, buf);  /* All other cases */  } @@ -1280,7 +1243,7 @@ again:  	 * (Must not hold any locks while building message.)  	 */ -	res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, +	res = tipc_msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,  			!sender->user_port, &buf);  	read_lock_bh(&tipc_net_lock); @@ -1319,7 +1282,7 @@ exit:  			 * then re-try fast path or fragment the message  			 */ -			sender->publ.max_pkt = link_max_pkt(l_ptr); +			sender->publ.max_pkt = l_ptr->max_pkt;  			tipc_node_unlock(node);  			read_unlock_bh(&tipc_net_lock); @@ -1391,7 +1354,7 @@ again:  	/* Prepare reusable fragment header: */  	msg_dbg(hdr, ">FRAGMENTING>"); -	msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, +	tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,  		 INT_H_SIZE, msg_destnode(hdr));  	msg_set_link_selector(&fragm_hdr, sender->publ.ref);  	msg_set_size(&fragm_hdr, max_pkt); @@ -1482,8 +1445,8 @@ error:  			tipc_node_unlock(node);  			goto reject;  		} -		if (link_max_pkt(l_ptr) < max_pkt) { -			sender->publ.max_pkt = link_max_pkt(l_ptr); +		if (l_ptr->max_pkt < max_pkt) { +			sender->publ.max_pkt = l_ptr->max_pkt;  			tipc_node_unlock(node);  			for (; buf_chain; buf_chain = buf) {  				buf = buf_chain->next; @@ -1553,7 +1516,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)  	/* Continue retransmission now, if there is anything: */ -	if (r_q_size && buf && !skb_cloned(buf)) { +	if (r_q_size && buf) {  		msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));  		msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);  		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { @@ -1650,7 +1613,7 @@ static void link_reset_all(unsigned long addr)  	tipc_node_lock(n_ptr);  	warn("Resetting all links to %s\n", -	     addr_string_fill(addr_string, n_ptr->addr)); +	     tipc_addr_string_fill(addr_string, n_ptr->addr));  	for (i = 0; i < MAX_BEARERS; i++) {  		if (n_ptr->links[i]) { @@ -1692,7 +1655,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)  		n_ptr = l_ptr->owner->next;  		tipc_node_lock(n_ptr); -		addr_string_fill(addr_string, n_ptr->addr); +		tipc_addr_string_fill(addr_string, n_ptr->addr);  		tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string);  		tipc_printf(TIPC_OUTPUT, "Supported: %d,  ", n_ptr->bclink.supported);  		tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); @@ -1722,15 +1685,16 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,  	dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);  	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { -		if (!skb_cloned(buf)) { +		if (l_ptr->retransm_queue_size == 0) {  			msg_dbg(msg, ">NO_RETR->BCONG>");  			dbg_print_link(l_ptr, "   ");  			l_ptr->retransm_queue_head = msg_seqno(msg);  			l_ptr->retransm_queue_size = retransmits; -			return;  		} else { -			/* Don't retransmit if driver already has the buffer */ +			err("Unexpected retransmit on link %s (qsize=%d)\n", +			    l_ptr->name, l_ptr->retransm_queue_size);  		} +		return;  	} else {  		/* Detect repeated retransmit failures on uncongested bearer */ @@ -1745,7 +1709,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,  		}  	} -	while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { +	while (retransmits && (buf != l_ptr->next_out) && buf) {  		msg = buf_msg(buf);  		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));  		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); @@ -2434,7 +2398,7 @@ void tipc_link_changeover(struct link *l_ptr)  		return;  	} -	msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, +	tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,  		 ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr);  	msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);  	msg_set_msgcnt(&tunnel_hdr, msgcount); @@ -2489,7 +2453,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel)  	struct sk_buff *iter;  	struct tipc_msg tunnel_hdr; -	msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, +	tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,  		 DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr);  	msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size);  	msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); @@ -2680,7 +2644,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)  	u32 dsz = msg_data_sz(inmsg);  	unchar *crs = buf->data;  	u32 rest = insize; -	u32 pack_sz = link_max_pkt(l_ptr); +	u32 pack_sz = l_ptr->max_pkt;  	u32 fragm_sz = pack_sz - INT_H_SIZE;  	u32 fragm_no = 1;  	u32 destaddr; @@ -2695,7 +2659,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)  	/* Prepare reusable fragment header: */ -	msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, +	tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,  		 INT_H_SIZE, destaddr);  	msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg));  	msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); @@ -3126,7 +3090,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)  	tipc_printf(&pb, "Link <%s>\n"  			 "  %s  MTU:%u  Priority:%u  Tolerance:%u ms"  			 "  Window:%u packets\n", -		    l_ptr->name, status, link_max_pkt(l_ptr), +		    l_ptr->name, status, l_ptr->max_pkt,  		    l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]);  	tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",  		    l_ptr->next_in_no - l_ptr->stats.recv_info, @@ -3271,7 +3235,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector)  		tipc_node_lock(n_ptr);  		l_ptr = n_ptr->active_links[selector & 1];  		if (l_ptr) -			res = link_max_pkt(l_ptr); +			res = l_ptr->max_pkt;  		tipc_node_unlock(n_ptr);  	}  	read_unlock_bh(&tipc_net_lock); @@ -3294,7 +3258,7 @@ static void link_dump_rec_queue(struct link *l_ptr)  			info("buffer %x invalid\n", crs);  			return;  		} -		msg_dbg(buf_msg(crs), "In rec queue: \n"); +		msg_dbg(buf_msg(crs), "In rec queue:\n");  		crs = crs->next;  	}  } @@ -3329,9 +3293,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,  		if (l_ptr->next_out)  			tipc_printf(buf, "%u..",  				    msg_seqno(buf_msg(l_ptr->next_out))); -		tipc_printf(buf, "%u]", -			    msg_seqno(buf_msg -				      (l_ptr->last_out)), l_ptr->out_queue_size); +		tipc_printf(buf, "%u]", msg_seqno(buf_msg(l_ptr->last_out)));  		if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) -  			 msg_seqno(buf_msg(l_ptr->first_out)))  		     != (l_ptr->out_queue_size - 1)) || diff --git a/net/tipc/link.h b/net/tipc/link.h index 6a51e38ad25..2e5385c47d3 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -292,4 +292,39 @@ static inline u32 lesser(u32 left, u32 right)  	return less_eq(left, right) ? left : right;  } + +/* + * Link status checking routines + */ + +static inline int link_working_working(struct link *l_ptr) +{ +	return (l_ptr->state == WORKING_WORKING); +} + +static inline int link_working_unknown(struct link *l_ptr) +{ +	return (l_ptr->state == WORKING_UNKNOWN); +} + +static inline int link_reset_unknown(struct link *l_ptr) +{ +	return (l_ptr->state == RESET_UNKNOWN); +} + +static inline int link_reset_reset(struct link *l_ptr) +{ +	return (l_ptr->state == RESET_RESET); +} + +static inline int link_blocked(struct link *l_ptr) +{ +	return (l_ptr->exp_msg_count || l_ptr->blocked); +} + +static inline int link_congested(struct link *l_ptr) +{ +	return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); +} +  #endif diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 73dcd00d674..381063817b4 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -40,6 +40,100 @@  #include "msg.h"  #include "bearer.h" +u32 tipc_msg_tot_importance(struct tipc_msg *m) +{ +	if (likely(msg_isdata(m))) { +		if (likely(msg_orignode(m) == tipc_own_addr)) +			return msg_importance(m); +		return msg_importance(m) + 4; +	} +	if ((msg_user(m) == MSG_FRAGMENTER)  && +	    (msg_type(m) == FIRST_FRAGMENT)) +		return msg_importance(msg_get_wrapped(m)); +	return msg_importance(m); +} + + +void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, +			    u32 hsize, u32 destnode) +{ +	memset(m, 0, hsize); +	msg_set_version(m); +	msg_set_user(m, user); +	msg_set_hdr_sz(m, hsize); +	msg_set_size(m, hsize); +	msg_set_prevnode(m, tipc_own_addr); +	msg_set_type(m, type); +	if (!msg_short(m)) { +		msg_set_orignode(m, tipc_own_addr); +		msg_set_destnode(m, destnode); +	} +} + +/** + * tipc_msg_calc_data_size - determine total data size for message + */ + +int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) +{ +	int dsz = 0; +	int i; + +	for (i = 0; i < num_sect; i++) +		dsz += msg_sect[i].iov_len; +	return dsz; +} + +/** + * tipc_msg_build - create message using specified header and data + * + * Note: Caller must not hold any locks in case copy_from_user() is interrupted! + * + * Returns message data size or errno + */ + +int tipc_msg_build(struct tipc_msg *hdr, +			    struct iovec const *msg_sect, u32 num_sect, +			    int max_size, int usrmem, struct sk_buff** buf) +{ +	int dsz, sz, hsz, pos, res, cnt; + +	dsz = tipc_msg_calc_data_size(msg_sect, num_sect); +	if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { +		*buf = NULL; +		return -EINVAL; +	} + +	pos = hsz = msg_hdr_sz(hdr); +	sz = hsz + dsz; +	msg_set_size(hdr, sz); +	if (unlikely(sz > max_size)) { +		*buf = NULL; +		return dsz; +	} + +	*buf = buf_acquire(sz); +	if (!(*buf)) +		return -ENOMEM; +	skb_copy_to_linear_data(*buf, hdr, hsz); +	for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { +		if (likely(usrmem)) +			res = !copy_from_user((*buf)->data + pos, +					      msg_sect[cnt].iov_base, +					      msg_sect[cnt].iov_len); +		else +			skb_copy_to_linear_data_offset(*buf, pos, +						       msg_sect[cnt].iov_base, +						       msg_sect[cnt].iov_len); +		pos += msg_sect[cnt].iov_len; +	} +	if (likely(res)) +		return dsz; + +	buf_discard(*buf); +	*buf = NULL; +	return -EFAULT; +}  #ifdef CONFIG_TIPC_DEBUG diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 7ee6ae23814..995d2da35b0 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -708,100 +708,13 @@ static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)  #define DSC_REQ_MSG          0  #define DSC_RESP_MSG         1 -static inline u32 msg_tot_importance(struct tipc_msg *m) -{ -	if (likely(msg_isdata(m))) { -		if (likely(msg_orignode(m) == tipc_own_addr)) -			return msg_importance(m); -		return msg_importance(m) + 4; -	} -	if ((msg_user(m) == MSG_FRAGMENTER)  && -	    (msg_type(m) == FIRST_FRAGMENT)) -		return msg_importance(msg_get_wrapped(m)); -	return msg_importance(m); -} - - -static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, -			    u32 hsize, u32 destnode) -{ -	memset(m, 0, hsize); -	msg_set_version(m); -	msg_set_user(m, user); -	msg_set_hdr_sz(m, hsize); -	msg_set_size(m, hsize); -	msg_set_prevnode(m, tipc_own_addr); -	msg_set_type(m, type); -	if (!msg_short(m)) { -		msg_set_orignode(m, tipc_own_addr); -		msg_set_destnode(m, destnode); -	} -} - -/** - * msg_calc_data_size - determine total data size for message - */ - -static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) -{ -	int dsz = 0; -	int i; - -	for (i = 0; i < num_sect; i++) -		dsz += msg_sect[i].iov_len; -	return dsz; -} - -/** - * msg_build - create message using specified header and data - * - * Note: Caller must not hold any locks in case copy_from_user() is interrupted! - * - * Returns message data size or errno - */ - -static inline int msg_build(struct tipc_msg *hdr, +u32 tipc_msg_tot_importance(struct tipc_msg *m); +void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, +			    u32 hsize, u32 destnode); +int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect); +int tipc_msg_build(struct tipc_msg *hdr,  			    struct iovec const *msg_sect, u32 num_sect, -			    int max_size, int usrmem, struct sk_buff** buf) -{ -	int dsz, sz, hsz, pos, res, cnt; - -	dsz = msg_calc_data_size(msg_sect, num_sect); -	if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { -		*buf = NULL; -		return -EINVAL; -	} - -	pos = hsz = msg_hdr_sz(hdr); -	sz = hsz + dsz; -	msg_set_size(hdr, sz); -	if (unlikely(sz > max_size)) { -		*buf = NULL; -		return dsz; -	} - -	*buf = buf_acquire(sz); -	if (!(*buf)) -		return -ENOMEM; -	skb_copy_to_linear_data(*buf, hdr, hsz); -	for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { -		if (likely(usrmem)) -			res = !copy_from_user((*buf)->data + pos, -					      msg_sect[cnt].iov_base, -					      msg_sect[cnt].iov_len); -		else -			skb_copy_to_linear_data_offset(*buf, pos, -						       msg_sect[cnt].iov_base, -						       msg_sect[cnt].iov_len); -		pos += msg_sect[cnt].iov_len; -	} -	if (likely(res)) -		return dsz; - -	buf_discard(*buf); -	*buf = NULL; -	return -EFAULT; -} +			    int max_size, int usrmem, struct sk_buff** buf);  static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)  { diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 10a69894e2f..6ac3c543250 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -103,7 +103,7 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)  	if (buf != NULL) {  		msg = buf_msg(buf); -		msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest); +		tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest);  		msg_set_size(msg, LONG_H_SIZE + size);  	}  	return buf; diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index acab41a48d6..8ba79620db3 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -627,7 +627,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)  	struct name_seq *seq;  	u32 ref; -	if (!in_scope(*destnode, tipc_own_addr)) +	if (!tipc_in_scope(*destnode, tipc_own_addr))  		return 0;  	read_lock_bh(&tipc_nametbl_lock); diff --git a/net/tipc/net.c b/net/tipc/net.c index f25b1cdb64e..f61b7694138 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -116,7 +116,7 @@  */  DEFINE_RWLOCK(tipc_net_lock); -struct _zone *tipc_zones[256] = { NULL, }; +static struct _zone *tipc_zones[256] = { NULL, };  struct network tipc_net = { tipc_zones };  struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) @@ -219,7 +219,7 @@ void tipc_net_route_msg(struct sk_buff *buf)  	/* Handle message for this node */  	dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); -	if (in_scope(dnode, tipc_own_addr)) { +	if (tipc_in_scope(dnode, tipc_own_addr)) {  		if (msg_isdata(msg)) {  			if (msg_mcast(msg))  				tipc_port_recv_mcast(buf, NULL); @@ -277,7 +277,7 @@ int tipc_net_start(u32 addr)  	info("Started in network mode\n");  	info("Own node address %s, network identity %u\n", -	     addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); +	     tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);  	return 0;  } @@ -291,6 +291,6 @@ void tipc_net_stop(void)  	tipc_bclink_stop();  	net_stop();  	write_unlock_bh(&tipc_net_lock); -	info("Left network mode \n"); +	info("Left network mode\n");  } diff --git a/net/tipc/node.c b/net/tipc/node.c index 2c24e7d6d95..b634942caba 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -268,7 +268,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr)  		if (n_ptr->link_cnt >= 2) {  			err("Attempt to create third link to %s\n", -			    addr_string_fill(addr_string, n_ptr->addr)); +			    tipc_addr_string_fill(addr_string, n_ptr->addr));  			return NULL;  		} @@ -278,9 +278,9 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr)  			n_ptr->link_cnt++;  			return n_ptr;  		} -		err("Attempt to establish second link on <%s> to %s \n", +		err("Attempt to establish second link on <%s> to %s\n",  		    l_ptr->b_ptr->publ.name, -		    addr_string_fill(addr_string, l_ptr->addr)); +		    tipc_addr_string_fill(addr_string, l_ptr->addr));  	}  	return NULL;  } @@ -439,7 +439,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)  		return;  	info("Lost contact with %s\n", -	     addr_string_fill(addr_string, n_ptr->addr)); +	     tipc_addr_string_fill(addr_string, n_ptr->addr));  	/* Abort link changeover */  	for (i = 0; i < MAX_BEARERS; i++) { @@ -602,7 +602,7 @@ u32 tipc_available_nodes(const u32 domain)  	read_lock_bh(&tipc_net_lock);  	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { -		if (!in_scope(domain, n_ptr->addr)) +		if (!tipc_in_scope(domain, n_ptr->addr))  			continue;  		if (tipc_node_is_up(n_ptr))  			cnt++; @@ -651,7 +651,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)  	/* Add TLVs for all nodes in scope */  	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { -		if (!in_scope(domain, n_ptr->addr)) +		if (!tipc_in_scope(domain, n_ptr->addr))  			continue;  		node_info.addr = htonl(n_ptr->addr);  		node_info.up = htonl(tipc_node_is_up(n_ptr)); @@ -711,7 +711,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)  	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {  		u32 i; -		if (!in_scope(domain, n_ptr->addr)) +		if (!tipc_in_scope(domain, n_ptr->addr))  			continue;  		tipc_node_lock(n_ptr);  		for (i = 0; i < MAX_BEARERS; i++) { diff --git a/net/tipc/port.c b/net/tipc/port.c index e70d27ea657..0737680e926 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -116,7 +116,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain,  	msg_set_namelower(hdr, seq->lower);  	msg_set_nameupper(hdr, seq->upper);  	msg_set_hdr_sz(hdr, MCAST_H_SIZE); -	res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, +	res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,  			!oport->user_port, &buf);  	if (unlikely(!buf))  		return res; @@ -241,13 +241,12 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,  	p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;  	p_ptr->publ.ref = ref;  	msg = &p_ptr->publ.phdr; -	msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); +	tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);  	msg_set_origport(msg, ref);  	p_ptr->last_in_seqno = 41;  	p_ptr->sent = 1;  	INIT_LIST_HEAD(&p_ptr->wait_list);  	INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); -	p_ptr->congested_link = NULL;  	p_ptr->dispatcher = dispatcher;  	p_ptr->wakeup = wakeup;  	p_ptr->user_port = NULL; @@ -396,7 +395,7 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,  	buf = buf_acquire(LONG_H_SIZE);  	if (buf) {  		msg = buf_msg(buf); -		msg_init(msg, usr, type, LONG_H_SIZE, destnode); +		tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);  		msg_set_errcode(msg, err);  		msg_set_destport(msg, destport);  		msg_set_origport(msg, origport); @@ -440,7 +439,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)  		return data_sz;  	}  	rmsg = buf_msg(rbuf); -	msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); +	tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg));  	msg_set_errcode(rmsg, err);  	msg_set_destport(rmsg, msg_origport(msg));  	msg_set_origport(rmsg, msg_destport(msg)); @@ -481,7 +480,7 @@ int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,  	struct sk_buff *buf;  	int res; -	res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, +	res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,  			!p_ptr->user_port, &buf);  	if (!buf)  		return res; @@ -1344,7 +1343,7 @@ int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,  	struct sk_buff *buf;  	int res; -	res = msg_build(&sender->publ.phdr, msg_sect, num_sect, +	res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect,  			MAX_MSG_SIZE, !sender->user_port, &buf);  	if (likely(buf))  		tipc_port_recv_msg(buf); @@ -1384,7 +1383,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)  	if (port_unreliable(p_ptr)) {  		p_ptr->publ.congested = 0;  		/* Just calculate msg length and return */ -		return msg_calc_data_size(msg_sect, num_sect); +		return tipc_msg_calc_data_size(msg_sect, num_sect);  	}  	return -ELINKCONG;  } @@ -1453,7 +1452,7 @@ int tipc_forward2name(u32 ref,  	struct port *p_ptr;  	struct tipc_msg *msg;  	u32 destnode = domain; -	u32 destport = 0; +	u32 destport;  	int res;  	p_ptr = tipc_port_deref(ref); @@ -1467,7 +1466,7 @@ int tipc_forward2name(u32 ref,  	msg_set_hdr_sz(msg, LONG_H_SIZE);  	msg_set_nametype(msg, name->type);  	msg_set_nameinst(msg, name->instance); -	msg_set_lookup_scope(msg, addr_scope(domain)); +	msg_set_lookup_scope(msg, tipc_addr_scope(domain));  	if (importance <= TIPC_CRITICAL_IMPORTANCE)  		msg_set_importance(msg,importance);  	destport = tipc_nametbl_translate(name->type, name->instance, &destnode); @@ -1484,7 +1483,7 @@ int tipc_forward2name(u32 ref,  			return res;  		if (port_unreliable(p_ptr)) {  			/* Just calculate msg length and return */ -			return msg_calc_data_size(msg_sect, num_sect); +			return tipc_msg_calc_data_size(msg_sect, num_sect);  		}  		return -ELINKCONG;  	} @@ -1525,7 +1524,7 @@ int tipc_forward_buf2name(u32 ref,  	struct port *p_ptr;  	struct tipc_msg *msg;  	u32 destnode = domain; -	u32 destport = 0; +	u32 destport;  	int res;  	p_ptr = (struct port *)tipc_ref_deref(ref); @@ -1540,7 +1539,7 @@ int tipc_forward_buf2name(u32 ref,  	msg_set_origport(msg, orig->ref);  	msg_set_nametype(msg, name->type);  	msg_set_nameinst(msg, name->instance); -	msg_set_lookup_scope(msg, addr_scope(domain)); +	msg_set_lookup_scope(msg, tipc_addr_scope(domain));  	msg_set_hdr_sz(msg, LONG_H_SIZE);  	msg_set_size(msg, LONG_H_SIZE + dsz);  	destport = tipc_nametbl_translate(name->type, name->instance, &destnode); @@ -1620,7 +1619,7 @@ int tipc_forward2port(u32 ref,  		return res;  	if (port_unreliable(p_ptr)) {  		/* Just calculate msg length and return */ -		return msg_calc_data_size(msg_sect, num_sect); +		return tipc_msg_calc_data_size(msg_sect, num_sect);  	}  	return -ELINKCONG;  } diff --git a/net/tipc/port.h b/net/tipc/port.h index ff31ee4a1dc..8d1652aab29 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -75,7 +75,6 @@ struct user_port {   * @wakeup: ptr to routine to call when port is no longer congested   * @user_port: ptr to user port associated with port (if any)   * @wait_list: adjacent ports in list of ports waiting on link congestion - * @congested_link: ptr to congested link port is waiting on   * @waiting_pkts:   * @sent:   * @acked: @@ -95,7 +94,6 @@ struct port {  	void (*wakeup)(struct tipc_port *);  	struct user_port *user_port;  	struct list_head wait_list; -	struct link *congested_link;  	u32 waiting_pkts;  	u32 sent;  	u32 acked; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 4b235fc1c70..66e889ba48f 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -40,9 +40,9 @@  #include <linux/socket.h>  #include <linux/errno.h>  #include <linux/mm.h> -#include <linux/slab.h>  #include <linux/poll.h>  #include <linux/fcntl.h> +#include <linux/gfp.h>  #include <asm/string.h>  #include <asm/atomic.h>  #include <net/sock.h> @@ -446,7 +446,7 @@ static unsigned int poll(struct file *file, struct socket *sock,  	struct sock *sk = sock->sk;  	u32 mask; -	poll_wait(file, sk->sk_sleep, wait); +	poll_wait(file, sk_sleep(sk), wait);  	if (!skb_queue_empty(&sk->sk_receive_queue) ||  	    (sock->state == SS_UNCONNECTED) || @@ -591,7 +591,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,  			break;  		}  		release_sock(sk); -		res = wait_event_interruptible(*sk->sk_sleep, +		res = wait_event_interruptible(*sk_sleep(sk),  					       !tport->congested);  		lock_sock(sk);  		if (res) @@ -650,7 +650,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,  			break;  		}  		release_sock(sk); -		res = wait_event_interruptible(*sk->sk_sleep, +		res = wait_event_interruptible(*sk_sleep(sk),  			(!tport->congested || !tport->connected));  		lock_sock(sk);  		if (res) @@ -931,7 +931,7 @@ restart:  			goto exit;  		}  		release_sock(sk); -		res = wait_event_interruptible(*sk->sk_sleep, +		res = wait_event_interruptible(*sk_sleep(sk),  			(!skb_queue_empty(&sk->sk_receive_queue) ||  			 (sock->state == SS_DISCONNECTING)));  		lock_sock(sk); @@ -1064,7 +1064,7 @@ restart:  			goto exit;  		}  		release_sock(sk); -		res = wait_event_interruptible(*sk->sk_sleep, +		res = wait_event_interruptible(*sk_sleep(sk),  			(!skb_queue_empty(&sk->sk_receive_queue) ||  			 (sock->state == SS_DISCONNECTING)));  		lock_sock(sk); @@ -1271,8 +1271,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)  		tipc_disconnect_port(tipc_sk_port(sk));  	} -	if (waitqueue_active(sk->sk_sleep)) -		wake_up_interruptible(sk->sk_sleep); +	if (waitqueue_active(sk_sleep(sk))) +		wake_up_interruptible(sk_sleep(sk));  	return TIPC_OK;  } @@ -1343,8 +1343,8 @@ static void wakeupdispatch(struct tipc_port *tport)  {  	struct sock *sk = (struct sock *)tport->usr_handle; -	if (waitqueue_active(sk->sk_sleep)) -		wake_up_interruptible(sk->sk_sleep); +	if (waitqueue_active(sk_sleep(sk))) +		wake_up_interruptible(sk_sleep(sk));  }  /** @@ -1426,7 +1426,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,  	/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */  	release_sock(sk); -	res = wait_event_interruptible_timeout(*sk->sk_sleep, +	res = wait_event_interruptible_timeout(*sk_sleep(sk),  			(!skb_queue_empty(&sk->sk_receive_queue) ||  			(sock->state != SS_CONNECTING)),  			sk->sk_rcvtimeo); @@ -1521,7 +1521,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)  			goto exit;  		}  		release_sock(sk); -		res = wait_event_interruptible(*sk->sk_sleep, +		res = wait_event_interruptible(*sk_sleep(sk),  				(!skb_queue_empty(&sk->sk_receive_queue)));  		lock_sock(sk);  		if (res) @@ -1632,8 +1632,8 @@ restart:  		/* Discard any unreceived messages; wake up sleeping tasks */  		discard_rx_queue(sk); -		if (waitqueue_active(sk->sk_sleep)) -			wake_up_interruptible(sk->sk_sleep); +		if (waitqueue_active(sk_sleep(sk))) +			wake_up_interruptible(sk_sleep(sk));  		res = 0;  		break; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ff123e56114..ab6eab4c45e 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -274,7 +274,7 @@ static void subscr_cancel(struct tipc_subscr *s,  {  	struct subscription *sub;  	struct subscription *sub_temp; -	__u32 type, lower, upper; +	__u32 type, lower, upper, timeout, filter;  	int found = 0;  	/* Find first matching subscription, exit if not found */ @@ -282,12 +282,18 @@ static void subscr_cancel(struct tipc_subscr *s,  	type = ntohl(s->seq.type);  	lower = ntohl(s->seq.lower);  	upper = ntohl(s->seq.upper); +	timeout = ntohl(s->timeout); +	filter = ntohl(s->filter) & ~TIPC_SUB_CANCEL;  	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,  				 subscription_list) {  			if ((type == sub->seq.type) &&  			    (lower == sub->seq.lower) && -			    (upper == sub->seq.upper)) { +			    (upper == sub->seq.upper) && +			    (timeout == sub->timeout) && +                            (filter == sub->filter) && +                             !memcmp(s->usr_handle,sub->evt.s.usr_handle, +				     sizeof(s->usr_handle)) ){  				found = 1;  				break;  			} @@ -304,7 +310,7 @@ static void subscr_cancel(struct tipc_subscr *s,  		k_term_timer(&sub->timer);  		spin_lock_bh(subscriber->lock);  	} -	dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", +	dbg("Cancel: removing sub %u,%u,%u from subscriber %p list\n",  	    sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);  	subscr_del(sub);  } @@ -352,8 +358,7 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s,  	sub->seq.upper = ntohl(s->seq.upper);  	sub->timeout = ntohl(s->timeout);  	sub->filter = ntohl(s->filter); -	if ((!(sub->filter & TIPC_SUB_PORTS) == -	     !(sub->filter & TIPC_SUB_SERVICE)) || +	if ((sub->filter && (sub->filter != TIPC_SUB_PORTS)) ||  	    (sub->seq.lower > sub->seq.upper)) {  		warn("Subscription rejected, illegal request\n");  		kfree(sub); | 
