aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-08-22 18:09:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-23 14:18:34 -0400
commit6c9808ce09f778a1de7b207b82cfc36a59cda2d3 (patch)
treedce467a4bd4be90896e7243f87335e1b41cded75 /net/tipc/socket.c
parent9b50fd087a9f1454d6a8b613fff376dfb6d6ea93 (diff)
tipc: remove port_lock
In previous commits we have reduced usage of port_lock to a minimum, and complemented it with usage of bh_lock_sock() at the remaining locations. The purpose has been to remove this lock altogether, since it largely duplicates the role of bh_lock_sock. We are now ready to do this. However, we still need to protect the BH callers from inadvertent release of the socket while they hold a reference to it. We do this by replacing port_lock by a combination of a rw-lock protecting the reference table as such, and updating the socket reference counter while the socket is referenced from BH. This technique is more standard and comprehensible than the previous approach, and turns out to have a positive effect on overall performance. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c64
1 files changed, 26 insertions, 38 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 247f245ff596..7e6240e41e69 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -35,6 +35,7 @@
35 */ 35 */
36 36
37#include "core.h" 37#include "core.h"
38#include "ref.h"
38#include "port.h" 39#include "port.h"
39#include "name_table.h" 40#include "name_table.h"
40#include "node.h" 41#include "node.h"
@@ -111,13 +112,6 @@ static struct proto tipc_proto_kern;
111 112
112#include "socket.h" 113#include "socket.h"
113 114
114/* tipc_sk_lock_next: find & lock next socket in registry from given port number
115*/
116static struct tipc_sock *tipc_sk_lock_next(u32 *ref)
117{
118 return (struct tipc_sock *)tipc_ref_lock_next(ref);
119}
120
121/** 115/**
122 * advance_rx_queue - discard first buffer in socket receive queue 116 * advance_rx_queue - discard first buffer in socket receive queue
123 * 117 *
@@ -200,7 +194,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
200 194
201 tsk = tipc_sk(sk); 195 tsk = tipc_sk(sk);
202 port = &tsk->port; 196 port = &tsk->port;
203 ref = tipc_ref_acquire(tsk, &port->lock); 197 ref = tipc_ref_acquire(tsk);
204 if (!ref) { 198 if (!ref) {
205 pr_warn("Socket create failed; reference table exhausted\n"); 199 pr_warn("Socket create failed; reference table exhausted\n");
206 return -ENOMEM; 200 return -ENOMEM;
@@ -226,7 +220,6 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
226 tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; 220 tsk->conn_timeout = CONN_TIMEOUT_DEFAULT;
227 tsk->sent_unacked = 0; 221 tsk->sent_unacked = 0;
228 atomic_set(&tsk->dupl_rcvcnt, 0); 222 atomic_set(&tsk->dupl_rcvcnt, 0);
229 tipc_port_unlock(port);
230 223
231 if (sock->state == SS_READY) { 224 if (sock->state == SS_READY) {
232 tipc_port_set_unreturnable(port, true); 225 tipc_port_set_unreturnable(port, true);
@@ -364,9 +357,7 @@ static int tipc_release(struct socket *sock)
364 } 357 }
365 358
366 tipc_withdraw(port, 0, NULL); 359 tipc_withdraw(port, 0, NULL);
367 spin_lock_bh(port->lock);
368 tipc_ref_discard(port->ref); 360 tipc_ref_discard(port->ref);
369 spin_unlock_bh(port->lock);
370 k_cancel_timer(&port->timer); 361 k_cancel_timer(&port->timer);
371 if (port->connected) { 362 if (port->connected) {
372 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, 363 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
@@ -1651,7 +1642,7 @@ int tipc_sk_rcv(struct sk_buff *buf)
1651 u32 dnode; 1642 u32 dnode;
1652 1643
1653 /* Validate destination and message */ 1644 /* Validate destination and message */
1654 tsk = tipc_port_lock(dport); 1645 tsk = tipc_sk_get(dport);
1655 if (unlikely(!tsk)) { 1646 if (unlikely(!tsk)) {
1656 rc = tipc_msg_eval(buf, &dnode); 1647 rc = tipc_msg_eval(buf, &dnode);
1657 goto exit; 1648 goto exit;
@@ -1672,8 +1663,7 @@ int tipc_sk_rcv(struct sk_buff *buf)
1672 rc = -TIPC_ERR_OVERLOAD; 1663 rc = -TIPC_ERR_OVERLOAD;
1673 } 1664 }
1674 bh_unlock_sock(sk); 1665 bh_unlock_sock(sk);
1675 tipc_port_unlock(port); 1666 tipc_sk_put(tsk);
1676
1677 if (likely(!rc)) 1667 if (likely(!rc))
1678 return 0; 1668 return 0;
1679exit: 1669exit:
@@ -1997,23 +1987,23 @@ restart:
1997 1987
1998static void tipc_sk_timeout(unsigned long ref) 1988static void tipc_sk_timeout(unsigned long ref)
1999{ 1989{
2000 struct tipc_sock *tsk = tipc_port_lock(ref); 1990 struct tipc_sock *tsk;
2001 struct tipc_port *port; 1991 struct tipc_port *port;
2002 struct sock *sk; 1992 struct sock *sk;
2003 struct sk_buff *buf = NULL; 1993 struct sk_buff *buf = NULL;
2004 struct tipc_msg *msg = NULL;
2005 u32 peer_port, peer_node; 1994 u32 peer_port, peer_node;
2006 1995
1996 tsk = tipc_sk_get(ref);
2007 if (!tsk) 1997 if (!tsk)
2008 return; 1998 goto exit;
2009 1999 sk = &tsk->sk;
2010 port = &tsk->port; 2000 port = &tsk->port;
2001
2002 bh_lock_sock(sk);
2011 if (!port->connected) { 2003 if (!port->connected) {
2012 tipc_port_unlock(port); 2004 bh_unlock_sock(sk);
2013 return; 2005 goto exit;
2014 } 2006 }
2015 sk = &tsk->sk;
2016 bh_lock_sock(sk);
2017 peer_port = tipc_port_peerport(port); 2007 peer_port = tipc_port_peerport(port);
2018 peer_node = tipc_port_peernode(port); 2008 peer_node = tipc_port_peernode(port);
2019 2009
@@ -2031,12 +2021,10 @@ static void tipc_sk_timeout(unsigned long ref)
2031 k_start_timer(&port->timer, port->probing_interval); 2021 k_start_timer(&port->timer, port->probing_interval);
2032 } 2022 }
2033 bh_unlock_sock(sk); 2023 bh_unlock_sock(sk);
2034 tipc_port_unlock(port); 2024 if (buf)
2035 if (!buf) 2025 tipc_link_xmit(buf, peer_node, ref);
2036 return; 2026exit:
2037 2027 tipc_sk_put(tsk);
2038 msg = buf_msg(buf);
2039 tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg));
2040} 2028}
2041 2029
2042static int tipc_sk_show(struct tipc_port *port, char *buf, 2030static int tipc_sk_show(struct tipc_port *port, char *buf,
@@ -2100,13 +2088,13 @@ struct sk_buff *tipc_sk_socks_show(void)
2100 pb = TLV_DATA(rep_tlv); 2088 pb = TLV_DATA(rep_tlv);
2101 pb_len = ULTRA_STRING_MAX_LEN; 2089 pb_len = ULTRA_STRING_MAX_LEN;
2102 2090
2103 tsk = tipc_sk_lock_next(&ref); 2091 tsk = tipc_sk_get_next(&ref);
2104 for (; tsk; tsk = tipc_sk_lock_next(&ref)) { 2092 for (; tsk; tsk = tipc_sk_get_next(&ref)) {
2105 bh_lock_sock(&tsk->sk); 2093 lock_sock(&tsk->sk);
2106 str_len += tipc_sk_show(&tsk->port, pb + str_len, 2094 str_len += tipc_sk_show(&tsk->port, pb + str_len,
2107 pb_len - str_len, 0); 2095 pb_len - str_len, 0);
2108 bh_unlock_sock(&tsk->sk); 2096 release_sock(&tsk->sk);
2109 tipc_port_unlock(&tsk->port); 2097 tipc_sk_put(tsk);
2110 } 2098 }
2111 str_len += 1; /* for "\0" */ 2099 str_len += 1; /* for "\0" */
2112 skb_put(buf, TLV_SPACE(str_len)); 2100 skb_put(buf, TLV_SPACE(str_len));
@@ -2122,15 +2110,15 @@ void tipc_sk_reinit(void)
2122{ 2110{
2123 struct tipc_msg *msg; 2111 struct tipc_msg *msg;
2124 u32 ref = 0; 2112 u32 ref = 0;
2125 struct tipc_sock *tsk = tipc_sk_lock_next(&ref); 2113 struct tipc_sock *tsk = tipc_sk_get_next(&ref);
2126 2114
2127 for (; tsk; tsk = tipc_sk_lock_next(&ref)) { 2115 for (; tsk; tsk = tipc_sk_get_next(&ref)) {
2128 bh_lock_sock(&tsk->sk); 2116 lock_sock(&tsk->sk);
2129 msg = &tsk->port.phdr; 2117 msg = &tsk->port.phdr;
2130 msg_set_prevnode(msg, tipc_own_addr); 2118 msg_set_prevnode(msg, tipc_own_addr);
2131 msg_set_orignode(msg, tipc_own_addr); 2119 msg_set_orignode(msg, tipc_own_addr);
2132 bh_unlock_sock(&tsk->sk); 2120 release_sock(&tsk->sk);
2133 tipc_port_unlock(&tsk->port); 2121 tipc_sk_put(tsk);
2134 } 2122 }
2135} 2123}
2136 2124