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