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:
parent
29d84e8033
commit
3c63d0830f
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue