Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/lfs Do not needlessly dirty segment table blocks dur...



details:   https://anonhg.NetBSD.org/src/rev/79662ed38129
branches:  trunk
changeset: 499127:79662ed38129
user:      perseant <perseant%NetBSD.org@localhost>
date:      Sun Nov 12 07:58:36 2000 +0000

description:
Do not needlessly dirty segment table blocks during lfs_segwrite,
preventing needless disk activity when the filesystem is idle.  (PR #10979.)

diffstat:

 sys/ufs/lfs/lfs.h         |  14 ++++++++-
 sys/ufs/lfs/lfs_bio.c     |  10 ++----
 sys/ufs/lfs/lfs_segment.c |  68 ++++++++++++++++++++++++++++++++--------------
 sys/ufs/lfs/lfs_vnops.c   |   6 +++-
 4 files changed, 68 insertions(+), 30 deletions(-)

diffs (229 lines):

diff -r a7e5172ebb78 -r 79662ed38129 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sun Nov 12 06:52:37 2000 +0000
+++ b/sys/ufs/lfs/lfs.h Sun Nov 12 07:58:36 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.32 2000/09/13 00:07:56 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.33 2000/11/12 07:58:36 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -482,6 +482,18 @@
        (CP) = (CLEANERINFO *)(BP)->b_data;                             \
 }
 
+/* Synchronize the Ifile cleaner info with current avail and bfree */
+#define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do {                \
+    if ((w) || (cip)->bfree != (fs)->lfs_bfree ||                \
+        (cip)->avail != (fs)->lfs_avail - (fs)->lfs_ravail) {    \
+        printf("update cleaner info at %s:%d\n", __FILE__, __LINE__); \
+       (cip)->bfree = (fs)->lfs_bfree;                          \
+        (cip)->avail = (fs)->lfs_avail - (fs)->lfs_ravail;       \
+       (void) VOP_BWRITE(bp); /* Ifile */                       \
+    } else                                                       \
+       brelse(bp);                                              \
+} while(0)
+
 /* Read in the block with a specific inode from the ifile. */
 #define        LFS_IENTRY(IP, F, IN, BP) {                                     \
        int _e;                                                         \
diff -r a7e5172ebb78 -r 79662ed38129 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Sun Nov 12 06:52:37 2000 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Sun Nov 12 07:58:36 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.30 2000/09/13 00:07:56 perseant Exp $    */
+/*     $NetBSD: lfs_bio.c,v 1.31 2000/11/12 07:58:36 perseant Exp $    */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -154,9 +154,7 @@
 
                /* Wake up the cleaner */
                LFS_CLEANERINFO(cip, fs, bp);
-               cip->bfree = fs->lfs_bfree;
-               cip->avail = fs->lfs_avail - fs->lfs_ravail;
-               (void) VOP_BWRITE(bp); /* Ifile */
+               LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
                wakeup(&lfs_allclean_wakeup);
                wakeup(&fs->lfs_nextseg);
                        
@@ -279,9 +277,7 @@
                         * so it CANT_WAIT.
                         */
                        LFS_CLEANERINFO(cip, fs, cbp);
-                       cip->bfree = fs->lfs_bfree;
-                       cip->avail = fs->lfs_avail;
-                       (void) VOP_BWRITE(cbp);
+                       LFS_SYNC_CLEANERINFO(cip, fs, cbp, 0);
 
                        printf("lfs_bwrite: out of available space, "
                               "waiting on cleaner\n");
diff -r a7e5172ebb78 -r 79662ed38129 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sun Nov 12 06:52:37 2000 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sun Nov 12 07:58:36 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.60 2000/11/12 02:13:51 toshii Exp $  */
+/*     $NetBSD: lfs_segment.c,v 1.61 2000/11/12 07:58:36 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -466,10 +466,10 @@
        struct segment *sp;
        struct vnode *vp;
        SEGUSE *segusep;
-       CLEANERINFO *cip;
        ufs_daddr_t ibno;
-       int do_ckp, error, i;
+       int do_ckp, did_ckp, error, i;
        int writer_set = 0;
+       int dirty;
        
        fs = VFSTOUFS(mp)->um_lfs;
 
@@ -478,15 +478,21 @@
 
        lfs_imtime(fs);
 
+       /* printf("lfs_segwrite: ifile flags are 0x%lx\n",
+              (long)(VTOI(fs->lfs_ivnode)->i_flag)); */
+
 #if 0  
        /*
         * If we are not the cleaner, and there is no space available,
         * wait until cleaner writes.
         */
-       if(!(flags & SEGM_CLEAN)
-          && (!fs->lfs_seglock || !(fs->lfs_sp->seg_flags & SEGM_CLEAN)))
+       if(!(flags & SEGM_CLEAN) && !(fs->lfs_seglock && fs->lfs_sp &&
+                                     (fs->lfs_sp->seg_flags & SEGM_CLEAN)))
        {
                while (fs->lfs_avail <= 0) {
+                       LFS_CLEANERINFO(cip, fs, bp);
+                       LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
+       
                        wakeup(&lfs_allclean_wakeup);
                        wakeup(&fs->lfs_nextseg);
                        error = tsleep(&fs->lfs_avail, PRIBIO + 1, "lfs_av2",
@@ -498,14 +504,6 @@
        }
 #endif
        /*
-        * Synchronize cleaner information
-        */
-       LFS_CLEANERINFO(cip, fs, bp);
-       cip->bfree = fs->lfs_bfree;
-       cip->avail = fs->lfs_avail - fs->lfs_ravail;
-       (void) VOP_BWRITE(bp); /* Ifile */
-       
-       /*
         * Allocate a segment structure and enough space to hold pointers to
         * the maximum possible number of buffers which can be described in a
         * single summary block.
@@ -550,23 +548,34 @@
        if (do_ckp) {
                for (ibno = fs->lfs_cleansz + fs->lfs_segtabsz;
                     --ibno >= fs->lfs_cleansz; ) {
+                       dirty = 0;
                        if (bread(fs->lfs_ivnode, ibno, fs->lfs_bsize, NOCRED, &bp))
 
                                panic("lfs_segwrite: ifile read");
                        segusep = (SEGUSE *)bp->b_data;
-                       for (i = fs->lfs_sepb; i--; segusep++)
-                               segusep->su_flags &= ~SEGUSE_ACTIVE;
+                       for (i = fs->lfs_sepb; i--; segusep++) {
+                               if (segusep->su_flags & SEGUSE_ACTIVE) {
+                                       segusep->su_flags &= ~SEGUSE_ACTIVE;
+                                       ++dirty;
+                               }
+                       }
                                
                        /* But the current segment is still ACTIVE */
                        segusep = (SEGUSE *)bp->b_data;
                        if (datosn(fs, fs->lfs_curseg) / fs->lfs_sepb ==
-                           (ibno-fs->lfs_cleansz))
+                           (ibno-fs->lfs_cleansz)) {
                                segusep[datosn(fs, fs->lfs_curseg) %
                                        fs->lfs_sepb].su_flags |= SEGUSE_ACTIVE;
-                       error = VOP_BWRITE(bp); /* Ifile */
+                               --dirty;
+                       }
+                       if (dirty)
+                               error = VOP_BWRITE(bp); /* Ifile */
+                       else
+                               brelse(bp);
                }
        }
-       
+
+       did_ckp = 0;
        if (do_ckp || fs->lfs_doifile) {
        redo:
                vp = fs->lfs_ivnode;
@@ -576,12 +585,16 @@
                ip = VTOI(vp);
                if (vp->v_dirtyblkhd.lh_first != NULL)
                        lfs_writefile(fs, sp, vp);
-               (void)lfs_writeinode(fs, sp, ip);
+               if (ip->i_flag & IN_ALLMOD)
+                       ++did_ckp;
+               (void) lfs_writeinode(fs, sp, ip);
 
                vput(vp);
 
                if (lfs_writeseg(fs, sp) && do_ckp)
                        goto redo;
+               /* The ifile should now be all clear */
+               LFS_CLR_UINO(ip, IN_ALLMOD);
        } else {
                (void) lfs_writeseg(fs, sp);
        }
@@ -594,7 +607,20 @@
        fs->lfs_doifile = 0;
        if(writer_set && --fs->lfs_writer==0)
                wakeup(&fs->lfs_dirops);
-       
+
+       /*
+        * If we didn't write the Ifile, we didn't really do anything.
+        * That means that (1) there is a checkpoint on disk and (2)
+        * nothing has changed since it was written.
+        *
+        * Take the flags off of the segment so that lfs_segunlock
+        * doesn't have to write the superblock either.
+        */
+       if (did_ckp == 0) {
+               sp->seg_flags &= ~(SEGM_SYNC|SEGM_CKP);
+               /* if(do_ckp) printf("lfs_segwrite: no checkpoint\n"); */
+       }
+
        if(lfs_dostats) {
                ++lfs_stats.nwrites;
                if (sp->seg_flags & SEGM_SYNC)
@@ -1225,7 +1251,7 @@
        --cip->clean;
        ++cip->dirty;
        fs->lfs_nclean = cip->clean;
-       (void) VOP_BWRITE(bp); /* Ifile */
+       LFS_SYNC_CLEANERINFO(cip, fs, bp, 1);
        
        fs->lfs_lastseg = fs->lfs_curseg;
        fs->lfs_curseg = fs->lfs_nextseg;
diff -r a7e5172ebb78 -r 79662ed38129 sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c   Sun Nov 12 06:52:37 2000 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c   Sun Nov 12 07:58:36 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vnops.c,v 1.46 2000/10/14 23:22:14 perseant Exp $  */
+/*     $NetBSD: lfs_vnops.c,v 1.47 2000/11/12 07:58:36 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -287,6 +287,10 @@
                struct proc *a_p;
        } */ *ap = v;
        
+       /* Ignore the trickle syncer */
+       if (ap->a_flags & FSYNC_LAZY)
+               return 0;
+
        return (VOP_UPDATE(ap->a_vp, NULL, NULL,
                           (ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0));
 }



Home | Main Index | Thread Index | Old Index