dynamic-vcache-allocation-20090319
authorDerrick Brashear <shadow@dementia.org>
Fri, 20 Mar 2009 02:30:49 +0000 (02:30 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 20 Mar 2009 02:30:49 +0000 (02:30 +0000)
LICENSE IPL10
FIXES 124334

add dynamic allocation of vcaches when possible (currently just for linux)

12 files changed:
doc/man-pages/pod8/afsd.pod
src/afs/afs_call.c
src/afs/afs_cbqueue.c
src/afs/afs_daemons.c
src/afs/afs_init.c
src/afs/afs_prototypes.h
src/afs/afs_vcache.c
src/afsd/afsd.c
src/config/afs_args.h
src/config/param.amd64_linux26.h
src/config/param.ia64_linux26.h
src/config/param.linux26.h

index 8d0f54e..d46c35e 100644 (file)
@@ -29,6 +29,7 @@ B<afsd> [B<-afsdb>] [B<-backuptree>]
      [B<-settime>] [B<-shutdown>]
      S<<< [B<-splitcache> <I<RW/RO ratio>>] >>>
      S<<< [B<-stat> <I<number of stat entries>>] >>> [B<-verbose>]
+     [B<-disable-dynamic-vcaches>] 
      S<<< [B<-volumes> <I<number of volume entries>>] >>>
      [B<-waitclose>]
 
@@ -669,6 +670,13 @@ standard output stream.
 Specifies the number of memory structures to allocate for storing volume
 location information. The default value is C<50>.
 
+=item B<-disable-dynamic-vcaches>
+
+By default, dynamic vcache overrides the B<-stat> option by using the value of
+B<-stat> (or the default) as the initial size of the stat (or vcache) pool and
+increases the pool dynamically as needed on supported platforms. This flag will
+disable this new functionality and honor the '-stat' setting.
+
 =item B<-waitclose>
 
 Has no effect on the operation of the Cache Manager. The behavior it
index bccb764..04610ef 100644 (file)
@@ -794,7 +794,8 @@ afs_syscall_call(long parm, long parm2, long parm3, long parm4, long parm5, long
            afs_CacheInit(cparms.cacheScaches, cparms.cacheFiles,
                          cparms.cacheBlocks, cparms.cacheDcaches,
                          cparms.cacheVolumes, cparms.chunkSize,
-                         cparms.memCacheFlag, cparms.inodes, cparms.users);
+                         cparms.memCacheFlag, cparms.inodes, cparms.users, 
+                         cparms.dynamic_vcaches);
 
     } else if (parm == AFSOP_CACHEINODE) {
        ino_t ainode = parm2;
index e9628f2..7264f15 100644 (file)
@@ -180,7 +180,7 @@ afs_DequeueCallback(struct vcache *avc)
  */
 
 /* Sanity check on the callback queue. Allow for slop in the computation. */
-#ifdef AFS_OSF_ENV
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
 #define CBQ_LIMIT (afs_maxvcount + 10)
 #else
 #define CBQ_LIMIT (afs_cacheStats + afs_stats_cmperf.vcacheXAllocs + 10)
index 7de581e..c459d81 100644 (file)
@@ -42,6 +42,8 @@ static int rxepoch_checked = 0;
 #define afs_CheckRXEpoch() {if (rxepoch_checked == 0 && rxkad_EpochWasSet) { \
        rxepoch_checked = 1; afs_GCUserData(/* force flag */ 1);  } }
 
+extern int afsd_dynamic_vcaches;
+
 /* PAG garbage collection */
 /* We induce a compile error if param.h does not define AFS_GCPAGS */
 afs_int32 afs_gcpags = AFS_GCPAGS;
@@ -136,13 +138,13 @@ afs_Daemon(void)
     struct afs_exporter *exporter;
     afs_int32 now;
     afs_int32 last3MinCheck, last10MinCheck, last60MinCheck, lastNMinCheck;
-    afs_int32 last1MinCheck;
+    afs_int32 last1MinCheck, last5MinCheck;
     afs_uint32 lastCBSlotBump;
     char cs_warned = 0;
 
     AFS_STATCNT(afs_Daemon);
     last1MinCheck = last3MinCheck = last60MinCheck = last10MinCheck =
-       lastNMinCheck = 0;
+    last5MinCheck = lastNMinCheck = 0;
 
     afs_rootFid.Fid.Volume = 0;
     while (afs_initState < 101)
@@ -168,6 +170,7 @@ afs_Daemon(void)
     last3MinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);
     last60MinCheck = now - 1800 + ((afs_random() & 0x7fffffff) % 3600);
     last10MinCheck = now - 300 + ((afs_random() & 0x7fffffff) % 600);
+    last5MinCheck = now - 150 + ((afs_random() & 0x7fffffff) % 300);
     lastNMinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);
 
     /* start off with afs_initState >= 101 (basic init done) */
@@ -211,6 +214,19 @@ afs_Daemon(void)
                                         * tickets */
            last3MinCheck = now;
        }
+#ifdef AFS_MAXVCOUNT_ENV
+    if (afsd_dynamic_vcaches && (last5MinCheck + 300 < now)) {
+        /* start with trying to drop us back to our base usage */
+        int anumber;
+        if (afs_maxvcount <= afs_cacheStats) 
+        anumber = VCACHE_FREE;
+        else
+        anumber = VCACHE_FREE + (afs_maxvcount - afs_cacheStats);
+
+        afs_ShakeLooseVCaches(anumber);
+        last5MinCheck = now;
+    }
+#endif
        if (!afs_CheckServerDaemonStarted) {
            /* Do the check here if the correct afsd is not installed. */
            if (!cs_warned) {
index fd79310..b59db08 100644 (file)
@@ -50,6 +50,9 @@ afs_rwlock_t afs_discon_lock;
 extern afs_rwlock_t afs_disconDirtyLock;
 #endif
 
+/* This is the kernel side of the dynamic vcache setting */
+int afsd_dynamic_vcaches = 0;  /* Enable dynamic-vcache support */
+
 /*
  * Initialization order is important.  Must first call afs_CacheInit,
  * then cache file and volume file initialization routines.  Next, the
@@ -86,7 +89,7 @@ static int afs_cacheinit_flag = 0;
 int
 afs_CacheInit(afs_int32 astatSize, afs_int32 afiles, afs_int32 ablocks,
              afs_int32 aDentries, afs_int32 aVolumes, afs_int32 achunk,
-             afs_int32 aflags, afs_int32 ninodes, afs_int32 nusers)
+             afs_int32 aflags, afs_int32 ninodes, afs_int32 nusers, afs_int32 dynamic_vcaches)
 {
     register afs_int32 i;
     register struct volume *tv;
@@ -103,6 +106,13 @@ afs_CacheInit(afs_int32 astatSize, afs_int32 afiles, afs_int32 ablocks,
     afs_stats_cmperf.sysName_ID = SYS_NAME_ID_UNDEFINED;
 #endif /* SYS_NAME_ID */
 
+#ifdef AFS_MAXVCOUNT_ENV
+       afsd_dynamic_vcaches = dynamic_vcaches;
+    printf("%s dynamically allocated vcaches\n", ( afsd_dynamic_vcaches ? "enabling" : "disabling" ));
+#else
+       afsd_dynamic_vcaches = 0;
+#endif
+
     printf("Starting AFS cache scan...");
     if (afs_cacheinit_flag)
        return 0;
index 450403f..0e8b3fe 100644 (file)
@@ -419,7 +419,7 @@ extern int afs_CacheInit(afs_int32 astatSize, afs_int32 afiles,
                         afs_int32 ablocks, afs_int32 aDentries,
                         afs_int32 aVolumes, afs_int32 achunk,
                         afs_int32 aflags, afs_int32 ninodes,
-                        afs_int32 nusers);
+                        afs_int32 nusers, afs_int32 dynamic_vcaches);
 extern void afs_ComputeCacheParms(void);
 extern int afs_InitCacheInfo(register char *afile);
 extern int afs_InitVolumeInfo(char *afile);
index 1992d2e..a8c5c32 100644 (file)
@@ -82,6 +82,7 @@ struct afs_q afs_vhashTV[VCSIZE];
 static struct afs_cbr *afs_cbrHashT[CBRSIZE];
 afs_int32 afs_bulkStatsLost;
 int afs_norefpanic = 0;
+extern int afsd_dynamic_vcaches;
 
 
 /* Disk backed vcache definitions 
@@ -261,6 +262,7 @@ afs_FlushVCache(struct vcache *avc, int *slept)
        VN_UNLOCK(AFSTOV(avc));
 #endif
        AFS_RELE(AFSTOV(avc));
+       afs_stats_cmperf.vcacheXAllocs--;
     } else {
        if (afs_norefpanic) {
            printf("flush vc refcnt < 1");
@@ -621,52 +623,29 @@ afs_FlushReclaimedVcaches(void)
 #endif
 }
 
-/*!
- *   This routine is responsible for allocating a new cache entry
- * from the free list.  It formats the cache entry and inserts it
- * into the appropriate hash tables.  It must be called with
- * afs_xvcache write-locked so as to prevent several processes from
- * trying to create a new cache entry simultaneously.
- *
- * LOCK: afs_NewVCache  afs_xvcache W
- *
- * \param afid The file id of the file whose cache entry is being created.
- *
- * \return The new vcache struct.
- */
-struct vcache *
-afs_NewVCache(struct VenusFid *afid, struct server *serverp)
+static int
+afs_ShakeLooseVCaches(afs_int32 anumber)
 {
-    struct vcache *tvc;
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
     afs_int32 i, j;
-    afs_int32 anumber = VCACHE_FREE;
-#ifdef AFS_AIX_ENV
-    struct gnode *gnodepnt;
-#endif
-#ifdef AFS_OSF_ENV
-    struct vcache *nvc;
-#endif /* AFS_OSF_ENV */
+    struct vcache *tvc;
     struct afs_q *tq, *uq;
     int code, fv_slept;
+    afs_int32 target = anumber;
+    int haveGlock = 1;
 
-    AFS_STATCNT(afs_NewVCache);
-
-    afs_FlushReclaimedVcaches();
+    /* Should probably deal better */
+    if (!ISAFS_GLOCK()) {
+       haveGlock = 0;
+       AFS_GLOCK();
+    }
 
-#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
-# if defined(AFS_OSF30_ENV) || defined(AFS_LINUX22_ENV)
-    if (afs_vcount >= afs_maxvcount)
-# else
-    /*
-     * If we are using > 33 % of the total system vnodes for AFS vcache
-     * entries or we are using the maximum number of vcache entries,
-     * then free some.  (if our usage is > 33% we should free some, if
-     * our usage is > afs_maxvcount, set elsewhere to 0.5*nvnode,
-     * we _must_ free some -- no choice).
-     */
-    if (((3 * afs_vcount) > nvnode) || (afs_vcount >= afs_maxvcount))
-# endif
-    {
+    if (
+#ifdef AFS_MAXVCOUNT_ENV
+       afsd_dynamic_vcaches || /* Always run if dynamic vcaches are enabled. */
+#endif
+       afs_vcount >= afs_maxvcount
+       ) {
        int i;
 
        i = 0;
@@ -675,7 +654,11 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
            uq = QPrev(tq);
            if (tvc->f.states & CVFlushed) {
                refpanic("CVFlushed on VLRU");
-           } else if (i++ > afs_maxvcount) {
+           } else if (
+#ifdef AFS_MAXVCOUNT_ENV
+           ! afsd_dynamic_vcaches && 
+#endif
+           i++ > afs_maxvcount) {
                refpanic("Exceeded pool of AFS vnodes(VLRU cycle?)");
            } else if (QNext(uq) != tq) {
                refpanic("VLRU inconsistent");
@@ -683,14 +666,14 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
                refpanic("refcnt 0 on VLRU");
            }
 
-# if defined(AFS_LINUX22_ENV)
+#if defined(AFS_LINUX22_ENV)
            if (tvc != afs_globalVp && VREFCOUNT(tvc) > 1 && tvc->opens == 0) {
                 struct dentry *dentry;
                 struct list_head *cur, *head;
                 AFS_GUNLOCK();
-#  if defined(AFS_LINUX24_ENV)
+#if defined(AFS_LINUX24_ENV)
                 spin_lock(&dcache_lock);
-#  endif /* AFS_LINUX24_ENV */
+#endif /* AFS_LINUX24_ENV */
                head = &(AFSTOV(tvc))->i_dentry;
 
 restart:
@@ -703,27 +686,27 @@ restart:
 
                    dget_locked(dentry);
 
-#  if defined(AFS_LINUX24_ENV)
+#if defined(AFS_LINUX24_ENV)
                    spin_unlock(&dcache_lock);
-#  endif /* AFS_LINUX24_ENV */
+#endif /* AFS_LINUX24_ENV */
                    if (d_invalidate(dentry) == -EBUSY) {
                        dput(dentry);
                        /* perhaps lock and try to continue? (use cur as head?) */
                        goto inuse;
                    }
                    dput(dentry);
-#  if defined(AFS_LINUX24_ENV)
+#if defined(AFS_LINUX24_ENV)
                    spin_lock(&dcache_lock);
-#  endif /* AFS_LINUX24_ENV */
+#endif /* AFS_LINUX24_ENV */
                    goto restart;
                }                   
-#  if defined(AFS_LINUX24_ENV)
+#if defined(AFS_LINUX24_ENV)
                spin_unlock(&dcache_lock);
-#  endif /* AFS_LINUX24_ENV */
+#endif /* AFS_LINUX24_ENV */
            inuse:
                AFS_GLOCK();
            }
-# endif /* AFS_LINUX22_ENV */
+#endif /* AFS_LINUX22_ENV */
 
            if (VREFCOUNT_GT(tvc,0) && !VREFCOUNT_GT(tvc,1) &&
                tvc->opens == 0
@@ -741,47 +724,96 @@ restart:
            if (tq == uq)
                break;
        }
-       if (anumber == VCACHE_FREE) {
-           printf("afs_NewVCache: warning none freed, using %d of %d\n",
+       if (
+#ifdef AFS_MAXVCOUNT_ENV
+        !afsd_dynamic_vcaches &&
+#endif
+        anumber == target) {
+           printf("afs_ShakeLooseVCaches: warning none freed, using %d of %d\n",
                   afs_vcount, afs_maxvcount);
-           if (afs_vcount >= afs_maxvcount) {
-               printf("afs_NewVCache - none freed\n");
-               return NULL;
-           }
        }
     } /* finished freeing up space */
+/*
+    printf("recycled %d entries\n", target-anumber);
+*/
+    if (!haveGlock)
+       AFS_GUNLOCK();
+#endif
+    return 0;
+}
 
 /* Alloc new vnode. */
-#if defined(AFS_LINUX22_ENV)
+
+static struct vcache *
+afs_AllocVCache(void) 
 {
+    struct vcache *tvc;
+#if defined(AFS_OSF30_ENV)
+    struct vcache *nvc;
+    AFS_GUNLOCK();
+    if (getnewvnode(MOUNT_AFS, &Afs_vnodeops, &nvc)) {
+       /* What should we do ???? */
+       osi_Panic("afs_AllocVCache: no more vnodes");
+    }
+    AFS_GLOCK();
+
+    tvc = nvc;
+    tvc->nextfree = NULL;
+    afs_vcount++;
+#elif defined(AFS_LINUX22_ENV)
     struct inode *ip;
 
     AFS_GUNLOCK();
     ip = new_inode(afs_globalVFS);
     if (!ip)
-       osi_Panic("afs_NewVCache: no more inodes");
+       osi_Panic("afs_AllocVCache: no more inodes");
     AFS_GLOCK();
-#  if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
+#if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
     tvc = VTOAFS(ip);
-#  else
+#else
     tvc = afs_osi_Alloc(sizeof(struct vcache));
     ip->u.generic_ip = tvc;
     tvc->v = ip;
-#  endif
-}
-# else
-    AFS_GUNLOCK();
-    if (getnewvnode(MOUNT_AFS, &Afs_vnodeops, &nvc)) {
-       /* What should we do ???? */
-       osi_Panic("afs_NewVCache: no more vnodes");
-    }
-    AFS_GLOCK();
+#endif
 
-    tvc = nvc;
-    tvc->nextfree = NULL;
-# endif
     afs_vcount++;
-
+#ifdef AFS_MAXVCOUNT_ENV
+    /* track the peak */
+    if (afsd_dynamic_vcaches && afs_maxvcount < afs_vcount) {
+       afs_maxvcount = afs_vcount;
+       printf("peak vnodes: %d\n", afs_maxvcount);
+    }
+#endif
+    afs_stats_cmperf.vcacheXAllocs++;  /* count in case we have a leak */
+#else
+    /* none free, making one is better than a panic */
+    afs_stats_cmperf.vcacheXAllocs++;  /* count in case we have a leak */
+    tvc = (struct vcache *)afs_osi_Alloc(sizeof(struct vcache));
+#if defined(AFS_DARWIN_ENV) && !defined(UKERNEL)
+    tvc->v = NULL; /* important to clean this, or use memset 0 */
+#endif
+#ifdef KERNEL_HAVE_PIN
+    pin((char *)tvc, sizeof(struct vcache));   /* XXX */
+#endif
+#if defined(AFS_SGI_ENV)
+    {
+       char name[METER_NAMSZ];
+       memset(tvc, 0, sizeof(struct vcache));
+       tvc->v.v_number = ++afsvnumbers;
+       tvc->vc_rwlockid = OSI_NO_LOCKID;
+       initnsema(&tvc->vc_rwlock, 1,
+                 makesname(name, "vrw", tvc->v.v_number));
+#ifndef        AFS_SGI53_ENV
+       initnsema(&tvc->v.v_sync, 0,
+                 makesname(name, "vsy", tvc->v.v_number));
+#endif
+#ifndef AFS_SGI62_ENV
+       initnlock(&tvc->v.v_lock,
+                 makesname(name, "vlk", tvc->v.v_number));
+#endif
+    }
+#endif /* AFS_SGI_ENV */
+#endif
 #ifdef AFS_DISCON_ENV
     /* If we create a new inode, we either give it a new slot number,
      * or if one's available, use a slot number from the slot free list
@@ -798,7 +830,52 @@ restart:
     }
 #endif
 
-#else /* AFS_OSF_ENV || AFS_LINUX22_ENV */
+    return tvc;
+}
+
+/*!
+ *   This routine is responsible for allocating a new cache entry
+ * from the free list.  It formats the cache entry and inserts it
+ * into the appropriate hash tables.  It must be called with
+ * afs_xvcache write-locked so as to prevent several processes from
+ * trying to create a new cache entry simultaneously.
+ *
+ * LOCK: afs_NewVCache  afs_xvcache W
+ *
+ * \param afid The file id of the file whose cache entry is being created.
+ *
+ * \return The new vcache struct.
+ */
+struct vcache *
+afs_NewVCache(struct VenusFid *afid, struct server *serverp)
+{
+    struct vcache *tvc;
+    afs_int32 i, j;
+    afs_int32 anumber = VCACHE_FREE;
+#ifdef AFS_AIX_ENV
+    struct gnode *gnodepnt;
+#endif
+    struct afs_q *tq, *uq;
+    int code, fv_slept;
+
+    AFS_STATCNT(afs_NewVCache);
+
+    afs_FlushReclaimedVcaches();
+
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
+#ifdef AFS_MAXVCOUNT_ENV
+    if(!afsd_dynamic_vcaches) {
+#endif
+       afs_ShakeLooseVCaches(anumber);
+       if (afs_vcount >= afs_maxvcount) {
+           printf("afs_NewVCache - none freed\n");
+           return NULL;
+       }
+#ifdef AFS_MAXVCOUNT_ENV
+    }
+#endif
+    tvc = afs_AllocVCache();
+#else /* AFS_OSF_ENV */
     /* pull out a free cache entry */
     if (!freeVCList) {
         int loop = 0;
@@ -818,13 +895,13 @@ restart:
             }
 
            if (!VREFCOUNT_GT(tvc,0)
-# if defined(AFS_DARWIN_ENV) && !defined(UKERNEL) && !defined(AFS_DARWIN80_ENV)
+#if defined(AFS_DARWIN_ENV) && !defined(UKERNEL) && !defined(AFS_DARWIN80_ENV)
                || ((VREFCOUNT(tvc) == 1) && 
                    (UBCINFOEXISTS(AFSTOV(tvc))))
-# endif
+#endif
                && tvc->opens == 0 && (tvc->f.states & CUnlinkedDel) == 0) {
-# if defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#  ifdef AFS_DARWIN80_ENV
+#if defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#ifdef AFS_DARWIN80_ENV
                vnode_t tvp = AFSTOV(tvc);
                /* VREFCOUNT_GT only sees usecounts, not iocounts */
                /* so this may fail to actually recycle the vnode now */
@@ -852,7 +929,7 @@ restart:
                    code = EBUSY;
                } else
                    code = 0;
-#  else /* AFS_DARWIN80_ENV */
+#else /* AFS_DARWIN80_ENV */
                 /*
                  * vgone() reclaims the vnode, which calls afs_FlushVCache(),
                  * then it puts the vnode on the free list.
@@ -865,10 +942,10 @@ restart:
                 fv_slept = 0;
                 code = 0;
                 AFS_GLOCK();
-#  endif
-# else /* AFS_DARWIN80_ENV || AFS_XBSD_ENV */
+#endif
+#else /* AFS_DARWIN80_ENV || AFS_XBSD_ENV */
                 code = afs_FlushVCache(tvc, &fv_slept);
-# endif /* AFS_DARWIN80_ENV || AFS_XBSD_ENV */
+#endif /* AFS_DARWIN80_ENV || AFS_XBSD_ENV */
                if (code == 0) {
                    anumber--;
                }
@@ -886,49 +963,7 @@ restart:
     } /* end of if (!freeVCList) */
 
     if (!freeVCList) {
-       /* none free, making one is better than a panic */
-       afs_stats_cmperf.vcacheXAllocs++;       /* count in case we have a leak */
-       tvc = (struct vcache *)afs_osi_Alloc(sizeof(struct vcache));
-# if defined(AFS_DARWIN_ENV) && !defined(UKERNEL)
-       tvc->v = NULL; /* important to clean this, or use memset 0 */
-# endif
-# ifdef        KERNEL_HAVE_PIN
-       pin((char *)tvc, sizeof(struct vcache));        /* XXX */
-# endif
-
-#ifdef AFS_DISCON_ENV
-       /* If we create a new inode, we either give it a new slot number,
-         * or if one's available, use a slot number from the slot free list
-         */
-        if (afs_freeSlotList != NULL) {
-           struct afs_slotlist *tmp;
-       
-            tvc->diskSlot = afs_freeSlotList->slot;
-            tmp = afs_freeSlotList;
-           afs_freeSlotList = tmp->next;
-           afs_osi_Free(tmp, sizeof(struct afs_slotlist));
-        } else {
-           tvc->diskSlot = afs_nextVcacheSlot++;
-        }
-#endif
-# if defined(AFS_SGI_ENV)
-       {
-           char name[METER_NAMSZ];
-           memset(tvc, 0, sizeof(struct vcache));
-           tvc->v.v_number = ++afsvnumbers;
-           tvc->vc_rwlockid = OSI_NO_LOCKID;
-           initnsema(&tvc->vc_rwlock, 1,
-                     makesname(name, "vrw", tvc->v.v_number));
-#ifndef        AFS_SGI53_ENV
-           initnsema(&tvc->v.v_sync, 0,
-                     makesname(name, "vsy", tvc->v.v_number));
-#endif
-#ifndef AFS_SGI62_ENV
-           initnlock(&tvc->v.v_lock,
-                     makesname(name, "vlk", tvc->v.v_number));
-#endif
-       }
-#endif /* AFS_SGI_ENV */
+       tvc = afs_AllocVCache();
     } else {
        tvc = freeVCList;       /* take from free list */
        freeVCList = tvc->nextfree;
@@ -944,7 +979,7 @@ restart:
 
 #if !defined(AFS_SGI_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
 
-# if AFS_DISCON_ENV
+#if defined(AFS_DISCON_ENV)
     /* We need to preserve the slot that we're being stored into on
      * disk */
     { 
@@ -953,9 +988,9 @@ restart:
        memset((char *)tvc, 0, sizeof(struct vcache));
        tvc->diskSlot = slot;
     }
-# else
+#else
     memset((char *)tvc, 0, sizeof(struct vcache));
-# endif
+#endif
 
 #else
     tvc->uncred = 0;
@@ -1909,7 +1944,7 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq,
        newvcache = 1;
 
        ConvertWToSLock(&afs_xvcache);
-       if (!tvc)
+       if (tvc == NULL)
        {
                ReleaseSharedLock(&afs_xvcache);
                return NULL;
index 53784b8..11ac16d 100644 (file)
@@ -32,6 +32,9 @@
   *    -nosettime  Don't keep checking the time to avoid drift (default).
   *     -settime    Keep checking the time to avoid drift.
   *    -verbose     Be chatty.
+  *    -disable-dynamic-vcaches     Disable the use of -stat value as the starting size of
+  *                          the size of the vcache/stat cache pool, 
+  *                          but increase that pool dynamically as needed.
   *    -debug     Print out additional debugging info.
   *    -kerndev    [OBSOLETE] The kernel device for AFS.
   *    -dontfork   [OBSOLETE] Don't fork off as a new process.
@@ -320,6 +323,7 @@ static int enable_splitcache = 0;
 #ifdef notdef
 static int inodes = 60;                /* VERY conservative, but has to be */
 #endif
+int afsd_dynamic_vcaches = 0;  /* Enable dynamic-vcache support */
 int afsd_verbose = 0;          /*Are we being chatty? */
 int afsd_debug = 0;            /*Are we printing debugging info? */
 int afsd_CloseSynch = 0;       /*Are closes synchronous or not? */
@@ -1747,6 +1751,25 @@ mainproc(struct cmd_syndesc *as, void *arock)
            }
        }
     }
+    if (as->parms[35].items) {
+#ifdef AFS_MAXVCOUNT_ENV
+       /* -disable-dynamic-vcaches */
+       afsd_dynamic_vcaches = FALSE;
+#else
+       printf("afsd: Error toggling flag, dynamically allocated vcaches not supported on your platform\n");
+       exit(1);
+#endif
+    }
+#ifdef AFS_MAXVCOUNT_ENV
+    else {
+       /* -dynamic-vcaches */
+       afsd_dynamic_vcaches = TRUE;
+    }
+
+    if (afsd_verbose)
+    printf("afsd: %s dynamically allocated vcaches\n", ( afsd_dynamic_vcaches ? "enabling" : "disabling" ));
+#endif
+
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
      * the cellular community we're willing to let our users see.
@@ -2085,6 +2108,7 @@ mainproc(struct cmd_syndesc *as, void *arock)
     cparams.chunkSize = chunkSize;
     cparams.setTimeFlag = cacheSetTime;
     cparams.memCacheFlag = cacheFlags;
+    cparams.dynamic_vcaches = afsd_dynamic_vcaches;
 #ifdef notdef
     cparams.inodes = inodes;
 #endif
@@ -2473,6 +2497,8 @@ main(int argc, char **argv)
                "set rx_extraPackets to this value");
     cmd_AddParm(ts, "-splitcache", CMD_SINGLE, CMD_OPTIONAL,
                "Percentage RW versus RO in cache (specify as 60/40)");
+     cmd_AddParm(ts, "-disable-dynamic-vcaches", CMD_FLAG, CMD_OPTIONAL, 
+        "disable stat/vcache cache growing as needed");
 
     return (cmd_Dispatch(argc, argv));
 }
index 2db7d34..1983cb5 100644 (file)
@@ -142,6 +142,7 @@ struct afs_cacheParams {
     afs_int32 memCacheFlag;
     afs_int32 inodes;
     afs_int32 users;
+    afs_int32 dynamic_vcaches;
 };
 
 /*
index 2ad1196..42ce403 100644 (file)
@@ -19,6 +19,7 @@
 #define AFS_AMD64_LINUX26_ENV  1
 #define AFS_LINUX_64BIT_KERNEL 1
 #define AFS_64BITPOINTER_ENV   1       /* pointers are 64 bits */
+#define AFS_MAXVCOUNT_ENV       1
 
 #else /* !defined(UKERNEL) */
 
index 8d67d2a..5ae045e 100644 (file)
@@ -19,6 +19,7 @@
 #define AFS_IA64_LINUX26_ENV   1
 #define AFS_LINUX_64BIT_KERNEL 1
 #define AFS_64BITPOINTER_ENV   1       /* pointers are 64 bits. */
+#define AFS_MAXVCOUNT_ENV       1
 
 #else /* !defined(UKERNEL) */
 
index 6b9d869..1a05b08 100644 (file)
@@ -31,6 +31,7 @@
 #define AFS_HAVE_STATVFS       0       /* System doesn't support statvfs */
 #define AFS_VM_RDWR_ENV                1       /* read/write implemented via VM */
 #define AFS_USE_GETTIMEOFDAY   1       /* use gettimeofday to implement rx clock */
+#define AFS_MAXVCOUNT_ENV       1
 
 #if defined(__KERNEL__) && !defined(KDUMP_KERNEL)
 #define AFS_GLOBAL_SUNLOCK