- Use a custom version of copyinuio() to implement readv/writev using
kern_readv/writev. - Use kern_sched_rr_get_interval() rather than the stackgap.
This commit is contained in:
parent
50b584201d
commit
3dde27da5e
@ -212,99 +212,75 @@ struct iovec32 {
|
|||||||
u_int32_t iov_base;
|
u_int32_t iov_base;
|
||||||
int iov_len;
|
int iov_len;
|
||||||
};
|
};
|
||||||
#define STACKGAPLEN 400
|
|
||||||
|
|
||||||
CTASSERT(sizeof(struct iovec32) == 8);
|
CTASSERT(sizeof(struct iovec32) == 8);
|
||||||
|
|
||||||
|
static int
|
||||||
|
linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
|
||||||
|
{
|
||||||
|
struct iovec32 iov32;
|
||||||
|
struct iovec *iov;
|
||||||
|
struct uio *uio;
|
||||||
|
u_int iovlen;
|
||||||
|
int error, i;
|
||||||
|
|
||||||
|
*uiop = NULL;
|
||||||
|
if (iovcnt > UIO_MAXIOV)
|
||||||
|
return (EINVAL);
|
||||||
|
iovlen = iovcnt * sizeof(struct iovec);
|
||||||
|
uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
|
||||||
|
iov = (struct iovec *)(uio + 1);
|
||||||
|
for (i = 0; i < iovcnt; i++) {
|
||||||
|
error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
|
||||||
|
if (error) {
|
||||||
|
free(uio, M_IOV);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
iov[i].iov_base = PTRIN(iov32.iov_base);
|
||||||
|
iov[i].iov_len = iov32.iov_len;
|
||||||
|
}
|
||||||
|
uio->uio_iov = iov;
|
||||||
|
uio->uio_iovcnt = iovcnt;
|
||||||
|
uio->uio_segflg = UIO_USERSPACE;
|
||||||
|
uio->uio_offset = -1;
|
||||||
|
uio->uio_resid = 0;
|
||||||
|
for (i = 0; i < iovcnt; i++) {
|
||||||
|
if (iov->iov_len > INT_MAX - uio->uio_resid) {
|
||||||
|
free(uio, M_IOV);
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
uio->uio_resid += iov->iov_len;
|
||||||
|
iov++;
|
||||||
|
}
|
||||||
|
*uiop = uio;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
linux_readv(struct thread *td, struct linux_readv_args *uap)
|
linux_readv(struct thread *td, struct linux_readv_args *uap)
|
||||||
{
|
{
|
||||||
int error, osize, nsize, i;
|
struct uio *auio;
|
||||||
caddr_t sg;
|
int error;
|
||||||
struct readv_args /* {
|
|
||||||
syscallarg(int) fd;
|
|
||||||
syscallarg(struct iovec *) iovp;
|
|
||||||
syscallarg(u_int) iovcnt;
|
|
||||||
} */ a;
|
|
||||||
struct iovec32 *oio;
|
|
||||||
struct iovec *nio;
|
|
||||||
|
|
||||||
sg = stackgap_init();
|
error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
||||||
|
if (error)
|
||||||
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
|
return (error);
|
||||||
return (EINVAL);
|
error = kern_readv(td, uap->fd, auio);
|
||||||
|
free(auio, M_IOV);
|
||||||
osize = uap->iovcnt * sizeof (struct iovec32);
|
|
||||||
nsize = uap->iovcnt * sizeof (struct iovec);
|
|
||||||
|
|
||||||
oio = malloc(osize, M_TEMP, M_WAITOK);
|
|
||||||
nio = malloc(nsize, M_TEMP, M_WAITOK);
|
|
||||||
|
|
||||||
error = 0;
|
|
||||||
if ((error = copyin(uap->iovp, oio, osize)))
|
|
||||||
goto punt;
|
|
||||||
for (i = 0; i < uap->iovcnt; i++) {
|
|
||||||
nio[i].iov_base = PTRIN(oio[i].iov_base);
|
|
||||||
nio[i].iov_len = oio[i].iov_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.fd = uap->fd;
|
|
||||||
a.iovp = stackgap_alloc(&sg, nsize);
|
|
||||||
a.iovcnt = uap->iovcnt;
|
|
||||||
|
|
||||||
if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
|
|
||||||
goto punt;
|
|
||||||
error = readv(td, &a);
|
|
||||||
|
|
||||||
punt:
|
|
||||||
free(oio, M_TEMP);
|
|
||||||
free(nio, M_TEMP);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
linux_writev(struct thread *td, struct linux_writev_args *uap)
|
linux_writev(struct thread *td, struct linux_writev_args *uap)
|
||||||
{
|
{
|
||||||
int error, i, nsize, osize;
|
struct uio *auio;
|
||||||
caddr_t sg;
|
int error;
|
||||||
struct writev_args /* {
|
|
||||||
syscallarg(int) fd;
|
|
||||||
syscallarg(struct iovec *) iovp;
|
|
||||||
syscallarg(u_int) iovcnt;
|
|
||||||
} */ a;
|
|
||||||
struct iovec32 *oio;
|
|
||||||
struct iovec *nio;
|
|
||||||
|
|
||||||
sg = stackgap_init();
|
error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
||||||
|
if (error)
|
||||||
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
|
return (error);
|
||||||
return (EINVAL);
|
error = kern_writev(td, uap->fd, auio);
|
||||||
|
free(auio, M_IOV);
|
||||||
osize = uap->iovcnt * sizeof (struct iovec32);
|
|
||||||
nsize = uap->iovcnt * sizeof (struct iovec);
|
|
||||||
|
|
||||||
oio = malloc(osize, M_TEMP, M_WAITOK);
|
|
||||||
nio = malloc(nsize, M_TEMP, M_WAITOK);
|
|
||||||
|
|
||||||
error = 0;
|
|
||||||
if ((error = copyin(uap->iovp, oio, osize)))
|
|
||||||
goto punt;
|
|
||||||
for (i = 0; i < uap->iovcnt; i++) {
|
|
||||||
nio[i].iov_base = PTRIN(oio[i].iov_base);
|
|
||||||
nio[i].iov_len = oio[i].iov_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.fd = uap->fd;
|
|
||||||
a.iovp = stackgap_alloc(&sg, nsize);
|
|
||||||
a.iovcnt = uap->iovcnt;
|
|
||||||
|
|
||||||
if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
|
|
||||||
goto punt;
|
|
||||||
error = writev(td, &a);
|
|
||||||
|
|
||||||
punt:
|
|
||||||
free(oio, M_TEMP);
|
|
||||||
free(nio, M_TEMP);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1013,20 +989,11 @@ int
|
|||||||
linux_sched_rr_get_interval(struct thread *td,
|
linux_sched_rr_get_interval(struct thread *td,
|
||||||
struct linux_sched_rr_get_interval_args *uap)
|
struct linux_sched_rr_get_interval_args *uap)
|
||||||
{
|
{
|
||||||
struct sched_rr_get_interval_args bsd_args;
|
|
||||||
caddr_t sg, psgts;
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
struct l_timespec ts32;
|
struct l_timespec ts32;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sg = stackgap_init();
|
error = kern_sched_rr_get_interval(td, uap->pid, &ts);
|
||||||
psgts = stackgap_alloc(&sg, sizeof(struct timespec));
|
|
||||||
bsd_args.pid = uap->pid;
|
|
||||||
bsd_args.interval = (void *)psgts;
|
|
||||||
error = sched_rr_get_interval(td, &bsd_args);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
error = copyin(psgts, &ts, sizeof(ts));
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
ts32.tv_sec = ts.tv_sec;
|
ts32.tv_sec = ts.tv_sec;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user