summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrigoriy Orlov <gluk@cvs.openbsd.org>2001-09-10 08:48:43 +0000
committerGrigoriy Orlov <gluk@cvs.openbsd.org>2001-09-10 08:48:43 +0000
commit60d5f3573fef0e8bd3308dd339a5de6195fbb33a (patch)
tree8a3d4536794f8f4d7b68b6bebc88a9da2f83c09d
parent3d8a07c4d7807081d3e435f655dfe9d5b86f697a (diff)
Mark buffers with dependencies as B_DEFERRED and skip them one time
when doing sync. From FreeBSD. art@ ok.
-rw-r--r--sys/sys/buf.h3
-rw-r--r--sys/ufs/ffs/ffs_vnops.c18
2 files changed, 19 insertions, 2 deletions
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 5aa361e7563..1bd2c267cef 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: buf.h,v 1.26 2001/08/30 12:41:14 gluk Exp $ */
+/* $OpenBSD: buf.h,v 1.27 2001/09/10 08:48:42 gluk Exp $ */
/* $NetBSD: buf.h,v 1.25 1997/04/09 21:12:17 mycroft Exp $ */
/*
@@ -150,6 +150,7 @@ struct buf {
#define B_XXX 0x02000000 /* Debugging flag. */
#define B_VFLUSH 0x04000000 /* Buffer is being synced. */
#define B_SCANNED 0x08000000 /* Block already pushed during sync */
+#define B_DEFERRED 0x10000000 /* Skipped over for cleaning */
/*
* This structure describes a clustered I/O. It is stored in the b_saveaddr
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 3dac84c2203..dae8b5c9528 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vnops.c,v 1.18 2001/06/27 04:58:48 art Exp $ */
+/* $OpenBSD: ffs_vnops.c,v 1.19 2001/09/10 08:48:42 gluk Exp $ */
/* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */
/*
@@ -251,12 +251,28 @@ loop:
bp->b_flags &= ~B_SCANNED;
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
nbp = LIST_NEXT(bp, b_vnbufs);
+ /*
+ * Reasons to skip this buffer: it has already been considered
+ * on this pass, this pass is the first time through on a
+ * synchronous flush request and the buffer being considered
+ * is metadata, the buffer has dependencies that will cause
+ * it to be redirtied and it has not already been deferred,
+ * or it is already being written.
+ */
if (bp->b_flags & (B_BUSY | B_SCANNED))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("ffs_fsync: not dirty");
if (skipmeta && bp->b_lblkno < 0)
continue;
+ if (ap->a_waitfor != MNT_WAIT &&
+ LIST_FIRST(&bp->b_dep) != NULL &&
+ (bp->b_flags & B_DEFERRED) == 0 &&
+ buf_countdeps(bp, 0, 1)) {
+ bp->b_flags |= B_DEFERRED;
+ continue;
+ }
+
bremfree(bp);
bp->b_flags |= B_BUSY | B_SCANNED;
splx(s);