Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a9ee0be authored by Jon Paul Maloy's avatar Jon Paul Maloy Committed by David S. Miller
Browse files

tipc: use registry when scanning sockets



The functions tipc_port_get_ports() and tipc_port_reinit() scan over
all sockets/ports to access each of them. This is done by using a
dedicated linked list, 'tipc_socks' where all sockets are members. The
list is in turn protected by a spinlock, 'port_list_lock', while each
socket is locked by using port_lock at the moment of access.

In order to reduce complexity and risk of deadlock, we want to get
rid of the linked list and the accompanying spinlock.

This is what we do in this commit. Instead of the linked list, we use
the port registry to scan across the sockets. We also add usage of
bh_lock_sock() inside the scope of port_lock in both functions, as a
preparation for the complete removal of port_lock.

Finally, we move the functions from port.c to socket.c, and rename them
to tipc_sk_sock_show() and tipc_sk_reinit() repectively.

Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5b8fa7ce
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
 */

#include "core.h"
#include "port.h"
#include "socket.h"
#include "name_table.h"
#include "config.h"
#include "server.h"
@@ -266,7 +266,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
		rep_tlv_buf = tipc_media_get_names();
		break;
	case TIPC_CMD_SHOW_PORTS:
		rep_tlv_buf = tipc_port_get_ports();
		rep_tlv_buf = tipc_sk_socks_show();
		break;
	case TIPC_CMD_SHOW_STATS:
		rep_tlv_buf = tipc_show_stats();
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ int tipc_net_start(u32 addr)

	tipc_own_addr = addr;
	tipc_named_reinit();
	tipc_port_reinit();
	tipc_sk_reinit();
	res = tipc_bclink_init();
	if (res)
		return res;
+0 −87
Original line number Diff line number Diff line
@@ -63,93 +63,6 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg)
		(!peernode && (orignode == tipc_own_addr));
}

static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
{
	struct publication *publ;
	int ret;

	if (full_id)
		ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
				    tipc_zone(tipc_own_addr),
				    tipc_cluster(tipc_own_addr),
				    tipc_node(tipc_own_addr), p_ptr->ref);
	else
		ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref);

	if (p_ptr->connected) {
		u32 dport = tipc_port_peerport(p_ptr);
		u32 destnode = tipc_port_peernode(p_ptr);

		ret += tipc_snprintf(buf + ret, len - ret,
				     " connected to <%u.%u.%u:%u>",
				     tipc_zone(destnode),
				     tipc_cluster(destnode),
				     tipc_node(destnode), dport);
		if (p_ptr->conn_type != 0)
			ret += tipc_snprintf(buf + ret, len - ret,
					     " via {%u,%u}", p_ptr->conn_type,
					     p_ptr->conn_instance);
	} else if (p_ptr->published) {
		ret += tipc_snprintf(buf + ret, len - ret, " bound to");
		list_for_each_entry(publ, &p_ptr->publications, pport_list) {
			if (publ->lower == publ->upper)
				ret += tipc_snprintf(buf + ret, len - ret,
						     " {%u,%u}", publ->type,
						     publ->lower);
			else
				ret += tipc_snprintf(buf + ret, len - ret,
						     " {%u,%u,%u}", publ->type,
						     publ->lower, publ->upper);
		}
	}
	ret += tipc_snprintf(buf + ret, len - ret, "\n");
	return ret;
}

struct sk_buff *tipc_port_get_ports(void)
{
	struct sk_buff *buf;
	struct tlv_desc *rep_tlv;
	char *pb;
	int pb_len;
	struct tipc_port *p_ptr;
	int str_len = 0;

	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
	if (!buf)
		return NULL;
	rep_tlv = (struct tlv_desc *)buf->data;
	pb = TLV_DATA(rep_tlv);
	pb_len = ULTRA_STRING_MAX_LEN;

	spin_lock_bh(&tipc_port_list_lock);
	list_for_each_entry(p_ptr, &tipc_socks, port_list) {
		spin_lock_bh(p_ptr->lock);
		str_len += port_print(p_ptr, pb, pb_len, 0);
		spin_unlock_bh(p_ptr->lock);
	}
	spin_unlock_bh(&tipc_port_list_lock);
	str_len += 1;	/* for "\0" */
	skb_put(buf, TLV_SPACE(str_len));
	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);

	return buf;
}

void tipc_port_reinit(void)
{
	struct tipc_port *p_ptr;
	struct tipc_msg *msg;

	spin_lock_bh(&tipc_port_list_lock);
	list_for_each_entry(p_ptr, &tipc_socks, port_list) {
		msg = &p_ptr->phdr;
		msg_set_prevnode(msg, tipc_own_addr);
		msg_set_orignode(msg, tipc_own_addr);
	}
	spin_unlock_bh(&tipc_port_list_lock);
}

int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
		 struct tipc_name_seq const *seq)
{
+0 −5
Original line number Diff line number Diff line
@@ -73,7 +73,6 @@ struct tipc_port {
	u32 max_pkt;
	u32 ref;
	struct tipc_msg phdr;
	struct list_head port_list;
	struct list_head publications;
	u32 pub_count;
	u32 probing_state;
@@ -81,9 +80,6 @@ struct tipc_port {
	struct timer_list timer;
};

extern struct list_head tipc_socks;
extern spinlock_t tipc_port_list_lock;

/*
 * TIPC port manipulation routines
 */
@@ -100,7 +96,6 @@ int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,

int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg);

struct sk_buff *tipc_port_get_ports(void);
void tipc_port_reinit(void);

/**
+20 −0
Original line number Diff line number Diff line
@@ -264,3 +264,23 @@ void *tipc_ref_lock(u32 ref)
	}
	return NULL;
}

/* tipc_ref_lock_next - lock & return next object after referenced one
*/
void *tipc_ref_lock_next(u32 *ref)
{
	struct reference *entry;
	uint index = *ref & tipc_ref_table.index_mask;

	while (++index < tipc_ref_table.capacity) {
		entry = &tipc_ref_table.entries[index];
		if (!entry->object)
			continue;
		spin_lock_bh(&entry->lock);
		*ref = entry->ref;
		if (entry->object)
			return entry->object;
		spin_unlock_bh(&entry->lock);
	}
	return NULL;
}
Loading