summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2007-05-30 04:27:44 +0000
committerBob Beck <beck@cvs.openbsd.org>2007-05-30 04:27:44 +0000
commit63fc4e315f0893c9554193f74b2a056de91af696 (patch)
treeeba15b44fd77f600449d301128e7fe5966c3f823
parent54f7b30b37ba36f7ac06d3f70c0ca4244b9d0a93 (diff)
back out vfs change - todd fries has seen afs issues, and I'm suspicious
this can cause other problems.
-rw-r--r--sys/kern/vfs_cache.c137
-rw-r--r--sys/kern/vfs_getcwd.c16
-rw-r--r--sys/kern/vfs_subr.c93
-rw-r--r--sys/sys/namei.h5
-rw-r--r--sys/sys/vnode.h6
-rw-r--r--sys/xfs/xfs_node-bsd.c25
6 files changed, 105 insertions, 177 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 6c10bb5f269..aa5978fc664 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_cache.c,v 1.23 2007/05/29 17:33:27 beck Exp $ */
+/* $OpenBSD: vfs_cache.c,v 1.24 2007/05/30 04:27:42 beck Exp $ */
/* $NetBSD: vfs_cache.c,v 1.13 1996/02/04 02:18:09 christos Exp $ */
/*
@@ -69,10 +69,8 @@
* Structures associated with name caching.
*/
LIST_HEAD(nchashhead, namecache) *nchashtbl;
-TAILQ_HEAD (, namecache) ncneq;
u_long nchash; /* size of hash table - 1 */
long numcache; /* number of cache entries allocated */
-long numcachehv; /* number of holding vnodes */
TAILQ_HEAD(, namecache) nclruhead; /* LRU chain */
struct nchstats nchstats; /* cache effectiveness statistics */
@@ -131,15 +129,10 @@ cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
ncpp = &nchashtbl[NCHASH(dvp, cnp)];
LIST_FOREACH(ncp, ncpp, nc_hash) {
if (ncp->nc_dvp == dvp &&
+ ncp->nc_dvpid == dvp->v_id &&
ncp->nc_nlen == cnp->cn_namelen &&
- !memcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen)) {
-#ifdef DIAGNOSTIC
- if (ncp->nc_dvpid != dvp->v_id)
- panic("ncp->nc_dvpid %x != dvp->v_id %x\n",
- ncp->nc_dvpid, dvp->v_id);
-#endif
- break;
- }
+ !memcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
+ break;
}
if (ncp == NULL) {
nchstats.ncs_miss++;
@@ -166,10 +159,8 @@ cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
goto remove;
}
} else if (ncp->nc_vpid != ncp->nc_vp->v_id) {
-#ifdef DIAGNOSTIC
- panic("ncp->vpid %x != ncp->nc_vp->v_id %x\n", ncp->nc_vpid,
- ncp->nc_vp->v_id);
-#endif
+ nchstats.ncs_falsehits++;
+ goto remove;
}
vp = ncp->nc_vp;
@@ -210,10 +201,8 @@ cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
*/
if (error || vpid != vp->v_id) {
if (!error) {
-#ifdef DIAGNOSTIC
- panic("vpid %x != vp->vid %x\n", vpid, vp->v_id);
vput(vp);
-#endif
+ nchstats.ncs_falsehits++;
} else
nchstats.ncs_badhits++;
/*
@@ -247,7 +236,17 @@ remove:
* the cache entry is invalid, or otherwise don't
* want cache entry to exist.
*/
- cache_delete(ncp);
+ TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
+ LIST_REMOVE(ncp, nc_hash);
+ ncp->nc_hash.le_prev = NULL;
+
+ if (ncp->nc_vhash.le_prev != NULL) {
+ LIST_REMOVE(ncp, nc_vhash);
+ ncp->nc_vhash.le_prev = NULL;
+ }
+
+ pool_put(&nch_pool, ncp);
+ numcache--;
return (-1);
}
@@ -281,13 +280,12 @@ cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp, char *bufp)
LIST_FOREACH(ncp, nvcpp, nc_vhash) {
if (ncp->nc_vp == vp &&
+ ncp->nc_vpid == vp->v_id &&
(dvp = ncp->nc_dvp) != NULL &&
/* avoid pesky '.' entries.. */
dvp != vp && ncp->nc_dvpid == dvp->v_id) {
+
#ifdef DIAGNOSTIC
- if (ncp->nc_vpid != vp->v_id)
- panic("ncp->nc_vpid %x != vp->v_id %x\n",
- ncp->nc_vpid, vp->v_id);
if (ncp->nc_nlen == 1 &&
ncp->nc_name[0] == '.')
panic("cache_revlookup: found entry for .");
@@ -340,7 +338,6 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
struct namecache *ncp;
struct nchashhead *ncpp;
struct ncvhashhead *nvcpp;
- int hold = 0;
if (!doingcache || cnp->cn_namelen > NCHNAMLEN)
return;
@@ -348,13 +345,22 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
/*
* Free the cache slot at head of lru chain.
*/
- while ((numcache >= desiredvnodes) &&
- ((ncp = TAILQ_FIRST(&nclruhead)) != NULL)){
- cache_delete(ncp);
- }
- ncp = pool_get(&nch_pool, PR_WAITOK);
- bzero((char *)ncp, sizeof *ncp);
- numcache++;
+ if (numcache < desiredvnodes) {
+ ncp = pool_get(&nch_pool, PR_WAITOK);
+ bzero((char *)ncp, sizeof *ncp);
+ numcache++;
+ } else if ((ncp = TAILQ_FIRST(&nclruhead)) != NULL) {
+ TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
+ if (ncp->nc_hash.le_prev != NULL) {
+ LIST_REMOVE(ncp, nc_hash);
+ ncp->nc_hash.le_prev = NULL;
+ }
+ if (ncp->nc_vhash.le_prev != NULL) {
+ LIST_REMOVE(ncp, nc_vhash);
+ ncp->nc_vhash.le_prev = NULL;
+ }
+ } else
+ return;
/* grab the vnode we just found */
ncp->nc_vp = vp;
if (vp)
@@ -368,15 +374,6 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
ncpp = &nchashtbl[NCHASH(dvp, cnp)];
LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
- /* record references to us in various vnodes... */
- if (LIST_EMPTY(&dvp->v_cache_src)) {
- hold = 1;
- numcachehv++;
- }
- LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
- if (vp)
- TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst);
-
/*
* Create reverse-cache entries (used in getcwd) for
* directories.
@@ -392,8 +389,6 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
nvcpp = &ncvhashtbl[NCVHASH(vp)];
LIST_INSERT_HEAD(nvcpp, ncp, nc_vhash);
}
- if (hold)
- vhold(dvp);
}
/*
@@ -402,6 +397,7 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
void
nchinit(void)
{
+
TAILQ_INIT(&nclruhead);
nchashtbl = hashinit(desiredvnodes, M_CACHE, M_WAITOK, &nchash);
ncvhashtbl = hashinit(desiredvnodes/8, M_CACHE, M_WAITOK, &ncvhash);
@@ -409,45 +405,6 @@ nchinit(void)
&pool_allocator_nointr);
}
-void
-cache_delete (struct namecache *ncp)
-{
- /*
- * just make it go away...
- */
- struct vnode *vp = NULL;
- /*
- * XXX abuse of the queue macro internals is endemic to this
- * and needs fixing - for now this is inherited from earlier evil.
- */
- if (ncp->nc_lru.tqe_prev != NULL) {
- TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
- ncp->nc_lru.tqe_prev = NULL;
- }
- if (ncp->nc_hash.le_prev != NULL) {
- LIST_REMOVE(ncp, nc_hash);
- ncp->nc_hash.le_prev = NULL;
- }
- if (ncp->nc_vhash.le_prev != NULL) {
- LIST_REMOVE(ncp, nc_vhash);
- ncp->nc_vhash.le_prev = NULL;
- }
- LIST_REMOVE(ncp, nc_src);
- if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) {
- vp = ncp->nc_dvp;
- numcachehv--;
- }
- if (ncp->nc_vp)
- TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
- ncp->nc_vp = NULL;
- ncp->nc_dvp = NULL;
- pool_put(&nch_pool, ncp);
- numcache--;
- if (vp) {
- vdrop(vp);
- }
-}
-
/*
* Cache flush, a particular vnode; called when a vnode is renamed to
* hide entries that would now be invalid
@@ -458,12 +415,6 @@ cache_purge(struct vnode *vp)
struct namecache *ncp;
struct nchashhead *ncpp;
- while (!LIST_EMPTY(&vp->v_cache_src)) {
- cache_delete(LIST_FIRST(&vp->v_cache_src));
- }
- while (!TAILQ_EMPTY(&vp->v_cache_dst)) {
- cache_delete(TAILQ_FIRST(&vp->v_cache_dst));
- }
vp->v_id = ++nextvnodeid;
if (nextvnodeid != 0)
return;
@@ -491,6 +442,18 @@ cache_purgevfs(struct mount *mp)
if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp)
continue;
/* free the resources we had */
- cache_delete(ncp);
+ ncp->nc_vp = NULL;
+ ncp->nc_dvp = NULL;
+ TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
+ if (ncp->nc_hash.le_prev != NULL) {
+ LIST_REMOVE(ncp, nc_hash);
+ ncp->nc_hash.le_prev = NULL;
+ }
+ if (ncp->nc_vhash.le_prev != NULL) {
+ LIST_REMOVE(ncp, nc_vhash);
+ ncp->nc_vhash.le_prev = NULL;
+ }
+ pool_put(&nch_pool, ncp);
+ numcache--;
}
}
diff --git a/sys/kern/vfs_getcwd.c b/sys/kern/vfs_getcwd.c
index d05b3ba609b..99c52dfe584 100644
--- a/sys/kern/vfs_getcwd.c
+++ b/sys/kern/vfs_getcwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_getcwd.c,v 1.10 2007/05/29 05:28:53 beck Exp $ */
+/* $OpenBSD: vfs_getcwd.c,v 1.11 2007/05/30 04:27:42 beck Exp $ */
/* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */
/*
@@ -239,17 +239,17 @@ vfs_getcwd_getcache(struct vnode **lvpp, struct vnode **uvpp, char **bpp,
if (error)
*uvpp = NULL;
-
-#ifdef DIAGNOSTIC
- /* XXX should not happen with vhold/vdrop in cache layer now. */
- if (vpid != uvp->v_id)
- panic("vpid %d != uvp->v_id %d\n");
-#endif
- if (error) {
+ /*
+ * Verify that vget() succeeded, and check that vnode capability
+ * didn't change while we were waiting for the lock.
+ */
+ if (error || (vpid != uvp->v_id)) {
/*
* Try to get our lock back. If that works, tell the caller to
* try things the hard way, otherwise give up.
*/
+ if (!error)
+ vput(uvp);
*uvpp = NULL;
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 0a5ce5265dd..0aec0ef126d 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.150 2007/05/29 05:28:54 beck Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.151 2007/05/30 04:27:42 beck Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -339,50 +339,47 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
{
struct proc *p = curproc;
struct freelst *listhd;
+ static int toggle;
struct vnode *vp;
int s;
/*
- * Allocate a new vnode if we have less than the desired
- * number allocated, otherwise, recycle one. Generally we only
+ * We must choose whether to allocate a new vnode or recycle an
+ * existing one. The criterion for allocating a new one is that
+ * the total number of vnodes is less than the number desired or
+ * there are no vnodes on either free list. Generally we only
* want to recycle vnodes that have no buffers associated with
- * them, so we look first on the vnode_free_list. If it is
- * empty, we next consider vnodes with referencing buffers on
- * the vnode_hold_list. We are reticent to recycle vnodes from
- * the vnode_hold_list because we will lose the identity of
- * all its referencing buffers.
+ * them, so we look first on the vnode_free_list. If it is empty,
+ * we next consider vnodes with referencing buffers on the
+ * vnode_hold_list. The toggle ensures that half the time we
+ * will use a buffer from the vnode_hold_list, and half the time
+ * we will allocate a new one unless the list has grown to twice
+ * the desired size. We are reticent to recycle vnodes from the
+ * vnode_hold_list because we will lose the identity of all its
+ * referencing buffers.
*/
- simple_lock(&vnode_free_list_slock);
+ toggle ^= 1;
+ if (numvnodes > 2 * desiredvnodes)
+ toggle = 0;
+
s = splbio();
- if (numvnodes < desiredvnodes) {
+ if ((numvnodes < desiredvnodes) ||
+ ((TAILQ_FIRST(listhd = &vnode_free_list) == NULL) &&
+ ((TAILQ_FIRST(listhd = &vnode_hold_list) == NULL) || toggle))) {
splx(s);
vp = pool_get(&vnode_pool, PR_WAITOK);
bzero((char *)vp, sizeof *vp);
- LIST_INIT(&vp->v_cache_src);
- TAILQ_INIT(&vp->v_cache_dst);
numvnodes++;
} else {
- for (vp = TAILQ_FIRST(listhd = &vnode_free_list); vp != NULLVP;
+ for (vp = TAILQ_FIRST(listhd); vp != NULLVP;
vp = TAILQ_NEXT(vp, v_freelist)) {
if (VOP_ISLOCKED(vp) == 0)
break;
}
- /*
- * There is nothing on the free list, so we have to try to
- * recycle one off the hold list
- */
- if (vp == NULL) {
- for (vp = TAILQ_FIRST(listhd = &vnode_hold_list);
- vp != NULLVP;
- vp = TAILQ_NEXT(vp, v_freelist)) {
- if ((VOP_ISLOCKED(vp) == 0) && (vp->v_holdcnt == 0))
- break;
- }
- }
/*
- * We have made a pass through both the free and hold list
- * and not encountered an unlocked entry. So this is close
- * enough to being empty.
+ * Unless this is a bad time of the month, at most
+ * the first NCPUS items on the free list are
+ * locked, so this is close enough to being empty.
*/
if (vp == NULL) {
splx(s);
@@ -396,11 +393,6 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
vprint("free vnode", vp);
panic("free vnode isn't");
}
-
- if (vp->v_holdcnt) {
- vprint("held vnode", vp);
- panic("unheld vnode being held!");
- }
#endif
TAILQ_REMOVE(listhd, vp, v_freelist);
@@ -766,7 +758,7 @@ vrele(struct vnode *vp)
void vhold(struct vnode *vp);
/*
- * declare interest in a vnode.
+ * Page or buffer structure gets a reference.
*/
void
vhold(struct vnode *vp)
@@ -783,27 +775,6 @@ vhold(struct vnode *vp)
vp->v_holdcnt++;
}
-void vdrop(struct vnode *vp);
-
-/*
- * lose interest in a vnode
- */
-void
-vdrop(struct vnode *vp)
-{
- vp->v_holdcnt--;
-
- /*
- * If it is on the holdlist and the hold count drops to
- * zero, move it to the free list.
- */
- if ((vp->v_bioflag & VBIOONFREELIST) &&
- vp->v_holdcnt == 0 && vp->v_usecount == 0) {
- TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
- TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
- }
-}
-
/*
* Remove any vnodes in the vnode table belonging to mount point mp.
*
@@ -2022,7 +1993,17 @@ brelvp(struct buf *bp)
if (vp->v_holdcnt == 0)
panic("brelvp: holdcnt");
#endif
- vdrop(vp);
+ vp->v_holdcnt--;
+
+ /*
+ * If it is on the holdlist and the hold count drops to
+ * zero, move it to the free list.
+ */
+ if ((vp->v_bioflag & VBIOONFREELIST) &&
+ vp->v_holdcnt == 0 && vp->v_usecount == 0) {
+ TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
+ TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+ }
}
/*
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index 2cbdfff7538..83cf2ff28b8 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: namei.h,v 1.17 2007/05/29 05:28:54 beck Exp $ */
+/* $OpenBSD: namei.h,v 1.18 2007/05/30 04:27:43 beck Exp $ */
/* $NetBSD: namei.h,v 1.11 1996/02/09 18:25:20 christos Exp $ */
/*
@@ -161,8 +161,6 @@ struct namecache {
LIST_ENTRY(namecache) nc_hash; /* hash chain */
LIST_ENTRY(namecache) nc_vhash; /* (reverse) directory hash chain */
TAILQ_ENTRY(namecache) nc_lru; /* LRU chain */
- LIST_ENTRY(namecache) nc_src; /* source vnodes */
- TAILQ_ENTRY(namecache) nc_dst; /* destination vnodes */
struct vnode *nc_dvp; /* vnode of parent of name */
u_long nc_dvpid; /* capability number of nc_dvp */
struct vnode *nc_vp; /* vnode the name refers to */
@@ -177,7 +175,6 @@ int namei(struct nameidata *ndp);
int lookup(struct nameidata *ndp);
int relookup(struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp);
-void cache_delete(struct namecache *);
void cache_purge(struct vnode *);
int cache_lookup(struct vnode *, struct vnode **, struct componentname *);
void cache_enter(struct vnode *, struct vnode *, struct componentname *);
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 37d0654dd4b..bccd2357db3 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vnode.h,v 1.84 2007/05/29 16:25:07 thib Exp $ */
+/* $OpenBSD: vnode.h,v 1.85 2007/05/30 04:27:43 beck Exp $ */
/* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */
/*
@@ -91,8 +91,6 @@ struct vnode {
u_int v_bioflag;
u_int v_holdcnt; /* buffer references */
u_int v_id; /* capability identifier */
- LIST_HEAD(, namecache) v_cache_src; /* cache entries from us */
- TAILQ_HEAD(, namecache) v_cache_dst; /* cache entries to us */
struct mount *v_mount; /* ptr to vfs we are in */
TAILQ_ENTRY(vnode) v_freelist; /* vnode freelist */
LIST_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */
@@ -407,8 +405,6 @@ void vntblinit(void);
int vwaitforio(struct vnode *, int, char *, int);
void vwakeup(struct vnode *);
void vput(struct vnode *);
-void vhold(struct vnode *);
-void vdrop(struct vnode *);
int vrecycle(struct vnode *, struct proc *);
void vrele(struct vnode *);
void vref(struct vnode *);
diff --git a/sys/xfs/xfs_node-bsd.c b/sys/xfs/xfs_node-bsd.c
index 0ceea050e63..56e4f2d3638 100644
--- a/sys/xfs/xfs_node-bsd.c
+++ b/sys/xfs/xfs_node-bsd.c
@@ -420,8 +420,6 @@ static struct long_entry tbl;
static void
tbl_clear (void)
{
- vdrop(tbl.vp);
- vdrop(tbl.dvp);
tbl.dvp = tbl.vp = NULL;
tbl.name[0] = '\0';
tbl.len = 0;
@@ -435,8 +433,6 @@ tbl_clear (void)
static void
tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
{
- vhold(vp);
- vhold(dvp);
tbl.len = len;
bcopy(name, tbl.name, len);
tbl.dvp = dvp;
@@ -457,15 +453,10 @@ tbl_lookup (struct componentname *cnp,
{
if (tbl.dvp == dvp
&& tbl.len == cnp->cn_namelen
- && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0) {
-#ifdef DIAGNOSTIC
- if (tbl.vpid != tbl.vp->v_id)
- panic("tbl.vpid %x != tbl.vp->v_id %x", tbl.vpid,
- tbl.vp->v_id);
- if (tbl.dvpid != tbl.dvp->v_id)
- panic("tbl.dvpid %x != tbl.dvp->v_id %x", tbl.dvpid,
- tbl.dvp->v_id);
-#endif
+ && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0
+ && tbl.dvpid == tbl.dvp->v_id
+ && tbl.vpid == tbl.vp->v_id) {
+
*res = tbl.vp;
return -1;
} else
@@ -676,10 +667,10 @@ xfs_dnlc_lock(struct vnode *dvp,
xfs_vfs_writelock(dvp, xfs_cnp_to_proc(cnp));
#endif
-#ifdef DIAGNOSTIC
- if (dvp->v_id != vpid)
- panic("dvp->v_id %x != vpid %x", dvp->v_id, vpid);
-#endif
+ if (error == 0 && dvp->v_id != vpid) {
+ vput(*res);
+ return 0;
+ }
} else {
#ifdef HAVE_FREEBSD_THREAD
error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));