Address ufs_hashlock/ufs_ihashins protocol bug, discovered while doing a

post-mortem of a production machine.  Also, take the active dirop
count off of the fs and make it global (since it is measuring a global
resource) and tie the threshold value LFS_MAXDIROP to desiredvnodes.
This commit is contained in:
perseant 1999-11-06 20:33:05 +00:00
parent 29d84e8033
commit 3c63d0830f
6 changed files with 31 additions and 40 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs.h,v 1.16 1999/06/15 22:25:41 perseant Exp $ */
/* $NetBSD: lfs.h,v 1.17 1999/11/06 20:33:05 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -85,9 +85,10 @@
/*
* Parameters and generic definitions
*/
#define BW_CLEAN 1
#define MIN_FREE_SEGS 4
#define LFS_MAX_ACTIVE 10
#define BW_CLEAN 1
#define MIN_FREE_SEGS 4
#define LFS_MAX_ACTIVE 10
#define LFS_MAXDIROP (desiredvnodes>>2)
#ifndef LFS_ATIME_IFILE
# define LFS_ITIMES(ip, acc, mod, cre) FFS_ITIMES((ip),(acc),(mod),(cre))
@ -309,8 +310,6 @@ struct lfs {
#ifdef LFS_TRACK_IOS
daddr_t lfs_pending[LFS_THROTTLE]; /* daddrs of pending writes */
#endif /* LFS_TRACK_IOS */
# define LFS_MAXDIROP 32
int lfs_dirvcount; /* number of VDIROP-marked vnodes */
#ifdef LFS_CANNOT_ROLLFW
daddr_t lfs_sbactive; /* disk address of in-progress sb write */
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_alloc.c,v 1.25 1999/09/03 22:48:51 perseant Exp $ */
/* $NetBSD: lfs_alloc.c,v 1.26 1999/11/06 20:33:05 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -117,16 +117,16 @@ lfs_valloc(v)
ino_t new_ino;
u_long i, max;
int error;
extern int lfs_dirvcount;
fs = VTOI(ap->a_pvp)->i_lfs;
/*
* Prevent a race getting lfs_free - XXX - KS
* (this should be a proper lock, in struct lfs)
* Prevent a race getting lfs_free. We use
* the ufs_hashlock here because we need that anyway for
* the hash insertion later.
*/
while(lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
;
lockmgr(&ufs_hashlock, LK_EXCLUSIVE, 0);
/* Get the head of the freelist. */
new_ino = fs->lfs_free;
@ -189,7 +189,6 @@ lfs_valloc(v)
return (error);
}
}
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
#ifdef DIAGNOSTIC
if(fs->lfs_free == LFS_UNUSED_INUM)
@ -197,8 +196,10 @@ lfs_valloc(v)
#endif /* DIAGNOSTIC */
/* Create a vnode to associate with the inode. */
if ((error = lfs_vcreate(ap->a_pvp->v_mount, new_ino, &vp)) != 0)
if ((error = lfs_vcreate(ap->a_pvp->v_mount, new_ino, &vp)) != 0) {
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
return (error);
}
ip = VTOI(vp);
/* Zero out the direct and indirect block addresses. */
@ -210,6 +211,7 @@ lfs_valloc(v)
/* Insert into the inode hash table. */
ufs_ihashins(ip);
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
error = ufs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p, &vp);
if (error) {
@ -221,7 +223,7 @@ lfs_valloc(v)
*ap->a_vpp = vp;
if(!(vp->v_flag & VDIROP)) {
lfs_vref(vp);
++fs->lfs_dirvcount;
++lfs_dirvcount;
}
vp->v_flag |= VDIROP;
VREF(ip->i_devvp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_bio.c,v 1.12 1999/10/21 16:53:43 perseant Exp $ */
/* $NetBSD: lfs_bio.c,v 1.13 1999/11/06 20:33:05 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -348,6 +348,7 @@ lfs_check(vp, blkno, flags)
{
int error;
struct lfs *fs;
extern int lfs_dirvcount;
error = 0;
@ -363,7 +364,7 @@ lfs_check(vp, blkno, flags)
if (locked_queue_count > LFS_MAX_BUFS
|| locked_queue_bytes > LFS_MAX_BYTES
|| fs->lfs_dirvcount > LFS_MAXDIROP
|| lfs_dirvcount > LFS_MAXDIROP
|| fs->lfs_diropwait > 0)
{
++fs->lfs_writer;

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_segment.c,v 1.31 1999/10/01 22:07:42 mycroft Exp $ */
/* $NetBSD: lfs_segment.c,v 1.32 1999/11/06 20:33:05 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -137,6 +137,7 @@ int lfs_writevnodes __P((struct lfs *fs, struct mount *mp,
int lfs_allclean_wakeup; /* Cleaner wakeup address. */
int lfs_writeindir = 1; /* whether to flush indir on non-ckp */
int lfs_clean_vnhead = 0; /* Allow freeing to head of vn list */
int lfs_dirvcount = 0; /* # active dirops */
/* Statistics Counters */
int lfs_dostats = 1;
@ -416,9 +417,9 @@ lfs_writevnodes(fs, mp, sp, op)
}
if(vp->v_flag & VDIROP) {
--fs->lfs_dirvcount;
--lfs_dirvcount;
vp->v_flag &= ~VDIROP;
wakeup(&fs->lfs_dirvcount);
wakeup(&lfs_dirvcount);
lfs_vunref(vp);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_vfsops.c,v 1.40 1999/10/20 14:32:11 enami Exp $ */
/* $NetBSD: lfs_vfsops.c,v 1.41 1999/11/06 20:33:06 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -402,7 +402,6 @@ lfs_mountfs(devvp, mp, p)
/* Set up the I/O information */
fs->lfs_iocount = 0;
fs->lfs_dirvcount = 0;
fs->lfs_diropwait = 0;
fs->lfs_activesb = 0;
#ifdef LFS_CANNOT_ROLLFW
@ -627,9 +626,7 @@ lfs_sync(mp, waitfor, cred, p)
return (error);
}
#ifdef USE_UFS_HASHLOCK
extern struct lock ufs_hashlock;
#endif
/*
* Look up an LFS dinode number to find its incore vnode. If not already
@ -658,14 +655,10 @@ lfs_vget(mp, ino, vpp)
ump = VFSTOUFS(mp);
dev = ump->um_dev;
#ifdef USE_UFS_HASHLOCK
do {
#endif
if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
return (0);
#ifdef USE_UFS_HASHLOCK
} while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
#endif
/* Translate the inode number to a disk address. */
fs = ump->um_lfs;
@ -679,9 +672,7 @@ lfs_vget(mp, ino, vpp)
#endif
brelse(bp);
if (daddr == LFS_UNUSED_DADDR) {
#ifdef USE_UFS_HASHLOCK
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
#endif
return (ENOENT);
}
}
@ -689,9 +680,7 @@ lfs_vget(mp, ino, vpp)
/* Allocate new vnode/inode. */
if ((error = lfs_vcreate(mp, ino, &vp)) != 0) {
*vpp = NULL;
#ifdef USE_UFS_HASHLOCK
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
#endif
return (error);
}
@ -703,9 +692,7 @@ lfs_vget(mp, ino, vpp)
*/
ip = VTOI(vp);
ufs_ihashins(ip);
#ifdef USE_UFS_HASHLOCK
lockmgr(&ufs_hashlock, LK_RELEASE, 0);
#endif
/*
* XXX

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_vnops.c,v 1.30 1999/11/05 20:14:56 perseant Exp $ */
/* $NetBSD: lfs_vnops.c,v 1.31 1999/11/06 20:33:06 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -293,20 +293,21 @@ lfs_fsync(v)
*/
#define SET_DIROP(fs) lfs_set_dirop(fs)
static int lfs_set_dirop __P((struct lfs *));
extern int lfs_dirvcount;
static int lfs_set_dirop(fs)
struct lfs *fs;
{
int error;
while (fs->lfs_writer || fs->lfs_dirvcount>LFS_MAXDIROP) {
while (fs->lfs_writer || lfs_dirvcount>LFS_MAXDIROP) {
if(fs->lfs_writer)
tsleep(&fs->lfs_dirops, PRIBIO + 1, "lfs_dirop", 0);
if(fs->lfs_dirvcount > LFS_MAXDIROP) {
if(lfs_dirvcount > LFS_MAXDIROP) {
#ifdef DEBUG_LFS
printf("(dirvcount=%d)\n",fs->lfs_dirvcount);
printf("(dirvcount=%d)\n",lfs_dirvcount);
#endif
if((error=tsleep(&fs->lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0))!=0)
if((error=tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0))!=0)
return error;
}
}
@ -327,7 +328,7 @@ static int lfs_set_dirop(fs)
#define MARK_VNODE(dvp) do { \
if(!((dvp)->v_flag & VDIROP)) { \
lfs_vref(dvp); \
++VTOI((dvp))->i_lfs->lfs_dirvcount; \
++lfs_dirvcount; \
} \
(dvp)->v_flag |= VDIROP; \
} while(0)