Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_aio.c
Show First 20 Lines • Show All 811 Lines • ▼ Show 20 Lines | aio_process_rw(struct kaiocb *job) | ||||
job->msgrcv = msgrcv_end - msgrcv_st; | job->msgrcv = msgrcv_end - msgrcv_st; | ||||
job->msgsnd = msgsnd_end - msgsnd_st; | job->msgsnd = msgsnd_end - msgsnd_st; | ||||
job->inblock = inblock_end - inblock_st; | job->inblock = inblock_end - inblock_st; | ||||
job->outblock = oublock_end - oublock_st; | job->outblock = oublock_end - oublock_st; | ||||
if (error != 0 && job->uiop->uio_resid != cnt) { | if (error != 0 && job->uiop->uio_resid != cnt) { | ||||
if (error == ERESTART || error == EINTR || error == EWOULDBLOCK) | if (error == ERESTART || error == EINTR || error == EWOULDBLOCK) | ||||
error = 0; | error = 0; | ||||
if (error == EPIPE && | if (error == EPIPE && (opcode & LIO_WRITE)) { | ||||
(opcode == LIO_WRITE || opcode == LIO_WRITEV)) { | |||||
PROC_LOCK(job->userproc); | PROC_LOCK(job->userproc); | ||||
kern_psignal(job->userproc, SIGPIPE); | kern_psignal(job->userproc, SIGPIPE); | ||||
PROC_UNLOCK(job->userproc); | PROC_UNLOCK(job->userproc); | ||||
} | } | ||||
} | } | ||||
cnt -= job->uiop->uio_resid; | cnt -= job->uiop->uio_resid; | ||||
td->td_ucred = td_savedcred; | td->td_ucred = td_savedcred; | ||||
if (error) | if (error) | ||||
aio_complete(job, -1, error); | aio_complete(job, -1, error); | ||||
else | else | ||||
aio_complete(job, cnt, 0); | aio_complete(job, cnt, 0); | ||||
} | } | ||||
static void | static void | ||||
aio_process_sync(struct kaiocb *job) | aio_process_sync(struct kaiocb *job) | ||||
{ | { | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct ucred *td_savedcred = td->td_ucred; | struct ucred *td_savedcred = td->td_ucred; | ||||
struct file *fp = job->fd_file; | struct file *fp = job->fd_file; | ||||
int error = 0; | int error = 0; | ||||
KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC || | KASSERT(job->uaiocb.aio_lio_opcode & LIO_SYNC, | ||||
job->uaiocb.aio_lio_opcode == LIO_DSYNC, | |||||
("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); | ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); | ||||
td->td_ucred = job->cred; | td->td_ucred = job->cred; | ||||
if (fp->f_vnode != NULL) { | if (fp->f_vnode != NULL) { | ||||
error = aio_fsync_vnode(td, fp->f_vnode, | error = aio_fsync_vnode(td, fp->f_vnode, | ||||
job->uaiocb.aio_lio_opcode); | job->uaiocb.aio_lio_opcode); | ||||
} | } | ||||
td->td_ucred = td_savedcred; | td->td_ucred = td_savedcred; | ||||
▲ Show 20 Lines • Show All 380 Lines • ▼ Show 20 Lines | if (fp == NULL || fp->f_type != DTYPE_VNODE) | ||||
return (-1); | return (-1); | ||||
vp = fp->f_vnode; | vp = fp->f_vnode; | ||||
if (vp->v_type != VCHR) | if (vp->v_type != VCHR) | ||||
return (-1); | return (-1); | ||||
if (vp->v_bufobj.bo_bsize == 0) | if (vp->v_bufobj.bo_bsize == 0) | ||||
return (-1); | return (-1); | ||||
bio_cmd = opcode == LIO_WRITE || opcode == LIO_WRITEV ? BIO_WRITE : | bio_cmd = (opcode & LIO_WRITE) ? BIO_WRITE : BIO_READ; | ||||
BIO_READ; | |||||
iovcnt = job->uiop->uio_iovcnt; | iovcnt = job->uiop->uio_iovcnt; | ||||
if (iovcnt > max_buf_aio) | if (iovcnt > max_buf_aio) | ||||
return (-1); | return (-1); | ||||
for (i = 0; i < iovcnt; i++) { | for (i = 0; i < iovcnt; i++) { | ||||
if (job->uiop->uio_iov[i].iov_len % vp->v_bufobj.bo_bsize != 0) | if (job->uiop->uio_iov[i].iov_len % vp->v_bufobj.bo_bsize != 0) | ||||
return (-1); | return (-1); | ||||
if (job->uiop->uio_iov[i].iov_len > maxphys) { | if (job->uiop->uio_iov[i].iov_len > maxphys) { | ||||
error = -1; | error = -1; | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | |||||
aiocb_copyin(struct aiocb *ujob, struct kaiocb *kjob, int type) | aiocb_copyin(struct aiocb *ujob, struct kaiocb *kjob, int type) | ||||
{ | { | ||||
struct aiocb *kcb = &kjob->uaiocb; | struct aiocb *kcb = &kjob->uaiocb; | ||||
int error; | int error; | ||||
error = copyin(ujob, kcb, sizeof(struct aiocb)); | error = copyin(ujob, kcb, sizeof(struct aiocb)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if (type == LIO_READV || type == LIO_WRITEV) { | if (type & LIO_VECTORED) { | ||||
/* malloc a uio and copy in the iovec */ | /* malloc a uio and copy in the iovec */ | ||||
error = copyinuio(__DEVOLATILE(struct iovec*, kcb->aio_iov), | error = copyinuio(__DEVOLATILE(struct iovec*, kcb->aio_iov), | ||||
kcb->aio_iovcnt, &kjob->uiop); | kcb->aio_iovcnt, &kjob->uiop); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | case LIO_NOP: | ||||
error = fget(td, fd, &cap_no_rights, &fp); | error = fget(td, fd, &cap_no_rights, &fp); | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
} | } | ||||
if (error) | if (error) | ||||
goto err3; | goto err3; | ||||
if ((opcode == LIO_SYNC || opcode == LIO_DSYNC) && fp->f_vnode == NULL) { | if ((opcode & LIO_SYNC) && fp->f_vnode == NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto err3; | goto err3; | ||||
} | } | ||||
if ((opcode == LIO_READ || opcode == LIO_READV || | if ((opcode == LIO_READ || opcode == LIO_READV || | ||||
opcode == LIO_WRITE || opcode == LIO_WRITEV) && | opcode == LIO_WRITE || opcode == LIO_WRITEV) && | ||||
job->uaiocb.aio_offset < 0 && | job->uaiocb.aio_offset < 0 && | ||||
(fp->f_vnode == NULL || fp->f_vnode->v_type != VCHR)) { | (fp->f_vnode == NULL || fp->f_vnode->v_type != VCHR)) { | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | no_kqueue: | ||||
ops->store_error(ujob, EINPROGRESS); | ops->store_error(ujob, EINPROGRESS); | ||||
job->uaiocb._aiocb_private.error = EINPROGRESS; | job->uaiocb._aiocb_private.error = EINPROGRESS; | ||||
job->userproc = p; | job->userproc = p; | ||||
job->cred = crhold(td->td_ucred); | job->cred = crhold(td->td_ucred); | ||||
job->jobflags = KAIOCB_QUEUEING; | job->jobflags = KAIOCB_QUEUEING; | ||||
job->lio = lj; | job->lio = lj; | ||||
switch (opcode) { | if (opcode & LIO_VECTORED) { | ||||
case LIO_READV: | |||||
case LIO_WRITEV: | |||||
/* Use the uio copied in by aio_copyin */ | /* Use the uio copied in by aio_copyin */ | ||||
MPASS(job->uiop != &job->uio && job->uiop != NULL); | MPASS(job->uiop != &job->uio && job->uiop != NULL); | ||||
break; | } else { | ||||
case LIO_READ: | |||||
case LIO_WRITE: | |||||
/* Setup the inline uio */ | /* Setup the inline uio */ | ||||
job->iov[0].iov_base = (void *)(uintptr_t)job->uaiocb.aio_buf; | job->iov[0].iov_base = (void *)(uintptr_t)job->uaiocb.aio_buf; | ||||
job->iov[0].iov_len = job->uaiocb.aio_nbytes; | job->iov[0].iov_len = job->uaiocb.aio_nbytes; | ||||
job->uio.uio_iov = job->iov; | job->uio.uio_iov = job->iov; | ||||
job->uio.uio_iovcnt = 1; | job->uio.uio_iovcnt = 1; | ||||
job->uio.uio_resid = job->uaiocb.aio_nbytes; | job->uio.uio_resid = job->uaiocb.aio_nbytes; | ||||
job->uio.uio_segflg = UIO_USERSPACE; | job->uio.uio_segflg = UIO_USERSPACE; | ||||
/* FALLTHROUGH */ | |||||
default: | |||||
job->uiop = &job->uio; | job->uiop = &job->uio; | ||||
break; | |||||
} | } | ||||
switch (opcode) { | switch (opcode & (LIO_READ | LIO_WRITE)) { | ||||
case LIO_READ: | case LIO_READ: | ||||
case LIO_READV: | |||||
job->uiop->uio_rw = UIO_READ; | job->uiop->uio_rw = UIO_READ; | ||||
break; | break; | ||||
case LIO_WRITE: | case LIO_WRITE: | ||||
case LIO_WRITEV: | |||||
job->uiop->uio_rw = UIO_WRITE; | job->uiop->uio_rw = UIO_WRITE; | ||||
break; | break; | ||||
} | } | ||||
job->uiop->uio_offset = job->uaiocb.aio_offset; | job->uiop->uio_offset = job->uaiocb.aio_offset; | ||||
job->uiop->uio_td = td; | job->uiop->uio_td = td; | ||||
if (opcode == LIO_MLOCK) { | if (opcode == LIO_MLOCK) { | ||||
aio_schedule(job, aio_process_mlock); | aio_schedule(job, aio_process_mlock); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | if (fp->f_type == DTYPE_VNODE) { | ||||
} | } | ||||
} | } | ||||
if (!(safe || enable_aio_unsafe)) { | if (!(safe || enable_aio_unsafe)) { | ||||
counted_warning(&unsafe_warningcnt, | counted_warning(&unsafe_warningcnt, | ||||
"is attempting to use unsafe AIO requests"); | "is attempting to use unsafe AIO requests"); | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | } | ||||
switch (job->uaiocb.aio_lio_opcode) { | if (job->uaiocb.aio_lio_opcode & (LIO_WRITE | LIO_READ)) { | ||||
case LIO_READ: | |||||
case LIO_READV: | |||||
case LIO_WRITE: | |||||
case LIO_WRITEV: | |||||
aio_schedule(job, aio_process_rw); | aio_schedule(job, aio_process_rw); | ||||
error = 0; | error = 0; | ||||
break; | } else if (job->uaiocb.aio_lio_opcode & LIO_SYNC) { | ||||
case LIO_SYNC: | |||||
case LIO_DSYNC: | |||||
AIO_LOCK(ki); | AIO_LOCK(ki); | ||||
TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { | TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { | ||||
if (job2->fd_file == job->fd_file && | if (job2->fd_file == job->fd_file && | ||||
job2->uaiocb.aio_lio_opcode != LIO_SYNC && | ((job2->uaiocb.aio_lio_opcode & LIO_SYNC) == 0) && | ||||
job2->uaiocb.aio_lio_opcode != LIO_DSYNC && | |||||
job2->seqno < job->seqno) { | job2->seqno < job->seqno) { | ||||
job2->jobflags |= KAIOCB_CHECKSYNC; | job2->jobflags |= KAIOCB_CHECKSYNC; | ||||
job->pending++; | job->pending++; | ||||
} | } | ||||
} | } | ||||
if (job->pending != 0) { | if (job->pending != 0) { | ||||
if (!aio_set_cancel_function_locked(job, | if (!aio_set_cancel_function_locked(job, | ||||
aio_cancel_sync)) { | aio_cancel_sync)) { | ||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
aio_cancel(job); | aio_cancel(job); | ||||
return (0); | return (0); | ||||
} | } | ||||
TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); | TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); | ||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
return (0); | return (0); | ||||
} | } | ||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
aio_schedule(job, aio_process_sync); | aio_schedule(job, aio_process_sync); | ||||
error = 0; | error = 0; | ||||
break; | } else { | ||||
default: | |||||
error = EINVAL; | error = EINVAL; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
aio_kick_nowait(struct proc *userp) | aio_kick_nowait(struct proc *userp) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 633 Lines • ▼ Show 20 Lines | aio_biowakeup(struct bio *bp) | ||||
nblks = btodb(nbytes); | nblks = btodb(nbytes); | ||||
error = 0; | error = 0; | ||||
/* | /* | ||||
* If multiple bios experienced an error, the job will reflect the | * If multiple bios experienced an error, the job will reflect the | ||||
* error of whichever failed bio completed last. | * error of whichever failed bio completed last. | ||||
*/ | */ | ||||
if (flags & BIO_ERROR) | if (flags & BIO_ERROR) | ||||
atomic_set_int(&job->error, bio_error); | atomic_set_int(&job->error, bio_error); | ||||
if (opcode == LIO_WRITE || opcode == LIO_WRITEV) | if (opcode & LIO_WRITE) | ||||
atomic_add_int(&job->outblock, nblks); | atomic_add_int(&job->outblock, nblks); | ||||
else | else | ||||
atomic_add_int(&job->inblock, nblks); | atomic_add_int(&job->inblock, nblks); | ||||
atomic_subtract_int(&job->nbio, 1); | atomic_subtract_int(&job->nbio, 1); | ||||
if (atomic_load_int(&job->nbio) == 0) { | if (atomic_load_int(&job->nbio) == 0) { | ||||
if (atomic_load_int(&job->error)) | if (atomic_load_int(&job->error)) | ||||
▲ Show 20 Lines • Show All 321 Lines • ▼ Show 20 Lines | aiocb32_copyin(struct aiocb *ujob, struct kaiocb *kjob, int type) | ||||
int error; | int error; | ||||
error = copyin(ujob, &job32, sizeof(job32)); | error = copyin(ujob, &job32, sizeof(job32)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
CP(job32, *kcb, aio_fildes); | CP(job32, *kcb, aio_fildes); | ||||
CP(job32, *kcb, aio_offset); | CP(job32, *kcb, aio_offset); | ||||
CP(job32, *kcb, aio_lio_opcode); | CP(job32, *kcb, aio_lio_opcode); | ||||
if (type == LIO_READV || type == LIO_WRITEV) { | if (type & LIO_VECTORED) { | ||||
iov32 = PTRIN(job32.aio_iov); | iov32 = PTRIN(job32.aio_iov); | ||||
CP(job32, *kcb, aio_iovcnt); | CP(job32, *kcb, aio_iovcnt); | ||||
/* malloc a uio and copy in the iovec */ | /* malloc a uio and copy in the iovec */ | ||||
error = freebsd32_copyinuio(iov32, | error = freebsd32_copyinuio(iov32, | ||||
kcb->aio_iovcnt, &kjob->uiop); | kcb->aio_iovcnt, &kjob->uiop); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 323 Lines • Show Last 20 Lines |