Source-Changes-HG archive

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

[src/netbsd-1-4]: src/sys/ufs/lfs Pull up revision 1.38 (requested by perseant):



details:   https://anonhg.NetBSD.org/src/rev/dc34c9522028
branches:  netbsd-1-4
changeset: 470058:dc34c9522028
user:      he <he%NetBSD.org@localhost>
date:      Sat Jan 15 18:01:45 2000 +0000

description:
Pull up revision 1.38 (requested by perseant):
  Handle flushing a vnode during cleaning, and cleaning the Ifile,
  more correctly, avoiding possible disk corruption in some cases.

diffstat:

 sys/ufs/lfs/lfs_segment.c |  82 +++++++++++++++++++++++++++++++---------------
 1 files changed, 55 insertions(+), 27 deletions(-)

diffs (141 lines):

diff -r ade81a5ffdc1 -r dc34c9522028 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat Jan 15 17:55:34 2000 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat Jan 15 18:01:45 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.23.2.8 2000/01/15 17:51:34 he Exp $  */
+/*     $NetBSD: lfs_segment.c,v 1.23.2.9 2000/01/15 18:01:45 he Exp $  */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -188,7 +188,7 @@
        struct inode *ip;
        struct lfs *fs;
        struct segment *sp;
-       struct buf *bp, *nbp;
+       struct buf *bp, *nbp, *tbp, *tnbp;
        int error, s;
 
        ip = VTOI(vp);
@@ -203,6 +203,28 @@
                        fs->lfs_uinodes--;
                } else
                        ip->i_flag |= IN_MODIFIED;
+               /*
+                * Toss any cleaning buffers that have real counterparts
+                * to avoid losing new data
+                */
+               s = splbio();
+               for(bp=vp->v_dirtyblkhd.lh_first; bp; bp=nbp) {
+                       nbp = bp->b_vnbufs.le_next;
+                       if(bp->b_flags & B_CALL) {
+                               for(tbp=vp->v_dirtyblkhd.lh_first; tbp;
+                                   tbp=tnbp)
+                               {
+                                       tnbp = tbp->b_vnbufs.le_next;
+                                       if(tbp->b_vp == bp->b_vp
+                                          && tbp->b_lblkno == bp->b_lblkno
+                                          && tbp != bp)
+                                       {
+                                               lfs_freebuf(bp);
+                                       }
+                               }
+                       }
+               }
+               splx(s);
        }
 
        /* If the node is being written, wait until that is done */
@@ -364,6 +386,7 @@
                }
 
                if(op == VN_CLEAN && ip->i_number != LFS_IFILE_INUM
+                  && vp != fs->lfs_flushvp
                   && !(ip->i_flag & IN_CLEANING)) {
                        vndebug(vp,"cleaning");
                        continue;
@@ -491,24 +514,24 @@
         * If we're cleaning we only write cleaning and ifile blocks, and
         * no dirops, since otherwise we'd risk corruption in a crash.
         */
-       if(fs->lfs_flushvp)
-               lfs_writevnodes(fs, mp, sp, VN_REG);
-       else if(sp->seg_flags & SEGM_CLEAN)
+       if(sp->seg_flags & SEGM_CLEAN)
                lfs_writevnodes(fs, mp, sp, VN_CLEAN);
        else {
                lfs_writevnodes(fs, mp, sp, VN_REG);
-               while(fs->lfs_dirops)
-                       if((error = tsleep(&fs->lfs_writer, PRIBIO + 1,
-                                       "lfs writer", 0)))
-                       {
-                               free(sp->bpp, M_SEGMENT);
-                               free(sp, M_SEGMENT); 
-                               return (error);
-                       }
-               fs->lfs_writer++;
-               writer_set=1;
-               lfs_writevnodes(fs, mp, sp, VN_DIROP);
-               ((SEGSUM *)(sp->segsum))->ss_flags &= ~(SS_CONT);
+               if(!fs->lfs_dirops || !fs->lfs_flushvp) {
+                       while(fs->lfs_dirops)
+                               if((error = tsleep(&fs->lfs_writer, PRIBIO + 1,
+                                               "lfs writer", 0)))
+                               {
+                                       free(sp->bpp, M_SEGMENT);
+                                       free(sp, M_SEGMENT); 
+                                       return (error);
+                               }
+                       fs->lfs_writer++;
+                       writer_set=1;
+                       lfs_writevnodes(fs, mp, sp, VN_DIROP);
+                       ((SEGSUM *)(sp->segsum))->ss_flags &= ~(SS_CONT);
+               }
        }       
 
        /*
@@ -617,6 +640,21 @@
        fip->fi_version = ifp->if_version;
        brelse(bp);
        
+       if(sp->seg_flags & SEGM_CLEAN)
+       {
+               lfs_gather(fs, sp, vp, lfs_match_fake);
+               /*
+                * For a file being flushed, we need to write *all* blocks.
+                * This means writing the cleaning blocks first, and then
+                * immediately following with any non-cleaning blocks.
+                * The same is true of the Ifile since checkpoints assume
+                * that all valid Ifile blocks are written.
+                */
+               if(IS_FLUSHING(fs,vp) || VTOI(vp)->i_number == LFS_IFILE_INUM)
+                       lfs_gather(fs, sp, vp, lfs_match_data);
+       } else
+               lfs_gather(fs, sp, vp, lfs_match_data);
+
        /*
         * It may not be necessary to write the meta-data blocks at this point,
         * as the roll-forward recovery code should be able to reconstruct the
@@ -626,23 +664,13 @@
         * vnode is being flushed (for reuse by vinvalbuf); or (2) we are
         * checkpointing.
         */
-       if((sp->seg_flags & SEGM_CLEAN)
-          && VTOI(vp)->i_number != LFS_IFILE_INUM
-          && !IS_FLUSHING(fs,vp))
-       {
-               lfs_gather(fs, sp, vp, lfs_match_fake);
-       } else
-               lfs_gather(fs, sp, vp, lfs_match_data);
-
        if(lfs_writeindir
           || IS_FLUSHING(fs,vp)
           || (sp->seg_flags & SEGM_CKP))
        {
                lfs_gather(fs, sp, vp, lfs_match_indir);
                lfs_gather(fs, sp, vp, lfs_match_dindir);
-/* XXX KS - when is TRIPLE not true? */ /* #ifdef TRIPLE */
                lfs_gather(fs, sp, vp, lfs_match_tindir);
-/* #endif */
        }
        fip = sp->fip;
        if (fip->fi_nblocks != 0) {



Home | Main Index | Thread Index | Old Index