git: 20bef7f7c2e2 - stable/14 - socket: Split up soreceive_stream()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 03 Sep 2024 14:55:04 UTC
The branch stable/14 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=20bef7f7c2e249a073a22677785b1c51a5ce36c2
commit 20bef7f7c2e249a073a22677785b1c51a5ce36c2
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-19 14:20:03 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-09-03 14:54:43 +0000
socket: Split up soreceive_stream()
Factor out the bits that run with the sock I/O lock held into a separate
function. No functional change intended.
Reviewed by: gallatin, glebius
MFC after: 2 weeks
Sponsored by: Klara, Inc.
Sponsored by: Stormshield
Differential Revision: https://reviews.freebsd.org/D46303
(cherry picked from commit aa141adc039a5418d7b7800094115d861baf91a0)
---
sys/kern/uipc_socket.c | 109 ++++++++++++++++++++++++++++---------------------
sys/sys/socketvar.h | 4 ++
2 files changed, 66 insertions(+), 47 deletions(-)
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 7801054315ef..8a688e41ee88 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -2517,56 +2517,15 @@ release:
/*
* Optimized version of soreceive() for stream (TCP) sockets.
*/
-int
-soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio,
- struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
+static int
+soreceive_stream_locked(struct socket *so, struct sockbuf *sb,
+ struct sockaddr **psa, struct uio *uio, struct mbuf **mp0,
+ struct mbuf **controlp, int flags)
{
- int len = 0, error = 0, flags, oresid;
- struct sockbuf *sb;
+ int len = 0, error = 0, oresid;
struct mbuf *m, *n = NULL;
- /* We only do stream sockets. */
- if (so->so_type != SOCK_STREAM)
- return (EINVAL);
- if (psa != NULL)
- *psa = NULL;
- if (flagsp != NULL)
- flags = *flagsp &~ MSG_EOR;
- else
- flags = 0;
- if (controlp != NULL)
- *controlp = NULL;
- if (flags & MSG_OOB)
- return (soreceive_rcvoob(so, uio, flags));
- if (mp0 != NULL)
- *mp0 = NULL;
-
- sb = &so->so_rcv;
-
-#ifdef KERN_TLS
- /*
- * KTLS store TLS records as records with a control message to
- * describe the framing.
- *
- * We check once here before acquiring locks to optimize the
- * common case.
- */
- if (sb->sb_tls_info != NULL)
- return (soreceive_generic(so, psa, uio, mp0, controlp,
- flagsp));
-#endif
-
- /* Prevent other readers from entering the socket. */
- error = SOCK_IO_RECV_LOCK(so, SBLOCKWAIT(flags));
- if (error)
- return (error);
-#ifdef KERN_TLS
- if (__predict_false(sb->sb_tls_info != NULL)) {
- SOCK_IO_RECV_UNLOCK(so);
- return (soreceive_generic(so, psa, uio, mp0, controlp,
- flagsp));
- }
-#endif
+ SOCK_IO_RECV_ASSERT_LOCKED(so);
SOCKBUF_LOCK(sb);
/* Easy one, no space to copyout anything. */
@@ -2729,6 +2688,62 @@ out:
SBLASTRECORDCHK(sb);
SBLASTMBUFCHK(sb);
SOCKBUF_UNLOCK(sb);
+ return (error);
+}
+
+int
+soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio,
+ struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
+{
+ struct sockbuf *sb;
+ int error, flags;
+
+ sb = &so->so_rcv;
+
+ /* We only do stream sockets. */
+ if (so->so_type != SOCK_STREAM)
+ return (EINVAL);
+ if (psa != NULL)
+ *psa = NULL;
+ if (flagsp != NULL)
+ flags = *flagsp & ~MSG_EOR;
+ else
+ flags = 0;
+ if (controlp != NULL)
+ *controlp = NULL;
+ if (flags & MSG_OOB)
+ return (soreceive_rcvoob(so, uio, flags));
+ if (mp0 != NULL)
+ *mp0 = NULL;
+
+#ifdef KERN_TLS
+ /*
+ * KTLS store TLS records as records with a control message to
+ * describe the framing.
+ *
+ * We check once here before acquiring locks to optimize the
+ * common case.
+ */
+ if (sb->sb_tls_info != NULL)
+ return (soreceive_generic(so, psa, uio, mp0, controlp,
+ flagsp));
+#endif
+
+ /*
+ * Prevent other threads from reading from the socket. This lock may be
+ * dropped in order to sleep waiting for data to arrive.
+ */
+ error = SOCK_IO_RECV_LOCK(so, SBLOCKWAIT(flags));
+ if (error)
+ return (error);
+#ifdef KERN_TLS
+ if (__predict_false(sb->sb_tls_info != NULL)) {
+ SOCK_IO_RECV_UNLOCK(so);
+ return (soreceive_generic(so, psa, uio, mp0, controlp,
+ flagsp));
+ }
+#endif
+ error = soreceive_stream_locked(so, sb, psa, uio, mp0, controlp, flags);
SOCK_IO_RECV_UNLOCK(so);
return (error);
}
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 485494b605ec..7d194462acba 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -313,11 +313,15 @@ soeventmtx(struct socket *so, const sb_which which)
#define SOCK_IO_SEND_UNLOCK(so) \
soiounlock(&(so)->so_snd_sx)
#define SOCK_IO_SEND_OWNED(so) sx_xlocked(&(so)->so_snd_sx)
+#define SOCK_IO_SEND_ASSERT_LOCKED(so) \
+ sx_assert(&(so)->so_snd_sx, SA_XLOCKED)
#define SOCK_IO_RECV_LOCK(so, flags) \
soiolock((so), &(so)->so_rcv_sx, (flags))
#define SOCK_IO_RECV_UNLOCK(so) \
soiounlock(&(so)->so_rcv_sx)
#define SOCK_IO_RECV_OWNED(so) sx_xlocked(&(so)->so_rcv_sx)
+#define SOCK_IO_RECV_ASSERT_LOCKED(so) \
+ sx_assert(&(so)->so_rcv_sx, SA_XLOCKED)
/* do we have to send all at once on a socket? */
#define sosendallatonce(so) \