Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/lfs Fixes to make dirops and lfs_vflush play togethe...



details:   https://anonhg.NetBSD.org/src/rev/c2f674fb52e5
branches:  trunk
changeset: 467553:c2f674fb52e5
user:      perseant <perseant%NetBSD.org@localhost>
date:      Thu Mar 25 22:26:52 1999 +0000

description:
Fixes to make dirops and lfs_vflush play together well.  In particular,
if we are short on vnodes, lfs_vflush from another process can grab a
vnode that lfs_markv has already processed but not yet written; but
lfs_markv holds the seglock.  When lfs_vflush gets around to writing it,
the context for copyin is gone.  So, now lfs_markv calls copyin itself,
rather than having lfs_writeseg do it.

diffstat:

 sys/ufs/lfs/lfs_bio.c      |   7 ++--
 sys/ufs/lfs/lfs_segment.c  |  69 ++++++++++++++++++++++++---------------------
 sys/ufs/lfs/lfs_syscalls.c |  25 ++++++++--------
 3 files changed, 54 insertions(+), 47 deletions(-)

diffs (201 lines):

diff -r 48c03d94e0cb -r c2f674fb52e5 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Thu Mar 25 22:21:09 1999 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Thu Mar 25 22:26:52 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.8 1999/03/25 21:39:18 perseant Exp $     */
+/*     $NetBSD: lfs_bio.c,v 1.9 1999/03/25 22:26:52 perseant Exp $     */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -228,7 +228,7 @@
                }
                
                ip = VTOI(bp->b_vp);
-               if ((bp->b_flags & (B_CALL|B_INVAL)) == (B_CALL|B_INVAL))
+               if (bp->b_flags & B_CALL)
                {
                        if(!(ip->i_flag & IN_CLEANING))
                                ++fs->lfs_uinodes;
@@ -256,9 +256,10 @@
                s = splbio();
                reassignbuf(bp, bp->b_vp);
                splx(s);
+
        }
        
-       if((bp->b_flags & (B_CALL|B_INVAL)) == (B_CALL|B_INVAL))
+       if(bp->b_flags & B_CALL)
                bp->b_flags &= ~B_BUSY;
        else
                brelse(bp);
diff -r 48c03d94e0cb -r c2f674fb52e5 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Thu Mar 25 22:21:09 1999 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Thu Mar 25 22:26:52 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.18 1999/03/25 22:02:36 perseant Exp $        */
+/*     $NetBSD: lfs_segment.c,v 1.19 1999/03/25 22:26:52 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -186,7 +186,25 @@
        struct lfs *fs;
        struct segment *sp;
        int error;
-       struct buf *bp;
+
+       if(ip->i_flag & IN_CLEANING) {
+#ifdef DEBUG_LFS
+               ivndebug(vp,"vflush/in_cleaning");
+#endif
+               ip->i_flag &= ~IN_CLEANING;
+               if(ip->i_flag & IN_MODIFIED) {
+                       fs->lfs_uinodes--;
+               } else
+                       ip->i_flag |= IN_MODIFIED;
+       }
+
+       /* If the node is being written, wait until that is done */
+       if(WRITEINPROG(vp)) {
+#ifdef DEBUG_LFS
+               ivndebug(vp,"vflush/writeinprog");
+#endif
+               tsleep(vp, PRIBIO+1, "lfs_vw", 0);
+       }
 
        /* Protect against VXLOCK deadlock in vinvalbuf() */
        fs = VFSTOUFS(vp->v_mount)->um_lfs;
@@ -203,44 +221,29 @@
        ip = VTOI(vp);
        if (vp->v_dirtyblkhd.lh_first == NULL) {
                lfs_writevnodes(fs, vp->v_mount, sp, VN_EMPTY);
+       } else if((ip->i_flag & IN_CLEANING) && (fs->lfs_sp->seg_flags & SEGM_CLEAN)) {
+#ifdef DEBUG_LFS
+               ivndebug(vp,"vflush/clean");
+#endif
+               lfs_writevnodes(fs, vp->v_mount, sp, VN_CLEAN);
        }
        else if(lfs_dostats) {
                if(vp->v_dirtyblkhd.lh_first || (VTOI(vp)->i_flag & (IN_MODIFIED|IN_UPDATE|IN_ACCESS|IN_CHANGE|IN_CLEANING)))
                        ++lfs_stats.vflush_invoked;
 #ifdef DEBUG_LFS
-               printf("V");
+               ivndebug(vp,"vflush");
 #endif
        }
 
-       /* XXX KS - can this ever happen?  I think so.... */
-       if(ip->i_flag & IN_CLEANING) {
-#ifdef DEBUG_LFS
-               printf("C");
+#ifdef DIAGNOSTIC
+       if(vp->v_flag & VDIROP) {
+               panic("VDIROP being freed...this can\'t happen");
+       }
+       if(vp->v_usecount<0) {
+               printf("usecount=%d\n",vp->v_usecount);
+               panic("lfs_vflush: usecount<0");
+       }
 #endif
-               ip->i_flag &= ~IN_CLEANING;
-               /*
-                * XXX Copyin all of the fake buffers *now* to avoid
-                * a later panic; and take off B_INVAL.
-                */
-               for(bp=vp->v_dirtyblkhd.lh_first; bp; bp=bp->b_vnbufs.le_next) {
-                       if((bp->b_flags & (B_CALL|B_INVAL))==(B_CALL|B_INVAL)) {
-                               bp->b_data = malloc(bp->b_bufsize, M_SEGMENT, M_WAITOK);
-                               copyin(bp->b_saveaddr, bp->b_data, bp->b_bcount);
-                               bp->b_flags &= ~B_INVAL;
-                       }
-               }
-
-               if(ip->i_flag & IN_MODIFIED) {
-                       fs->lfs_uinodes--;
-#ifdef DEBUG_LFS
-                       if((int32_t)fs->lfs_uinodes<0) {
-                               printf("U4");
-                               fs->lfs_uinodes=0;
-                       }
-#endif
-               } else
-                       ip->i_flag |= IN_MODIFIED;
-       }
 
        do {
                do {
@@ -1248,6 +1251,8 @@
                                bp->b_flags &= ~B_NEEDCOMMIT;
                                wakeup(bp);
                        }
+                       /* if(vn->v_dirtyblkhd.lh_first == NULL) */
+                               wakeup(vn);
                        bpp++;
                }
                ++cbp->b_vp->v_numoutput;
@@ -1347,7 +1352,7 @@
        struct lfs *fs;
        struct buf *bp;
 {
-       return (bp->b_flags & (B_CALL|B_INVAL))==(B_CALL|B_INVAL);
+       return (bp->b_flags & B_CALL);
 }
 
 int
diff -r 48c03d94e0cb -r c2f674fb52e5 sys/ufs/lfs/lfs_syscalls.c
--- a/sys/ufs/lfs/lfs_syscalls.c        Thu Mar 25 22:21:09 1999 +0000
+++ b/sys/ufs/lfs/lfs_syscalls.c        Thu Mar 25 22:26:52 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_syscalls.c,v 1.24 1999/03/25 21:54:10 perseant Exp $       */
+/*     $NetBSD: lfs_syscalls.c,v 1.25 1999/03/25 22:26:52 perseant Exp $       */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -101,7 +101,6 @@
 int clean_vnlocked = 0;
 int clean_inlocked = 0;
 int verbose_debug = 0;
-int lfs_clean_vnhead = 1;
     
 pid_t lfs_cleaner_pid = 0;
 
@@ -649,7 +648,7 @@
                                        v_daddr = LFS_UNUSED_DADDR;
                                        need_unlock = 0;
 #ifdef DEBUG_LFS
-                                       printf("lfs_bmapv: vget of ino %d failed with %d)",blkp->bi_inode,error);
+                                       printf("lfs_bmapv: vget of ino %d failed with %d",blkp->bi_inode,error);
 #endif
                                        continue;
                                } else {
@@ -1037,20 +1036,22 @@
        caddr_t uaddr;
 {
        struct buf *bp;
+       int error;
        
-#ifdef DEBUG
-       /* Check for duplicates too */
-       if(incore(vp,lbn)) {
-               printf("Fake buffer (%d/%d) is in core\n", VTOI(vp)->i_number,
-                      lbn);
-               if(bread(vp, lbn, size, NOCRED, &bp))
-                       return NULL;
+#ifndef ALLOW_VFLUSH_CORRUPTION
+       bp = lfs_newbuf(vp, lbn, size);
+       error = copyin(uaddr, bp->b_data, size);
+       if(error) {
+               lfs_freebuf(bp);
+               return NULL;
        }
-#endif
+#else
        bp = lfs_newbuf(vp, lbn, 0);
+       bp->b_flags |= B_INVAL;
        bp->b_saveaddr = uaddr;
+#endif
+
        bp->b_bufsize = size;
        bp->b_bcount = size;
-       bp->b_flags |= B_INVAL;
        return (bp);
 }



Home | Main Index | Thread Index | Old Index