From nobody Wed Dec 14 18:03:09 2022 X-Original-To: dev-commits-src-main@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 4NXNWd3QhBz4kC8R; Wed, 14 Dec 2022 18:03:09 +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 4NXNWd2r04z3pC8; Wed, 14 Dec 2022 18:03:09 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671040989; 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=RmXEvRWmwWKWpEID4eDeFAdesVVwY2fGyhhS2XVD0qk=; b=vSC1Y31dMr5KjPUMcWK9DSLcBFp0+d2y//f+t1IJSeP5mNrrc+xx9ptxyyiZMAJ+9CjNka x1hU9sjbRVZ43Jt2fdgxmzZF0sAYLAMxwDL2iIP/cJaAI3QZQOHH6Gthopd84GdbAvNJxy bmgg72SepVon4wManXSdWgfwmIshapd2oggXRTXGWkZQqJeWCFDdUTiDHBcY/35ziEV1cY jrL7rbymR4/kGoIN4YHCElZ1Q+4x81MUotub9zI/ONWB2fy5FPAIOtO8iX3ChhVHuVVyl8 Tj1djs/TvlFRPGVZm+qaOIgk0Y8XQ/h4GeKO5531BQFGjg5Xz3XJ1DfwnhD9Rw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671040989; 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=RmXEvRWmwWKWpEID4eDeFAdesVVwY2fGyhhS2XVD0qk=; b=YEC1Xhg2TKn1xKWXAhJNcPGilZpnh3d8tbhmmmB/bW9H39BQy5MASXGOpIHH5uUcYJ91es flgNhBtQjXxYUeo4uPOi3KpOsYI1lt6VrQqfT0Rx5F2sUFfStD1IPxlfMx00kJJbxRnzxw S4WzSHfT4OnSI1gUkyqlwI03YJIlMvmuezNNlVyc66lEx1A/mefR5bKm5a1Y5CRtaEBGcX MqxXiSkLnecdd3nT9NljVQmvKx8g5Lx+3B0+c8tWmByJ/nFr0SfV+O+Vk48Ef/PxOG6MHz sRNKT0c7YjIL+dSiQzs4yew2bIzeNpGJQHEzJJwPDsZKFJdXy2mTZKilbyADPg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1671040989; a=rsa-sha256; cv=none; b=BUxrxDzoZFg+9M8eSlHRJTJKWksfnAHKbDtXe6rAKAyDboZOtDW+TajzWOswXrKK7HrVyj qIaXmoNAUPRmQ7b41pDcywVKJVaT7wQ0w9huJ0cTuEco0MM16gWqzsydIwcjDMltmPCftX tRFXI0sQpaCpFRGhjn/32KemlNqOoaOrh6n9mN3/6HTOCaLWWfvMvhKbJHF3PUlZKx3ROn jaah5BtP2ZfPkHNkRgFkQ3aaO6PFgj0fNIoEOlX901nUoebUT8S+yXzUdSH1/GpdztIblo 4COju9G/w+CQd23J//Ok+x/6B/yUqH7PKWaRvZMGOGlfmJcU5tOQX16Pdi1dwA== 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 4NXNWd1vTzz13QT; Wed, 14 Dec 2022 18:03:09 +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 2BEI39Sg092691; Wed, 14 Dec 2022 18:03:09 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2BEI39AN092690; Wed, 14 Dec 2022 18:03:09 GMT (envelope-from git) Date: Wed, 14 Dec 2022 18:03:09 GMT Message-Id: <202212141803.2BEI39AN092690@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: 7a2c93b86ef7 - main - sockets: provide sousrsend() that does socket specific error handling List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: 7a2c93b86ef75390a60a4b4d6e3911b36221dfbe Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=7a2c93b86ef75390a60a4b4d6e3911b36221dfbe commit 7a2c93b86ef75390a60a4b4d6e3911b36221dfbe Author: Gleb Smirnoff AuthorDate: 2022-12-14 18:02:44 +0000 Commit: Gleb Smirnoff CommitDate: 2022-12-14 18:02:44 +0000 sockets: provide sousrsend() that does socket specific error handling Sockets have special handling for EPIPE on a write, that was spread out into several places. Treating transient errors is also special - if protocol is atomic, than we should ignore any changes to uio_resid, a transient error means the write had completely failed (see d2b3a0ed31e). - Provide sousrsend() that expects a valid uio, and leave sosend() for kernel consumers only. Do all special error handling right here. - In dofilewrite() don't do special handling of error for DTYPE_SOCKET. - For send(2), write(2) and aio_write(2) call into sousrsend() and remove error handling for kern_sendit(), soo_write() and soaio_process_job(). PR: 265087 Reported by: rz-rpi03 at h-ka.de Reviewed by: markj Differential revision: https://reviews.freebsd.org/D35863 --- sys/kern/sys_generic.c | 10 +++++++--- sys/kern/sys_socket.c | 17 +++-------------- sys/kern/uipc_socket.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ sys/kern/uipc_syscalls.c | 16 +--------------- sys/sys/socketvar.h | 2 ++ 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index b181a818e359..cf4084904b79 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -562,12 +562,16 @@ dofilewrite(struct thread *td, int fd, struct file *fp, struct uio *auio, ktruio = cloneuio(auio); #endif cnt = auio->uio_resid; - if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) { + error = fo_write(fp, auio, td->td_ucred, flags, td); + /* + * Socket layer is responsible for special error handling, + * see sousrsend(). + */ + if (error != 0 && fp->f_type != DTYPE_SOCKET) { if (auio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; - /* Socket layer is responsible for issuing SIGPIPE. */ - if (fp->f_type != DTYPE_SOCKET && error == EPIPE) { + if (error == EPIPE) { PROC_LOCK(td->td_proc); tdsignal(td, SIGPIPE); PROC_UNLOCK(td->td_proc); diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 3455cfee564c..5cfb366c150b 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -145,13 +145,7 @@ soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred, if (error) return (error); #endif - error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td); - if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) { - PROC_LOCK(uio->uio_td->td_proc); - tdsignal(uio->uio_td, SIGPIPE); - PROC_UNLOCK(uio->uio_td->td_proc); - } - return (error); + return (sousrsend(so, NULL, uio, NULL, 0, NULL)); } static int @@ -646,15 +640,10 @@ retry: error = mac_socket_check_send(fp->f_cred, so); if (error == 0) #endif - error = sosend(so, NULL, job->uiop, NULL, NULL, flags, - td); + error = sousrsend(so, NULL, job->uiop, NULL, flags, + job->userproc); if (td->td_ru.ru_msgsnd != ru_before) job->msgsnd = 1; - if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) { - PROC_LOCK(job->userproc); - kern_psignal(job->userproc, SIGPIPE); - PROC_UNLOCK(job->userproc); - } } done += cnt - job->uiop->uio_resid; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 6c09b14c4f72..b7e43d496d1d 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1822,6 +1822,14 @@ out: return (error); } +/* + * Send to a socket from a kernel thread. + * + * XXXGL: in almost all cases uio is NULL and the mbuf is supplied. + * Exception is nfs/bootp_subr.c. It is arguable that the VNET context needs + * to be set at all. This function should just boil down to a static inline + * calling the protocol method. + */ int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td) @@ -1835,6 +1843,47 @@ sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, return (error); } +/* + * send(2), write(2) or aio_write(2) on a socket. + */ +int +sousrsend(struct socket *so, struct sockaddr *addr, struct uio *uio, + struct mbuf *control, int flags, struct proc *userproc) +{ + struct thread *td; + ssize_t len; + int error; + + td = uio->uio_td; + len = uio->uio_resid; + CURVNET_SET(so->so_vnet); + error = so->so_proto->pr_sosend(so, addr, uio, NULL, control, flags, + td); + CURVNET_RESTORE(); + if (error != 0) { + if (uio->uio_resid != len && + (so->so_proto->pr_flags & PR_ATOMIC) == 0 && + (error == ERESTART || error == EINTR || + error == EWOULDBLOCK)) + error = 0; + /* Generation of SIGPIPE can be controlled per socket. */ + if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0 && + (flags & MSG_NOSIGNAL) == 0) { + if (userproc != NULL) { + /* aio(4) job */ + PROC_LOCK(userproc); + kern_psignal(userproc, SIGPIPE); + PROC_UNLOCK(userproc); + } else { + PROC_LOCK(td->td_proc); + tdsignal(td, SIGPIPE); + PROC_UNLOCK(td->td_proc); + } + } + } + return (error); +} + /* * The part of soreceive() that implements reading non-inline out-of-band * data from a socket. For more complete comments, see soreceive(), from diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 9c5c9719c204..cbf45e53f96f 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -798,21 +798,7 @@ kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, ktruio = cloneuio(&auio); #endif len = auio.uio_resid; - error = sosend(so, mp->msg_name, &auio, 0, control, flags, td); - if (error != 0) { - if (auio.uio_resid != len && - (so->so_proto->pr_flags & PR_ATOMIC) == 0 && - (error == ERESTART || error == EINTR || - error == EWOULDBLOCK)) - error = 0; - /* Generation of SIGPIPE can be controlled per socket */ - if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && - !(flags & MSG_NOSIGNAL)) { - PROC_LOCK(td->td_proc); - tdsignal(td, SIGPIPE); - PROC_UNLOCK(td->td_proc); - } - } + error = sousrsend(so, mp->msg_name, &auio, control, flags, NULL); if (error == 0) td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index e46eb0520e47..1e24a162b34b 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -506,6 +506,8 @@ void sorflush(struct socket *so); int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td); +int sousrsend(struct socket *so, struct sockaddr *addr, struct uio *uio, + struct mbuf *control, int flags, struct proc *); int sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td);