Page MenuHomeFreeBSD

D48924.diff
No OneTemporary

D48924.diff

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -90,6 +90,7 @@
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/vnode.h>
+#include <machine/stack.h>
#include <net/vnet.h>
@@ -1059,18 +1060,19 @@
static int
uipc_sosend_stream_or_seqpacket(struct socket *so, struct sockaddr *addr,
- struct uio *uio, struct mbuf *m, struct mbuf *c, int flags,
+ struct uio *uio0, struct mbuf *m, struct mbuf *c, int flags,
struct thread *td)
{
struct unpcb *unp2;
struct socket *so2;
struct sockbuf *sb;
+ struct uio *uio;
struct mchain mc, cmc;
- ssize_t resid, sent;
- bool nonblock, eor;
+ size_t resid, sent;
+ bool nonblock, eor, aio;
int error;
- MPASS((uio != NULL && m == NULL) || (m != NULL && uio == NULL));
+ MPASS((uio0 != NULL && m == NULL) || (m != NULL && uio0 == NULL));
MPASS(m == NULL || c == NULL);
if (__predict_false(flags & MSG_OOB))
@@ -1083,17 +1085,37 @@
mc = MCHAIN_INITIALIZER(&mc);
cmc = MCHAIN_INITIALIZER(&cmc);
sent = 0;
+ aio = false;
if (m == NULL) {
if (c != NULL && (error = unp_internalize(c, &cmc, td)))
goto out;
+ /*
+ * This function may read more data from the uio than it would
+ * then place on socket. That would leave uio inconsistent
+ * upon return. Normally uio is allocated on the stack of the
+ * syscall thread and we don't care about leaving it consistent.
+ * However, aio(9) will allocate a uio as part of job and will
+ * use it to track progress. We detect aio(9) checking the
+ * SB_AIO_RUNNING flag. It is safe to check it without lock
+ * cause it is set and cleared in the same taskqueue thread.
+ */
+ if (__predict_false(so->so_snd.sb_flags & SB_AIO_RUNNING)) {
+ MPASS(nonblock);
+ uio = cloneuio(uio0);
+ aio = true;
+ } else {
+ MPASS(kstack_contains(curthread, (vm_offset_t)uio0,
+ sizeof(struct uio)));
+ uio = uio0;
+ resid = uio->uio_resid;
+ }
/*
* Optimization for a case when our send fits into the receive
* buffer - do the copyin before taking any locks, sized to our
* send buffer. Later copyins will also take into account
* space in the peer's receive buffer.
*/
- resid = uio->uio_resid;
error = mc_uiotomc(&mc, uio, so->so_snd.sb_hiwat, 0, M_WAITOK,
eor ? M_EOR : 0);
if (__predict_false(error))
@@ -1240,15 +1262,17 @@
out3:
SOCK_IO_SEND_UNLOCK(so);
out2:
+ if (aio) {
+ freeuio(uio);
+ uioadvance(uio0, sent);
+ } else if (uio != NULL)
+ uio->uio_resid = resid - sent;
if (!mc_empty(&cmc))
unp_scan(mc_first(&cmc), unp_freerights);
out:
mc_freem(&mc);
mc_freem(&cmc);
- if (uio != NULL)
- uio->uio_resid = resid - sent;
-
return (error);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 15, 11:50 AM (10 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16602172
Default Alt Text
D48924.diff (2 KB)

Event Timeline