Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/lfs Add simple_lock protection for lfs_seglock and l...
details: https://anonhg.NetBSD.org/src/rev/28baad81c008
branches: trunk
changeset: 544234:28baad81c008
user: perseant <perseant%NetBSD.org@localhost>
date: Sat Mar 15 06:58:49 2003 +0000
description:
Add simple_lock protection for lfs_seglock and lfs_subsys_pages; these will
be expanded to cover other per-fs and subsystem-wide data as well.
Fix a case of IN_MODIFIED being set without updating lfs_uinodes, resulting
in a "lfs_uinodes < 0" panic.
Fix a deadlock in lfs_putpages arising from the need to busy all pages in a
block; unbusy any that had already been busied before starting over.
diffstat:
sys/ufs/lfs/lfs.h | 7 ++++++-
sys/ufs/lfs/lfs_alloc.c | 12 +++++++-----
sys/ufs/lfs/lfs_balloc.c | 6 ++----
sys/ufs/lfs/lfs_bio.c | 30 ++++++++++++++++++++++++------
sys/ufs/lfs/lfs_segment.c | 37 +++++++------------------------------
sys/ufs/lfs/lfs_subr.c | 24 ++++++++++++++++++------
sys/ufs/lfs/lfs_syscalls.c | 7 ++-----
sys/ufs/lfs/lfs_vfsops.c | 5 +++--
sys/ufs/lfs/lfs_vnops.c | 24 +++++++++++++++++-------
9 files changed, 86 insertions(+), 66 deletions(-)
diffs (truncated from 549 to 300 lines):
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs.h Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs.h,v 1.57 2003/03/11 02:47:39 perseant Exp $ */
+/* $NetBSD: lfs.h,v 1.58 2003/03/15 06:58:49 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -187,6 +187,7 @@
#define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_ACCESSED|IN_CLEANING)
#define LFS_SET_UINO(ip, flags) do { \
+ simple_lock(&(ip)->i_lfs->lfs_interlock); \
if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED)) \
++(ip)->i_lfs->lfs_uinodes; \
if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING)) \
@@ -194,9 +195,11 @@
if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED)) \
++(ip)->i_lfs->lfs_uinodes; \
(ip)->i_flag |= (flags); \
+ simple_unlock(&(ip)->i_lfs->lfs_interlock); \
} while (0)
#define LFS_CLR_UINO(ip, flags) do { \
+ simple_lock(&(ip)->i_lfs->lfs_interlock); \
if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED)) \
--(ip)->i_lfs->lfs_uinodes; \
if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING)) \
@@ -207,6 +210,7 @@
if ((ip)->i_lfs->lfs_uinodes < 0) { \
panic("lfs_uinodes < 0"); \
} \
+ simple_unlock(&(ip)->i_lfs->lfs_interlock); \
} while (0)
#ifdef DEBUG
@@ -527,6 +531,7 @@
#define LFS_MAX_CLEANIND 64
int32_t lfs_cleanint[LFS_MAX_CLEANIND]; /* Active cleaning intervals */
int lfs_cleanind; /* Index into intervals */
+ struct simplelock lfs_interlock; /* lock for lfs_seglock */
};
/*
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_alloc.c,v 1.64 2003/02/20 04:27:23 perseant Exp $ */
+/* $NetBSD: lfs_alloc.c,v 1.65 2003/03/15 06:58:50 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.64 2003/02/20 04:27:23 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.65 2003/03/15 06:58:50 perseant Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -98,8 +98,6 @@
extern int lfs_dirvcount;
extern struct lock ufs_hashlock;
-extern struct simplelock lfs_subsys_lock;
-extern int lfs_subsys_pages;
static int extend_ifile(struct lfs *, struct ucred *);
static int lfs_ialloc(struct lfs *, struct vnode *, ino_t, int, struct vnode **);
@@ -217,7 +215,8 @@
}
/*
- * Called with the Ifile inode locked.
+ * Add a new block to the Ifile, to accommodate future file creations.
+ * Called with the segment lock held.
*/
static int
extend_ifile(struct lfs *fs, struct ucred *cred)
@@ -350,6 +349,9 @@
return lfs_ialloc(fs, ap->a_pvp, new_ino, new_gen, ap->a_vpp);
}
+/*
+ * Finish allocating a new inode, given an inode and generation number.
+ */
static int
lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen,
struct vnode **vpp)
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_balloc.c
--- a/sys/ufs/lfs/lfs_balloc.c Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_balloc.c Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_balloc.c,v 1.38 2003/02/28 07:36:32 perseant Exp $ */
+/* $NetBSD: lfs_balloc.c,v 1.39 2003/03/15 06:58:50 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.38 2003/02/28 07:36:32 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.39 2003/03/15 06:58:50 perseant Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -98,8 +98,6 @@
#include <uvm/uvm.h>
-extern int lfs_subsys_pages;
-
int lfs_fragextend(struct vnode *, int, int, daddr_t, struct buf **, struct ucred *);
/*
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_bio.c Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_bio.c,v 1.63 2003/03/02 04:34:31 perseant Exp $ */
+/* $NetBSD: lfs_bio.c,v 1.64 2003/03/15 06:58:50 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.63 2003/03/02 04:34:31 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.64 2003/03/15 06:58:50 perseant Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -108,7 +108,9 @@
int lfs_subsys_pages = 0L; /* Total number LFS-written pages */
int lfs_writing = 0; /* Set if already kicked off a writer
because of buffer space */
-struct simplelock lfs_subsys_lock; /* Lock on subsys_pages */
+/* Lock for lfs_subsys_pages */
+struct simplelock lfs_subsys_lock = SIMPLELOCK_INITIALIZER;
+
extern int lfs_dostats;
extern int lfs_do_flush;
@@ -373,10 +375,14 @@
struct buf *cbp;
/* Push cleaner blocks through regardless */
+ simple_lock(&fs->lfs_interlock);
if (fs->lfs_seglock &&
fs->lfs_lockpid == curproc->p_pid &&
- fs->lfs_sp->seg_flags & (SEGM_CLEAN | SEGM_FORCE_CKP))
+ fs->lfs_sp->seg_flags & (SEGM_CLEAN | SEGM_FORCE_CKP)) {
+ simple_unlock(&fs->lfs_interlock);
return 0;
+ }
+ simple_unlock(&fs->lfs_interlock);
while (!lfs_fits(fs, fsb)) {
/*
@@ -523,7 +529,9 @@
ltsleep(&lfs_writing, PRIBIO + 1, "lfsflush", 0, 0);
lfs_writing = 1;
+ simple_lock(&lfs_subsys_lock);
lfs_subsys_pages = 0; /* XXXUBC need a better way to count this */
+ simple_unlock(&lfs_subsys_lock);
wakeup(&lfs_subsys_pages);
simple_lock(&mountlist_slock);
@@ -573,6 +581,7 @@
* If we would flush below, but dirops are active, sleep.
* Note that a dirop cannot ever reach this code!
*/
+ simple_lock(&lfs_subsys_lock);
while (fs->lfs_dirops > 0 &&
(locked_queue_count + INOCOUNT(fs) > LFS_MAX_BUFS ||
locked_queue_bytes + INOBYTES(fs) > LFS_MAX_BYTES ||
@@ -580,7 +589,8 @@
lfs_dirvcount > LFS_MAX_DIROP || fs->lfs_diropwait > 0))
{
++fs->lfs_diropwait;
- tsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0);
+ ltsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0,
+ &lfs_subsys_lock);
--fs->lfs_diropwait;
}
@@ -598,12 +608,15 @@
if (fs->lfs_diropwait > 0)
printf("ldvw = %d\n", fs->lfs_diropwait);
#endif
+
if (locked_queue_count + INOCOUNT(fs) > LFS_MAX_BUFS ||
locked_queue_bytes + INOBYTES(fs) > LFS_MAX_BYTES ||
lfs_subsys_pages > LFS_MAX_PAGES ||
lfs_dirvcount > LFS_MAX_DIROP || fs->lfs_diropwait > 0)
{
+ simple_unlock(&lfs_subsys_lock);
lfs_flush(fs, flags);
+ simple_lock(&lfs_subsys_lock);
}
while (locked_queue_count + INOCOUNT(fs) > LFS_WAIT_BUFS ||
@@ -611,6 +624,7 @@
lfs_subsys_pages > LFS_WAIT_PAGES ||
lfs_dirvcount > LFS_MAX_DIROP)
{
+ simple_unlock(&lfs_subsys_lock);
if (lfs_dostats)
++lfs_stats.wait_exceeded;
#ifdef DEBUG_LFS
@@ -619,8 +633,10 @@
#endif
error = tsleep(&locked_queue_count, PCATCH | PUSER,
"buffers", hz * LFS_BUFWAIT);
- if (error != EWOULDBLOCK)
+ if (error != EWOULDBLOCK) {
+ simple_lock(&lfs_subsys_lock);
break;
+ }
/*
* lfs_flush might not flush all the buffers, if some of the
* inodes were locked or if most of them were Ifile blocks
@@ -632,7 +648,9 @@
{
lfs_flush(fs, flags | SEGM_CKP);
}
+ simple_lock(&lfs_subsys_lock);
}
+ simple_unlock(&lfs_subsys_lock);
return (error);
}
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_segment.c,v 1.110 2003/03/15 02:27:18 kristerw Exp $ */
+/* $NetBSD: lfs_segment.c,v 1.111 2003/03/15 06:58:50 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.110 2003/03/15 02:27:18 kristerw Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.111 2003/03/15 06:58:50 perseant Exp $");
#define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
@@ -109,7 +109,6 @@
extern int count_lock_queue(void);
extern struct simplelock vnode_free_list_slock; /* XXX */
-extern int lfs_subsys_pages;
static void lfs_generic_callback(struct buf *, void (*)(struct buf *));
static void lfs_super_aiodone(struct buf *);
@@ -405,11 +404,15 @@
* We compare the iocount against 1, not 0, because it is
* artificially incremented by lfs_seglock().
*/
+ simple_lock(&fs->lfs_interlock);
if (fs->lfs_seglock > 1) {
+ simple_unlock(&fs->lfs_interlock);
while (fs->lfs_iocount > 1)
(void)tsleep(&fs->lfs_iocount, PRIBIO + 1,
"lfs_vflush", 0);
- }
+ } else
+ simple_unlock(&fs->lfs_interlock);
+
lfs_segunlock(fs);
CLR_FLUSHING(fs,vp);
@@ -543,31 +546,6 @@
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 &&
- (fs->lfs_sp->seg_flags & SEGM_CLEAN)))
- {
- while (fs->lfs_avail <= 0) {
- LFS_CLEANERINFO(cip, fs, bp);
- LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
-
Home |
Main Index |
Thread Index |
Old Index