summaryrefslogtreecommitdiffstats
path: root/fs/coda/namecache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/namecache.c')
-rw-r--r--fs/coda/namecache.c832
1 files changed, 0 insertions, 832 deletions
diff --git a/fs/coda/namecache.c b/fs/coda/namecache.c
deleted file mode 100644
index 08f1ee9e7..000000000
--- a/fs/coda/namecache.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- * Cache operations for Coda.
- * Original version: (C) 1996 Peter Braam
- * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
- *
- * Carnegie Mellon encourages users of this code to contribute improvements
- * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
- */
-
-/*
- * This module contains the routines to implement the CFS name cache. The
- * purpose of this cache is to reduce the cost of translating pathnames
- * into Vice FIDs. Each entry in the cache contains the name of the file,
- * the vnode (FID) of the parent directory, and the cred structure of the
- * user accessing the file.
- *
- * The first time a file is accessed, it is looked up by the local Venus
- * which first insures that the user has access to the file. In addition
- * we are guaranteed that Venus will invalidate any name cache entries in
- * case the user no longer should be able to access the file. For these
- * reasons we do not need to keep access list information as well as a
- * cred structure for each entry.
- *
- * The table can be accessed through the routines cnc_init(), cnc_enter(),
- * cnc_lookup(), cnc_rmfidcred(), cnc_rmfid(), cnc_rmcred(), and cnc_purge().
- * There are several other routines which aid in the implementation of the
- * hash table.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <linux/string.h>
-
-#include <linux/coda.h>
-#include <linux/coda_linux.h>
-#include <linux/coda_cnode.h>
-#include <linux/coda_namecache.h>
-
-int cfsnc_use;
-
-static struct cfscache * cfsnc_find(struct cnode *dcp, const char * name, int namelen, int hash);
-static void cfsnc_remove(struct cfscache *cncp);
-static inline int nchash(const char *, int, struct cnode *);
-static inline int ncmatch(struct cfscache *, const char *, int,
- struct cnode *);
-static inline void hashins(struct cfscache *a, struct cfscache *pred);
-static inline void hashrem(struct cfscache *a);
-static inline void hashnull(struct cfscache *);
-static inline void lrurem(struct cfscache *a);
-static inline void lruins(struct cfscache *a, struct cfscache *pred);
-static void cfsnc_gather_stats(void);
-
-
-/* externals */
-extern int coda_fideq(ViceFid *fid1, ViceFid *fid2);
-extern int coda_debug;
-extern int coda_print_entry;
-extern struct super_block *coda_super_block;
-
-
-
-/*
- * Declaration of the name cache data structure.
- */
-
-int cfsnc_use = 0; /* Indicate use of CFS Name Cache */
-int cfsnc_size = CFSNC_CACHESIZE; /* size of the cache */
-int cfsnc_hashsize = CFSNC_HASHSIZE; /* size of the primary hash */
-int cfsnc_flushme = 0;
-int cfsnc_procsize = 0;
-static int cfsnc_force = 0;
-
-struct cfshash {
- struct cfscache *hash_next, *hash_prev;
- int length;
-};
-
-struct cfslruhead {
- struct cfscache *dummy1, *dummy2;
- struct cfscache *lru_next, *lru_prev;
-};
-
-struct cfscache *cfsncheap; /* pointer to the cache entries */
-struct cfshash *cfsnchash; /* hash table of cfscache pointers */
-struct cfslruhead cfsnc_lru; /* head of lru chain; prev = lru */
-
-struct cfsnc_statistics cfsnc_stat; /* Keep various stats */
-
-#define TOTAL_CACHE_SIZE (sizeof(struct cfscache) * cfsnc_size)
-#define TOTAL_HASH_SIZE (sizeof(struct cfshash) * cfsnc_hashsize)
-int cfsnc_initialized = 0; /* Initially the cache has not been initialized */
-
-/*
- * for testing purposes
- */
-int cfsnc_debug = 1;
-
-
-/*
- * Auxillary routines -- shouldn't be entry points
- */
-
-
-/*
- * Hash function for the primary hash.
- * First try -- (first + last letters + length + (int)cp) mod size
- * 2nd try -- same, except dir fid.vnode instead of cp
- */
-static inline int
-nchash(const char *name, int namelen, struct cnode *cp)
-{
- return ((name[0] + name[namelen-1] +
- namelen + (int)(cp)) & (cfsnc_hashsize-1));
-}
-
-/* matching function */
-static inline int ncmatch(struct cfscache *cp, const char *name, int namelen,
- struct cnode *dcp)
-{
- return ((namelen == cp->namelen) && (dcp == cp->dcp) &&
- (memcmp(cp->name,name,namelen) == 0));
-}
-
-/* insert a behind pred */
-static inline void hashins(struct cfscache *a, struct cfscache *pred)
-{
- a->hash_next = pred->hash_next;
- pred->hash_next->hash_prev= a;
- pred->hash_next = a;
- a->hash_prev = pred;
-}
-
-static inline void hashrem(struct cfscache *a)
-{
- a->hash_prev->hash_next = a->hash_next;
- a->hash_next->hash_prev = a->hash_prev;
-}
-
-static inline void hashnull(struct cfscache *elem) {
- elem->hash_next = elem;
- elem->hash_prev = elem;
-}
-
-static inline void lrurem(struct cfscache *a)
-{
- a->lru_prev->lru_next = a->lru_next;
- a->lru_next->lru_prev = a->lru_prev;
-}
-
-static inline void lruins(struct cfscache *a, struct cfscache *pred)
-{
- pred->lru_next->lru_prev= a;
- a->lru_next = pred->lru_next;
-
- a->lru_prev = pred;
- pred->lru_next = a;
-}
-
-static struct cfscache *
-cfsnc_find(struct cnode *dcp, const char * name, int namelen, int hash)
-{
- /*
- * hash to find the appropriate bucket, look through the chain
- * for the right entry
- */
- register struct cfscache *cncp;
- int count = 1;
-
- CDEBUG(D_CACHE, "dcp 0x%x, name %s, len %d, hash %d\n",
- (int)dcp, name, namelen, hash);
-
- for (cncp = cfsnchash[hash].hash_next;
- cncp != (struct cfscache *)&cfsnchash[hash];
- cncp = cncp->hash_next, count++)
- {
-
- if (ncmatch(cncp, name, namelen, dcp))
- {
- cfsnc_stat.Search_len += count;
- CDEBUG(D_CACHE, "dcp 0x%x,found.\n", (int) dcp);
- return(cncp);
-
- }
- }
- CDEBUG(D_CACHE, "dcp 0x%x,not found.\n", (int) dcp);
- return((struct cfscache *)0);
-}
-
-static void
-cfsnc_remove(struct cfscache *cncp)
-{
- /*
- * remove an entry -- VN_RELE(cncp->dcp, cp), crfree(cred),
- * remove it from it's hash chain, and
- * place it at the head of the lru list.
- */
- CDEBUG(D_CACHE, "remove %s from parent %lx.%lx.%lx\n",
- cncp->name, (cncp->dcp)->c_fid.Volume,
- (cncp->dcp)->c_fid.Vnode, (cncp->dcp)->c_fid.Unique);
-
- hashrem(cncp);
- hashnull(cncp); /* have it be a null chain */
-
- /* VN_RELE(CTOV(cncp->dcp)); */
- iput(CTOI(cncp->cp));
- /* crfree(cncp->cred); */
-
- memset(DATA_PART(cncp), 0 ,DATA_SIZE);
- cncp->cp = NULL;
- cncp->dcp = (struct cnode *) 0;
-
- /* Put the null entry just after the least-recently-used entry */
- lrurem(cncp);
- lruins(cncp, cfsnc_lru.lru_prev);
-}
-
-
-/*
- * Entry points for the CFS Name Cache
- */
-
-/*
- * Initialize the cache, the LRU structure and the Hash structure(s)
- */
-void
-cfsnc_init(void)
-{
- register int i;
-
- /* zero the statistics structure */
- cfsnc_procsize = 10000 * cfsnc_hashsize + cfsnc_size;
- memset(&cfsnc_stat, 0, (sizeof(struct cfsnc_statistics)));
-
- CODA_ALLOC(cfsncheap, struct cfscache *, TOTAL_CACHE_SIZE);
- CODA_ALLOC(cfsnchash, struct cfshash *, TOTAL_HASH_SIZE);
-
- cfsnc_lru.lru_next = cfsnc_lru.lru_prev = (struct cfscache *)&cfsnc_lru;
-
- /* initialize the heap */
- for (i=0; i < cfsnc_size; i++) {
- lruins(&cfsncheap[i], (struct cfscache *) &cfsnc_lru);
- hashnull(&cfsncheap[i]);
- cfsncheap[i].cp = cfsncheap[i].dcp = (struct cnode *)0;
- }
-
- for (i=0; i < cfsnc_hashsize; i++) { /* initialize the hashtable */
- hashnull((struct cfscache *)&cfsnchash[i]);
- cfsnchash[i].length=0; /* bucket length */
- }
-
- cfsnc_initialized = 1;
- CDEBUG(D_CACHE, "cfsnc_initialized is now 1.\n");
-}
-
-/*
- * Enter a new (dir cnode, name) pair into the cache, updating the
- * LRU and Hash as needed.
- */
-
-void
-cfsnc_enter(struct cnode *dcp, register const char *name, int namelen, struct cnode *cp)
-{
- register struct cfscache *cncp;
- register int hash;
-
- if (cfsnc_use == 0) /* Cache is off */
- return;
-
- CDEBUG(D_CACHE, "dcp 0x%x cp 0x%x name %s, ind 0x%x \n",
- (int)dcp, (int)cp, name, (int)cp->c_vnode);
-
- if (namelen > CFSNC_NAMELEN) {
- CDEBUG(D_CACHE, "long name enter %s\n",name);
- cfsnc_stat.long_name_enters++; /* record stats */
- return;
- }
-
- hash = nchash(name, namelen, dcp);
- CDEBUG(D_CACHE, "Calling find with name %s, dcp %d, hash %d\n",
- name, (int) dcp, (int) hash);
-
- cncp = cfsnc_find(dcp, name, namelen, hash);
- if (cncp != (struct cfscache *) 0) {
- printk("cfsnc_enter: Duplicate cache entry; tell Peter.\n");
- cfsnc_stat.dbl_enters++; /* duplicate entry */
- return;
- }
-
- cfsnc_stat.enters++; /* record the enters statistic */
-
- /* Grab the lru element in the lru chain */
- cncp = cfsnc_lru.lru_prev;
-
- lrurem(cncp); /* remove it from the lists */
-
- /* if cncp is on hash list remove it */
- if ( cncp->dcp != (struct cnode *) 0 ) {
- /* We have to decrement the appropriate hash bucket length
- here, so we have to find the hash bucket */
- cfsnchash[nchash(cncp->name, cncp->namelen, cncp->dcp)].length--;
- cfsnc_stat.lru_rm++; /* zapped a valid entry */
- hashrem(cncp);
- iput(CTOI(cncp->cp));
- /* VN_RELE(CTOV(cncp->dcp)); */
- /* crfree(cncp->cred); */
- }
- /*
- * Put a hold on the current vnodes and fill in the cache entry.
- */
- iget((CTOI(cp))->i_sb, CTOI(cp)->i_ino);
- /* VN_HOLD(CTOV(dcp)); */
- /* XXXX crhold(cred); */
- cncp->dcp = dcp;
- cncp->cp = cp;
- cncp->namelen = namelen;
- /* cncp->cred = cred; */
-
- memcpy(cncp->name, name, (unsigned)namelen);
-
- /* Insert into the lru and hash chains. */
-
- lruins(cncp, (struct cfscache *) &cfsnc_lru);
- hashins(cncp, (struct cfscache *)&cfsnchash[hash]);
- cfsnchash[hash].length++; /* Used for tuning */
- CDEBUG(D_CACHE, "Entering:\n");
- coda_print_ce(cncp);
-}
-
-/*
- * Find the (dir cnode, name) pair in the cache, if it's cred
- * matches the input, return it, otherwise return 0
- */
-
-struct cnode *
-cfsnc_lookup(struct cnode *dcp, register const char *name, int namelen)
-{
- register int hash;
- register struct cfscache *cncp;
- /* this should go into a callback funcntion for /proc/sys
- don't know how at the moment? */
- if (cfsnc_flushme == 1) {
- cfsnc_flush();
- cfsnc_flushme = 0;
- }
-
- if (cfsnc_procsize != 10000*cfsnc_hashsize + cfsnc_size ) {
- int hsh = cfsnc_procsize/10000;
- int siz = cfsnc_procsize%10000;
- int rc;
-
- if ( (hsh > 1) && (siz > 2) ) {
- rc = cfsnc_resize(hsh, siz);
- if ( !rc ) {
- printk("Coda:cache size (hash,size) (%d,%d)\n",
- hsh, siz);
- } else {
- printk("Coda: cache resize failed\n");
- }
- }
- }
-
- if (cfsnc_use == 0) /* Cache is off */
- return((struct cnode *) 0);
-
- if (namelen > CFSNC_NAMELEN) {
- CDEBUG(D_CACHE,"long name lookup %s\n",name);
- cfsnc_stat.long_name_lookups++; /* record stats */
- return((struct cnode *) 0);
- }
-
- /* Use the hash function to locate the starting point,
- then the search routine to go down the list looking for
- the correct cred.
- */
-
- hash = nchash(name, namelen, dcp);
- CDEBUG(D_CACHE, "Calling find with name %s, dcp %d, hash %d\n",
- name, (int) dcp, (int) hash);
- cncp = cfsnc_find(dcp, name, namelen, hash);
- if (cncp == (struct cfscache *) 0) {
- cfsnc_stat.misses++; /* record miss */
- return((struct cnode *) 0);
- }
-
- cfsnc_stat.hits++;
-
- /* put this entry at the mru end of the LRU */
- lrurem(cncp);
- lruins(cncp, (struct cfscache *) &cfsnc_lru);
-
- /* move it to the front of the hash chain */
- /* don't need to change the hash bucket length */
- hashrem(cncp);
- hashins(cncp, (struct cfscache *) &cfsnchash[hash]);
-
- CDEBUG(D_CACHE, "lookup: dcp 0x%x, name %s, cp 0x%x\n",
- (int) dcp, name, (int) cncp->cp);
-
- return(cncp->cp);
-}
-
-/*
- * Remove all entries with a parent which has the input fid.
- */
-
-void
-cfsnc_zapParentfid(ViceFid *fid)
-{
- /* To get to a specific fid, we might either have another hashing
- function or do a sequential search through the cache for the
- appropriate entries. The later may be acceptable since I don't
- think callbacks or whatever Case 1 covers are frequent occurences.
- */
- register struct cfscache *cncp, *ncncp;
- register int i;
-
- if (cfsnc_use == 0) /* Cache is off */
- return;
-
- CDEBUG(D_CACHE, " fid 0x%lx, 0x%lx, 0x%lx \n",
- fid->Volume, fid->Vnode, fid->Unique);
-
- cfsnc_stat.zapPfids++;
-
- for (i = 0; i < cfsnc_hashsize; i++) {
-
- /*
- * Need to save the hash_next pointer in case we remove the
- * entry. remove causes hash_next to point to itself.
- */
-
- for (cncp = cfsnchash[i].hash_next;
- cncp != (struct cfscache *) &cfsnchash[i];
- cncp = ncncp) {
- ncncp = cncp->hash_next;
- if ( coda_fideq(&cncp->dcp->c_fid, fid) ) {
- cfsnchash[i].length--; /* Used for tuning */
- cfsnc_remove(cncp);
- }
- }
- }
-}
-
-/*
- * Remove all entries which have the same fid as the input
- */
-void
-cfsnc_zapfid(ViceFid *fid)
-{
- /* See comment for zapParentfid. This routine will be used
- if attributes are being cached.
- */
- register struct cfscache *cncp, *ncncp;
- register int i;
-
- if (cfsnc_use == 0) /* Cache is off */
- return;
-
- CDEBUG(D_CACHE, "Zapfid: fid 0x%lx, 0x%lx, 0x%lx \n",
- fid->Volume, fid->Vnode, fid->Unique);
-
- cfsnc_stat.zapFids++;
-
- for (i = 0; i < cfsnc_hashsize; i++) {
- for (cncp = cfsnchash[i].hash_next;
- cncp != (struct cfscache *) &cfsnchash[i];
- cncp = ncncp) {
- ncncp = cncp->hash_next;
- if (coda_fideq(&(cncp->cp->c_fid), fid)) {
- CDEBUG(D_CACHE, "Found cncp: name %s\n", cncp->name);
- cfsnchash[i].length--; /* Used for tuning */
- cfsnc_remove(cncp);
- }
- }
- }
-}
-
-
-/*
- * Remove all entries which have the (dir vnode, name) pair
- */
-void
-cfsnc_zapfile(struct cnode *dcp, register const char *name, int length)
-{
- /* use the hash function to locate the file, then zap all
- entries of it regardless of the cred.
- */
- register struct cfscache *cncp;
- int hash;
-
- if (cfsnc_use == 0) /* Cache is off */
- return;
-
- CDEBUG(D_CACHE,"Zapfile: dcp 0x%x name %s \n",
- (int) dcp, name);
-
- if (length > CFSNC_NAMELEN) {
- cfsnc_stat.long_remove++; /* record stats */
- return;
- }
-
- cfsnc_stat.zapFile++;
-
- hash = nchash(name, length, dcp);
- /* remove entries: remember they might exist for more than a
- single cred */
- while ( (cncp = cfsnc_find(dcp, name, length, hash)) != NULL ) {
- cfsnchash[hash].length--;
- cfsnc_remove(cncp);
- }
-}
-
-/*
- * Remove all the entries for a particular user. Used when tokens expire.
- * A user is determined by his/her effective user id (id_uid).
- */
-
-void
-cfsnc_purge_user(struct CodaCred *cred)
-{
- /* I think the best approach is to go through the entire cache
- via HASH or whatever and zap all entries which match the
- input cred. Or just flush the whole cache.
- It might be best to go through on basis of LRU since cache
- will almost always be full and LRU is more straightforward.
- */
-
- register struct cfscache *cncp;
- int hash;
-
- if (cfsnc_use == 0) /* Cache is off */
- return;
-
- CDEBUG(D_CACHE,"ZapDude: uid %ld\n",cred->cr_uid);
- cfsnc_stat.zapUsers++;
-
- for (cncp = cfsnc_lru.lru_next;
- cncp != (struct cfscache *) &cfsnc_lru;
- cncp = cncp->lru_next) {
-
- if ((CFSNC_VALID(cncp)) &&
- ((cncp->cred)->cr_uid == cred->cr_uid)) {
- /* Seems really ugly, but we have to decrement the appropriate
- hash bucket length here, so we have to find the hash bucket
- */
- hash = nchash(cncp->name, cncp->namelen, cncp->dcp);
- cfsnchash[hash].length--; /* For performance tuning */
-
- cfsnc_remove(cncp);
- }
- }
-}
-
-/*
- * Flush the entire name cache. In response to a flush of the Venus cache.
- */
-
-void
-cfsnc_flush(void)
-{
- /* One option is to deallocate the current name cache and
- call init to start again. Or just deallocate, then rebuild.
- Or again, we could just go through the array and zero the
- appropriate fields.
- */
-
- /*
- * Go through the whole lru chain and kill everything as we go.
- * I don't use remove since that would rebuild the lru chain
- * as it went and that seemed unneccesary.
- */
- register struct cfscache *cncp;
- int i;
-
- if ((cfsnc_use == 0 || cfsnc_initialized == 0) && (cfsnc_force == 0) )
- return;
-
- cfsnc_stat.Flushes++;
-
- for (cncp = cfsnc_lru.lru_next;
- cncp != (struct cfscache *) &cfsnc_lru;
- cncp = cncp->lru_next) {
- if ( cncp->cp ) {
- hashrem(cncp); /* only zero valid nodes */
- hashnull(cncp);
- iput(CTOI(cncp->cp));
- /* crfree(cncp->cred); */
- memset(DATA_PART(cncp), 0, DATA_SIZE);
- }
- }
-
- for (i = 0; i < cfsnc_hashsize; i++)
- cfsnchash[i].length = 0;
-}
-
-/*
- * This routine replaces a ViceFid in the name cache with another.
- * It is added to allow Venus during reintegration to replace
- * locally allocated temp fids while disconnected with global fids
- * even when the reference count on those fids are not zero.
- */
-void
-cfsnc_replace(ViceFid *f1, ViceFid *f2)
-{
- /*
- * Replace f1 with f2 throughout the name cache
- */
- int hash;
- register struct cfscache *cncp;
-
- CDEBUG(D_CACHE,
- "cfsnc_replace fid_1 = (%lx.%lx.%lx) and fid_2 = (%lx.%lx.%lx)\n",
- f1->Volume, f1->Vnode, f1->Unique,
- f2->Volume, f2->Vnode, f2->Unique);
-
- for (hash = 0; hash < cfsnc_hashsize; hash++) {
- for (cncp = cfsnchash[hash].hash_next;
- cncp != (struct cfscache *) &cfsnchash[hash];
- cncp = cncp->hash_next) {
- if (!memcmp(&cncp->cp->c_fid, f1, sizeof(ViceFid))) {
- memcpy(&cncp->cp->c_fid, f2, sizeof(ViceFid));
- continue; /* no need to check cncp->dcp now */
- }
- if (!memcmp(&cncp->dcp->c_fid, f1, sizeof(ViceFid)))
- memcpy(&cncp->dcp->c_fid, f2, sizeof(ViceFid));
- }
- }
-}
-
-/*
- * Debugging routines
- */
-
-/*
- * This routine should print out all the hash chains to the console.
- */
-
-void
-print_cfsnc(void)
-{
- int hash;
- register struct cfscache *cncp;
-
- for (hash = 0; hash < cfsnc_hashsize; hash++) {
- printk("\nhash %d\n",hash);
-
- for (cncp = cfsnchash[hash].hash_next;
- cncp != (struct cfscache *)&cfsnchash[hash];
- cncp = cncp->hash_next) {
- printk("cp 0x%x dcp 0x%x cred 0x%x name %s ino %d count %d dev %d\n",
- (int)cncp->cp, (int)cncp->dcp,
- (int)cncp->cred, cncp->name, CTOI(cncp->cp)->i_count, CTOI(cncp->cp)->i_count, CTOI(cncp->cp)->i_dev);
- }
- }
-}
-
-int
-cfsnc_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- int hash;
- int len=0;
- off_t pos=0;
- off_t begin;
- struct cfscache *cncp;
- char tmpbuf[80];
-
- if (offset < 80)
- len += sprintf(buffer, "%-79s\n",
- "hash len volume vnode unique name ino pino ct");
- if ( !cfsnc_initialized ) {
- *start = buffer;
- return len;
- }
- pos = 80;
- for (hash = 0; hash < cfsnc_hashsize; hash++) {
- for (cncp = cfsnchash[hash].hash_next;
- cncp != (struct cfscache *)&cfsnchash[hash];
- cncp = cncp->hash_next) {
- pos += 80;
- if (pos < offset)
- continue;
- sprintf(tmpbuf, "%4d %3d %8x %8x %8x %16s %10ld %10ld %2d",
- hash, cfsnchash[hash].length, (int) cncp->cp->c_fid.Volume,
- (int) cncp->cp->c_fid.Vnode, (int) cncp->cp->c_fid.Unique , cncp->name,
- CTOI(cncp->cp)->i_ino,
- CTOI(cncp->dcp)->i_ino,
- CTOI(cncp->cp)->i_count);
- len += sprintf(buffer+len, "%-79s\n", tmpbuf);
- if(len >= length)
- break;
- }
- if(len>= length)
- break;
- }
- begin = len - (pos - offset);
- *start = buffer + begin;
- len -= begin;
- if(len>length)
- len = length;
- return len;
-}
-
-int
-cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- int len=0;
- off_t begin;
-
- cfsnc_gather_stats();
-
- /* this works as long as we are below 1024 characters! */
- len += sprintf(buffer,"Coda minicache statistics\n\n");
- len += sprintf(buffer+len, "cfsnc_hits : %d\n", cfsnc_stat.hits);
- len += sprintf(buffer+len, "cfsnc_misses : %d\n", cfsnc_stat.misses);
- len += sprintf(buffer+len, "cfsnc_enters : %d\n", cfsnc_stat.enters);
- len += sprintf(buffer+len, "cfsnc_dbl_enters : %d\n", cfsnc_stat.dbl_enters);
- len += sprintf(buffer+len, "cfsnc_long_name_enters : %d\n", cfsnc_stat.long_name_enters);
- len += sprintf(buffer+len, "cfsnc_long_name_lookups : %d\n", cfsnc_stat.long_name_lookups);
- len += sprintf(buffer+len, "cfsnc_long_remove : %d\n", cfsnc_stat.long_remove);
- len += sprintf(buffer+len, "cfsnc_lru_rm : %d\n", cfsnc_stat.lru_rm);
- len += sprintf(buffer+len, "cfsnc_zapPfids : %d\n", cfsnc_stat.zapPfids);
- len += sprintf(buffer+len, "cfsnc_zapFids : %d\n", cfsnc_stat.zapFids);
- len += sprintf(buffer+len, "cfsnc_zapFile : %d\n", cfsnc_stat.zapFile);
- len += sprintf(buffer+len, "cfsnc_zapUsers : %d\n", cfsnc_stat.zapUsers);
- len += sprintf(buffer+len, "cfsnc_Flushes : %d\n", cfsnc_stat.Flushes);
- len += sprintf(buffer+len, "cfsnc_SumLen : %d\n", cfsnc_stat.Sum_bucket_len);
- len += sprintf(buffer+len, "cfsnc_Sum2Len : %d\n", cfsnc_stat.Sum2_bucket_len);
- len += sprintf(buffer+len, "cfsnc_# 0 len : %d\n", cfsnc_stat.Num_zero_len);
- len += sprintf(buffer+len, "cfsnc_MaxLen : %d\n", cfsnc_stat.Max_bucket_len);
- len += sprintf(buffer+len, "cfsnc_SearchLen : %d\n", cfsnc_stat.Search_len);
- begin = offset;
- *start = buffer + begin;
- len -= begin;
-
- if(len>length)
- len = length;
- if (len< 0)
- len = 0;
- return len;
-}
-
-
-
-void
-coda_print_ce(struct cfscache *ce)
-{
-CDEBUG(D_CACHE, "cp 0x%x, dcp 0x%x, name %s, inod 0x%x, ino %d, count %d, dev %d\n",
- (int)ce->cp, (int)ce->dcp, ce->name, (int)CTOI(ce->cp),(int)CTOI(ce->cp)->i_ino, CTOI(ce->cp)->i_count, CTOI(ce->cp)->i_dev);
-}
-
-static void
-cfsnc_gather_stats(void)
-{
- int i, max = 0, sum = 0, temp, zeros = 0, ave, n;
-
- for (i = 0; i < cfsnc_hashsize; i++) {
- if (cfsnchash[i].length) {
- sum += cfsnchash[i].length;
- } else {
- zeros++;
- }
-
- if (cfsnchash[i].length > max)
- max = cfsnchash[i].length;
- }
-
-/*
- * When computing the Arithmetic mean, only count slots which
- * are not empty in the distribution.
- */
- cfsnc_stat.Sum_bucket_len = sum;
- cfsnc_stat.Num_zero_len = zeros;
- cfsnc_stat.Max_bucket_len = max;
-
- if ((n = cfsnc_hashsize - zeros) > 0)
- ave = sum / n;
- else
- ave = 0;
-
- sum = 0;
- for (i = 0; i < cfsnc_hashsize; i++) {
- if (cfsnchash[i].length) {
- temp = cfsnchash[i].length - ave;
- sum += temp * temp;
- }
- }
- cfsnc_stat.Sum2_bucket_len = sum;
-}
-
-/*
- * The purpose of this routine is to allow the hash and cache sizes to be
- * changed dynamically. This should only be used in controlled environments,
- * it makes no effort to lock other users from accessing the cache while it
- * is in an improper state (except by turning the cache off).
- */
-int
-cfsnc_resize(int hashsize, int heapsize)
-{
- if ( !cfsnc_use )
- return 0;
-
- if ((hashsize % 2) || (heapsize % 2)) { /* Illegal hash or cache sizes */
- return(EINVAL);
- }
-
- cfsnc_use = 0; /* Turn the cache off */
- cfsnc_force = 1; /* otherwise we can't flush */
-
- cfsnc_flush(); /* free any cnodes in the cache */
- cfsnc_force = 0;
-
- /* WARNING: free must happen *before* size is reset */
- CODA_FREE(cfsncheap,TOTAL_CACHE_SIZE);
- CODA_FREE(cfsnchash,TOTAL_HASH_SIZE);
-
- cfsnc_hashsize = hashsize;
- cfsnc_size = heapsize;
-
- cfsnc_init(); /* Set up a cache with the new size */
-
- cfsnc_use = 1; /* Turn the cache back on */
- return(0);
-}
-
-
-