* [MPTCP] [PATCH RFC mptcp 3/4] mptcp: add and use mptcp_subflow_hold
@ 2019-02-07 14:27 Florian Westphal
0 siblings, 0 replies; only message in thread
From: Florian Westphal @ 2019-02-07 14:27 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 4185 bytes --]
subflow sockets already have lifetime managed by RCU, so we can
switch to atimic_inc_not_zero and skip/pretend we did not find
such socket in the mptcp subflow list.
This is required to get rid of synchronize_rcu() from mptcp_close().
Signed-off-by: Florian Westphal <fw(a)strlen.de>
---
net/mptcp/protocol.c | 63 ++++++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 26 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 12857eeded8b..91db8a0c222d 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -31,14 +31,35 @@ static inline bool before64(__u64 seq1, __u64 seq2)
}
#define after64(seq2, seq1) before64(seq1, seq2)
+static bool mptcp_subflow_hold(struct subflow_sock *sk)
+{
+ struct sock *_sk = (struct sock *)sk;
+
+ return refcount_inc_not_zero(&_sk->sk_refcnt);
+}
+
+static struct sock *mptcp_subflow_get_ref(const struct mptcp_sock *msk)
+{
+ struct subflow_sock *subflow;
+
+ rcu_read_lock();
+ mptcp_for_each_subflow(msk, subflow) {
+ if (mptcp_subflow_hold(subflow)) {
+ rcu_read_unlock();
+ return (struct sock *)subflow;
+ }
+ }
+
+ rcu_read_unlock();
+ return NULL;
+}
+
static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
struct mptcp_sock *msk = mptcp_sk(sk);
int mss_now, size_goal, poffset, ret;
struct mptcp_skb_cb *mcb = NULL;
- struct subflow_sock *subflow;
struct page *page = NULL;
- struct hlist_node *node;
struct sk_buff *skb;
struct sock *ssk;
size_t psize;
@@ -49,20 +70,17 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
return sock_sendmsg(msk->subflow, msg);
}
- rcu_read_lock();
- node = rcu_dereference(hlist_first_rcu(&msk->conn_list));
- subflow = hlist_entry(node, struct subflow_sock, node);
- ssk = sock_sk(subflow);
- sock_hold(ssk);
- rcu_read_unlock();
+ ssk = mptcp_subflow_get_ref(msk);
+ if (!ssk)
+ return -ENOTCONN;
if (!msg_data_left(msg)) {
pr_debug("empty send");
- ret = sock_sendmsg(sock_sk(subflow)->sk_socket, msg);
+ ret = sock_sendmsg(ssk->sk_socket, msg);
goto put_out;
}
- pr_debug("conn_list->subflow=%p", subflow);
+ pr_debug("conn_list->subflow=%p", ssk);
if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL)) {
ret = -ENOTSUPP;
@@ -279,7 +297,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
struct mptcp_sock *msk = mptcp_sk(sk);
struct subflow_sock *subflow;
struct mptcp_read_arg arg;
- struct hlist_node *node;
read_descriptor_t desc;
struct tcp_sock *tp;
struct sock *ssk;
@@ -291,13 +308,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
return sock_recvmsg(msk->subflow, msg, flags);
}
- rcu_read_lock();
- node = rcu_dereference(hlist_first_rcu(&msk->conn_list));
- subflow = hlist_entry(node, struct subflow_sock, node);
- ssk = sock_sk(subflow);
- sock_hold(ssk);
- rcu_read_unlock();
+ ssk = mptcp_subflow_get_ref(msk);
+ if (!ssk)
+ return -ENOTCONN;
+ subflow = subflow_sk(ssk);
tp = tcp_sk(ssk);
desc.arg.data = &arg;
@@ -715,8 +730,6 @@ int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int mptcp_stream_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
{
struct mptcp_sock *msk = mptcp_sk(sock->sk);
- struct subflow_sock *subflow;
- struct hlist_node *node;
struct sock *ssk;
int ret;
@@ -731,14 +744,12 @@ int mptcp_stream_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
* is connected and there are multiple subflows is not defined.
* For now just use the first subflow on the list.
*/
- rcu_read_lock();
- node = rcu_dereference(hlist_first_rcu(&msk->conn_list));
- subflow = hlist_entry(node, struct subflow_sock, node);
- ssk = sock_sk(subflow);
- sock_hold(ssk);
- rcu_read_unlock();
- ret = inet_getname(sock_sk(subflow)->sk_socket, uaddr, peer);
+ ssk = mptcp_subflow_get_ref(msk);
+ if (!ssk)
+ return -ENOTCONN;
+
+ ret = inet_getname(ssk->sk_socket, uaddr, peer);
sock_put(ssk);
return ret;
}
--
2.19.2
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2019-02-07 14:27 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-07 14:27 [MPTCP] [PATCH RFC mptcp 3/4] mptcp: add and use mptcp_subflow_hold Florian Westphal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.