Index: vfs_cache.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_cache.c,v retrieving revision 1.82 diff -u -r1.82 vfs_cache.c --- vfs_cache.c 20 Mar 2003 10:40:45 -0000 1.82 +++ vfs_cache.c 8 Jun 2003 11:54:00 -0000 @@ -53,6 +53,8 @@ #include #include +#include + /* * This structure describes the elements in the cache of recent * names looked up by namei. @@ -109,6 +111,31 @@ #endif struct nchstats nchstats; /* cache effectiveness statistics */ +/* + * Cache Zones. + */ +uma_zone_t cache_zone_small; +uma_zone_t cache_zone_large; + +#define CACHE_ZONE_SMALL (sizeof(struct namecache) + 64) +#define CACHE_ZONE_LARGE (sizeof(struct namecache) + NAME_MAX) +#define CACHE_ZONE_ALLOC 0x012 +#define CACHE_ZONE_FREE 0x013 + +static int cache_zone_small_count = 0; +static int cache_zone_large_count = 0; +static int cache_zone_total_count = 0; /* should equal vfs.numcache */ +static int cache_zone_miss_count = 0; /* sigh */ + +SYSCTL_INT(_debug, OID_AUTO, cache_small_count, CTLFLAG_RD, + &cache_zone_small_count, 0, "Small namecache allocations"); +SYSCTL_INT(_debug, OID_AUTO, cache_large_count, CTLFLAG_RD, + &cache_zone_large_count, 0, "Large namecache allocations"); +SYSCTL_INT(_debug, OID_AUTO, cache_miss_count, CTLFLAG_RD, + &cache_zone_miss_count, 0, "Missed namecache allocations"); +SYSCTL_INT(_debug, OID_AUTO, cache_total_count, CTLFLAG_RD, + &cache_zone_total_count, 0, "Total namecache allocations"); + static int doingcache = 1; /* 1 => enable the cache */ SYSCTL_INT(_debug, OID_AUTO, vfscache, CTLFLAG_RW, &doingcache, 0, ""); @@ -228,6 +255,62 @@ SYSCTL_PROC(_debug_hashstat, OID_AUTO, nchash, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_debug_hashstat_nchash, "I", "nchash chain lengths"); +static __inline int +cache_alloc(struct namecache *ncp, u_char len, int flags) +{ + + uma_zone_t zone = NULL; + if (cache_zone_small == NULL) + if (cache_zone_large == NULL) + panic("Invalid Zones!"); + + if (len <= CACHE_ZONE_SMALL) { + printf("Small zone allocation " + "(len = %d)\n", len); + zone = cache_zone_small; + cache_zone_small_count++; + } else if (len <= NAME_MAX) { + printf("Large zone allocation " + "(len = %d)\n", len); + zone = cache_zone_large; + cache_zone_large_count++; + } else { + printf("Missed zone allocation: %d\n", len); + cache_zone_miss_count++; + return (EFBIG); + } + + if (flags & CACHE_ZONE_ALLOC) { + printf("CACHE_ZONE_ALLOC is called\n"); + goto cachealloc; + } + else if (flags & CACHE_ZONE_FREE) { + printf("CACHE_ZONE_FREE is called\n"); + goto cachefree; + } + +cachealloc: + ncp = uma_zalloc(zone, M_WAITOK); + if (ncp != NULL) { + cache_zone_total_count++; + return (0); + } else { + cache_zone_miss_count++; + return (ENOMEM); + } + +cachefree: + if (ncp != NULL) { + uma_zfree(zone, ncp); + return (0); + } else { + printf("Free ncp passed!?!"); + return (EINVAL); + } + + return 0; +} + /* * cache_zap(): * @@ -238,6 +321,7 @@ cache_zap(ncp) struct namecache *ncp; { + int error = 0; LIST_REMOVE(ncp, nc_hash); LIST_REMOVE(ncp, nc_src); if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) { @@ -251,7 +335,13 @@ numneg--; } numcache--; - free(ncp, M_VFSCACHE); + + error = cache_alloc(ncp, ncp->nc_nlen, CACHE_ZONE_FREE); + if (error) { + printf("cache_alloc returned error (%d) \n", error); + return; + } + // free(ncp, M_VFSCACHE); } /* @@ -392,10 +482,10 @@ struct vnode *vp; struct componentname *cnp; { - struct namecache *ncp; + struct namecache *ncp = NULL; struct nchashhead *ncpp; u_int32_t hash; - int len; + int len, error; if (!doingcache) return; @@ -415,9 +505,16 @@ return; } } - + + error = cache_alloc(ncp, cnp->cn_namelen, CACHE_ZONE_ALLOC); + if (error) { + printf("cache_alloc returned error (%d)\n", error); + return; /* XXX do we have to do anything more? */ + } +#if 0 ncp = (struct namecache *) malloc(sizeof *ncp + cnp->cn_namelen, M_VFSCACHE, M_WAITOK); +#endif bzero((char *)ncp, sizeof *ncp); numcache++; if (!vp) { @@ -470,6 +567,19 @@ { TAILQ_INIT(&ncneg); + + u_int16_t cache_zone_flags = UMA_ZONE_ZINIT; + + /* + * Initialise the cache zones. Two zones are used for allocation, + * because storing all components in NAME_MAX sized zones will be + * a space waste (just think about vfs.cache.numcache * 255!) + */ + cache_zone_small = uma_zcreate("CACHESMALL", CACHE_ZONE_SMALL, NULL, + NULL, NULL, NULL, UMA_ALIGN_CACHE, cache_zone_flags); + cache_zone_large = uma_zcreate("CACHELARGE", CACHE_ZONE_LARGE, NULL, + NULL, NULL, NULL, UMA_ALIGN_CACHE, cache_zone_flags); + nchashtbl = hashinit(desiredvnodes * 2, M_VFSCACHE, &nchash); } SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nchinit, NULL)