--- //depot/vendor/freebsd/src/sys/kern/vfs_cache.c 2009/02/19 22:30:40 +++ //depot/user/attilio/attilio_lockmgr/kern/vfs_cache.c 2009/03/06 01:25:51 @@ -53,6 +53,9 @@ #include +#define CACHEZ_UNREM 0x00 +#define CACHEZ_REM 0x01 + /* * This structure describes the elements in the cache of recent * names looked up by namei. @@ -103,10 +106,6 @@ SYSCTL_ULONG(_debug, OID_AUTO, numcache, CTLFLAG_RD, &numcache, 0, ""); static u_long numcachehv; /* number of cache entries with vnodes held */ SYSCTL_ULONG(_debug, OID_AUTO, numcachehv, CTLFLAG_RD, &numcachehv, 0, ""); -#if 0 -static u_long numcachepl; /* number of cache purge for leaf entries */ -SYSCTL_ULONG(_debug, OID_AUTO, numcachepl, CTLFLAG_RD, &numcachepl, 0, ""); -#endif struct nchstats nchstats; /* cache effectiveness statistics */ static struct rwlock cache_lock; @@ -172,7 +171,7 @@ -static void cache_zap(struct namecache *ncp); +static void cache_zap(struct namecache *ncp, int removal); static int vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen); static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen); @@ -276,28 +275,37 @@ * pointer to a vnode or if it is just a negative cache entry. */ static void -cache_zap(ncp) +cache_zap(ncp, removal) struct namecache *ncp; + int removal; { struct vnode *vp; + MPASS(ncp != NULL && ncp->nc_dvp != NULL); rw_assert(&cache_lock, RA_WLOCKED); + mtx_assert(VI_MTX(ncp->nc_dvp), MA_NOTOWNED); CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, ncp->nc_vp); vp = NULL; + LIST_REMOVE(ncp, nc_hash); - LIST_REMOVE(ncp, nc_src); + VI_LOCK(ncp->nc_dvp); + if (removal == CACHEZ_REM) + LIST_REMOVE(ncp, nc_src); if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) { vp = ncp->nc_dvp; - numcachehv--; + atomic_subtract_long(&numcachehv, 1); } + VI_UNLOCK(ncp->nc_dvp); if (ncp->nc_vp) { + VI_LOCK(ncp->nc_vp); TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst); ncp->nc_vp->v_dd = NULL; + VI_UNLOCK(ncp->nc_vp); } else { TAILQ_REMOVE(&ncneg, ncp, nc_dst); - numneg--; + atomic_subtract_long(&numneg, 1); } - numcache--; + atomic_subtract_long(&numcache, 1); cache_free(ncp); if (vp) vdrop(vp); @@ -351,11 +359,14 @@ } if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') { dotdothits++; + VI_LOCK(dvp); if (dvp->v_dd == NULL || (cnp->cn_flags & MAKEENTRY) == 0) { + VI_UNLOCK(dvp); goto unlock; } *vpp = dvp->v_dd; + VI_UNLOCK(dvp); CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..", dvp, cnp->cn_nameptr, *vpp); goto success; @@ -388,7 +399,7 @@ nchstats.ncs_badhits++; if (!wlocked && !CACHE_UPGRADE_LOCK()) goto wlock; - cache_zap(ncp); + cache_zap(ncp, CACHEZ_REM); CACHE_WUNLOCK(); return (0); } @@ -409,7 +420,7 @@ nchstats.ncs_badhits++; if (!wlocked && !CACHE_UPGRADE_LOCK()) goto wlock; - cache_zap(ncp); + cache_zap(ncp, CACHEZ_REM); CACHE_WUNLOCK(); return (0); } @@ -544,10 +555,10 @@ * cache_purge() time. */ if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') { - CACHE_WLOCK(); + VI_LOCK(dvp); if (!TAILQ_EMPTY(&dvp->v_cache_dst)) dvp->v_dd = vp; - CACHE_WUNLOCK(); + VI_UNLOCK(dvp); return; } } @@ -584,14 +595,14 @@ } } - numcache++; + atomic_add_long(&numcache, 1); if (!vp) { - numneg++; + atomic_add_long(&numneg, 1); ncp->nc_flag = cnp->cn_flags & ISWHITEOUT ? NCF_WHITE : 0; - } else if (vp->v_type == VDIR) { - vp->v_dd = dvp; } else { - vp->v_dd = NULL; + VI_LOCK(vp); + vp->v_dd = (vp->v_type == VDIR) ? dvp : NULL; + VI_UNLOCK(vp); } /* @@ -599,18 +610,22 @@ * within the cache entries table. */ LIST_INSERT_HEAD(ncpp, ncp, nc_hash); + VI_LOCK(dvp); if (LIST_EMPTY(&dvp->v_cache_src)) { hold = 1; - numcachehv++; + atomic_add_long(&numcachehv, 1); } LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src); + VI_UNLOCK(dvp); /* * If the entry is "negative", we place it into the * "negative" cache queue, otherwise, we place it into the * destination vnode's cache entries queue. */ if (vp) { + VI_LOCK(vp); TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst); + VI_UNLOCK(vp); } else { TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst); } @@ -621,7 +636,7 @@ if (hold) vhold(dvp); if (zap) - cache_zap(ncp); + cache_zap(ncp, CACHEZ_REM); CACHE_WUNLOCK(); } @@ -651,15 +666,32 @@ cache_purge(vp) struct vnode *vp; { + struct namecache *ncp; + mtx_assert(VI_MTX(vp), MA_NOTOWNED); CTR1(KTR_VFS, "cache_purge(%p)", vp); - CACHE_WLOCK(); - while (!LIST_EMPTY(&vp->v_cache_src)) - cache_zap(LIST_FIRST(&vp->v_cache_src)); - while (!TAILQ_EMPTY(&vp->v_cache_dst)) - cache_zap(TAILQ_FIRST(&vp->v_cache_dst)); + + VI_LOCK(vp); + while (!LIST_EMPTY(&vp->v_cache_src)) { + ncp = LIST_FIRST(&vp->v_cache_src); + LIST_REMOVE(ncp, nc_src); + VI_UNLOCK(vp); + CACHE_WLOCK(); + cache_zap(ncp, CACHEZ_UNREM); + CACHE_WUNLOCK(); + VI_LOCK(vp); + } + while (!TAILQ_EMPTY(&vp->v_cache_dst)) { + ncp = TAILQ_FIRST(&vp->v_cache_dst); + LIST_REMOVE(ncp, nc_src); + VI_UNLOCK(vp); + CACHE_WLOCK(); + cache_zap(ncp, CACHEZ_UNREM); + CACHE_WUNLOCK(); + VI_LOCK(vp); + } vp->v_dd = NULL; - CACHE_WUNLOCK(); + VI_UNLOCK(vp); } /* @@ -672,12 +704,18 @@ struct namecache *cp, *ncp; CTR1(KTR_VFS, "cache_purge_negative(%p)", vp); - CACHE_WLOCK(); + VI_LOCK(vp); LIST_FOREACH_SAFE(cp, &vp->v_cache_src, nc_src, ncp) { - if (cp->nc_vp == NULL) - cache_zap(cp); + if (cp->nc_vp == NULL) { + LIST_REMOVE(cp, nc_src); + VI_UNLOCK(vp); + CACHE_WLOCK(); + cache_zap(cp, CACHEZ_UNREM); + CACHE_WUNLOCK(); + VI_LOCK(vp); + } } - CACHE_WUNLOCK(); + VI_UNLOCK(vp); } /* @@ -695,7 +733,7 @@ for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) { LIST_FOREACH_SAFE(ncp, ncpp, nc_hash, nnp) { if (ncp->nc_dvp->v_mount == mp) - cache_zap(ncp); + cache_zap(ncp, CACHEZ_REM); } } CACHE_WUNLOCK(); @@ -943,7 +981,9 @@ CACHE_RLOCK(); numfullpathcalls++; if (vp->v_type != VDIR) { + VI_LOCK(vp); ncp = TAILQ_FIRST(&vp->v_cache_dst); + VI_UNLOCK(vp); if (ncp != NULL) { for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--) *--bp = ncp->nc_name[i]; @@ -984,7 +1024,9 @@ error = ENOTDIR; break; } + VI_LOCK(vp); ncp = TAILQ_FIRST(&vp->v_cache_dst); + VI_UNLOCK(vp); if (ncp != NULL) { MPASS(vp->v_dd == NULL || ncp->nc_dvp == vp->v_dd); buflen -= ncp->nc_nlen - 1; @@ -1037,12 +1079,12 @@ struct namecache *ncp; int l; - CACHE_RLOCK(); + VI_LOCK(vp); ncp = TAILQ_FIRST(&vp->v_cache_dst); - if (!ncp) { - CACHE_RUNLOCK(); + VI_UNLOCK(vp); + if (ncp == NULL) return (ENOENT); - } + CACHE_RLOCK(); l = min(ncp->nc_nlen, buflen - 1); memcpy(buf, ncp->nc_name, l); CACHE_RUNLOCK(); --- //depot/vendor/freebsd/src/sys/sys/vnode.h 2009/02/19 22:30:40 +++ //depot/user/attilio/attilio_lockmgr/sys/vnode.h 2009/03/06 01:25:51 @@ -73,7 +73,6 @@ * Reading or writing any of these items requires holding the appropriate lock. * * Lock reference: - * c - namecache mutex * f - freelist mutex * G - Giant * i - interlock @@ -133,9 +132,9 @@ /* * VFS_namecache stuff */ - LIST_HEAD(, namecache) v_cache_src; /* c Cache entries from us */ - TAILQ_HEAD(, namecache) v_cache_dst; /* c Cache entries to us */ - struct vnode *v_dd; /* c .. vnode */ + LIST_HEAD(, namecache) v_cache_src; /* i Cache entries from us */ + TAILQ_HEAD(, namecache) v_cache_dst; /* i Cache entries to us */ + struct vnode *v_dd; /* i .. vnode */ /* * clustering stuff