split-dcache-20050427
authorDerrick Brashear <shadow@dementia.org>
Thu, 28 Apr 2005 23:14:57 +0000 (23:14 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 28 Apr 2005 23:14:57 +0000 (23:14 +0000)
split for rw/ro dcaches to allow portion of cache to be dedicated

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================

update

src/afs/LINUX/osi_sysctl.c
src/afs/afs.h
src/afs/afs_call.c
src/afs/afs_dcache.c
src/afs/afs_prototypes.h
src/afs/afs_stats.h
src/afsd/afsd.c
src/config/afs_args.h
src/xstat/xstat_cm_test.c

index 1fc7336..eaee80a 100644 (file)
 extern afs_int32 hm_retry_RO;
 extern afs_int32 hm_retry_RW;
 extern afs_int32 hm_retry_int;
+extern afs_int32 afs_blocksUsed_0;
+extern afs_int32 afs_blocksUsed_1;
+extern afs_int32 afs_blocksUsed_2;
+extern afs_int32 afs_pct1;
+extern afs_int32 afs_pct2;
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *afs_sysctl = NULL;
@@ -49,6 +54,34 @@ static ctl_table afs_sysctl_table[] = {
      &afs_bkvolpref, sizeof(afs_int32), 0644, NULL,
      &proc_dointvec}
     ,
+    {7, "afs_blocksUsed",
+     &afs_blocksUsed, sizeof(afs_int32), 0444, NULL,
+     &proc_dointvec}
+    ,
+    {8, "afs_blocksUsed_0",
+     &afs_blocksUsed_0, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
+    {9, "afs_blocksUsed_1",
+     &afs_blocksUsed_1, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
+    {10, "afs_blocksUsed_2",
+     &afs_blocksUsed_2, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
+    {11, "afs_pct1",
+     &afs_pct1, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
+    {12, "afs_pct2",
+     &afs_pct2, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
+    {13, "afs_cacheBlocks",
+     &afs_cacheBlocks, sizeof(afs_int32), 0644, NULL,
+     &proc_dointvec}
+    ,
     {0}
 };
 
index ed661bd..97e2740 100644 (file)
@@ -828,6 +828,9 @@ struct cm_initparams {
 
 #define        NULLIDX     (-1)        /* null index definition */
 /* struct dcache states bits */
+#define DRO         1
+#define DBackup     2
+#define DRW         4
 #define        DWriting    8           /* file being written (used for cache validation) */
 
 /* dcache data flags */
@@ -953,7 +956,7 @@ struct dcache {
     char mflags;               /* Meta flags */
     struct fcache f;           /* disk image */
     afs_int32 stamp;           /* used with vtodc struct for hints */
-
+    afs_int32 bucket;           /* which bucket these dcache entries are in */
     /*
      * Locking rules:
      *
index 5260e4f..39bf206 100644 (file)
@@ -517,6 +517,18 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
        DInit(temp);
        afs_rootFid.Fid.Volume = 0;
        code = 0;
+    } else if (parm == AFSOP_BUCKETPCT) {
+       /* need to enable this now, will disable again before GO
+          if we don't have 100% */
+       splitdcache = 1;
+       switch (parm2) {
+       case 1:
+           afs_tpct1 = parm3;
+           break;
+       case 2:
+           afs_tpct2 = parm3;
+           break;
+       }           
     } else if (parm == AFSOP_ADDCELL) {
        /* add a cell.  Parameter 2 is 8 hosts (in net order),  parm 3 is the null-terminated
         * name.  Parameter 4 is the length of the name, including the null.  Parm 5 is the
@@ -693,6 +705,13 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
            afs_osi_Sleep(&afs_initState);
        afs_initState = 101;
        afs_setTime = parm2;
+       if (afs_tpct1 + afs_tpct2 != 100) {
+           afs_tpct1 = 0;
+           afs_tpct2 = 0;
+           splitdcache = 0;
+       } else {        
+           splitdcache = 1;
+       }
        afs_osi_Wakeup(&afs_initState);
 #if    (!defined(AFS_NONFSTRANS)) || defined(AFS_AIX_IAUTH_ENV)
        afs_nfsclient_init();
index 54f3955..3db7b85 100644 (file)
@@ -23,14 +23,31 @@ RCSID
 #include "afs/afs_osidnlc.h"
 
 /* Forward declarations. */
-static void afs_GetDownD(int anumber, int *aneedSpace);
+static void afs_GetDownD(int anumber, int *aneedSpace, afs_int32 buckethint);
 static void afs_FreeDiscardedDCache(void);
 static void afs_DiscardDCache(struct dcache *);
 static void afs_FreeDCache(struct dcache *);
+/* For split cache */
+static afs_int32 afs_DCGetBucket(struct vcache *);
+static void afs_DCAdjustSize(struct dcache *, afs_int32, afs_int32);
+static void afs_DCMoveBucket(struct dcache *, afs_int32, afs_int32);
+static void afs_DCSizeInit(void);
+static afs_int32 afs_DCWhichBucket(afs_int32, afs_int32);
+
 
 /*
  * --------------------- Exported definitions ---------------------
  */
+/* For split cache */
+afs_int32 afs_blocksUsed_0;    /*1K blocks in cache - in theory is zero */
+afs_int32 afs_blocksUsed_1;    /*1K blocks in cache */
+afs_int32 afs_blocksUsed_2;    /*1K blocks in cache */
+afs_int32 afs_pct1 = -1;
+afs_int32 afs_pct2 = -1;
+afs_uint32 afs_tpct1 = 0;
+afs_uint32 afs_tpct2 = 0;
+afs_uint32 splitdcache = 0;
+
 afs_lock_t afs_xdcache;                /*Lock: alloc new disk cache entries */
 afs_int32 afs_freeDCList;      /*Free list for disk cache entries */
 afs_int32 afs_freeDCCount;     /*Count of elts in freeDCList */
@@ -119,7 +136,110 @@ struct afs_cacheOps afs_MemCacheOps = {
 int cacheDiskType;             /*Type of backing disk for cache */
 struct afs_cacheOps *afs_cacheType;
 
+static afs_int32
+afs_DCGetBucket(struct vcache *avc) 
+{
+  /* This should be replaced with some sort of user configurable function */
+  if (avc->states & CRO) {
+      return 2;
+  } else if (avc->states & CBackup) {
+      return 1;
+  } else {
+    /* RW */
+  }
+  /* main bucket */
+  return 1;
+}
+
+static void 
+afs_DCAdjustSize(struct dcache *adc, afs_int32 oldSize, afs_int32 newSize)
+{
+    afs_int32 adjustSize = newSize - oldSize;
+
+    if (!splitdcache) 
+       return;
 
+    switch (adc->bucket) 
+    {
+    case 0:
+       afs_blocksUsed_0 += adjustSize;
+       afs_stats_cmperf.cacheBucket0_Discarded += oldSize;
+       break;
+    case 1:
+       afs_blocksUsed_1 += adjustSize;
+       afs_stats_cmperf.cacheBucket1_Discarded += oldSize;
+       break;
+    case 2:
+       afs_blocksUsed_2 += adjustSize;
+       afs_stats_cmperf.cacheBucket2_Discarded += oldSize;
+       break;
+    }
+
+    return;
+}
+
+static void 
+afs_DCMoveBucket(struct dcache *adc, afs_int32 size, afs_int32 newBucket)
+{
+    if (!splitdcache) 
+       return;
+
+    switch (adc->bucket) 
+    {
+    case 0:
+       afs_blocksUsed_0 -= size;
+       break;
+    case 1:
+       afs_blocksUsed_1 -= size;
+       break;
+    case 2:
+       afs_blocksUsed_2 -= size;
+       break;
+    }
+
+    adc->bucket = newBucket;
+
+    switch (adc->bucket) 
+    {
+    case 0:
+       afs_blocksUsed_0 += size;
+       break;
+    case 1:
+       afs_blocksUsed_1 += size;
+       break;
+    case 2:
+       afs_blocksUsed_2 += size;
+       break;
+    }
+    
+    return;
+}
+
+static void 
+afs_DCSizeInit(void) 
+{
+    afs_blocksUsed_0 = afs_blocksUsed_1 = afs_blocksUsed_2 = 0;
+}
+
+static afs_int32
+afs_DCWhichBucket(afs_int32 phase, afs_int32 bucket) 
+{
+    if (!splitdcache) 
+       return 0;
+
+    afs_pct1 = afs_blocksUsed_1*100/afs_cacheBlocks;    
+    afs_pct2 = afs_blocksUsed_2*100/afs_cacheBlocks;
+
+    /* Short cut: if we don't know about it, try to kill it */
+    if (phase < 2 && afs_blocksUsed_0) 
+       return 0;
+    
+    if (afs_pct1 > afs_tpct1) 
+       return 1;
+    if (afs_pct2 > afs_tpct2)
+       return 2;
+    return 0; /* unlikely */
+}
 
 
 /*
@@ -245,7 +365,7 @@ afs_CacheTruncateDaemon(void)
                    afs_blocksUsed - afs_blocksDiscarded - cb_lowat;
                slots_needed =
                    dc_hiwat - afs_freeDCCount - afs_discardDCCount;
-               afs_GetDownD(slots_needed, &space_needed);
+               afs_GetDownD(slots_needed, &space_needed, 0);
                if ((space_needed <= 0) && (slots_needed <= 0)) {
                    break;
                }
@@ -340,6 +460,7 @@ afs_AdjustSize(register struct dcache *adc, register afs_int32 newSize)
     if (!newSize)
        adc->validPos = 0;
     newSize = ((newSize + afs_fsfragsize) ^ afs_fsfragsize) >> 10;     /* round up */
+    afs_DCAdjustSize(adc, oldSize, newSize);
     if (newSize > oldSize) {
        /* We're growing the file, wakeup the daemon */
        afs_MaybeWakeupTruncateDaemon();
@@ -376,7 +497,7 @@ afs_AdjustSize(register struct dcache *adc, register afs_int32 newSize)
 
 #define        MAXATONCE   16          /* max we can obtain at once */
 static void
-afs_GetDownD(int anumber, int *aneedSpace)
+afs_GetDownD(int anumber, int *aneedSpace, afs_int32 buckethint)
 {
 
     struct dcache *tdc;
@@ -392,6 +513,7 @@ afs_GetDownD(int anumber, int *aneedSpace)
     afs_hyper_t maxVictimTime; /* youngest (largest LRU time) victim */
     afs_uint32 maxVictimPtr;   /* where it is */
     int discard;
+    int curbucket;
 
     AFS_STATCNT(afs_GetDownD);
     if (CheckLock(&afs_xdcache) != -1)
@@ -408,12 +530,20 @@ afs_GetDownD(int anumber, int *aneedSpace)
     if (anumber > MAXATONCE)
        anumber = MAXATONCE;    /* all we can do */
 
+    /* rewrite so phases include a better eligiblity for gc test*/
     /*
      * The phase variable manages reclaims.  Set to 0, the first pass,
-     * we don't reclaim active entries.  Set to 1, we reclaim even active
-     * ones.
+     * we don't reclaim active entries, or other than target bucket.  
+     * Set to 1, we reclaim even active ones in target bucket.
+     * Set to 2, we reclaim any inactive one.
+     * Set to 3, we reclaim even active ones.
      */
-    phase = 0;
+    if (splitdcache) {
+       phase = 0;
+    } else {
+       phase = 4;
+    }
+
     for (i = 0; i < afs_cacheFiles; i++)
        /* turn off all flags */
        afs_indexFlags[i] &= ~IFFlag;
@@ -422,6 +552,7 @@ afs_GetDownD(int anumber, int *aneedSpace)
        /* find oldest entries for reclamation */
        maxVictimPtr = victimPtr = 0;
        hzero(maxVictimTime);
+       curbucket = afs_DCWhichBucket(phase, buckethint);
        /* select victims from access time array */
        for (i = 0; i < afs_cacheFiles; i++) {
            if (afs_indexFlags[i] & (IFDataMod | IFFree | IFDiscarded)) {
@@ -429,6 +560,11 @@ afs_GetDownD(int anumber, int *aneedSpace)
                continue;
            }
            tdc = afs_indexTable[i];
+           if (tdc && (curbucket != tdc->bucket) && (phase < 4))
+           {
+               /* Wrong bucket; can't use it! */
+               continue;
+           }
            if (tdc && (tdc->refCount != 0)) {
                /* Referenced; can't use it! */
                continue;
@@ -510,12 +646,12 @@ afs_GetDownD(int anumber, int *aneedSpace)
                if (tvc) {
                    tchunkoffset = AFS_CHUNKTOBASE(tdc->f.chunk);
                    chunkFlags = afs_indexFlags[tdc->index];
-                   if (phase == 0 && osi_Active(tvc))
-                       skip = 1;
-                   if (phase > 0 && osi_Active(tvc)
-                       && (tvc->states & CDCLock)
-                       && (chunkFlags & IFAnyPages))
-                       skip = 1;
+                   if ((((phase / 2) & 1) == 0) && osi_Active(tvc))
+                        skip = 1;
+                   if ((((phase / 2) & 1) == 1) && osi_Active(tvc)
+                        && (tvc->states & CDCLock)
+                        && (chunkFlags & IFAnyPages))
+                        skip = 1;
                    if (chunkFlags & IFDataMod)
                        skip = 1;
                    afs_Trace4(afs_iclSetp, CM_TRACE_GETDOWND,
@@ -647,17 +783,17 @@ afs_GetDownD(int anumber, int *aneedSpace)
            afs_PutDCache(tdc);
        }
 
-       if (phase == 0) {
+       if (phase < 5) {
            /* Phase is 0 and no one was found, so try phase 1 (ignore
             * osi_Active flag) */
            if (j == 0) {
-               phase = 1;
+               phase++;
                for (i = 0; i < afs_cacheFiles; i++)
                    /* turn off all flags */
                    afs_indexFlags[i] &= ~IFFlag;
            }
        } else {
-           /* found no one in phase 1, we're hosed */
+           /* found no one in phases 0-5, we're hosed */
            if (victimPtr == 0)
                break;
        }
@@ -916,6 +1052,8 @@ afs_FreeDiscardedDCache(void)
     afs_CFileTruncate(tfile, 0);
     afs_CFileClose(tfile);
     afs_AdjustSize(tdc, 0);
+    tdc->f.states &= ~(DRO|DBackup|DRW);
+    afs_DCMoveBucket(tdc, 0, 0);
 
     /*
      * Free the element we just truncated
@@ -1214,6 +1352,7 @@ afs_FindDCache(register struct vcache *avc, afs_size_t abyte)
                break;          /* leaving refCount high for caller */
            }
            afs_PutDCache(tdc);
+           tdc = NULL;
        }
        index = afs_dcnextTbl[index];
     }
@@ -1707,7 +1846,8 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
                while (1) {
                    if (!setLocks)
                        avc->states |= CDCLock;
-                   afs_GetDownD(5, (int *)0);  /* just need slots */
+                   /* just need slots */
+                   afs_GetDownD(5, (int *)0, afs_DCGetBucket(avc));
                    if (!setLocks)
                        avc->states &= ~CDCLock;
                    if (afs_discardDCList != NULLIDX
@@ -1748,6 +1888,8 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
                size =
                    ((tdc->f.chunkBytes +
                      afs_fsfragsize) ^ afs_fsfragsize) >> 10;
+               tdc->f.states &= ~(DRO|DBackup|DRW);
+               afs_DCMoveBucket(tdc, size, 0);
                afs_blocksDiscarded -= size;
                afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
                if (aflags & 2) {
@@ -1772,6 +1914,13 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
             */
            afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages);
            tdc->f.fid = avc->fid;
+           if (avc->states & CRO) 
+               tdc->f.states = DRO;
+           else if (avc->states & CBackup) 
+               tdc->f.states = DBackup;
+           else 
+               tdc->f.states = DRW;
+           afs_DCMoveBucket(tdc, 0, afs_DCGetBucket(avc));
            afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique;
            hones(tdc->f.versionNo);    /* invalid value */
            tdc->f.chunk = chunk;
@@ -1791,7 +1940,6 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
            afs_dvhashTbl[i] = tdc->index;
            tdc->dflags = DFEntryMod;
            tdc->mflags = 0;
-           tdc->f.states = 0;
            afs_MaybeWakeupTruncateDaemon();
            MReleaseWriteLock(&afs_xdcache);
            ConvertWToSLock(&tdc->lock);
@@ -2414,6 +2562,8 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
            if (vType(avc) == VDIR) {
                DZap(tdc);
            }
+           tdc->f.states &= ~(DRO|DBackup|DRW);
+           afs_DCMoveBucket(tdc, 0, 0);
            ReleaseWriteLock(&tdc->lock);
            afs_PutDCache(tdc);
            ObtainWriteLock(&afs_xcbhash, 454);
@@ -2427,6 +2577,8 @@ afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
             * avc->lock(W); assert(!setLocks || slowPass)
             */
            osi_Assert(!setLocks || slowPass);
+           tdc->f.states &= ~(DRO|DBackup|DRW);
+           afs_DCMoveBucket(tdc, 0, 0);
            tdc = NULL;
            goto done;
        }
@@ -2837,6 +2989,18 @@ afs_UFSGetDSlot(register afs_int32 aslot, register struct dcache *tmpdc)
 #endif
        lasterrtime = osi_Time();
        afs_indexUnique[aslot] = tdc->f.fid.Fid.Unique;
+       tdc->f.states &= ~(DRO|DBackup|DRW);
+       afs_DCMoveBucket(tdc, 0, 0);
+    } else {
+       if (&tdc->f != 0) {
+           if (tdc->f.states & DRO) {
+               afs_DCMoveBucket(tdc, 0, 2);
+           } else if (tdc->f.states & DBackup) {
+               afs_DCMoveBucket(tdc, 0, 1);
+           } else {
+               afs_DCMoveBucket(tdc, 0, 1); 
+           }
+       } 
     }
     tdc->refCount = 1;
     tdc->index = aslot;
@@ -3060,6 +3224,8 @@ afs_InitCacheFile(char *afile, ino_t ainode)
        tdc->f.fid.Fid.Volume = 0;      /* not in the hash table */
        if (tstat.size != 0)
            osi_UFSTruncate(tfile, 0);
+       tdc->f.states &= ~(DRO|DBackup|DRW);
+       afs_DCMoveBucket(tdc, 0, 0);
        /* put entry in free cache slot list */
        afs_dvnextTbl[tdc->index] = afs_freeDCList;
        afs_freeDCList = index;
@@ -3234,6 +3400,10 @@ afs_dcacheInit(int afiles, int ablocks, int aDentries, int achunk, int aflags)
 
     afs_dcentries = aDentries;
     afs_blocksUsed = 0;
+    afs_stats_cmperf.cacheBucket0_Discarded = 
+       afs_stats_cmperf.cacheBucket1_Discarded = 
+       afs_stats_cmperf.cacheBucket2_Discarded = 0;
+    afs_DCSizeInit();
     QInit(&afs_DLRU);
 }
 
@@ -3274,6 +3444,9 @@ shutdown_dcache(void)
     afs_osi_Free(afs_dchashTbl, afs_dhashsize * sizeof(afs_int32));
 
     afs_blocksUsed = afs_dcentries = 0;
+    afs_stats_cmperf.cacheBucket0_Discarded = 
+       afs_stats_cmperf.cacheBucket1_Discarded = 
+       afs_stats_cmperf.cacheBucket2_Discarded = 0;
     hzero(afs_indexCounter);
 
     afs_freeDCCount = 0;
index 96f17b9..1fc969e 100644 (file)
@@ -297,6 +297,7 @@ extern afs_int32 afs_blocksUsed;
 extern afs_int32 afs_blocksDiscarded;
 extern int afs_WaitForCacheDrain;
 extern int cacheDiskType;
+extern afs_uint32 afs_tpct1, afs_tpct2, splitdcache;
 extern unsigned char *afs_indexFlags;
 extern struct afs_cacheOps *afs_cacheType;
 extern ino_t cacheInode;
index 0206c47..9eb4b5a 100644 (file)
@@ -802,10 +802,14 @@ struct afs_stats_CMPerf {
     afs_uint32 cbloops;
     afs_uint32 osiread_efaults;
     afs_int32 cacheBlocksDiscarded;    /*# cache blocks free but not truncated */
+    afs_int32 cacheBucket0_Discarded;  
+    afs_int32 cacheBucket1_Discarded;  
+    afs_int32 cacheBucket2_Discarded;  
+
     /*
      * Spares for future expansion.
      */
-    afs_int32 spare[13];       /*Spares */
+    afs_int32 spare[10];       /*Spares */
 };
 
 
index 5c44cfd..67448c7 100644 (file)
@@ -230,6 +230,8 @@ afs_int32 enable_rxbind = 0;
 afs_int32 afs_shutdown = 0;
 afs_int32 cacheBlocks;         /*Num blocks in the cache */
 afs_int32 cacheFiles = 1000;   /*Optimal # of files in workstation cache */
+afs_int32 rwpct = 0;
+afs_int32 ropct = 0;
 afs_int32 cacheStatEntries = 300;      /*Number of stat cache entries */
 char cacheBaseDir[1024];       /*Where the workstation AFS cache lives */
 char confDir[1024];            /*Where the workstation AFS configuration lives */
@@ -275,6 +277,7 @@ static int enable_dynroot = 0;      /* enable dynroot support */
 static int enable_fakestat = 0;        /* enable fakestat support */
 static int enable_backuptree = 0;      /* enable backup tree support */
 static int enable_nomount = 0; /* do not mount */
+static int enable_splitcache = 0;
 #ifdef notdef
 static int inodes = 60;                /* VERY conservative, but has to be */
 #endif
@@ -1535,7 +1538,21 @@ mainproc(as, arock)
        exit(1);
        }
     }
-    
+    if (as->parms[34].items) {
+       char *c;
+       if (!as->parms[34].items->data ||
+           ((c = strchr(as->parms[34].items->data, '/')) == NULL)) 
+           printf("ignoring splitcache (specify as RW/RO percentages: 60/40)\n"); 
+       else {
+           ropct = atoi((char *)c+1);
+          *c = '\0'; 
+           rwpct = atoi((char *)as->parms[30].items->data);
+           if ((rwpct != 0) && (ropct != 0) && (ropct+rwpct == 100)) {
+               /* -splitcache */
+               enable_splitcache = 1;
+          }
+       }
+    }    
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
      * the cellular community we're willing to let our users see.
@@ -1813,6 +1830,13 @@ mainproc(as, arock)
     cparams.inodes = inodes;
 #endif
     call_syscall(AFSOP_CACHEINIT, &cparams);
+
+    /* do it before we init the cache inodes */
+    if (enable_splitcache) {
+       call_syscall(AFSOP_BUCKETPCT, 1, rwpct);
+       call_syscall(AFSOP_BUCKETPCT, 2, ropct);
+    }
+
     if (afsd_CloseSynch)
        call_syscall(AFSOP_CLOSEWAIT);
 
@@ -2178,6 +2202,8 @@ main(argc, argv)
     cmd_AddParm(ts, "-settime", CMD_FLAG, CMD_OPTIONAL,
                "don't set the time");
     cmd_AddParm(ts, "-rxpck", CMD_SINGLE, CMD_OPTIONAL, "set rx_extraPackets to this value");
+    cmd_AddParm(ts, "-splitcache", CMD_SINGLE, CMD_OPTIONAL, "Percentage RW versus RO in cache (specify as 60/40)");
+
     return (cmd_Dispatch(argc, argv));
 }
 
index 0c8b263..7f969c3 100644 (file)
@@ -47,6 +47,7 @@
 #define AFSOP_BASIC_INIT        36     /* used to be part of START_AFS */
 #define AFSOP_SET_BACKUPTREE    37     /* enable backup tree support */
 #define AFSOP_SET_RXPCK                 38     /*set rx_extraPackets*/
+#define AFSOP_BUCKETPCT          39     /* bucket percentage */
 
 /* The range 20-30 is reserved for AFS system offsets in the afs_syscall */
 #define        AFSCALL_PIOCTL          20
index 64a62fa..55cc3cc 100644 (file)
@@ -755,6 +755,10 @@ PrintOverallPerfInfo(a_ovP)
     printf("\t%10d srvMaxChainLengthHWM\n", a_ovP->srvMaxChainLengthHWM);
     printf("\t%10d srvRecordsHWM\n", a_ovP->srvRecordsHWM);
 
+    printf("\t%10d cacheBucket0_Discarded\n",  a_ovP->cacheBucket0_Discarded);
+    printf("\t%10d cacheBucket1_Discarded\n",  a_ovP->cacheBucket1_Discarded);
+    printf("\t%10d cacheBucket2_Discarded\n",  a_ovP->cacheBucket2_Discarded);
+
     printf("\t%10d sysName_ID\n", a_ovP->sysName_ID);
 
     printf("\tFile Server up/downtimes, same cell:\n");