diff options
author | Bob Beck <beck@cvs.openbsd.org> | 2007-05-30 04:27:44 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 2007-05-30 04:27:44 +0000 |
commit | 63fc4e315f0893c9554193f74b2a056de91af696 (patch) | |
tree | eba15b44fd77f600449d301128e7fe5966c3f823 | |
parent | 54f7b30b37ba36f7ac06d3f70c0ca4244b9d0a93 (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.c | 137 | ||||
-rw-r--r-- | sys/kern/vfs_getcwd.c | 16 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 93 | ||||
-rw-r--r-- | sys/sys/namei.h | 5 | ||||
-rw-r--r-- | sys/sys/vnode.h | 6 | ||||
-rw-r--r-- | sys/xfs/xfs_node-bsd.c | 25 |
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)); |