git: 801ac943ea08 - main - aio_fsync(2): Support O_DSYNC.

Thomas Munro tmunro at FreeBSD.org
Fri Jan 8 00:16:58 UTC 2021


The branch main has been updated by tmunro:

URL: https://cgit.FreeBSD.org/src/commit/?id=801ac943ea0821bbb34c69688a7e7bb126d8cf8d

commit 801ac943ea0821bbb34c69688a7e7bb126d8cf8d
Author:     Thomas Munro <tmunro at FreeBSD.org>
AuthorDate: 2021-01-07 11:11:38 +0000
Commit:     Thomas Munro <tmunro at FreeBSD.org>
CommitDate: 2021-01-08 00:15:56 +0000

    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
---
 lib/libc/sys/aio_fsync.2 | 18 ++++++++++++++----
 sys/kern/vfs_aio.c       | 37 ++++++++++++++++++++++++++++---------
 sys/sys/aio.h            |  1 +
 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);


More information about the dev-commits-src-all mailing list