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