Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/lfs lfs_truncate calls vinvalbuf to invalidate all c...
details: https://anonhg.NetBSD.org/src/rev/271124c36d19
branches: trunk
changeset: 467820:271124c36d19
user: perseant <perseant%NetBSD.org@localhost>
date: Mon Mar 29 21:51:38 1999 +0000
description:
lfs_truncate calls vinvalbuf to invalidate all currently-hald buffers, which
in turn forces a flush of the vnode, whether or not it is involved in a dirop.
(This can happen during a remove or rmdir, when the directory is shrunk.)
Because of the nature of dirops, however, flushing a vnode involved in a dirop
is disallowed (and was marked with a panic). This patch has lfs_truncate
call a specialized vinvalbuf that only invalidates buffers following the new
end-of-file, and thus does not require a flush. Also the panic is demoted,
in case I missed any other path to lfs_vflush.
diffstat:
sys/ufs/lfs/lfs_inode.c | 68 ++++++++++++++++++++++++++++++++++++++++++++--
sys/ufs/lfs/lfs_segment.c | 6 ++-
2 files changed, 69 insertions(+), 5 deletions(-)
diffs (114 lines):
diff -r 49032b0aff4f -r 271124c36d19 sys/ufs/lfs/lfs_inode.c
--- a/sys/ufs/lfs/lfs_inode.c Mon Mar 29 21:51:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_inode.c Mon Mar 29 21:51:38 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_inode.c,v 1.20 1999/03/25 21:39:18 perseant Exp $ */
+/* $NetBSD: lfs_inode.c,v 1.21 1999/03/29 21:51:38 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -94,6 +94,8 @@
#include <ufs/lfs/lfs.h>
#include <ufs/lfs/lfs_extern.h>
+static int lfs_vinvalbuf __P((struct vnode *, struct ucred *, struct proc *, ufs_daddr_t));
+
/* Search a block for a specific dinode. */
struct dinode *
lfs_ifind(fs, ino, dip)
@@ -439,8 +441,10 @@
}
#endif
fs->lfs_avail += fragstodb(fs, a_released);
- e1 = vinvalbuf(vp, (length > 0) ? V_SAVE : 0, ap->a_cred, ap->a_p,
- 0, 0);
+ if(length>0)
+ e1 = lfs_vinvalbuf(vp, ap->a_cred, ap->a_p, lastblock);
+ else
+ e1 = vinvalbuf(vp, 0, ap->a_cred, ap->a_p, 0, 0);
e2 = VOP_UPDATE(vp, NULL, NULL, 0);
if(e1)
printf("lfs_truncate: vinvalbuf: %d\n",e1);
@@ -449,3 +453,61 @@
return (e1 ? e1 : e2 ? e2 : 0);
}
+
+/*
+ * Get rid of blocks a la vinvalbuf; but only blocks that are of a higher
+ * lblkno than the file size allows.
+ */
+int
+lfs_vinvalbuf(vp, cred, p, maxblk)
+ register struct vnode *vp;
+ struct ucred *cred;
+ struct proc *p;
+ ufs_daddr_t maxblk;
+{
+ register struct buf *bp;
+ struct buf *nbp, *blist;
+ int i, s, error;
+
+ for (i=0;i<2;i++) {
+ if(i==0)
+ blist = vp->v_cleanblkhd.lh_first;
+ else /* i == 1 */
+ blist = vp->v_dirtyblkhd.lh_first;
+
+ for (bp = blist; bp; bp = nbp) {
+ nbp = bp->b_vnbufs.le_next;
+ s = splbio();
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ error = tsleep((caddr_t)bp,
+ (PRIBIO + 1), "lfs_vinval", 0);
+ splx(s);
+ if (error)
+ return (error);
+ break;
+ }
+ /*
+ * Don't touch gathered buffers; and certainly don't
+ * mark cleaner buffers B_INVAL, since that would
+ * change them to "fake buffers".
+ *
+ * But get rid of anything else that's past the new
+ * last block.
+ */
+ bp->b_flags |= B_BUSY;
+ splx(s);
+ if((bp->b_lblkno >= 0 && bp->b_lblkno > maxblk)
+ || (bp->b_lblkno < 0 && bp->b_lblkno < -maxblk-NIADDR))
+ {
+ if(!(bp->b_flags & (B_GATHERED|B_CALL)))
+ bp->b_flags |= B_INVAL;
+ }
+ if(bp->b_flags & B_CALL)
+ bp->b_flags &= ~B_BUSY;
+ else
+ brelse(bp);
+ }
+ }
+ return (0);
+}
diff -r 49032b0aff4f -r 271124c36d19 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Mon Mar 29 21:51:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Mon Mar 29 21:51:38 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_segment.c,v 1.20 1999/03/25 22:38:28 perseant Exp $ */
+/* $NetBSD: lfs_segment.c,v 1.21 1999/03/29 21:51:38 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -237,8 +237,10 @@
}
#ifdef DIAGNOSTIC
+ /* XXX KS This actually can happen right now, though it shouldn't(?) */
if(vp->v_flag & VDIROP) {
- panic("VDIROP being freed...this can\'t happen");
+ printf("lfs_vflush: flushing VDIROP, this shouldn\'t be\n");
+ /* panic("VDIROP being flushed...this can\'t happen"); */
}
if(vp->v_usecount<0) {
printf("usecount=%d\n",vp->v_usecount);
Home |
Main Index |
Thread Index |
Old Index