Subject: Re: Extension of fsync_range() to permit forcing disk cache flushing
To: Jason Thorpe <thorpej@shagadelic.org>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 12/16/2004 16:59:00
--NqNl6FRZtoRUn5bW
Content-Type: multipart/mixed; boundary="dwWFXG4JqVa0wfCP"
Content-Disposition: inline
--dwWFXG4JqVa0wfCP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
This time with the diff...
Take care,
Bill
--dwWFXG4JqVa0wfCP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fsync.diffie"
Content-Transfer-Encoding: quoted-printable
Index: lib/libc/sys/fsync.2
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/lib/libc/sys/fsync.2,v
retrieving revision 1.15
diff -u -u -r1.15 fsync.2
--- lib/libc/sys/fsync.2 18 Nov 2003 08:49:18 -0000 1.15
+++ lib/libc/sys/fsync.2 16 Dec 2004 22:00:46 -0000
@@ -79,6 +79,8 @@
data for the specified range.
.It Dv FFILESYNC
Synchronize all modified file data and meta-data for the specified range.
+.It Dv FDISKSYNC
+Force the requested synchronization to permanent storage.
.El
.Pp
If the
@@ -86,6 +88,36 @@
parameter is zero,
.Fn fsync_range
will synchronize all of the file data.
+.Pp
+Passing the
+.Dv FDISKSYNC
+flag to
+.Fn fsync_range
+will trigger synchronization of the data, both file data and relevant
+meta-data, to permanent storage.
+Without this flag (and for all cases for
+.Fn fsync ) ,
+the call may return when the write commands have completed.
+The difference arises if the backing disk has an enabled write-back
+cache.
+In the presence of a write-back disk cache, the=20
+.Dv FDISKSYNC
+flag permits an application to enforce its own policy regarding which
+writes need to have reached permanent storage, or if it is sufficient
+for the disk to report the write has been completed.
+.Pp
+The exact write cache synchronization policy triggered by the=20
+.Dv FDISKSYNC=20
+flag is implementation dependent.
+An implementation may issue write cache synchronization commands to flush
+only the file data and relevant meta-data from the disk cache, or an
+implementation may flush the write cache in its entirety.
+An implementation may support both behaviors, and use its own policy to
+choose between them.
+Different file systems on the same host may implement this flag differentl=
y.
+Flusshing the cache in its entirety may have a performance impact as
+data unrelated to the file being synchronized will be written to permanent
+storage.
.Sh RETURN VALUES
A 0 value is returned on success.
A \-1 value indicates an error.
Index: sys/kern/vfs_syscalls.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.213
diff -u -u -r1.213 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c 30 Nov 2004 04:25:44 -0000 1.213
+++ sys/kern/vfs_syscalls.c 16 Dec 2004 22:01:15 -0000
@@ -3022,7 +3022,7 @@
error =3D VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0, p);
if (error =3D=3D 0 && bioops.io_fsync !=3D NULL &&
vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
- (*bioops.io_fsync)(vp);
+ (*bioops.io_fsync)(vp, 0);
VOP_UNLOCK(vp, 0);
vn_finished_write(mp, 0);
FILE_UNUSE(fp, p);
@@ -3075,6 +3075,8 @@
nflags =3D FSYNC_DATAONLY | FSYNC_WAIT;
else
nflags =3D FSYNC_WAIT;
+ if (flags & FDISKSYNC)
+ nflags |=3D FSYNC_CACHE;
=20
len =3D SCARG(uap, length);
/* If length =3D=3D 0, we do the whole file, and s =3D l =3D 0 will do th=
at */
@@ -3096,7 +3098,7 @@
=20
if (error =3D=3D 0 && bioops.io_fsync !=3D NULL &&
vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
- (*bioops.io_fsync)(vp);
+ (*bioops.io_fsync)(vp, nflags);
=20
VOP_UNLOCK(vp, 0);
FILE_UNUSE(fp, p);
Index: sys/miscfs/genfs/genfs_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v
retrieving revision 1.91
diff -u -u -r1.91 genfs_vnops.c
--- sys/miscfs/genfs/genfs_vnops.c 4 Oct 2004 00:28:30 -0000 1.91
+++ sys/miscfs/genfs/genfs_vnops.c 16 Dec 2004 22:01:18 -0000
@@ -97,15 +97,26 @@
off_t offhi;
struct proc *a_p;
} */ *ap =3D v;
- struct vnode *vp =3D ap->a_vp;
+ struct vnode *vp =3D ap->a_vp, *dvp;
int wait;
+ int error;
=20
wait =3D (ap->a_flags & FSYNC_WAIT) !=3D 0;
vflushbuf(vp, wait);
if ((ap->a_flags & FSYNC_DATAONLY) !=3D 0)
- return (0);
+ error =3D 0;
else
- return (VOP_UPDATE(vp, NULL, NULL, wait ? UPDATE_WAIT : 0));
+ error =3D VOP_UPDATE(vp, NULL, NULL, wait ? UPDATE_WAIT : 0);
+ if (error =3D=3D 0 && ap->a_flags & FSYNC_CACHE) {
+ int l =3D 0;
+ if (VOP_BMAP(vp, 0, &dvp, NULL, NULL))
+ error =3D ENXIO;
+ else
+ error =3D VOP_IOCTL(dvp, DIOCCACHESYNC, &l, FWRITE,
+ ap->a_p->p_ucred, ap->a_p);
+ }
+
+ return (error);
}
=20
int
Index: sys/sys/buf.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/sys/buf.h,v
retrieving revision 1.77
diff -u -u -r1.77 buf.h
--- sys/sys/buf.h 28 Oct 2004 07:07:46 -0000 1.77
+++ sys/sys/buf.h 16 Dec 2004 22:01:19 -0000
@@ -102,7 +102,7 @@
void (*io_start)(struct buf *);
void (*io_complete)(struct buf *);
void (*io_deallocate)(struct buf *);
- int (*io_fsync)(struct vnode *);
+ int (*io_fsync)(struct vnode *, int);
int (*io_sync)(struct mount *);
void (*io_movedeps)(struct buf *, struct buf *);
int (*io_countdeps)(struct buf *, int);
Index: sys/sys/unistd.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/sys/unistd.h,v
retrieving revision 1.31
diff -u -u -r1.31 unistd.h
--- sys/sys/unistd.h 10 Nov 2004 04:02:52 -0000 1.31
+++ sys/sys/unistd.h 16 Dec 2004 22:01:19 -0000
@@ -123,6 +123,7 @@
*/
#define FDATASYNC 0x0010 /* sync data and minimal metadata */
#define FFILESYNC 0x0020 /* sync data and metadata */
+#define FDISKSYNC 0x0040 /* flush disk caches after sync */
#endif
=20
/* configurable pathname variables; use as argument to pathconf(3) */
Index: sys/sys/vnode.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/sys/vnode.h,v
retrieving revision 1.127
diff -u -u -r1.127 vnode.h
--- sys/sys/vnode.h 10 Nov 2004 17:30:56 -0000 1.127
+++ sys/sys/vnode.h 16 Dec 2004 22:01:20 -0000
@@ -272,6 +272,7 @@
#define FSYNC_DATAONLY 0x0002 /* fsync: hint: sync file data only */
#define FSYNC_RECLAIM 0x0004 /* fsync: hint: vnode is being reclaimed */
#define FSYNC_LAZY 0x0008 /* fsync: lazy sync (trickle) */
+#define FSYNC_CACHE 0x0100 /* fsync: flush disk caches too */
=20
#define UPDATE_WAIT 0x0001 /* update: wait for completion */
#define UPDATE_DIROP 0x0002 /* update: hint to fs to wait or not */
Index: sys/ufs/ffs/ffs_softdep.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_softdep.c,v
retrieving revision 1.60
diff -u -u -r1.60 ffs_softdep.c
--- sys/ufs/ffs/ffs_softdep.c 29 Aug 2004 10:13:48 -0000 1.60
+++ sys/ufs/ffs/ffs_softdep.c 16 Dec 2004 22:01:25 -0000
@@ -38,6 +38,7 @@
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/callout.h>
+#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mount.h>
@@ -202,7 +203,7 @@
static void softdep_disk_io_initiation __P((struct buf *));
static void softdep_disk_write_complete __P((struct buf *));
static void softdep_deallocate_dependencies __P((struct buf *));
-static int softdep_fsync __P((struct vnode *));
+static int softdep_fsync __P((struct vnode *, int));
static int softdep_process_worklist __P((struct mount *));
static void softdep_move_dependencies __P((struct buf *, struct buf *));
static int softdep_count_dependencies __P((struct buf *bp, int));
@@ -4663,8 +4664,9 @@
* entries for the inode have been written after the inode gets to disk.
*/
static int
-softdep_fsync(vp)
+softdep_fsync(vp, f)
struct vnode *vp; /* the "in_core" copy of the inode */
+ int f; /* Flags */
{
struct diradd *dap;
struct inodedep *inodedep;
@@ -4679,6 +4681,7 @@
int error, flushparent;
ino_t parentino;
daddr_t lbn;
+ int l;
=20
ip =3D VTOI(vp);
fs =3D ip->i_fs;
@@ -4777,6 +4780,14 @@
break;
}
FREE_LOCK(&lk);
+ if (f & FSYNC_CACHE) {
+ /*
+ * If requested, make sure all of these changes don't
+ * linger in disk caches
+ */
+ l =3D 0;
+ VOP_IOCTL(ip->i_devvp, DIOCCACHESYNC, &l, FWRITE, p->p_ucred, p);
+ }
return (0);
}
=20
Index: sys/ufs/ffs/ffs_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.66
diff -u -u -r1.66 ffs_vnops.c
--- sys/ufs/ffs/ffs_vnops.c 15 Nov 2003 01:19:38 -0000 1.66
+++ sys/ufs/ffs/ffs_vnops.c 16 Dec 2004 22:01:25 -0000
@@ -317,9 +317,17 @@
}
splx(s);
=20
- return (VOP_UPDATE(vp, NULL, NULL,
+ error =3D VOP_UPDATE(vp, NULL, NULL,
((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) =3D=3D FSYNC_WAIT)
- ? UPDATE_WAIT : 0));
+ ? UPDATE_WAIT : 0);
+
+ if (error =3D=3D 0 && ap->a_flags & FSYNC_CACHE) {
+ int l =3D 0;
+ error =3D VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE,
+ ap->a_p->p_ucred, ap->a_p);
+ }
+
+ return error;
}
=20
/*
@@ -451,7 +459,15 @@
waitfor =3D 0;
else
waitfor =3D (ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0;
- return (VOP_UPDATE(vp, NULL, NULL, waitfor));
+ error =3D VOP_UPDATE(vp, NULL, NULL, waitfor);
+
+ if (error =3D=3D 0 && ap->a_flags & FSYNC_WAIT) {
+ long i =3D 0;
+ VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE,
+ ap->a_p->p_ucred, ap->a_p);
+ }
+
+ return error;
}
=20
/*
Index: sys/ufs/lfs/lfs_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v
retrieving revision 1.132
diff -u -u -r1.132 lfs_vnops.c
--- sys/ufs/lfs/lfs_vnops.c 22 Apr 2004 10:45:00 -0000 1.132
+++ sys/ufs/lfs/lfs_vnops.c 16 Dec 2004 22:01:26 -0000
@@ -317,6 +317,11 @@
if (error)
return error;
error =3D VOP_UPDATE(vp, NULL, NULL, wait ? UPDATE_WAIT : 0);
+ if (error =3D=3D 0 && ap->a_flags & FSYNC_CACHE) {
+ int l =3D 0;
+ error =3D VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE,
+ ap->a_p->p_ucred, ap->a_p);
+ }
if (wait && !VPISEMPTY(vp))
LFS_SET_UINO(VTOI(vp), IN_MODIFIED);
=20
--dwWFXG4JqVa0wfCP--
--NqNl6FRZtoRUn5bW
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (NetBSD)
iD8DBQFBwi9UWz+3JHUci9cRAi6HAJ0ULctwsYjaULC2bVniP2hiVE/augCfTfch
0vqwzvESa5ayRi1Hnbq6wCY=
=fZbH
-----END PGP SIGNATURE-----
--NqNl6FRZtoRUn5bW--