137487Smckusick /* 237487Smckusick * Copyright (c) 1989 The Regents of the University of California. 337487Smckusick * All rights reserved. 437487Smckusick * 544455Sbostic * %sccs.include.redist.c% 637487Smckusick * 7*55544Smckusick * @(#)vfs_cache.c 7.13 (Berkeley) 07/22/92 837487Smckusick */ 937487Smckusick 1037487Smckusick #include "param.h" 1137487Smckusick #include "systm.h" 1237487Smckusick #include "time.h" 1345117Smckusick #include "mount.h" 1437487Smckusick #include "vnode.h" 1537487Smckusick #include "namei.h" 1638768Smckusick #include "errno.h" 1740881Smckusick #include "malloc.h" 1837487Smckusick 1937487Smckusick /* 2037487Smckusick * Name caching works as follows: 2137487Smckusick * 2237487Smckusick * Names found by directory scans are retained in a cache 2337487Smckusick * for future reference. It is managed LRU, so frequently 2437487Smckusick * used names will hang around. Cache is indexed by hash value 2538768Smckusick * obtained from (vp, name) where vp refers to the directory 2638768Smckusick * containing name. 2737487Smckusick * 2837487Smckusick * For simplicity (and economy of storage), names longer than 2937487Smckusick * a maximum length of NCHNAMLEN are not cached; they occur 3037487Smckusick * infrequently in any case, and are almost never of interest. 3137487Smckusick * 3237487Smckusick * Upon reaching the last segment of a path, if the reference 3337487Smckusick * is for DELETE, or NOCACHE is set (rewrite), and the 3437487Smckusick * name is located in the cache, it will be dropped. 3537487Smckusick */ 3637487Smckusick 3737487Smckusick /* 3837487Smckusick * Structures associated with name cacheing. 3937487Smckusick */ 40*55544Smckusick struct namecache **nchashtbl; 4140881Smckusick u_long nchash; /* size of hash table - 1 */ 4240881Smckusick long numcache; /* number of cache entries allocated */ 4337487Smckusick struct namecache *nchhead, **nchtail; /* LRU chain pointers */ 4437487Smckusick struct nchstats nchstats; /* cache effectiveness statistics */ 4537487Smckusick 4638768Smckusick int doingcache = 1; /* 1 => enable the cache */ 4738768Smckusick 4837487Smckusick /* 4937487Smckusick * Look for a the name in the cache. We don't do this 5037487Smckusick * if the segment name is long, simply so the cache can avoid 5137487Smckusick * holding long names (which would either waste space, or 5237487Smckusick * add greatly to the complexity). 5338768Smckusick * 5438768Smckusick * Lookup is called with ni_dvp pointing to the directory to search, 5538768Smckusick * ni_ptr pointing to the name of the entry being sought, ni_namelen 5638768Smckusick * tells the length of the name, and ni_hash contains a hash of 5738768Smckusick * the name. If the lookup succeeds, the vnode is returned in ni_vp 5838768Smckusick * and a status of -1 is returned. If the lookup determines that 5938768Smckusick * the name does not exist (negative cacheing), a status of ENOENT 6038768Smckusick * is returned. If the lookup fails, a status of zero is returned. 6137487Smckusick */ 6252231Sheideman int 6352306Sheideman cache_lookup(dvp, vpp, cnp) 6452231Sheideman struct vnode *dvp; 6552231Sheideman struct vnode **vpp; 6652231Sheideman struct componentname *cnp; 6737487Smckusick { 68*55544Smckusick register struct namecache *ncp, *ncq, **ncpp; 6937487Smckusick 7038768Smckusick if (!doingcache) 7138768Smckusick return (0); 7252231Sheideman if (cnp->cn_namelen > NCHNAMLEN) { 7337487Smckusick nchstats.ncs_long++; 7452231Sheideman cnp->cn_flags &= ~MAKEENTRY; 7537487Smckusick return (0); 7637487Smckusick } 77*55544Smckusick ncpp = &nchashtbl[cnp->cn_hash & nchash]; 78*55544Smckusick for (ncp = *ncpp; ncp; ncp = ncp->nc_forw) { 7938768Smckusick if (ncp->nc_dvp == dvp && 8038768Smckusick ncp->nc_dvpid == dvp->v_id && 8152231Sheideman ncp->nc_nlen == cnp->cn_namelen && 82*55544Smckusick !bcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen)) 8337487Smckusick break; 8437487Smckusick } 85*55544Smckusick if (ncp == NULL) { 8637487Smckusick nchstats.ncs_miss++; 8737487Smckusick return (0); 8837487Smckusick } 8952231Sheideman if (!(cnp->cn_flags & MAKEENTRY)) { 9038768Smckusick nchstats.ncs_badhits++; 9138768Smckusick } else if (ncp->nc_vp == NULL) { 9252306Sheideman if (cnp->cn_nameiop != CREATE) { 9346747Smckusick nchstats.ncs_neghits++; 9446747Smckusick /* 9546747Smckusick * Move this slot to end of LRU chain, 9646747Smckusick * if not already there. 9746747Smckusick */ 9846747Smckusick if (ncp->nc_nxt) { 9946747Smckusick /* remove from LRU chain */ 10046747Smckusick *ncp->nc_prev = ncp->nc_nxt; 10146747Smckusick ncp->nc_nxt->nc_prev = ncp->nc_prev; 10246747Smckusick /* and replace at end of it */ 10346747Smckusick ncp->nc_nxt = NULL; 10446747Smckusick ncp->nc_prev = nchtail; 10546747Smckusick *nchtail = ncp; 10646747Smckusick nchtail = &ncp->nc_nxt; 10746747Smckusick } 10846747Smckusick return (ENOENT); 10937487Smckusick } 11038768Smckusick } else if (ncp->nc_vpid != ncp->nc_vp->v_id) { 11138768Smckusick nchstats.ncs_falsehits++; 11238768Smckusick } else { 11337487Smckusick nchstats.ncs_goodhits++; 11438768Smckusick /* 11538768Smckusick * move this slot to end of LRU chain, if not already there 11638768Smckusick */ 11738768Smckusick if (ncp->nc_nxt) { 11838768Smckusick /* remove from LRU chain */ 11938768Smckusick *ncp->nc_prev = ncp->nc_nxt; 12038768Smckusick ncp->nc_nxt->nc_prev = ncp->nc_prev; 12138768Smckusick /* and replace at end of it */ 12238768Smckusick ncp->nc_nxt = NULL; 12338768Smckusick ncp->nc_prev = nchtail; 12438768Smckusick *nchtail = ncp; 12538768Smckusick nchtail = &ncp->nc_nxt; 12638768Smckusick } 12752231Sheideman *vpp = ncp->nc_vp; 12838768Smckusick return (-1); 12937487Smckusick } 13037487Smckusick 13137487Smckusick /* 13237487Smckusick * Last component and we are renaming or deleting, 13337487Smckusick * the cache entry is invalid, or otherwise don't 13437487Smckusick * want cache entry to exist. 13537487Smckusick */ 13637487Smckusick /* remove from LRU chain */ 137*55544Smckusick if (ncq = ncp->nc_nxt) 138*55544Smckusick ncq->nc_prev = ncp->nc_prev; 13937487Smckusick else 14037487Smckusick nchtail = ncp->nc_prev; 141*55544Smckusick *ncp->nc_prev = ncq; 14238768Smckusick /* remove from hash chain */ 143*55544Smckusick if (ncq = ncp->nc_forw) 144*55544Smckusick ncq->nc_back = ncp->nc_back; 145*55544Smckusick *ncp->nc_back = ncq; 146*55544Smckusick /* and make a dummy hash chain */ 147*55544Smckusick ncp->nc_forw = NULL; 148*55544Smckusick ncp->nc_back = NULL; 14937487Smckusick /* insert at head of LRU list (first to grab) */ 15037487Smckusick ncp->nc_nxt = nchhead; 15137487Smckusick ncp->nc_prev = &nchhead; 15237487Smckusick nchhead->nc_prev = &ncp->nc_nxt; 15337487Smckusick nchhead = ncp; 15437487Smckusick return (0); 15537487Smckusick } 15637487Smckusick 15737487Smckusick /* 15837487Smckusick * Add an entry to the cache 15937487Smckusick */ 16052306Sheideman cache_enter(dvp, vp, cnp) 16152231Sheideman struct vnode *dvp; 16252231Sheideman struct vnode *vp; 16352231Sheideman struct componentname *cnp; 16437487Smckusick { 165*55544Smckusick register struct namecache *ncp, *ncq, **ncpp; 16637487Smckusick 16755185Smckusick #ifdef DIAGNOSTIC 16855185Smckusick if (cnp->cn_namelen > NCHNAMLEN) 16955185Smckusick panic("cache_enter: name too long"); 17055185Smckusick #endif 17138768Smckusick if (!doingcache) 17238768Smckusick return; 17337487Smckusick /* 17437487Smckusick * Free the cache slot at head of lru chain. 17537487Smckusick */ 17640881Smckusick if (numcache < desiredvnodes) { 17740881Smckusick ncp = (struct namecache *) 17845117Smckusick malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK); 17940881Smckusick bzero((char *)ncp, sizeof *ncp); 18040881Smckusick numcache++; 18140881Smckusick } else if (ncp = nchhead) { 18237487Smckusick /* remove from lru chain */ 183*55544Smckusick if (ncq = ncp->nc_nxt) 184*55544Smckusick ncq->nc_prev = ncp->nc_prev; 18537487Smckusick else 18637487Smckusick nchtail = ncp->nc_prev; 187*55544Smckusick *ncp->nc_prev = ncq; 18838768Smckusick /* remove from old hash chain */ 189*55544Smckusick if (ncq = ncp->nc_forw) 190*55544Smckusick ncq->nc_back = ncp->nc_back; 191*55544Smckusick *ncp->nc_back = ncq; 19240881Smckusick } else 19340881Smckusick return; 19440881Smckusick /* grab the vnode we just found */ 19552231Sheideman ncp->nc_vp = vp; 19652231Sheideman if (vp) 19752231Sheideman ncp->nc_vpid = vp->v_id; 19840881Smckusick else 19940881Smckusick ncp->nc_vpid = 0; 20040881Smckusick /* fill in cache info */ 20152231Sheideman ncp->nc_dvp = dvp; 20252231Sheideman ncp->nc_dvpid = dvp->v_id; 20352231Sheideman ncp->nc_nlen = cnp->cn_namelen; 20452231Sheideman bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen); 20540881Smckusick /* link at end of lru chain */ 20640881Smckusick ncp->nc_nxt = NULL; 20740881Smckusick ncp->nc_prev = nchtail; 20840881Smckusick *nchtail = ncp; 20940881Smckusick nchtail = &ncp->nc_nxt; 21040881Smckusick /* and insert on hash chain */ 211*55544Smckusick ncpp = &nchashtbl[cnp->cn_hash & nchash]; 212*55544Smckusick if (ncq = *ncpp) 213*55544Smckusick ncq->nc_back = &ncp->nc_forw; 214*55544Smckusick ncp->nc_forw = ncq; 215*55544Smckusick ncp->nc_back = ncpp; 216*55544Smckusick *ncpp = ncp; 21737487Smckusick } 21837487Smckusick 21937487Smckusick /* 22040881Smckusick * Name cache initialization, from vfs_init() when we are booting 22137487Smckusick */ 22237487Smckusick nchinit() 22337487Smckusick { 22437487Smckusick 22537487Smckusick nchtail = &nchhead; 226*55544Smckusick nchashtbl = hashinit(desiredvnodes, M_CACHE, &nchash); 22737487Smckusick } 22837487Smckusick 22937487Smckusick /* 23037487Smckusick * Cache flush, a particular vnode; called when a vnode is renamed to 23138768Smckusick * hide entries that would now be invalid 23237487Smckusick */ 23337487Smckusick cache_purge(vp) 23438768Smckusick struct vnode *vp; 23537487Smckusick { 236*55544Smckusick struct namecache *ncp, **ncpp; 23737487Smckusick 23838768Smckusick vp->v_id = ++nextvnodeid; 23938768Smckusick if (nextvnodeid != 0) 24038768Smckusick return; 241*55544Smckusick for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) { 242*55544Smckusick for (ncp = *ncpp; ncp; ncp = ncp->nc_forw) { 24340881Smckusick ncp->nc_vpid = 0; 24440881Smckusick ncp->nc_dvpid = 0; 24540881Smckusick } 24637487Smckusick } 24738768Smckusick vp->v_id = ++nextvnodeid; 24837487Smckusick } 24937487Smckusick 25037487Smckusick /* 25137487Smckusick * Cache flush, a whole filesystem; called when filesys is umounted to 25237487Smckusick * remove entries that would now be invalid 25337487Smckusick * 25437487Smckusick * The line "nxtcp = nchhead" near the end is to avoid potential problems 25537487Smckusick * if the cache lru chain is modified while we are dumping the 25637487Smckusick * inode. This makes the algorithm O(n^2), but do you think I care? 25737487Smckusick */ 25837487Smckusick cache_purgevfs(mp) 25945117Smckusick struct mount *mp; 26037487Smckusick { 26137487Smckusick register struct namecache *ncp, *nxtcp; 26237487Smckusick 26337487Smckusick for (ncp = nchhead; ncp; ncp = nxtcp) { 264*55544Smckusick if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp) { 265*55544Smckusick nxtcp = ncp->nc_nxt; 26637487Smckusick continue; 267*55544Smckusick } 26837487Smckusick /* free the resources we had */ 26937487Smckusick ncp->nc_vp = NULL; 27038768Smckusick ncp->nc_dvp = NULL; 271*55544Smckusick /* remove entry from its hash chain */ 272*55544Smckusick if (nxtcp = ncp->nc_forw) 273*55544Smckusick nxtcp->nc_back = ncp->nc_back; 274*55544Smckusick *ncp->nc_back = nxtcp; 275*55544Smckusick ncp->nc_forw = NULL; 276*55544Smckusick ncp->nc_back = NULL; 27737487Smckusick /* delete this entry from LRU chain */ 278*55544Smckusick if (nxtcp = ncp->nc_nxt) 27937487Smckusick nxtcp->nc_prev = ncp->nc_prev; 28037487Smckusick else 28137487Smckusick nchtail = ncp->nc_prev; 282*55544Smckusick *ncp->nc_prev = nxtcp; 28337487Smckusick /* cause rescan of list, it may have altered */ 28437487Smckusick nxtcp = nchhead; 28537487Smckusick /* put the now-free entry at head of LRU */ 28637487Smckusick ncp->nc_nxt = nxtcp; 28737487Smckusick ncp->nc_prev = &nchhead; 28837487Smckusick nxtcp->nc_prev = &ncp->nc_nxt; 28937487Smckusick nchhead = ncp; 29037487Smckusick } 29137487Smckusick } 292