summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-07-10 15:42:16 +0000
committerphk <phk@FreeBSD.org>2004-07-10 15:42:16 +0000
commitb9f13e4266e1a358f8e0f5ee3542e657eabb8a19 (patch)
treede46976e3a829fc81580355aafed8ed3f3fcdb8e
parentafe21b6175db45f3406c5cd8c0d1516078e4e32c (diff)
downloadFreeBSD-src-b9f13e4266e1a358f8e0f5ee3542e657eabb8a19.zip
FreeBSD-src-b9f13e4266e1a358f8e0f5ee3542e657eabb8a19.tar.gz
Clean up and wash struct iovec and struct uio handling.
Add copyiniov() which copies a struct iovec array in from userland into a malloc'ed struct iovec. Caller frees. Change uiofromiov() to malloc the uio (caller frees) and name it copyinuio() which is more appropriate. Add cloneuio() which returns a malloc'ed copy. Caller frees. Use them throughout.
-rw-r--r--sys/compat/linux/linux_socket.c27
-rw-r--r--sys/compat/svr4/svr4_stream.c44
-rw-r--r--sys/kern/kern_ktrace.c8
-rw-r--r--sys/kern/kern_subr.c63
-rw-r--r--sys/kern/subr_prf.c17
-rw-r--r--sys/kern/sys_generic.c211
-rw-r--r--sys/kern/uipc_syscalls.c197
-rw-r--r--sys/kern/vfs_mount.c38
-rw-r--r--sys/sys/uio.h6
9 files changed, 204 insertions, 407 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 465c573..c73a57a 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -993,35 +993,22 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
{
struct linux_sendmsg_args linux_args;
struct msghdr msg;
- struct iovec aiov[UIO_SMALLIOV], *iov;
+ struct iovec *iov;
int error;
- if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ error = copyin(args, &linux_args, sizeof(linux_args));
+ if (error)
return (error);
-
error = copyin(linux_args.msg, &msg, sizeof(msg));
if (error)
return (error);
- if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
- if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
- return (EMSGSIZE);
- MALLOC(iov, struct iovec *,
- sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
- M_WAITOK);
- } else {
- iov = aiov;
- }
- if (msg.msg_iovlen &&
- (error = copyin(msg.msg_iov, iov,
- (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
- goto done;
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+ if (error)
+ return (error);
msg.msg_iov = iov;
msg.msg_flags = 0;
-
error = linux_sendit(td, linux_args.s, &msg, linux_args.flags);
-done:
- if (iov != aiov)
- FREE(iov, M_IOV);
+ free(iov, M_IOV);
return (error);
}
diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
index 853a272..d91c185 100644
--- a/sys/compat/svr4/svr4_stream.c
+++ b/sys/compat/svr4/svr4_stream.c
@@ -163,8 +163,7 @@ svr4_sendit(td, s, mp, flags)
int len, error;
struct socket *so;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
+ struct uio *ktruio = NULL;
#endif
if ((error = fgetsock(td, s, &so, NULL)) != 0)
@@ -212,13 +211,8 @@ svr4_sendit(td, s, mp, flags)
control = 0;
}
#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO)) {
- int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
-
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
@@ -236,13 +230,9 @@ svr4_sendit(td, s, mp, flags)
if (error == 0)
td->td_retval[0] = len - auio.uio_resid;
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = td->td_retval[0];
- ktrgenio(s, UIO_WRITE, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = td->td_retval[0];
+ ktrgenio(s, UIO_WRITE, ktruio, error);
}
#endif
bad:
@@ -269,8 +259,7 @@ svr4_recvit(td, s, mp, namelenp)
struct socket *so;
struct sockaddr *fromsa = 0;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
+ struct uio *ktruio = NULL;
#endif
if ((error = fgetsock(td, s, &so, NULL)) != 0)
@@ -299,13 +288,8 @@ svr4_recvit(td, s, mp, namelenp)
}
}
#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO)) {
- int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
-
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
@@ -317,13 +301,9 @@ svr4_recvit(td, s, mp, namelenp)
error = 0;
}
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = len - auio.uio_resid;
- ktrgenio(s, UIO_READ, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = len - auio.uio_resid;
+ ktrgenio(s, UIO_READ, ktruio, error);
}
#endif
if (error)
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index 8a2b0a5..694634a 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -413,13 +413,17 @@ ktrgenio(fd, rw, uio, error)
int datalen;
char *buf;
- if (error)
+ if (error) {
+ free(uio, M_IOV);
return;
+ }
uio->uio_offset = 0;
uio->uio_rw = UIO_WRITE;
datalen = imin(uio->uio_resid, ktr_geniosize);
buf = malloc(datalen, M_KTRACE, M_WAITOK);
- if (uiomove(buf, datalen, uio)) {
+ error = uiomove(buf, datalen, uio);
+ free(uio, M_IOV);
+ if (error) {
free(buf, M_KTRACE);
return;
}
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index 7ccccdd..8d5c6f0 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -474,40 +474,69 @@ copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len,
}
int
-uiofromiov(struct iovec *iovp, u_int iovcnt, struct uio *uio)
+copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error)
+{
+ u_int iovlen;
+
+ *iov = NULL;
+ if (iovcnt > UIO_MAXIOV)
+ return (error);
+ iovlen = iovcnt * sizeof (struct iovec);
+ *iov = malloc(iovlen, M_IOV, M_WAITOK);
+ error = copyin(iovp, *iov, iovlen);
+ if (error) {
+ free(*iov, M_IOV);
+ *iov = NULL;
+ }
+ return (error);
+}
+
+int
+copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop)
{
struct iovec *iov;
+ struct uio *uio;
u_int iovlen;
int error, i;
- /* note: can't use iovlen until iovcnt is validated */
+ *uiop = NULL;
+ if (iovcnt > UIO_MAXIOV)
+ return (EINVAL);
iovlen = iovcnt * sizeof (struct iovec);
- if (iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
+ uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
+ iov = (struct iovec *)(uio + 1);
+ error = copyin(iovp, iov, iovlen);
+ if (error) {
+ free(uio, M_IOV);
+ return (error);
}
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
uio->uio_iov = iov;
uio->uio_iovcnt = iovcnt;
uio->uio_segflg = UIO_USERSPACE;
uio->uio_offset = -1;
- if ((error = copyin(iovp, iov, iovlen)))
- goto done;
uio->uio_resid = 0;
for (i = 0; i < iovcnt; i++) {
if (iov->iov_len > INT_MAX - uio->uio_resid) {
- error = EINVAL;
- goto done;
+ free(uio, M_IOV);
+ return (EINVAL);
}
uio->uio_resid += iov->iov_len;
iov++;
}
+ *uiop = uio;
+ return (0);
+}
-done:
- if (error && uio->uio_iov) {
- FREE(uio->uio_iov, M_IOV);
- uio->uio_iov = NULL;
- }
- return (error);
-
+struct uio *
+cloneuio(struct uio *uiop)
+{
+ struct uio *uio;
+ int iovlen;
+
+ iovlen = uiop->uio_iovcnt * sizeof (struct iovec);
+ uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
+ *uio = *uiop;
+ uio->uio_iov = (struct iovec *)(uio + 1);
+ bcopy(uiop->uio_iov, uio->uio_iov, iovlen);
+ return (uio);
}
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index 9f4bedd..3650ca1 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -243,9 +243,7 @@ log(int level, const char *fmt, ...)
void
log_console(struct uio *uio)
{
- int c, i, error, iovlen, nl;
- struct uio muio;
- struct iovec *miov = NULL;
+ int c, i, error, nl;
char *consbuffer;
int pri;
@@ -253,13 +251,8 @@ log_console(struct uio *uio)
return;
pri = LOG_INFO | LOG_CONSOLE;
- muio = *uio;
- iovlen = uio->uio_iovcnt * sizeof (struct iovec);
- MALLOC(miov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, M_WAITOK);
- bcopy(muio.uio_iov, miov, iovlen);
- muio.uio_iov = miov;
- uio = &muio;
+ uio = cloneuio(uio);
+ consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
nl = 0;
while (uio->uio_resid > 0) {
@@ -278,8 +271,8 @@ log_console(struct uio *uio)
if (!nl)
msglogchar('\n', pri);
msgbuftrigger = 1;
- FREE(miov, M_TEMP);
- FREE(consbuffer, M_TEMP);
+ free(uio, M_IOV);
+ free(consbuffer, M_TEMP);
return;
}
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index ab48888..13b5125 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -164,9 +164,7 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags)
struct iovec aiov;
long cnt, error = 0;
#ifdef KTRACE
- struct iovec ktriov;
- struct uio ktruio;
- int didktr = 0;
+ struct uio *ktruio = NULL;
#endif
aiov.iov_base = buf;
@@ -181,14 +179,8 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags)
auio.uio_segflg = UIO_USERSPACE;
auio.uio_td = td;
#ifdef KTRACE
- /*
- * if tracing, save a copy of iovec
- */
- if (KTRPOINT(td, KTR_GENIO)) {
- ktriov = aiov;
- ktruio = auio;
- didktr = 1;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
cnt = nbyte;
@@ -199,10 +191,9 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags)
}
cnt -= auio.uio_resid;
#ifdef KTRACE
- if (didktr && error == 0) {
- ktruio.uio_iov = &ktriov;
- ktruio.uio_resid = cnt;
- ktrgenio(fd, UIO_READ, &ktruio, error);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = cnt;
+ ktrgenio(fd, UIO_READ, ktruio, error);
}
#endif
td->td_retval[0] = cnt;
@@ -223,86 +214,46 @@ struct readv_args {
* MPSAFE
*/
int
-readv(td, uap)
- struct thread *td;
- struct readv_args *uap;
+readv(struct thread *td, struct readv_args *uap)
{
struct file *fp;
- struct uio auio;
- struct iovec *iov;
- struct iovec *needfree;
- struct iovec aiov[UIO_SMALLIOV];
- long i, cnt;
+ struct uio *auio = NULL;
+ long cnt;
int error;
- u_int iovlen;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
+ struct uio *ktruio = NULL;
#endif
- if ((error = fget_read(td, uap->fd, &fp)) != 0)
+ error = fget_read(td, uap->fd, &fp);
+ if (error)
+ return (error);
+ error = copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error) {
+ fdrop(fp, td);
return (error);
- needfree = NULL;
- /* note: can't use iovlen until iovcnt is validated */
- iovlen = uap->iovcnt * sizeof (struct iovec);
- if (uap->iovcnt > UIO_SMALLIOV) {
- if (uap->iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = uap->iovcnt;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
- auio.uio_offset = -1;
- if ((error = copyin(uap->iovp, iov, iovlen)))
- goto done;
- auio.uio_resid = 0;
- for (i = 0; i < uap->iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
- error = EINVAL;
- goto done;
- }
- auio.uio_resid += iov->iov_len;
- iov++;
}
+ auio->uio_rw = UIO_READ;
+ auio->uio_td = td;
#ifdef KTRACE
- /*
- * if tracing, save a copy of iovec
- */
- if (KTRPOINT(td, KTR_GENIO)) {
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy(auio.uio_iov, ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(auio);
#endif
- cnt = auio.uio_resid;
- if ((error = fo_read(fp, &auio, td->td_ucred, 0, td))) {
- if (auio.uio_resid != cnt && (error == ERESTART ||
+ cnt = auio->uio_resid;
+ if ((error = fo_read(fp, auio, td->td_ucred, 0, td))) {
+ if (auio->uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
}
- cnt -= auio.uio_resid;
+ cnt -= auio->uio_resid;
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = cnt;
- ktrgenio(uap->fd, UIO_READ, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = cnt;
+ ktrgenio(uap->fd, UIO_READ, ktruio, error);
}
#endif
td->td_retval[0] = cnt;
-done:
+ free(auio, M_IOV);
fdrop(fp, td);
- if (needfree)
- FREE(needfree, M_IOV);
return (error);
}
@@ -389,9 +340,7 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags)
struct iovec aiov;
long cnt, error = 0;
#ifdef KTRACE
- struct iovec ktriov;
- struct uio ktruio;
- int didktr = 0;
+ struct uio *ktruio = NULL;
#endif
aiov.iov_base = (void *)(uintptr_t)buf;
@@ -406,14 +355,8 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags)
auio.uio_segflg = UIO_USERSPACE;
auio.uio_td = td;
#ifdef KTRACE
- /*
- * if tracing, save a copy of iovec and uio
- */
- if (KTRPOINT(td, KTR_GENIO)) {
- ktriov = aiov;
- ktruio = auio;
- didktr = 1;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
cnt = nbyte;
if (fp->f_type == DTYPE_VNODE)
@@ -431,10 +374,9 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags)
}
cnt -= auio.uio_resid;
#ifdef KTRACE
- if (didktr && error == 0) {
- ktruio.uio_iov = &ktriov;
- ktruio.uio_resid = cnt;
- ktrgenio(fd, UIO_WRITE, &ktruio, error);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = cnt;
+ ktrgenio(fd, UIO_WRITE, ktruio, error);
}
#endif
td->td_retval[0] = cnt;
@@ -455,68 +397,35 @@ struct writev_args {
* MPSAFE
*/
int
-writev(td, uap)
- struct thread *td;
- register struct writev_args *uap;
+writev(struct thread *td, struct writev_args *uap)
{
struct file *fp;
- struct uio auio;
- register struct iovec *iov;
- struct iovec *needfree;
- struct iovec aiov[UIO_SMALLIOV];
- long i, cnt, error = 0;
- u_int iovlen;
+ struct uio *auio = NULL;
+ long cnt;
+ int error;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
+ struct uio *ktruio = NULL;
#endif
- if ((error = fget_write(td, uap->fd, &fp)) != 0)
+ error = fget_write(td, uap->fd, &fp);
+ if (error)
return (EBADF);
- needfree = NULL;
- /* note: can't use iovlen until iovcnt is validated */
- iovlen = uap->iovcnt * sizeof (struct iovec);
- if (uap->iovcnt > UIO_SMALLIOV) {
- if (uap->iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = uap->iovcnt;
- auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
- auio.uio_offset = -1;
- if ((error = copyin(uap->iovp, iov, iovlen)))
- goto done;
- auio.uio_resid = 0;
- for (i = 0; i < uap->iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
- error = EINVAL;
- goto done;
- }
- auio.uio_resid += iov->iov_len;
- iov++;
+ error = copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
}
+ auio->uio_rw = UIO_WRITE;
+ auio->uio_td = td;
#ifdef KTRACE
- /*
- * if tracing, save a copy of iovec and uio
- */
- if (KTRPOINT(td, KTR_GENIO)) {
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy(auio.uio_iov, ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(auio);
#endif
- cnt = auio.uio_resid;
+ cnt = auio->uio_resid;
if (fp->f_type == DTYPE_VNODE)
bwillwrite();
- if ((error = fo_write(fp, &auio, td->td_ucred, 0, td))) {
- if (auio.uio_resid != cnt && (error == ERESTART ||
+ if ((error = fo_write(fp, auio, td->td_ucred, 0, td))) {
+ if (auio->uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
if (error == EPIPE) {
@@ -525,22 +434,16 @@ writev(td, uap)
PROC_UNLOCK(td->td_proc);
}
}
- cnt -= auio.uio_resid;
+ cnt -= auio->uio_resid;
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = cnt;
- ktrgenio(uap->fd, UIO_WRITE, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = cnt;
+ ktrgenio(uap->fd, UIO_WRITE, ktruio, error);
}
#endif
td->td_retval[0] = cnt;
-done:
fdrop(fp, td);
- if (needfree)
- FREE(needfree, M_IOV);
+ free(auio, M_IOV);
return (error);
}
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 27440d4..eeff60d 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -701,9 +701,7 @@ kern_sendit(td, s, mp, flags, control)
int i;
int len, error;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
- int iovlen;
+ struct uio *ktruio = NULL;
#endif
NET_LOCK_GIANT();
@@ -733,12 +731,8 @@ kern_sendit(td, s, mp, flags, control)
}
}
#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO)) {
- iovlen = auio.uio_iovcnt * sizeof (struct iovec);
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy(auio.uio_iov, ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
@@ -757,13 +751,9 @@ kern_sendit(td, s, mp, flags, control)
if (error == 0)
td->td_retval[0] = len - auio.uio_resid;
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = td->td_retval[0];
- ktrgenio(s, UIO_WRITE, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = td->td_retval[0];
+ ktrgenio(s, UIO_WRITE, ktruio, error);
}
#endif
bad:
@@ -842,41 +832,26 @@ osend(td, uap)
int
osendmsg(td, uap)
struct thread *td;
- register struct osendmsg_args /* {
+ struct osendmsg_args /* {
int s;
caddr_t msg;
int flags;
} */ *uap;
{
struct msghdr msg;
- struct iovec aiov[UIO_SMALLIOV], *iov;
+ struct iovec *iov;
int error;
error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
if (error)
- goto done2;
- if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
- if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
- error = EMSGSIZE;
- goto done2;
- }
- MALLOC(iov, struct iovec *,
- sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
- M_WAITOK);
- } else {
- iov = aiov;
- }
- error = copyin(msg.msg_iov, iov,
- (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
+ return (error);
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
if (error)
- goto done;
- msg.msg_flags = MSG_COMPAT;
+ return (error);
msg.msg_iov = iov;
+ msg.msg_flags = MSG_COMPAT;
error = sendit(td, uap->s, &msg, uap->flags);
-done:
- if (iov != aiov)
- FREE(iov, M_IOV);
-done2:
+ free(iov, M_IOV);
return (error);
}
#endif
@@ -887,56 +862,41 @@ done2:
int
sendmsg(td, uap)
struct thread *td;
- register struct sendmsg_args /* {
+ struct sendmsg_args /* {
int s;
caddr_t msg;
int flags;
} */ *uap;
{
struct msghdr msg;
- struct iovec aiov[UIO_SMALLIOV], *iov;
+ struct iovec *iov;
int error;
error = copyin(uap->msg, &msg, sizeof (msg));
if (error)
- goto done2;
- if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
- if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
- error = EMSGSIZE;
- goto done2;
- }
- MALLOC(iov, struct iovec *,
- sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
- M_WAITOK);
- } else {
- iov = aiov;
- }
- if (msg.msg_iovlen &&
- (error = copyin(msg.msg_iov, iov,
- (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
- goto done;
+ return (error);
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+ if (error)
+ return (error);
msg.msg_iov = iov;
#ifdef COMPAT_OLDSOCK
msg.msg_flags = 0;
#endif
error = sendit(td, uap->s, &msg, uap->flags);
-done:
- if (iov != aiov)
- FREE(iov, M_IOV);
-done2:
+ free(iov, M_IOV);
return (error);
}
static int
recvit(td, s, mp, namelenp)
- register struct thread *td;
+ struct thread *td;
int s;
- register struct msghdr *mp;
+ struct msghdr *mp;
void *namelenp;
{
struct uio auio;
- register struct iovec *iov;
- register int i;
+ struct iovec *iov;
+ int i;
socklen_t len;
int error;
struct mbuf *m, *control = 0;
@@ -944,9 +904,7 @@ recvit(td, s, mp, namelenp)
struct socket *so;
struct sockaddr *fromsa = 0;
#ifdef KTRACE
- struct iovec *ktriov = NULL;
- struct uio ktruio;
- int iovlen;
+ struct uio *ktruio = NULL;
#endif
NET_LOCK_GIANT();
@@ -982,12 +940,8 @@ recvit(td, s, mp, namelenp)
}
}
#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO)) {
- iovlen = auio.uio_iovcnt * sizeof (struct iovec);
- MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
- bcopy(auio.uio_iov, ktriov, iovlen);
- ktruio = auio;
- }
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
@@ -999,13 +953,9 @@ recvit(td, s, mp, namelenp)
error = 0;
}
#ifdef KTRACE
- if (ktriov != NULL) {
- if (error == 0) {
- ktruio.uio_iov = ktriov;
- ktruio.uio_resid = (int)len - auio.uio_resid;
- ktrgenio(s, UIO_READ, &ktruio, error);
- }
- FREE(ktriov, M_TEMP);
+ if (ktruio != NULL) {
+ ktruio->uio_resid = (int)len - auio.uio_resid;
+ ktrgenio(s, UIO_READ, ktruio, error);
}
#endif
if (error)
@@ -1189,46 +1139,29 @@ orecv(td, uap)
int
orecvmsg(td, uap)
struct thread *td;
- register struct orecvmsg_args /* {
+ struct orecvmsg_args /* {
int s;
struct omsghdr *msg;
int flags;
} */ *uap;
{
struct msghdr msg;
- struct iovec aiov[UIO_SMALLIOV], *iov;
+ struct iovec *iov;
int error;
error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
if (error)
return (error);
-
- if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
- if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
- error = EMSGSIZE;
- goto done2;
- }
- MALLOC(iov, struct iovec *,
- sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
- M_WAITOK);
- } else {
- iov = aiov;
- }
- msg.msg_flags = uap->flags | MSG_COMPAT;
- error = copyin(msg.msg_iov, iov,
- (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
if (error)
- goto done;
+ return (error);
+ msg.msg_flags = uap->flags | MSG_COMPAT;
msg.msg_iov = iov;
error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
-
if (msg.msg_controllen && error == 0)
error = copyout(&msg.msg_controllen,
&uap->msg->msg_accrightslen, sizeof (int));
-done:
- if (iov != aiov)
- FREE(iov, M_IOV);
-done2:
+ free(iov, M_IOV);
return (error);
}
#endif
@@ -1239,50 +1172,34 @@ done2:
int
recvmsg(td, uap)
struct thread *td;
- register struct recvmsg_args /* {
+ struct recvmsg_args /* {
int s;
struct msghdr *msg;
int flags;
} */ *uap;
{
struct msghdr msg;
- struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
- register int error;
+ struct iovec *uiov, *iov;
+ int error;
error = copyin(uap->msg, &msg, sizeof (msg));
if (error)
- goto done2;
- if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
- if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
- error = EMSGSIZE;
- goto done2;
- }
- MALLOC(iov, struct iovec *,
- sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
- M_WAITOK);
- } else {
- iov = aiov;
- }
-#ifdef COMPAT_OLDSOCK
- msg.msg_flags = uap->flags &~ MSG_COMPAT;
-#else
+ return (error);
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+ if (error)
+ return (error);
msg.msg_flags = uap->flags;
+#ifdef COMPAT_OLDSOCK
+ msg.msg_flags &= ~MSG_COMPAT;
#endif
uiov = msg.msg_iov;
msg.msg_iov = iov;
- error = copyin(uiov, iov,
- (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
- if (error)
- goto done;
error = recvit(td, uap->s, &msg, NULL);
- if (!error) {
+ if (error == 0) {
msg.msg_iov = uiov;
error = copyout(&msg, uap->msg, sizeof(msg));
}
-done:
- if (iov != aiov)
- FREE(iov, M_IOV);
-done2:
+ free(iov, M_IOV);
return (error);
}
@@ -1727,10 +1644,9 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
struct vm_page *pg;
struct writev_args nuap;
struct sf_hdtr hdtr;
- struct uio hdr_uio;
+ struct uio *hdr_uio = NULL;
off_t off, xfsize, hdtr_size, sbytes = 0;
int error, headersize = 0, headersent = 0;
- struct iovec *hdr_iov = NULL;
mtx_lock(&Giant);
@@ -1783,16 +1699,13 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
* Send any headers.
*/
if (hdtr.headers != NULL) {
- hdr_uio.uio_td = td;
- hdr_uio.uio_rw = UIO_WRITE;
- error = uiofromiov(hdtr.headers, hdtr.hdr_cnt,
- &hdr_uio);
+ error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio);
if (error)
goto done;
- /* Cache hdr_iov, m_uiotombuf may change it. */
- hdr_iov = hdr_uio.uio_iov;
- if (hdr_uio.uio_resid > 0) {
- m_header = m_uiotombuf(&hdr_uio, M_DONTWAIT, 0);
+ hdr_uio->uio_td = td;
+ hdr_uio->uio_rw = UIO_WRITE;
+ if (hdr_uio->uio_resid > 0) {
+ m_header = m_uiotombuf(hdr_uio, M_DONTWAIT, 0);
if (m_header == NULL)
goto done;
headersize = m_header->m_pkthdr.len;
@@ -2110,8 +2023,8 @@ done:
vrele(vp);
if (so)
fputsock(so);
- if (hdr_iov)
- FREE(hdr_iov, M_IOV);
+ if (hdr_uio != NULL)
+ free(hdr_uio, M_IOV);
if (m_header)
m_freem(m_header);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 22048f4..5252b3b 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -376,46 +376,32 @@ nmount(td, uap)
int flags;
} */ *uap;
{
- struct uio auio;
- struct iovec *iov, *needfree;
- struct iovec aiov[UIO_SMALLIOV];
+ struct uio *auio;
+ struct iovec *iov;
unsigned int i;
int error;
- u_int iovlen, iovcnt;
+ u_int iovcnt;
iovcnt = uap->iovcnt;
- iovlen = iovcnt * sizeof (struct iovec);
/*
* Check that we have an even number of iovec's
* and that we have at least two options.
*/
- if ((iovcnt & 1) || (iovcnt < 4) || (iovcnt > UIO_MAXIOV))
+ if ((iovcnt & 1) || (iovcnt < 4))
return (EINVAL);
-
- if (iovcnt > UIO_SMALLIOV) {
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else {
- iov = aiov;
- needfree = NULL;
- }
- auio.uio_iov = iov;
- auio.uio_iovcnt = iovcnt;
- auio.uio_segflg = UIO_USERSPACE;
- if ((error = copyin(uap->iovp, iov, iovlen)))
- goto finish;
-
+ error = copyinuio(uap->iovp, iovcnt, &auio);
+ if (error)
+ return (error);
+ iov = auio->uio_iov;
for (i = 0; i < iovcnt; i++) {
if (iov->iov_len > MMAXOPTIONLEN) {
- error = EINVAL;
- goto finish;
+ free(auio, M_IOV);
+ return (EINVAL);
}
iov++;
}
- error = vfs_nmount(td, uap->flags, &auio);
-finish:
- if (needfree != NULL)
- free(needfree, M_TEMP);
+ error = vfs_nmount(td, uap->flags, auio);
+ free(auio, M_IOV);
return (error);
}
diff --git a/sys/sys/uio.h b/sys/sys/uio.h
index 600fcff..f89c9c4 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -77,17 +77,19 @@ struct uio {
* IOV_MAX.
*/
#define UIO_MAXIOV 1024 /* max 1K of iov's */
-#define UIO_SMALLIOV 8 /* 8 on stack, else malloc */
struct vm_object;
struct vm_page;
+struct uio *cloneuio(struct uio *uiop);
int copyinfrom(const void * __restrict src, void * __restrict dst,
size_t len, int seg);
+int copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov,
+ int error);
int copyinstrfrom(const void * __restrict src, void * __restrict dst,
size_t len, size_t * __restrict copied, int seg);
+int copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop);
void uio_yield(void);
-int uiofromiov(struct iovec *iovp, u_int iovcnt, struct uio *auio);
int uiomove(void *cp, int n, struct uio *uio);
int uiomove_frombuf(void *buf, int buflen, struct uio *uio);
int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n,
OpenPOWER on IntegriCloud