Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_aio.c
Show First 20 Lines • Show All 709 Lines • ▼ Show 20 Lines | if (ki->kaio_active_count < max_aio_per_proc) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (job); | return (job); | ||||
} | } | ||||
/* | /* | ||||
* Move all data to a permanent storage device. This code | * Move all data to a permanent storage device. This code | ||||
* simulates the fsync syscall. | * simulates the fsync and fdatasync syscalls. | ||||
*/ | */ | ||||
static int | static int | ||||
aio_fsync_vnode(struct thread *td, struct vnode *vp) | aio_fsync_vnode(struct thread *td, struct vnode *vp, bool fullsync) | ||||
{ | { | ||||
struct mount *mp; | struct mount *mp; | ||||
int error; | int error; | ||||
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) | if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) | ||||
goto drop; | goto drop; | ||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | ||||
if (vp->v_object != NULL) { | if (vp->v_object != NULL) { | ||||
VM_OBJECT_WLOCK(vp->v_object); | VM_OBJECT_WLOCK(vp->v_object); | ||||
vm_object_page_clean(vp->v_object, 0, 0, 0); | vm_object_page_clean(vp->v_object, 0, 0, 0); | ||||
VM_OBJECT_WUNLOCK(vp->v_object); | VM_OBJECT_WUNLOCK(vp->v_object); | ||||
} | } | ||||
error = VOP_FSYNC(vp, MNT_WAIT, td); | error = fullsync ? VOP_FSYNC(vp, MNT_WAIT, td) : VOP_FDATASYNC(vp, td); | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
drop: | drop: | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
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; | ||||
bool fullsync; | |||||
KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC, | KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC || | ||||
job->uaiocb.aio_lio_opcode == LIO_DSYNC, | |||||
kib: This line should have 4-spaces indent. | |||||
("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); | ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); | ||||
fullsync = job->uaiocb.aio_lio_opcode == LIO_SYNC; | |||||
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, fullsync); | ||||
jhbUnsubmitted Done Inline ActionsYou could just pass the opcode through. It might be slightly easier to read to do the 'opcode == LIO_SYNC' comparison in aio_fsync_vnode() directly rather than here in the caller, but that's really minor. jhb: You could just pass the opcode through. It might be slightly easier to read to do the 'opcode… | |||||
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, 0, 0); | aio_complete(job, 0, 0); | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 669 Lines • ▼ Show 20 Lines | aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, | ||||
switch (opcode) { | switch (opcode) { | ||||
case LIO_WRITE: | case LIO_WRITE: | ||||
error = fget_write(td, fd, &cap_pwrite_rights, &fp); | error = fget_write(td, fd, &cap_pwrite_rights, &fp); | ||||
break; | break; | ||||
case LIO_READ: | case LIO_READ: | ||||
error = fget_read(td, fd, &cap_pread_rights, &fp); | error = fget_read(td, fd, &cap_pread_rights, &fp); | ||||
break; | break; | ||||
case LIO_SYNC: | case LIO_SYNC: | ||||
case LIO_DSYNC: | |||||
error = fget(td, fd, &cap_fsync_rights, &fp); | error = fget(td, fd, &cap_fsync_rights, &fp); | ||||
break; | break; | ||||
case LIO_MLOCK: | case LIO_MLOCK: | ||||
fp = NULL; | fp = NULL; | ||||
break; | break; | ||||
case LIO_NOP: | 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) { | ||||
uma_zfree(aiocb_zone, job); | uma_zfree(aiocb_zone, job); | ||||
ops->store_error(ujob, error); | ops->store_error(ujob, error); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (opcode == LIO_SYNC && fp->f_vnode == NULL) { | if ((opcode == LIO_SYNC || opcode == LIO_DSYNC) && fp->f_vnode == NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto aqueue_fail; | goto aqueue_fail; | ||||
} | } | ||||
if ((opcode == LIO_READ || opcode == LIO_WRITE) && | if ((opcode == LIO_READ || opcode == LIO_WRITE) && | ||||
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)) { | ||||
error = EINVAL; | error = EINVAL; | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | aio_queue_file(struct file *fp, struct kaiocb *job) | ||||
switch (job->uaiocb.aio_lio_opcode) { | switch (job->uaiocb.aio_lio_opcode) { | ||||
case LIO_READ: | case LIO_READ: | ||||
case LIO_WRITE: | case LIO_WRITE: | ||||
aio_schedule(job, aio_process_rw); | aio_schedule(job, aio_process_rw); | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
case LIO_SYNC: | case LIO_SYNC: | ||||
case LIO_DSYNC: | |||||
Done Inline ActionsA few lines below here is a check job2->uaiocb.aio_lio_opcode != LIO_SYNC. Why didn't you modify that to check for LIO_DSYNC too? Pro tip: if you generate the diff with svn diff -D9999 Phabricator will intelligently show more context. Or, install arcanist-php72 and create the review with arc diff --create. asomers: A few lines below here is a check `job2->uaiocb.aio_lio_opcode != LIO_SYNC`. Why didn't you… | |||||
Done Inline ActionsYeah, without that check it would set the KAIOCB_CHECKSYNC flag on other LIO_DSYNC requests queued earlier, which wasn't intentional. Fixed. tmunro: Yeah, without that check it would set the KAIOCB_CHECKSYNC flag on other LIO_DSYNC requests… | |||||
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 && | ||||
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)) { | ||||
▲ Show 20 Lines • Show All 725 Lines • ▼ Show 20 Lines | sys_aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) | ||||
return (kern_aio_waitcomplete(td, uap->aiocbp, tsp, &aiocb_ops)); | return (kern_aio_waitcomplete(td, uap->aiocbp, tsp, &aiocb_ops)); | ||||
} | } | ||||
static int | static int | ||||
kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob, | kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob, | ||||
struct aiocb_ops *ops) | struct aiocb_ops *ops) | ||||
{ | { | ||||
int listop; | |||||
if (op != O_SYNC) /* XXX lack of O_DSYNC */ | if (op != O_SYNC && op != O_DSYNC) | ||||
jhbUnsubmitted Done Inline ActionsI would perhaps consolidate the checks: switch (op) { case O_SYNC: listop = LIO_SYNC; break; case O_DYSNC: listop = LIO_DSYNC; break; default: return (EINVAL); } jhb: I would perhaps consolidate the checks:
```
switch (op) {
case O_SYNC:
listop… | |||||
return (EINVAL); | return (EINVAL); | ||||
return (aio_aqueue(td, ujob, NULL, LIO_SYNC, ops)); | listop = op == O_SYNC ? LIO_SYNC : LIO_DSYNC; | ||||
return (aio_aqueue(td, ujob, NULL, listop, ops)); | |||||
} | } | ||||
int | int | ||||
sys_aio_fsync(struct thread *td, struct aio_fsync_args *uap) | sys_aio_fsync(struct thread *td, struct aio_fsync_args *uap) | ||||
{ | { | ||||
return (kern_aio_fsync(td, uap->op, uap->aiocbp, &aiocb_ops)); | return (kern_aio_fsync(td, uap->op, uap->aiocbp, &aiocb_ops)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 506 Lines • Show Last 20 Lines |
This line should have 4-spaces indent.