Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/lfs Phase one of my three-phase plan to make LFS pla...



details:   https://anonhg.NetBSD.org/src/rev/1ded0637ec97
branches:  trunk
changeset: 526959:1ded0637ec97
user:      perseant <perseant%NetBSD.org@localhost>
date:      Tue May 14 20:03:53 2002 +0000

description:
Phase one of my three-phase plan to make LFS play nice with UBC, and bug-fixes
I found while making sure there weren't any new ones.

* Make the write clusters keep track of the buffers whose blocks they contain.
  This should make it possible to (1) write clusters using a page mapping
  instead of malloc, if desired, and (2) schedule blocks for rewriting
  (somewhere else) if a write error occurs.  Code is present to use
  pagemove() to construct the clusters but that is untested and will go away
  anyway in favor of page mapping.
* DEBUG now keeps a log of Ifile writes, so that any lingering instances of
  the "dirty bufs" problem can be properly debugged.
* Keep track of whether the Ifile has been dirtied by various routines that
  can be called by lfs_segwrite, and loop on that until it is clean, for
  a checkpoint.  Checkpoints need to be squeaky clean.
* Warn the user (once) if the Ifile grows larger than is reasonable for their
  buffer cache.  Both lfs_mountfs and lfs_unmount check since the Ifile can
  grow.
* If an inode is not found in a disk block, try rereading the block, under
  the assumption that the block was copied to a cluster and then freed.
* Protect WRITEINPROG() with splbio() to fix a hang in lfs_update.

diffstat:

 sys/ufs/lfs/lfs.h          |  103 +++++++-
 sys/ufs/lfs/lfs_alloc.c    |   65 ++++-
 sys/ufs/lfs/lfs_balloc.c   |   10 +-
 sys/ufs/lfs/lfs_bio.c      |   31 +-
 sys/ufs/lfs/lfs_debug.c    |   35 ++-
 sys/ufs/lfs/lfs_extern.h   |    8 +-
 sys/ufs/lfs/lfs_inode.c    |   33 +-
 sys/ufs/lfs/lfs_segment.c  |  549 +++++++++++++++++++++++++++++++++++---------
 sys/ufs/lfs/lfs_subr.c     |   35 ++-
 sys/ufs/lfs/lfs_syscalls.c |   92 +++----
 sys/ufs/lfs/lfs_vfsops.c   |  106 +++++++-
 sys/ufs/lfs/lfs_vnops.c    |   30 +-
 12 files changed, 833 insertions(+), 264 deletions(-)

diffs (truncated from 2247 to 300 lines):

diff -r 348b02f12100 -r 1ded0637ec97 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Tue May 14 19:44:57 2002 +0000
+++ b/sys/ufs/lfs/lfs.h Tue May 14 20:03:53 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.38 2001/11/23 21:44:25 chs Exp $     */
+/*     $NetBSD: lfs.h,v 1.39 2002/05/14 20:03:53 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -73,12 +73,19 @@
 /*
  * Compile-time options for LFS.
  */
+#define LFS_IFIND_RETRIES      16
 #define LFS_EAGAIN_FAIL          /* markv fail with EAGAIN if ino is locked */
-#define LFS_TRACK_IOS            /* attempt to avoid cleaning segments not yet fully written to disk */
 #define LFS_DEBUG_RFW            /* print roll-forward debugging info */
+#define LFS_NO_PAGEMOVE          /* Use malloc/copy to write clusters */
+#define LFS_AGGRESSIVE_SEGLOCK
+#define LFS_LOGLENGTH 1024
 
 /* #define DEBUG_LFS */              /* Intensive debugging of LFS subsystem */
 
+#ifdef LFS_NO_PAGEMOVE
+# define LFS_MALLOC_SUMMARY
+#endif
+
 /*
  * Parameters and generic definitions
  */
@@ -120,6 +127,20 @@
        (bp)->b_flags &= ~B_LOCKED;                                     \
 } while (0)
 
+#ifdef DEBUG_LOCKED_LIST
+# define LFS_DEBUG_COUNTLOCKED(m) do {                                  \
+       int _s;                                                         \
+       extern int locked_queue_count;                                  \
+       extern long locked_queue_bytes;                                 \
+        _s = splbio();                                                 \
+        lfs_countlocked(&locked_queue_count, &locked_queue_bytes, (m));        \
+        splx(_s);                                                      \
+        wakeup(&locked_queue_count);                                   \
+} while (0)
+#else
+# define LFS_DEBUG_COUNTLOCKED(m)
+#endif
+
 /* For convenience */
 #define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_ACCESSED|IN_CLEANING)
 
@@ -146,7 +167,42 @@
        }                                                               \
 } while (0)
 
+#ifdef DEBUG
+struct lfs_log_entry {
+       char *op;
+       char *file;
+       int line;
+       ufs_daddr_t block;
+       unsigned long flags;
+};
+extern int lfs_lognum;
+extern struct lfs_log_entry lfs_log[LFS_LOGLENGTH];
+# define LFS_BWRITE_LOG(bp) lfs_bwrite_log((bp), __FILE__, __LINE__)
+# define LFS_ENTER_LOG(theop, thefile, theline, lbn, theflags) do { \
+       int _s;                                                 \
+                                                               \
+       _s = splbio();                                          \
+       lfs_log[lfs_lognum].op = theop;                         \
+       lfs_log[lfs_lognum].file = thefile;                     \
+       lfs_log[lfs_lognum].line = (theline);                   \
+       lfs_log[lfs_lognum].block = (lbn);                      \
+       lfs_log[lfs_lognum].flags = (theflags);                 \
+       lfs_lognum = (lfs_lognum + 1) % LFS_LOGLENGTH;          \
+       splx(_s);                                               \
+} while (0)
+
+# define LFS_BCLEAN_LOG(fs, bp) do {                                   \
+       if ((bp)->b_vp == (fs)->lfs_ivnode)                             \
+               LFS_ENTER_LOG("clear", __FILE__, __LINE__, bp->b_lblkno, bp->b_flags); \
+} while (0)
+#else
+# define LFS_BCLEAN_LOG(fs, bp)
+# define LFS_BWRITE_LOG(bp)            VOP_BWRITE((bp))
+#endif
+       
 #define LFS_ITIMES(ip, acc, mod, cre)  do {                            \
+       struct lfs *_fs = (ip)->i_lfs;                                  \
+                                                                       \
                if ((ip)->i_flag & IN_ACCESS) {                                 \
                (ip)->i_ffs_atime = (acc)->tv_sec;                      \
                (ip)->i_ffs_atimensec = (acc)->tv_nsec;                 \
@@ -157,7 +213,8 @@
                        LFS_IENTRY(ifp, ip->i_lfs, ip->i_number, ibp);  \
                        ifp->if_atime_sec = (acc)->tv_sec;              \
                        ifp->if_atime_nsec = (acc)->tv_nsec;            \
-                       VOP_BWRITE(ibp);                                \
+                       LFS_BWRITE_LOG(ibp);                            \
+                       _fs->lfs_flags |= LFS_IFDIRTY;                  \
                } else {                                                \
                        LFS_SET_UINO(ip, IN_ACCESSED);                  \
                }                                                       \
@@ -310,7 +367,7 @@
 };
 
 /* Maximum number of io's we can have pending at once */
-#define LFS_THROTTLE  16 /* XXX should be better paramtrized - ? */
+#define LFS_THROTTLE  32 /* XXX should be better paramtrized - ? */
 
 /* In-memory super block. */
 struct lfs {
@@ -388,7 +445,9 @@
        u_int32_t lfs_nactive;          /* Number of segments since last ckp */
        int8_t    lfs_fmod;             /* super block modified flag */
        int8_t    lfs_ronly;            /* mounted read-only flag */
-#define LFS_NOTYET 0x01
+#define LFS_NOTYET  0x01
+#define LFS_IFDIRTY 0x02
+#define LFS_WARNED  0x04
        int8_t    lfs_flags;            /* currently unused flag */
        u_int16_t lfs_activesb;         /* toggle between superblocks */
 #ifdef LFS_TRACK_IOS
@@ -570,13 +629,13 @@
        ((ufs_daddr_t)(segtod((fs), (sn)) + (fs)->lfs_start))
 
 /* Read in the block with the cleaner info from the ifile. */
-#define LFS_CLEANERINFO(CP, F, BP) {                                   \
+#define LFS_CLEANERINFO(CP, F, BP) do {                                        \
        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        if (bread((F)->lfs_ivnode,                                      \
            (ufs_daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP)))             \
                panic("lfs: ifile read");                               \
        (CP) = (CLEANERINFO *)(BP)->b_data;                             \
-}
+} while(0)
 
 /* Synchronize the Ifile cleaner info with current avail and bfree */
 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do {                \
@@ -584,7 +643,9 @@
         (cip)->avail != (fs)->lfs_avail - (fs)->lfs_ravail) {    \
        (cip)->bfree = (fs)->lfs_bfree;                          \
         (cip)->avail = (fs)->lfs_avail - (fs)->lfs_ravail;       \
-       (void) VOP_BWRITE(bp); /* Ifile */                       \
+        if (((bp)->b_flags & B_GATHERED) == 0)                  \
+               (fs)->lfs_flags |= LFS_IFDIRTY;                  \
+       (void) LFS_BWRITE_LOG(bp); /* Ifile */                       \
     } else                                                       \
        brelse(bp);                                              \
 } while (0)
@@ -603,7 +664,8 @@
        if ((FS)->lfs_version > 1) {                                    \
                LFS_CLEANERINFO((CIP), (FS), (BP));                     \
                (CIP)->free_head = (VAL);                               \
-               VOP_BWRITE(BP);                                         \
+               LFS_BWRITE_LOG(BP);                                         \
+               (FS)->lfs_flags |= LFS_IFDIRTY;                          \
        }                                                               \
 } while (0)
 
@@ -616,7 +678,8 @@
 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do {                         \
        LFS_CLEANERINFO((CIP), (FS), (BP));                             \
        (CIP)->free_tail = (VAL);                                       \
-       VOP_BWRITE(BP);                                                 \
+       LFS_BWRITE_LOG(BP);                                             \
+       (FS)->lfs_flags |= LFS_IFDIRTY;                          \
 } while (0)
 
 /*
@@ -624,7 +687,7 @@
  * may not be mapped!
  */
 /* Read in the block with a specific inode from the ifile. */
-#define        LFS_IENTRY(IP, F, IN, BP) {                                     \
+#define        LFS_IENTRY(IP, F, IN, BP) do {                                  \
        int _e;                                                         \
        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        if ((_e = bread((F)->lfs_ivnode,                                \
@@ -635,10 +698,10 @@
                (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + (IN) % (F)->lfs_ifpb); \
        else                                                            \
                (IP) = (IFILE *)(BP)->b_data + (IN) % (F)->lfs_ifpb;    \
-}
+} while(0)
 
 /* Read in the block with a specific segment usage entry from the ifile. */
-#define        LFS_SEGENTRY(SP, F, IN, BP) {                                   \
+#define        LFS_SEGENTRY(SP, F, IN, BP) do {                                \
        int _e;                                                         \
        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        if ((_e = bread((F)->lfs_ivnode,                                \
@@ -650,7 +713,7 @@
                        ((IN) & ((F)->lfs_sepb - 1)));                  \
        else                                                            \
                (SP) = (SEGUSE *)(BP)->b_data + ((IN) % (F)->lfs_sepb); \
-}
+} while(0)
 
 /* Determine if a buffer belongs to the ifile */
 #define IS_IFILE(bp)   (VTOI(bp->b_vp)->i_number == LFS_IFILE_INUM)
@@ -704,6 +767,18 @@
        u_int16_t seg_flags;            /* run-time flags for this segment */
 };
 
+struct lfs_cluster {
+       struct buf **bpp;      /* Array of kept buffers */
+       int bufcount;          /* Number of kept buffers */
+       size_t bufsize;        /* Size of kept data */
+#define LFS_CL_MALLOC  0x00000001
+#define LFS_CL_SHIFT   0x00000002
+       u_int32_t flags;       /* Flags */
+       struct lfs *fs;        /* LFS that this belongs to */
+       void *saveaddr;        /* Original contents of saveaddr */
+       char *olddata;          /* Original b_data, if LFS_CL_MALLOC */
+};
+
 /*
  * Macros for determining free space on the disk, with the variable metadata
  * of segment summaries and inode blocks taken into account.
diff -r 348b02f12100 -r 1ded0637ec97 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c   Tue May 14 19:44:57 2002 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c   Tue May 14 20:03:53 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_alloc.c,v 1.55 2002/02/04 03:32:16 perseant Exp $  */
+/*     $NetBSD: lfs_alloc.c,v 1.56 2002/05/14 20:03:53 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.55 2002/02/04 03:32:16 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.56 2002/05/14 20:03:53 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -81,6 +81,7 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/buf.h>
+#include <sys/lock.h>
 #include <sys/vnode.h>
 #include <sys/syslog.h>
 #include <sys/mount.h>
@@ -109,6 +110,8 @@
  *
  * XXX this function does not have appropriate locking to be used on a live fs;
  * XXX but something similar could probably be used for an "undelete" call.
+ *
+ * Called with the Ifile inode locked.
  */
 int
 lfs_rf_valloc(struct lfs *fs, ino_t ino, int version, struct proc *p,
@@ -182,7 +185,7 @@
                        return ENOENT;
                }
                ifp->if_nextfree = oldnext;
-               VOP_BWRITE(bp);
+               LFS_BWRITE_LOG(bp);
        }
 
        error = lfs_ialloc(fs, fs->lfs_ivnode, ino, version, &vp);
@@ -211,6 +214,9 @@
        return error;
 }
 
+/*
+ * Called with the Ifile inode locked. 
+ */
 static int
 extend_ifile(struct lfs *fs, struct ucred *cred)
 {
@@ -225,19 +231,14 @@
        CLEANERINFO *cip;
 
        vp = fs->lfs_ivnode;
-       (void)lfs_vref(vp);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
        ip = VTOI(vp);
        blkno = lblkno(fs, ip->i_ffs_size);
        if ((error = VOP_BALLOC(vp, ip->i_ffs_size, fs->lfs_bsize, cred, 0,
                                &bp)) != 0) {
-               VOP_UNLOCK(vp, 0);
-               lfs_vunref(vp);
                return (error);
        }
        ip->i_ffs_size += fs->lfs_bsize;
        uvm_vnp_setsize(vp, ip->i_ffs_size);
-       VOP_UNLOCK(vp, 0);
        
        i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) *
                fs->lfs_ifpb;
@@ -269,8 +270,7 @@
        }
        LFS_PUT_TAILFREE(fs, cip, cbp, max - 1);
 
-       (void) VOP_BWRITE(bp); /* Ifile */



Home | Main Index | Thread Index | Old Index