From nobody Fri Jun 24 16:10:38 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 16F48865C3D; Fri, 24 Jun 2022 16:10:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4LV2Cg1b73z3JXB; Fri, 24 Jun 2022 16:10:39 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1656087039; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Dwhx+HJa5FIy5poE8g/C39ZuaYJ/ImA/gUeheGtqw6Y=; b=Hx7qottUpPVSznhztZtu9TsVqcOrjEP8MZ9vmikI2v6XQ3+f0rG0UhtLj3LdMqQKtKaBQy DtbLtW5uJG42LUfKRd4sGbyAo8FDWZ4r8EZoby6/8Y9sPmoaJJcw0OZ8w0IV0WhOFf0FeG DDsns3mkVOgHGV3HVxcaDiWRFi0aS1yKK+xZDKmFHXHlCeR76cx7ArrbPaCmPu7+NrQy9N z18T7GZrDkIieGS/Dljm1IyPGD05a55AxVpHE7tfoVgNbmzA6P6DR9Pq9qh0rZJKZu2aS5 yEe85mpdu9EfbluG1WkScTcN2uLtVXwQpySrGjoUGAdhVbKphmc59oibuZv6Mw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E5B5612B68; Fri, 24 Jun 2022 16:10:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 25OGAcTv006296; Fri, 24 Jun 2022 16:10:38 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 25OGAcom006295; Fri, 24 Jun 2022 16:10:38 GMT (envelope-from git) Date: Fri, 24 Jun 2022 16:10:38 GMT Message-Id: <202206241610.25OGAcom006295@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 1093f16487a9 - main - unix/dgram: reduce mbuf chain traversals in send(2) and recv(2) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1093f16487a93c3ecdea910ca7249375873969da Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1656087039; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Dwhx+HJa5FIy5poE8g/C39ZuaYJ/ImA/gUeheGtqw6Y=; b=RlTTXV9Fp0wYIOLVjM2SaUqnlWUsRKc6C2E+RNjzgvKlJN0b7qCTD9iWRTNjrgQEViUWhG On0goJR4L/IbCQCahrJ4NdtOzhW/GSqnoeRYakPD+RxppdPm0ygqzaKSrFcTSd6FVWs+/9 CNUHvaNYkb8rUSKWgSFphZ9M20962lI9IbUvyZ0+DnToNsOsXONd87ofrGSpHREXgu3Jpu HL/txt8KacOySsILh/tz6CDbZR5GmFokQdKYniuj7vArjDISvVQOrxFrmFroJfrTQsmyET 1n6bO6UAKAlGjixmy5Q8sL3XTHtSWnElByHub7w6yX09aUjSr7uyPsX01lP9cg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1656087039; a=rsa-sha256; cv=none; b=Iw+bbmBWUxldoX5hHMclRMkhijs+CEDUG9MxEXPlgWpyAgo/FLNiwCPdvLS3JkCjYYx0+C osENku49FqlQHDGJ3090fOiMuPkP/n1M+R3zdZQBZGoJ4DSXGQCNf6ZjeJ2kxt08ET3bzA JWneWNSiNjfFbonCfkr/SDFvO+ivAmzlIbUMGYMmr7YNWzyoD5UgUefkjELWBnN323XAv2 UNQW1YzUOk8ngQEw3cF9B9c7YBdmBv3QxtBJIDgy5toN7eWyeK9n+ag3WEKTO74YWUriBj 5YLnOqMPg9cHBbtVaj10+xAEoAA6XfhzhU80P3HKuXeNtfSJgqH7iUEaA4A5lw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=1093f16487a93c3ecdea910ca7249375873969da commit 1093f16487a93c3ecdea910ca7249375873969da Author: Gleb Smirnoff AuthorDate: 2022-06-24 16:09:11 +0000 Commit: Gleb Smirnoff CommitDate: 2022-06-24 16:09:11 +0000 unix/dgram: reduce mbuf chain traversals in send(2) and recv(2) o Use m_pkthdr.memlen from m_uiotombuf() o Modify unp_internalize() to keep track of allocated space and memory as well as pointer to the last buffer. o Modify unp_addsockcred() to keep track of allocated space and memory as well as pointer to the last buffer. o Record the datagram len/memlen/ctllen in the first (from) mbuf of the chain in uipc_sosend_dgram() and reuse it in uipc_soreceive_dgram(). Reviewed by: markj Differential revision: https://reviews.freebsd.org/D35302 --- sys/kern/uipc_usrreq.c | 151 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 38 deletions(-) diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index d1c87865c632..05fde7675b9f 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -302,11 +302,13 @@ static void unp_gc(__unused void *, int); static void unp_scan(struct mbuf *, void (*)(struct filedescent **, int)); static void unp_discard(struct file *); static void unp_freerights(struct filedescent **, int); -static int unp_internalize(struct mbuf **, struct thread *); +static int unp_internalize(struct mbuf **, struct thread *, + struct mbuf **, u_int *, u_int *); static void unp_internalize_fp(struct file *); static int unp_externalize(struct mbuf *, struct mbuf **, int); static int unp_externalize_fp(struct file *); -static struct mbuf *unp_addsockcred(struct thread *, struct mbuf *, int); +static struct mbuf *unp_addsockcred(struct thread *, struct mbuf *, + int, struct mbuf **, u_int *, u_int *); static void unp_process_defers(void * __unused, int); static void @@ -1014,7 +1016,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, error = EOPNOTSUPP; goto release; } - if (control != NULL && (error = unp_internalize(&control, td))) + if (control != NULL && + (error = unp_internalize(&control, td, NULL, NULL, NULL))) goto release; unp2 = NULL; @@ -1051,7 +1054,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, * SOCK_SEQPACKET (LOCAL_CREDS => WANTCRED_ONESHOT), or * forever (LOCAL_CREDS_PERSISTENT => WANTCRED_ALWAYS). */ - control = unp_addsockcred(td, control, unp2->unp_flags); + control = unp_addsockcred(td, control, unp2->unp_flags, NULL, + NULL, NULL); unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT; } @@ -1131,7 +1135,13 @@ release: * * Allocate a record consisting of 3 mbufs in the sequence of * from -> control -> data and append it to the socket buffer. + * + * The first mbuf carries sender's name and is a pkthdr that stores + * overall length of datagram, its memory consumption and control length. */ +#define ctllen PH_loc.thirtytwo[1] +_Static_assert(offsetof(struct pkthdr, memlen) + sizeof(u_int) <= + offsetof(struct pkthdr, ctllen), "unix/dgram can not store ctllen"); static int uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *m, struct mbuf *c, int flags, struct thread *td) @@ -1140,14 +1150,16 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, const struct sockaddr *from; struct socket *so2; struct sockbuf *sb; - struct mbuf *f; - u_int cc; + struct mbuf *f, *clast; + u_int cc, ctl, mbcnt; + u_int dcc __diagused, dctl __diagused, dmbcnt __diagused; int error; MPASS((uio != NULL && m == NULL) || (m != NULL && uio == NULL)); error = 0; f = NULL; + ctl = 0; if (__predict_false(flags & MSG_OOB)) { error = EOPNOTSUPP; @@ -1163,8 +1175,11 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, error = EFAULT; goto out; } - f = m_get(M_WAITOK, MT_SONAME); - if (c != NULL && (error = unp_internalize(&c, td))) + f = m_gethdr(M_WAITOK, MT_SONAME); + cc = m->m_pkthdr.len; + mbcnt = MSIZE + m->m_pkthdr.memlen; + if (c != NULL && + (error = unp_internalize(&c, td, &clast, &ctl, &mbcnt))) goto out; } else { /* pru_sosend() with mbuf usually is a kernel thread. */ @@ -1177,7 +1192,7 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, error = EMSGSIZE; goto out; } - if ((f = m_get(M_NOWAIT, MT_SONAME)) == NULL) { + if ((f = m_gethdr(M_NOWAIT, MT_SONAME)) == NULL) { error = ENOBUFS; goto out; } @@ -1189,6 +1204,14 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, m->m_pkthdr.csum_flags = 0; m->m_pkthdr.fibnum = 0; m->m_pkthdr.rsstype = 0; + + cc = m->m_pkthdr.len; + mbcnt = MSIZE; + for (struct mbuf *mb = m; mb != NULL; mb = mb->m_next) { + mbcnt += MSIZE; + if (mb->m_flags & M_EXT) + mbcnt += mb->m_ext.ext_size; + } } unp = sotounpcb(so); @@ -1240,7 +1263,8 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, } if (unp2->unp_flags & UNP_WANTCRED_MASK) - c = unp_addsockcred(td, c, unp2->unp_flags); + c = unp_addsockcred(td, c, unp2->unp_flags, &clast, &ctl, + &mbcnt); if (unp->unp_addr != NULL) from = (struct sockaddr *)unp->unp_addr; else @@ -1248,36 +1272,55 @@ uipc_sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, f->m_len = from->sa_len; MPASS(from->sa_len <= MLEN); bcopy(from, mtod(f, void *), from->sa_len); - cc = f->m_len + m->m_pkthdr.len; + ctl += f->m_len; - /* Concatenate: from -> control -> data. */ + /* + * Concatenate mbufs: from -> control -> data. + * Save overall cc and mbcnt in "from" mbuf. + */ if (c != NULL) { - struct mbuf *clast; +#ifdef INVARIANTS + struct mbuf *mc; - cc += m_length(c, &clast); + for (mc = c; mc->m_next != NULL; mc = mc->m_next); + MPASS(mc == clast); +#endif f->m_next = c; clast->m_next = m; c = NULL; } else f->m_next = m; m = NULL; +#ifdef INVARIANTS + dcc = dctl = dmbcnt = 0; + for (struct mbuf *mb = f; mb != NULL; mb = mb->m_next) { + if (mb->m_type == MT_DATA) + dcc += mb->m_len; + else + dctl += mb->m_len; + dmbcnt += MSIZE; + if (mb->m_flags & M_EXT) + dmbcnt += mb->m_ext.ext_size; + } + MPASS(dcc == cc); + MPASS(dctl == ctl); + MPASS(dmbcnt == mbcnt); +#endif + f->m_pkthdr.len = cc + ctl; + f->m_pkthdr.memlen = mbcnt; + f->m_pkthdr.ctllen = ctl; so2 = unp2->unp_socket; sb = &so2->so_rcv; SOCK_RECVBUF_LOCK(so2); if (cc <= sbspace(sb)) { STAILQ_INSERT_TAIL(&sb->uxdg_mb, f, m_stailqpkt); - /* XXX: would be nice if m_uiotombuf() returns count. */ - for (; f != NULL; f = f->m_next) { - if (f->m_type != MT_DATA) - sb->sb_ctl += f->m_len; - sb->sb_mbcnt += MSIZE; - if (f->m_flags & M_EXT) - sb->sb_mbcnt += f->m_ext.ext_size; - } - sb->sb_acc += cc; - sb->sb_ccc += cc; + sb->sb_acc += cc + ctl; + sb->sb_ccc += cc + ctl; + sb->sb_ctl += ctl; + sb->sb_mbcnt += mbcnt; sorwakeup_locked(so2); + f = NULL; } else { soroverflow_locked(so2); error = (so->so_state & SS_NBIO) ? EAGAIN : ENOBUFS; @@ -1366,7 +1409,7 @@ static int uipc_soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) { - struct mbuf *m, *m2; + struct mbuf *m; int flags, error; ssize_t len; bool nonblock; @@ -1419,7 +1462,9 @@ uipc_soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, return (error); } } - SOCK_RECVBUF_LOCK_ASSERT(so); + + M_ASSERTPKTHDR(m); + KASSERT(m->m_type == MT_SONAME, ("m->m_type == %d", m->m_type)); if (uio->uio_td) uio->uio_td->td_ru.ru_msgrcv++; @@ -1428,18 +1473,12 @@ uipc_soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, return (uipc_peek_dgram(so, psa, uio, controlp, flagsp)); STAILQ_REMOVE_HEAD(&so->so_rcv.uxdg_mb, m_stailqpkt); - for (m2 = m; m2 != NULL; m2 = m2->m_next) { - if (m2->m_type != MT_DATA) - so->so_rcv.sb_ctl -= m2->m_len; - so->so_rcv.sb_acc -= m2->m_len; - so->so_rcv.sb_ccc -= m2->m_len; - so->so_rcv.sb_mbcnt -= MSIZE; - if (m2->m_flags & M_EXT) - so->so_rcv.sb_mbcnt -= m2->m_ext.ext_size; - } + so->so_rcv.sb_acc -= m->m_pkthdr.len; + so->so_rcv.sb_ccc -= m->m_pkthdr.len; + so->so_rcv.sb_ctl -= m->m_pkthdr.ctllen; + so->so_rcv.sb_mbcnt -= m->m_pkthdr.memlen; SOCK_RECVBUF_UNLOCK(so); - KASSERT(m->m_type == MT_SONAME, ("m->m_type == %d", m->m_type)); if (psa != NULL) *psa = sodupsockaddr(mtod(m, struct sockaddr *), M_WAITOK); m = m_free(m); @@ -2510,7 +2549,8 @@ unp_internalize_cleanup_rights(struct mbuf *control) } static int -unp_internalize(struct mbuf **controlp, struct thread *td) +unp_internalize(struct mbuf **controlp, struct thread *td, + struct mbuf **clast, u_int *space, u_int *mbcnt) { struct mbuf *control, **initial_controlp; struct proc *p; @@ -2527,6 +2567,7 @@ unp_internalize(struct mbuf **controlp, struct thread *td) int i, j, error, *fdp, oldfds; u_int newlen; + MPASS((*controlp)->m_next == NULL); /* COMPAT_OLDSOCK may violate */ UNP_LINK_UNLOCK_ASSERT(); p = td->td_proc; @@ -2672,6 +2713,13 @@ unp_internalize(struct mbuf **controlp, struct thread *td) goto out; } + if (space != NULL) { + *space += (*controlp)->m_len; + *mbcnt += MSIZE; + if ((*controlp)->m_flags & M_EXT) + *mbcnt += (*controlp)->m_ext.ext_size; + *clast = *controlp; + } controlp = &(*controlp)->m_next; } if (clen > 0) @@ -2685,7 +2733,8 @@ out: } static struct mbuf * -unp_addsockcred(struct thread *td, struct mbuf *control, int mode) +unp_addsockcred(struct thread *td, struct mbuf *control, int mode, + struct mbuf **clast, u_int *space, u_int *mbcnt) { struct mbuf *m, *n, *n_prev; const struct cmsghdr *cm; @@ -2704,6 +2753,7 @@ unp_addsockcred(struct thread *td, struct mbuf *control, int mode) m = sbcreatecontrol(NULL, ctrlsz, cmsgtype, SOL_SOCKET, M_NOWAIT); if (m == NULL) return (control); + MPASS((m->m_flags & M_EXT) == 0 && m->m_next == NULL); if (mode & UNP_WANTCRED_ALWAYS) { struct sockcred2 *sc; @@ -2745,6 +2795,25 @@ unp_addsockcred(struct thread *td, struct mbuf *control, int mode) control = n->m_next; else n_prev->m_next = n->m_next; + if (space != NULL) { + MPASS(*space >= n->m_len); + *space -= n->m_len; + MPASS(*mbcnt >= MSIZE); + *mbcnt -= MSIZE; + if (n->m_flags & M_EXT) { + MPASS(*mbcnt >= + n->m_ext.ext_size); + *mbcnt -= n->m_ext.ext_size; + } + MPASS(clast); + if (*clast == n) { + MPASS(n->m_next == NULL); + if (n_prev == NULL) + *clast = m; + else + *clast = n_prev; + } + } n = m_free(n); } else { n_prev = n; @@ -2754,6 +2823,12 @@ unp_addsockcred(struct thread *td, struct mbuf *control, int mode) /* Prepend it to the head. */ m->m_next = control; + if (space != NULL) { + *space += m->m_len; + *mbcnt += MSIZE; + if (control == NULL) + *clast = m; + } return (m); }