Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add a new function to remove extra buffers when truncati...
details: https://anonhg.NetBSD.org/src/rev/c20d7b8cdf37
branches: trunk
changeset: 486746:c20d7b8cdf37
user: mycroft <mycroft%NetBSD.org@localhost>
date: Sun May 28 04:13:56 2000 +0000
description:
Add a new function to remove extra buffers when truncating a file. This is
more generic than the vinvalbuf(V_SAVEMETA) case, avoiding synchronous
operations when truncating to a non-zero length.
diffstat:
sys/kern/vfs_subr.c | 173 +++++++++++++++++++++++++++--------------
sys/msdosfs/msdosfs_denode.c | 14 +-
sys/sys/vnode.h | 5 +-
sys/ufs/ext2fs/ext2fs_inode.c | 24 +++--
sys/ufs/ffs/ffs_inode.c | 18 ++-
5 files changed, 146 insertions(+), 88 deletions(-)
diffs (truncated from 444 to 300 lines):
diff -r 9ec26ee89693 -r c20d7b8cdf37 sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c Sun May 28 03:42:23 2000 +0000
+++ b/sys/kern/vfs_subr.c Sun May 28 04:13:56 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_subr.c,v 1.125 2000/04/10 02:22:14 chs Exp $ */
+/* $NetBSD: vfs_subr.c,v 1.126 2000/05/28 04:13:56 mycroft Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -596,7 +596,8 @@
/*
* Flush out and invalidate all buffers associated with a vnode.
- * Called with the underlying object locked.
+ * Called with the underlying vnode locked, which should prevent new dirty
+ * buffers from being queued.
*/
int
vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
@@ -606,79 +607,131 @@
struct proc *p;
int slpflag, slptimeo;
{
- struct buf *bp;
- struct buf *nbp, *blist;
+ struct buf *bp, *nbp;
int s, error;
if (flags & V_SAVE) {
+ error = VOP_FSYNC(vp, cred, FSYNC_WAIT|FSYNC_RECLAIM, p);
+ if (error)
+ return (error);
+#ifdef DIAGNOSTIC
s = splbio();
- while (vp->v_numoutput) {
- vp->v_flag |= VBWAIT;
- tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1,
- "vbwait", 0);
- }
- splx(s);
- error = VOP_FSYNC(vp, cred, FSYNC_WAIT|FSYNC_RECLAIM, p);
- if (error != 0)
- return (error);
- s = splbio();
- if (vp->v_numoutput > 0 ||
- vp->v_dirtyblkhd.lh_first != NULL)
+ if (vp->v_numoutput > 0 || !LIST_EMPTY(&vp->v_dirtyblkhd))
panic("vinvalbuf: dirty bufs, vp %p", vp);
splx(s);
+#endif
}
s = splbio();
- for (;;) {
- if ((blist = vp->v_cleanblkhd.lh_first) && (flags & V_SAVEMETA))
- while (blist && blist->b_lblkno < 0)
- blist = blist->b_vnbufs.le_next;
- if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
- (flags & V_SAVEMETA)) {
- while (blist && blist->b_lblkno < 0)
- blist = blist->b_vnbufs.le_next;
+restart:
+ for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
+ nbp = LIST_NEXT(bp, b_vnbufs);
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
+ "vinvalbuf", slptimeo);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ goto restart;
}
- if (!blist)
- break;
+ bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
+ brelse(bp);
+ }
- for (bp = blist; bp; bp = nbp) {
- nbp = bp->b_vnbufs.le_next;
- if (flags & V_SAVEMETA && bp->b_lblkno < 0)
- continue;
- if (bp->b_flags & B_BUSY) {
- bp->b_flags |= B_WANTED;
- error = tsleep((caddr_t)bp,
- slpflag | (PRIBIO + 1), "vinvalbuf",
- slptimeo);
- if (error) {
- splx(s);
- return (error);
- }
- break;
+ for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
+ nbp = LIST_NEXT(bp, b_vnbufs);
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
+ "vinvalbuf", slptimeo);
+ if (error) {
+ splx(s);
+ return (error);
}
+ goto restart;
+ }
+ /*
+ * XXX Since there are no node locks for NFS, I believe
+ * there is a slight chance that a delayed write will
+ * occur while sleeping just above, so check for it.
+ */
+ if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
+#ifdef DEBUG
+ printf("buffer still DELWRI\n");
+#endif
bp->b_flags |= B_BUSY | B_VFLUSH;
- /*
- * XXX Since there are no node locks for NFS, I believe
- * there is a slight chance that a delayed write will
- * occur while sleeping just above, so check for it.
- */
- if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
- VOP_BWRITE(bp);
-#ifdef DEBUG
- printf("buffer still DELWRI\n");
-#endif
- /* VOP_FSYNC(vp, cred, FSYNC_WAIT, p); */
- continue;
- }
- bp->b_flags |= B_INVAL;
- brelse(bp);
+ VOP_BWRITE(bp);
+ goto restart;
}
+ bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
+ brelse(bp);
}
- if (!(flags & V_SAVEMETA) &&
- (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
+#ifdef DIAGNOSTIC
+ if (!LIST_EMPTY(&vp->v_cleanblkhd) || !LIST_EMPTY(&vp->v_dirtyblkhd))
panic("vinvalbuf: flush failed, vp %p", vp);
+#endif
+
+ splx(s);
+
+ return (0);
+}
+
+/*
+ * Destroy any in core blocks past the truncation length.
+ * Called with the underlying vnode locked, which should prevent new dirty
+ * buffers from being queued.
+ */
+int
+vtruncbuf(vp, lbn, slpflag, slptimeo)
+ struct vnode *vp;
+ daddr_t lbn;
+ int slpflag, slptimeo;
+{
+ struct buf *bp, *nbp;
+ int s, error;
+
+ s = splbio();
+
+restart:
+ for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
+ nbp = LIST_NEXT(bp, b_vnbufs);
+ if (bp->b_lblkno < lbn)
+ continue;
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
+ "vtruncbuf", slptimeo);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ goto restart;
+ }
+ bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
+ brelse(bp);
+ }
+
+ for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
+ nbp = LIST_NEXT(bp, b_vnbufs);
+ if (bp->b_lblkno < lbn)
+ continue;
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
+ "vtruncbuf", slptimeo);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ goto restart;
+ }
+ bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
+ brelse(bp);
+ }
splx(s);
@@ -695,8 +748,8 @@
loop:
s = splbio();
- for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
- nbp = bp->b_vnbufs.le_next;
+ for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
+ nbp = LIST_NEXT(bp, b_vnbufs);
if ((bp->b_flags & B_BUSY))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
@@ -722,7 +775,7 @@
tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "vflushbuf", 0);
}
splx(s);
- if (vp->v_dirtyblkhd.lh_first != NULL) {
+ if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
vprint("vflushbuf: dirty", vp);
goto loop;
}
diff -r 9ec26ee89693 -r c20d7b8cdf37 sys/msdosfs/msdosfs_denode.c
--- a/sys/msdosfs/msdosfs_denode.c Sun May 28 03:42:23 2000 +0000
+++ b/sys/msdosfs/msdosfs_denode.c Sun May 28 04:13:56 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: msdosfs_denode.c,v 1.43 2000/05/13 23:43:10 perseant Exp $ */
+/* $NetBSD: msdosfs_denode.c,v 1.44 2000/05/28 04:13:57 mycroft Exp $ */
/*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -349,10 +349,9 @@
{
int error;
int allerror;
- int vflags;
u_long eofentry;
u_long chaintofree;
- daddr_t bn;
+ daddr_t bn, lastblock;
int boff;
int isadir = dep->de_Attributes & ATTR_DIRECTORY;
struct buf *bp;
@@ -380,6 +379,7 @@
if (dep->de_FileSize < length)
return (deextend(dep, length, cred));
+ lastblock = de_clcount(pmp, length) - 1;
/*
* If the desired length is 0 then remember the starting cluster of
@@ -395,8 +395,7 @@
dep->de_StartCluster = 0;
eofentry = ~0;
} else {
- error = pcbmap(dep, de_clcount(pmp, length) - 1, 0,
- &eofentry, 0);
+ error = pcbmap(dep, lastblock, 0, &eofentry, 0);
if (error) {
#ifdef MSDOSFS_DEBUG
printf("detrunc(): pcbmap fails %d\n", error);
@@ -405,7 +404,7 @@
}
}
- fc_purge(dep, de_clcount(pmp, length));
+ fc_purge(dep, lastblock + 1);
/*
* If the new length is not a multiple of the cluster size then we
@@ -447,8 +446,7 @@
dep->de_FileSize = length;
if (!isadir)
dep->de_flag |= DE_UPDATE|DE_MODIFIED;
- vflags = (length > 0 ? V_SAVE : 0) | V_SAVEMETA;
- vinvalbuf(DETOV(dep), vflags, cred, p, 0, 0);
+ vtruncbuf(DETOV(dep), lastblock + 1, 0, 0);
allerror = deupdat(dep, 1);
#ifdef MSDOSFS_DEBUG
printf("detrunc(): allerror %d, eofentry %lu\n",
diff -r 9ec26ee89693 -r c20d7b8cdf37 sys/sys/vnode.h
--- a/sys/sys/vnode.h Sun May 28 03:42:23 2000 +0000
+++ b/sys/sys/vnode.h Sun May 28 04:13:56 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode.h,v 1.75 2000/05/13 23:43:12 perseant Exp $ */
+/* $NetBSD: vnode.h,v 1.76 2000/05/28 04:13:57 mycroft Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -229,7 +229,6 @@
#define WRITECLOSE 0x0004 /* vflush: only close writeable files */
#define DOCLOSE 0x0008 /* vclean: close active files */
#define V_SAVE 0x0001 /* vinvalbuf: sync file first */
-#define V_SAVEMETA 0x0002 /* vinvalbuf: leave indirect blocks */
/*
Home |
Main Index |
Thread Index |
Old Index