📄 vfs_dnlc.c
字号:
if (tvp != (struct vnode *) 0) { VN_RELE(tvp); }}/* * Look up a name in the directory name cache. *//* * This routine has been changed to handle locking of * the directory name lookup cache and to bump the ref count * the vnode found during the lookup before it is returned to the * caller. This lets us keep all the dnlc smp locking in this file. */struct vnode *dnlc_lookup(dp, name, cred) struct vnode *dp; register char *name; struct ucred *cred;{ register int namlen; register int hash; register struct ncache *ncp; register struct tvp; struct vnode *tvp; if (!dnlc_cache) { return ((struct vnode *) 0); } namlen = strlen(name); if (namlen > NC_NAMLEN) { /* SMP lock name cache statistics during access */ smp_lock(&lk_nfsdnlc, LK_RETRY); ncstats.long_look++; smp_unlock(&lk_nfsdnlc); return ((struct vnode *) 0); } hash = NC_HASH1(name, namlen, dp); /* SMP lock directory name cache during access */ smp_lock(&lk_nfsdnlc, LK_RETRY); ncp = dnlc_search(dp, name, namlen, hash, cred); if (ncp == (struct ncache *) 0) { ncstats.misses++; smp_unlock(&lk_nfsdnlc); return ((struct vnode *) 0); } ncstats.hits++; /* * Move this slot to the end of LRU * chain. */ RM_LRU(ncp); INS_LRU(ncp, nc_lru.lru_prev); /* * If not at the head of the hash chain, * move forward so will be found * earlier if looked up again. */ if (ncp->hash1_prev != (struct ncache *) &nc_hash1[hash]) { RM_HASH1(ncp); INS_HASH1(ncp, ncp->hash1_prev->hash1_prev); } tvp = ncp->vp; VN_HOLD(tvp); smp_unlock(&lk_nfsdnlc); return (tvp);}/* * Remove an entry in the directory name cache. */dnlc_remove(dp, name) struct vnode *dp; register char *name;{ register int namlen; register struct ncache *ncp; int hash; namlen = strlen(name); if (namlen > NC_NAMLEN) { return; } hash = NC_HASH1(name, namlen, dp); /* SMP lock access to directory name lookup cache */ smp_lock(&lk_nfsdnlc, LK_RETRY); while (ncp = dnlc_search(dp, name, namlen, hash, ANYCRED)) { dnlc_rm(ncp); } smp_unlock(&lk_nfsdnlc);}/* * Purge the entire cache. */dnlc_purge(){ register struct nc_hash *nch; register struct ncache *ncp; /* SMP lock access to directory name lookup cache */ smp_lock(&lk_nfsdnlc, LK_RETRY); ncstats.purges++;start: for (nch = nc_hash1; nch < &nc_hash1[nchashsize]; nch++) { ncp = nch->hash1_next; while (ncp != (struct ncache *) nch) { if (ncp->dp == 0 || ncp->vp == 0) { panic("dnlc_purge: zero vp"); } dnlc_rm(ncp); goto start; } } smp_unlock(&lk_nfsdnlc);}/* * Purge any cache entries referencing a vnode. */dnlc_purge_vp(vp) register struct vnode *vp;{ register int moretodo, hash; register struct nc_hash *nhp; register struct ncache *ncp; register int hitcnt = 0; /* SMP lock access to directory name lookup cache */ smp_lock(&lk_nfsdnlc, LK_RETRY); ncstats.purgevp++; do { moretodo = 0; hash = NC_HASH2(vp); (struct nc_hash *) ncp = nhp = &nc_hash2[hash]; while ((ncp = ncp->hash2_next) != (struct ncache *) nhp) { if (ncp->dp == vp) { dnlc_rm(ncp); moretodo = 1; hitcnt++; break; } } hash = NC_HASH3(vp); (struct nc_hash *) ncp = nhp = &nc_hash3[hash]; while ((ncp = ncp->hash3_next) != (struct ncache *) nhp) { if (ncp->vp == vp) { dnlc_rm(ncp); moretodo = 1; hitcnt++; break; } } } while (moretodo); if (hitcnt) ncstats.purgevpworked++; smp_unlock(&lk_nfsdnlc);}/* * Purge any cache entry. * Called by iget when inode freelist is empty. */dnlc_purge1(){ register struct ncache *ncp; smp_lock(&lk_nfsdnlc, LK_RETRY); for (ncp = nc_lru.lru_next; ncp != (struct ncache *) &nc_lru; ncp = ncp->lru_next) { if (ncp->dp && (((struct gnode *)ncp->vp)->g_count == 1 || (ncp->vp && ((struct gnode *)ncp->dp)->g_count == 1))) { dnlc_rm(ncp); ncstats.purge1yes++; smp_unlock(&lk_nfsdnlc); return (1); } } ncstats.purge1no++; smp_unlock(&lk_nfsdnlc); return (0);}/* * Obliterate a cache entry. *//* * Now assumes lk_nfsdnlc is held. This is unlocked long enough * to grele the gnodes associated with the cache entry. */staticdnlc_rm(ncp) register struct ncache *ncp;{ register struct vnode *tdp; register struct vnode *tvp; /* * Remove from LRU, hash chains. */ RM_LRU(ncp); if (NOT_NULL1(ncp)) { ncstats.hashedentries--; RM_HASH1(ncp); RM_HASH2(ncp); RM_HASH3(ncp); } /* * Release ref on vnodes. *//* VN_RELE(ncp->dp); */ tdp = ncp->dp; ncp->dp = (struct vnode *) 0;/* VN_RELE(ncp->vp); */ tvp = ncp->vp; ncp->vp = (struct vnode *) 0; if (ncp->cred != NOCRED) { crfree(ncp->cred); ncp->cred = NOCRED; } /* * Insert at head of LRU list (first to grab). */ INS_LRU(ncp, &nc_lru); /* * And make a dummy hash chain. */ NULL_HASH1(ncp); NULL_HASH2(ncp); NULL_HASH3(ncp); smp_unlock(&lk_nfsdnlc); VN_RELE(tdp); VN_RELE(tvp); smp_lock(&lk_nfsdnlc, LK_RETRY);}/* * Utility routine to search for a cache entry. */static struct ncache *dnlc_search(dp, name, namlen, hash, cred) register struct vnode *dp; register char *name; register int namlen; int hash; struct ucred *cred;{ register struct nc_hash *nhp; register struct ncache *ncp; nhp = &nc_hash1[hash]; for (ncp = nhp->hash1_next; ncp != (struct ncache *) nhp; ncp = ncp->hash1_next) { if (ncp->dp == dp && ncp->namlen == namlen && *ncp->name == *name && /* fast chk 1st chr */ bcmp(ncp->name, name, namlen) == 0 && (cred == ANYCRED || ncp->cred == cred || (cred->cr_uid == ncp->cred->cr_uid && cred->cr_gid == ncp->cred->cr_gid && bcmp((caddr_t)cred->cr_groups, (caddr_t)ncp->cred->cr_groups, NGROUPS * sizeof(cred->cr_groups[0])) == 0))) { return (ncp); } } return ((struct ncache *) 0);}/* * Insert into queue, where the queue pointers are * not in the first two longwords. * Should be in assembler like insque. */staticinsque2(ncp2, ncp1) register struct ncache *ncp2, *ncp1;{ register struct ncache *ncp3; ncp3 = ncp1->hash2_next; ncp1->hash2_next = ncp2; ncp2->hash2_next = ncp3; ncp3->hash2_prev = ncp2; ncp2->hash2_prev = ncp1;}staticinsque3(ncp2, ncp1) register struct ncache *ncp2, *ncp1;{ register struct ncache *ncp3; ncp3 = ncp1->hash3_next; ncp1->hash3_next = ncp2; ncp2->hash3_next = ncp3; ncp3->hash3_prev = ncp2; ncp2->hash3_prev = ncp1;}staticinsque4(ncp2, ncp1) register struct ncache *ncp2, *ncp1;{ register struct ncache *ncp3; ncp3 = ncp1->lru_next; ncp1->lru_next = ncp2; ncp2->lru_next = ncp3; ncp3->lru_prev = ncp2; ncp2->lru_prev = ncp1;}/* * Remove from queue, like insque2, insque3, insque4. */staticremque2(ncp) register struct ncache *ncp;{ ncp->hash2_prev->hash2_next = ncp->hash2_next; ncp->hash2_next->hash2_prev = ncp->hash2_prev;}staticremque3(ncp) register struct ncache *ncp;{ ncp->hash3_prev->hash3_next = ncp->hash3_next; ncp->hash3_next->hash3_prev = ncp->hash3_prev;}staticremque4(ncp) register struct ncache *ncp;{ ncp->lru_prev->lru_next = ncp->lru_next; ncp->lru_next->lru_prev = ncp->lru_prev;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -