[TIPC]: Overhaul of socket locking logic

This patch modifies TIPC's socket code to follow the same approach
used by other protocols.  This change eliminates the need for a
mutex in the TIPC-specific portion of the socket protocol data
structure -- in its place, the standard Linux socket backlog queue
and associated locking routines are utilized.  These changes fix
a long-standing receive queue bug on SMP systems, and also enable
individual read and write threads to utilize a socket without
unnecessarily interfering with each other.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Allan Stephens 2008-04-15 00:22:02 -07:00 committed by David S. Miller
parent b89741a0cc
commit 0c3141e910
3 changed files with 623 additions and 446 deletions

View file

@ -96,6 +96,12 @@ struct tipc_port *tipc_get_port(const u32 ref);
void *tipc_get_handle(const u32 ref);
/*
* The following routines require that the port be locked on entry
*/
int tipc_disconnect_port(struct tipc_port *tp_ptr);
#endif

View file

@ -1240,6 +1240,28 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
return res;
}
/**
* tipc_disconnect_port - disconnect port from peer
*
* Port must be locked.
*/
int tipc_disconnect_port(struct tipc_port *tp_ptr)
{
int res;
if (tp_ptr->connected) {
tp_ptr->connected = 0;
/* let timer expire on it's own to avoid deadlock! */
tipc_nodesub_unsubscribe(
&((struct port *)tp_ptr)->subscription);
res = TIPC_OK;
} else {
res = -ENOTCONN;
}
return res;
}
/*
* tipc_disconnect(): Disconnect port form peer.
* This is a node local operation.
@ -1248,17 +1270,12 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
int tipc_disconnect(u32 ref)
{
struct port *p_ptr;
int res = -ENOTCONN;
int res;
p_ptr = tipc_port_lock(ref);
if (!p_ptr)
return -EINVAL;
if (p_ptr->publ.connected) {
p_ptr->publ.connected = 0;
/* let timer expire on it's own to avoid deadlock! */
tipc_nodesub_unsubscribe(&p_ptr->subscription);
res = TIPC_OK;
}
res = tipc_disconnect_port((struct tipc_port *)p_ptr);
tipc_port_unlock(p_ptr);
return res;
}

File diff suppressed because it is too large Load diff