[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:
parent
b89741a0cc
commit
0c3141e910
3 changed files with 623 additions and 446 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
1032
net/tipc/socket.c
1032
net/tipc/socket.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue