diff options
author | Thomas Munro <tmunro@FreeBSD.org> | 2021-01-07 11:11:38 +0000 |
---|---|---|
committer | Thomas Munro <tmunro@FreeBSD.org> | 2021-01-08 00:15:56 +0000 |
commit | 801ac943ea0821bbb34c69688a7e7bb126d8cf8d (patch) | |
tree | f8dbf70fce887db9d515c27a03e11f37c883e125 | |
parent | e7347be9e34d05130df878d6af2ff847227610b6 (diff) | |
download | src-801ac943ea0821bbb34c69688a7e7bb126d8cf8d.tar.gz src-801ac943ea0821bbb34c69688a7e7bb126d8cf8d.zip |
aio_fsync(2): Support O_DSYNC.
aio_fsync(O_DSYNC, ...) is the asynchronous version of fdatasync(2).
Reviewed by: kib, asomers, jhb
Differential Review: https://reviews.freebsd.org/D25071
-rw-r--r-- | lib/libc/sys/aio_fsync.2 | 18 | ||||
-rw-r--r-- | sys/kern/vfs_aio.c | 37 | ||||
-rw-r--r-- | sys/sys/aio.h | 1 | ||||
-rw-r--r-- | tests/sys/aio/aio_test.c | 23 |
4 files changed, 61 insertions, 18 deletions
diff --git a/lib/libc/sys/aio_fsync.2 b/lib/libc/sys/aio_fsync.2 index 9d5d143416b3..0ce47edfb33f 100644 --- a/lib/libc/sys/aio_fsync.2 +++ b/lib/libc/sys/aio_fsync.2 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 19, 2016 +.Dd January 6, 2021 .Dt AIO_FSYNC 2 .Os .Sh NAME @@ -49,11 +49,15 @@ completed at the time the call returns. .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 the behavior of +.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 @@ -112,7 +116,9 @@ are unsafe and unsafe asynchronous I/O operations are disabled. A value of the .Fa op argument is not set to -.Dv O_SYNC . +.Dv O_SYNC +or +.Dv O_DSYNC . .El .Pp The following conditions may be synchronously detected when the @@ -176,3 +182,7 @@ The .Fn aio_fsync system call first appeared in .Fx 7.0 . +The +.Dv O_DSYNC +option appeared in +.Fx 13.0 . diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index d83c9d725e68..8666d6ea4217 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -718,10 +718,10 @@ restart: /* * 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, int op) { struct mount *mp; int error; @@ -734,7 +734,10 @@ aio_fsync_vnode(struct thread *td, struct vnode *vp) vm_object_page_clean(vp->v_object, 0, 0, 0); VM_OBJECT_WUNLOCK(vp->v_object); } - error = VOP_FSYNC(vp, MNT_WAIT, td); + if (op == LIO_DSYNC) + error = VOP_FDATASYNC(vp, td); + else + error = VOP_FSYNC(vp, MNT_WAIT, td); VOP_UNLOCK(vp); vn_finished_write(mp); @@ -838,12 +841,15 @@ aio_process_sync(struct kaiocb *job) struct file *fp = job->fd_file; 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)); td->td_ucred = job->cred; - if (fp->f_vnode != NULL) - error = aio_fsync_vnode(td, fp->f_vnode); + if (fp->f_vnode != NULL) { + error = aio_fsync_vnode(td, fp->f_vnode, + job->uaiocb.aio_lio_opcode); + } td->td_ucred = td_savedcred; if (error) aio_complete(job, -1, error); @@ -1579,6 +1585,7 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, 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: @@ -1592,7 +1599,7 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, if (error) goto err3; - if (opcode == LIO_SYNC && fp->f_vnode == NULL) { + if ((opcode == LIO_SYNC || opcode == LIO_DSYNC) && fp->f_vnode == NULL) { error = EINVAL; goto err3; } @@ -1805,10 +1812,12 @@ aio_queue_file(struct file *fp, struct kaiocb *job) 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 && job2->uaiocb.aio_lio_opcode != LIO_SYNC && + job2->uaiocb.aio_lio_opcode != LIO_DSYNC && job2->seqno < job->seqno) { job2->jobflags |= KAIOCB_CHECKSYNC; job->pending++; @@ -2587,10 +2596,20 @@ static int 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 */ + switch (op) { + case O_SYNC: + listop = LIO_SYNC; + break; + case O_DSYNC: + listop = LIO_DSYNC; + break; + default: return (EINVAL); - return (aio_aqueue(td, ujob, NULL, LIO_SYNC, ops)); + } + + return (aio_aqueue(td, ujob, NULL, listop, ops)); } int diff --git a/sys/sys/aio.h b/sys/sys/aio.h index c0e2b4eaaaf6..dbfbadcd1254 100644 --- a/sys/sys/aio.h +++ b/sys/sys/aio.h @@ -48,6 +48,7 @@ #define LIO_MLOCK 0x4 #define LIO_WRITEV 0x5 #define LIO_READV 0x6 +#define LIO_DSYNC 0x7 #endif /* diff --git a/tests/sys/aio/aio_test.c b/tests/sys/aio/aio_test.c index 891892e5e757..f563ec5fa5d9 100644 --- a/tests/sys/aio/aio_test.c +++ b/tests/sys/aio/aio_test.c @@ -1259,7 +1259,7 @@ ATF_TC_BODY(aio_fsync_errors, tc) 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)); @@ -1282,8 +1282,8 @@ ATF_TC_BODY(aio_fsync_errors, tc) /* * This test just performs a basic test of aio_fsync(). */ -ATF_TC_WITHOUT_HEAD(aio_fsync_test); -ATF_TC_BODY(aio_fsync_test, tc) +static void +aio_fsync_test(int op) { struct aiocb synccb, *iocbp; struct { @@ -1328,7 +1328,7 @@ ATF_TC_BODY(aio_fsync_test, tc) /* Queue the aio_fsync request. */ memset(&synccb, 0, sizeof(synccb)); synccb.aio_fildes = fd; - ATF_REQUIRE(aio_fsync(O_SYNC, &synccb) == 0); + ATF_REQUIRE(aio_fsync(op, &synccb) == 0); /* Wait for requests to complete. */ for (;;) { @@ -1359,6 +1359,18 @@ ATF_TC_BODY(aio_fsync_test, tc) close(fd); } +ATF_TC_WITHOUT_HEAD(aio_fsync_sync_test); +ATF_TC_BODY(aio_fsync_sync_test, tc) +{ + aio_fsync_test(O_SYNC); +} + +ATF_TC_WITHOUT_HEAD(aio_fsync_dsync_test); +ATF_TC_BODY(aio_fsync_dsync_test, tc) +{ + aio_fsync_test(O_DSYNC); +} + /* * We shouldn't be able to DoS the system by setting iov_len to an insane * value @@ -1782,7 +1794,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, md_thread); ATF_TP_ADD_TC(tp, md_waitcomplete); ATF_TP_ADD_TC(tp, aio_fsync_errors); - ATF_TP_ADD_TC(tp, aio_fsync_test); + ATF_TP_ADD_TC(tp, aio_fsync_sync_test); + ATF_TP_ADD_TC(tp, aio_fsync_dsync_test); ATF_TP_ADD_TC(tp, aio_large_read_test); ATF_TP_ADD_TC(tp, aio_socket_two_reads); ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write); |