[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
|
@ -96,6 +96,12 @@ struct tipc_port *tipc_get_port(const u32 ref);
|
||||||
|
|
||||||
void *tipc_get_handle(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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1240,6 +1240,28 @@ exit:
|
||||||
return res;
|
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.
|
* tipc_disconnect(): Disconnect port form peer.
|
||||||
* This is a node local operation.
|
* This is a node local operation.
|
||||||
|
@ -1248,17 +1270,12 @@ exit:
|
||||||
int tipc_disconnect(u32 ref)
|
int tipc_disconnect(u32 ref)
|
||||||
{
|
{
|
||||||
struct port *p_ptr;
|
struct port *p_ptr;
|
||||||
int res = -ENOTCONN;
|
int res;
|
||||||
|
|
||||||
p_ptr = tipc_port_lock(ref);
|
p_ptr = tipc_port_lock(ref);
|
||||||
if (!p_ptr)
|
if (!p_ptr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (p_ptr->publ.connected) {
|
res = tipc_disconnect_port((struct tipc_port *)p_ptr);
|
||||||
p_ptr->publ.connected = 0;
|
|
||||||
/* let timer expire on it's own to avoid deadlock! */
|
|
||||||
tipc_nodesub_unsubscribe(&p_ptr->subscription);
|
|
||||||
res = TIPC_OK;
|
|
||||||
}
|
|
||||||
tipc_port_unlock(p_ptr);
|
tipc_port_unlock(p_ptr);
|
||||||
return res;
|
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