diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2 --- a/lib/libc/sys/fcntl.2 +++ b/lib/libc/sys/fcntl.2 @@ -28,7 +28,7 @@ .\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd January 17, 2020 +.Dd January 6, 2021 .Dt FCNTL 2 .Os .Sh NAME @@ -196,7 +196,7 @@ .Dv F_GETFL and .Dv F_SETFL -flags are as follows: +commands are as follows: .Bl -tag -width O_NONBLOCKX .It Dv O_NONBLOCK Non-blocking I/O; if no data is available to a @@ -225,6 +225,21 @@ signal to be sent to the process group when I/O is possible, e.g., upon availability of data to be read. +.It Dv O_SYNC +Enable synchronous writes. +Corresponds to the +.Dv O_SYNC +flag of +.Xr open 2 . +.Dv O_FSYNC +is an historical synonym for +.Dv O_SYNC . +.It Dv O_DSYNC +Enable synchronous data writes. +Corresponds to the +.Dv O_DSYNC +flag of +.Xr open 2 . .El .Pp The seals that may be applied with diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2 --- a/lib/libc/sys/open.2 +++ b/lib/libc/sys/open.2 @@ -181,8 +181,9 @@ O_SHLOCK atomically obtain a shared lock O_EXLOCK atomically obtain an exclusive lock O_DIRECT eliminate or reduce cache effects -O_FSYNC synchronous writes +O_FSYNC synchronous writes (historical synonym for O_SYNC) O_SYNC synchronous writes +O_DSYNC synchronous data writes O_NOFOLLOW do not follow symlinks O_NOCTTY ignored O_TTY_INIT ignored @@ -230,15 +231,18 @@ The descriptor remains in non-blocking mode for subsequent operations. .Pp If -.Dv O_FSYNC +.Dv O_SYNC is used in the mask, all writes will immediately and synchronously be written to disk. -.Pp -.Dv O_SYNC -is a synonym for .Dv O_FSYNC -required by -.Tn POSIX . +is an historical synonym for +.Dv O_SYNC . +.Pp +If +.Dv O_DSYNC +is used in the mask, all data and metadata required to read the data will be +synchronously written to disk, but changes to metadata such as file access and +modification timestamps may be written later. .Pp If .Dv O_NOFOLLOW @@ -651,6 +655,8 @@ .Fn openat function was introduced in .Fx 8.0 . +.Dv O_DSYNC +appeared in 13.0. .Sh BUGS The Open Group Extended API Set 2 specification requires that the test for whether diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h @@ -168,7 +168,6 @@ #define O_LARGEFILE 0 #define O_RSYNC 0 -#define O_DSYNC 0 #ifndef LOCORE #ifndef HAVE_RPC_TYPES diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode.h --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode.h +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode.h @@ -127,7 +127,9 @@ #define FCREAT O_CREAT #define FTRUNC O_TRUNC #define FEXCL O_EXCL +#ifndef FDSYNC #define FDSYNC FFSYNC +#endif #define FRSYNC FFSYNC #define FSYNC FFSYNC #define FOFFMAX 0x00 diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1066,6 +1066,13 @@ if ((fp->f_flag & O_FSYNC) || (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) ioflag |= IO_SYNC; + /* + * For O_DSYNC we set both IO_SYNC and IO_DATASYNC, so that VOP_WRITE() + * implementations that don't understand IO_DATASYNC fall back to full + * O_SYNC behavior. + */ + if (fp->f_flag & O_DSYNC) + ioflag |= IO_SYNC | IO_DATASYNC; mp = NULL; if (vp->v_type != VCHR && (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -141,8 +141,10 @@ return back */ #endif +#define O_DSYNC 0x00800000 /* POSIX data sync */ + /* - * XXX missing O_DSYNC, O_RSYNC. + * XXX missing O_RSYNC. */ #ifdef _KERNEL @@ -158,9 +160,9 @@ #define OFLAGS(fflags) ((fflags) & O_EXEC ? (fflags) : (fflags) - 1) /* bits to save after open */ -#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT|FEXEC) +#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FDSYNC|FNONBLOCK|O_DIRECT|FEXEC) /* bits settable by fcntl(F_SETFL, ...) */ -#define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FRDAHEAD|O_DIRECT) +#define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FDSYNC|FNONBLOCK|FRDAHEAD|O_DIRECT) #if defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD6) || \ defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) @@ -185,15 +187,16 @@ #define FAPPEND O_APPEND /* kernel/compat */ #define FASYNC O_ASYNC /* kernel/compat */ #define FFSYNC O_FSYNC /* kernel */ +#define FDSYNC O_DSYNC /* kernel */ #define FNONBLOCK O_NONBLOCK /* kernel */ #define FNDELAY O_NONBLOCK /* compat */ #define O_NDELAY O_NONBLOCK /* compat */ #endif /* - * We are out of bits in f_flag (which is a short). However, - * the flag bits not set in FMASK are only meaningful in the - * initial open syscall. Those bits can thus be given a + * Historically, we ran out of bits in f_flag (which was once a short). + * However, the flag bits not set in FMASK are only meaningful in the + * initial open syscall. Those bits were thus given a * different meaning for fcntl(2). */ #if __BSD_VISIBLE diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -326,6 +326,7 @@ #define IO_NOMACCHECK 0x1000 /* MAC checks unnecessary */ #define IO_BUFLOCKED 0x2000 /* ffs flag; indir buf is locked */ #define IO_RANGELOCKED 0x4000 /* range locked */ +#define IO_DATASYNC 0x8000 /* do only data I/O synchronously */ #define IO_SEQMAX 0x7F /* seq heuristic max value */ #define IO_SEQSHIFT 16 /* seq heuristic in upper 16 bits */