Index: lib/libc/sys/aio_fsync.2 =================================================================== --- lib/libc/sys/aio_fsync.2 +++ lib/libc/sys/aio_fsync.2 @@ -49,11 +49,15 @@ .Pp The .Fa op -argument can only be set to +argument can be set to .Dv O_SYNC to cause all currently queued I/O operations to be completed as if by a call to -.Xr fsync 2 . +.Xr fsync 2 , +or +.Dv O_DSYNC +for +.Xr fdatasync 2 . .Pp If _POSIX_PRIORITIZED_IO is defined, and the descriptor supports it, then the enqueued operation is submitted at a priority equal to that @@ -176,3 +180,7 @@ .Fn aio_fsync system call first appeared in .Fx 7.0 . +The +.Dv O_DSYNC +option appeared in +.Fx 13.0 . Index: sys/kern/vfs_aio.c =================================================================== --- sys/kern/vfs_aio.c +++ sys/kern/vfs_aio.c @@ -715,10 +715,10 @@ /* * Move all data to a permanent storage device. This code - * simulates the fsync syscall. + * simulates the fsync and fdatasync syscalls. */ 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; int error; @@ -731,7 +731,7 @@ vm_object_page_clean(vp->v_object, 0, 0, 0); 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); vn_finished_write(mp); @@ -841,13 +841,16 @@ struct ucred *td_savedcred = td->td_ucred; struct file *fp = job->fd_file; 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, ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); + fullsync = job->uaiocb.aio_lio_opcode == LIO_SYNC; td->td_ucred = job->cred; if (fp->f_vnode != NULL) - error = aio_fsync_vnode(td, fp->f_vnode); + error = aio_fsync_vnode(td, fp->f_vnode, fullsync); td->td_ucred = td_savedcred; if (error) aio_complete(job, -1, error); @@ -1533,6 +1536,7 @@ error = fget_read(td, fd, &cap_pread_rights, &fp); break; case LIO_SYNC: + case LIO_DSYNC: error = fget(td, fd, &cap_fsync_rights, &fp); break; case LIO_MLOCK: @@ -1550,7 +1554,7 @@ return (error); } - if (opcode == LIO_SYNC && fp->f_vnode == NULL) { + if ((opcode == LIO_SYNC || opcode == LIO_DSYNC) && fp->f_vnode == NULL) { error = EINVAL; goto aqueue_fail; } @@ -1722,6 +1726,7 @@ error = 0; break; case LIO_SYNC: + case LIO_DSYNC: AIO_LOCK(ki); TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { if (job2->fd_file == job->fd_file && @@ -2467,10 +2472,12 @@ kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob, struct aiocb_ops *ops) { + int listop; - if (op != O_SYNC) /* XXX lack of O_DSYNC */ + if (op != O_SYNC && op != O_DSYNC) 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 Index: sys/sys/aio.h =================================================================== --- sys/sys/aio.h +++ sys/sys/aio.h @@ -45,6 +45,7 @@ #ifdef _KERNEL #define LIO_SYNC 0x3 #define LIO_MLOCK 0x4 +#define LIO_DSYNC 0x5 #endif /* Index: sys/sys/fcntl.h =================================================================== --- sys/sys/fcntl.h +++ sys/sys/fcntl.h @@ -138,8 +138,10 @@ #define O_BENEATH 0x00400000 /* Fail if not under cwd */ #endif +#define O_DSYNC 0x00800000 /* POSIX O_DSYNC */ + /* - * XXX missing O_DSYNC, O_RSYNC. + * XXX missing O_RSYNC. */ #ifdef _KERNEL Index: tests/sys/aio/aio_test.c =================================================================== --- tests/sys/aio/aio_test.c +++ tests/sys/aio/aio_test.c @@ -1055,7 +1055,7 @@ ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno)); unlink(FILE_PATHNAME); - /* aio_fsync should return EINVAL unless op is O_SYNC */ + /* aio_fsync should return EINVAL unless op is O_SYNC or O_DSYNC */ memset(&iocb, 0, sizeof(iocb)); iocb.aio_fildes = fd; ATF_CHECK_EQ(-1, aio_fsync(666, &iocb));