afsd-allow-maxmtu-override-20090530
[openafs.git] / src / afsd / afsd.c
index 6954bd6..85718d3 100644 (file)
   *    -cachedir    The base directory for the workstation cache.
   *    -mountdir   The directory on which the AFS is to be mounted.
   *    -confdir    The configuration directory .
-  *    -nosettime  Don't keep checking the time to avoid drift.
+  *    -nosettime  Don't keep checking the time to avoid drift (default).
+  *     -settime    Keep checking the time to avoid drift.
+  *    -rxmaxmtu   Set the max mtu to help with VPN issues.
   *    -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.
@@ -46,7 +51,8 @@
   *                system problems, which can only be ameliorated by changing
   *                NINODE (or equivalent) and rebuilding the kernel.
   *               This option is now disabled.
-  *    -logfile   Place where to put the logfile (default in <cache>/etc/AFSLog.
+  *    -logfile   [OBSOLETE] Place where to put the logfile (default in
+  *                <cache>/etc/AFSLog.
   *    -waitclose make close calls always synchronous (slows em down, tho)
   *    -files_per_subdir [n]   number of files per cache subdir. (def=2048)
   *    -shutdown  Shutdown afs daemons
@@ -77,6 +83,8 @@ RCSID
 #include <errno.h>
 #include <sys/time.h>
 #include <dirent.h>
+#include <sys/wait.h>
+
 
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
@@ -129,7 +137,6 @@ RCSID
 #include <netinet/in.h>
 #include <afs/afs_args.h>
 #include <afs/cellconfig.h>
-#include <afs/auth.h>
 #include <ctype.h>
 #include <afs/afssyscalls.h>
 #include <afs/afsutil.h>
@@ -152,12 +159,44 @@ void set_staticaddrs(void);
 #include <sys/resource.h>
 #endif
 #ifdef AFS_DARWIN_ENV
+#ifdef AFS_DARWIN80_ENV
+#include <sys/ioctl.h>
+#endif
 #include <mach/mach.h>
 /* Symbols from the DiskArbitration framework */
 kern_return_t DiskArbStart(mach_port_t *);
 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
                                                         char *);
 #define DISK_ARB_NETWORK_DISK_FLAG 8
+
+#include <mach/mach_port.h>
+#include <mach/mach_interface.h>
+#include <mach/mach_init.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDynamicStore.h>
+
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <IOKit/IOMessage.h>
+
+#include <dns_sd.h>
+
+typedef struct DNSSDState
+{
+    DNSServiceRef       service;
+    CFRunLoopSourceRef  source;
+    CFSocketRef         socket;
+} DNSSDState;
+
+static io_connect_t root_port;
+static IONotificationPortRef notify;
+static io_object_t iterator;
+static CFRunLoopSourceRef source;
+
+static int event_pid;
+
 #endif /* AFS_DARWIN_ENV */
 
 #ifndef MOUNT_AFS
@@ -176,11 +215,12 @@ kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
 #endif
 #endif
 
+
 #undef VIRTUE
 #undef VICE
 
+
 #define CACHEINFOFILE   "cacheinfo"
-#define        AFSLOGFILE      "AFSLog"
 #define        DCACHEFILE      "CacheItems"
 #define        VOLINFOFILE     "VolumeItems"
 #define CELLINFOFILE   "CellItems"
@@ -191,6 +231,7 @@ char LclCellName[64];
 
 #define MAX_CACHE_LOOPS 4
 
+
 /*
  * Internet address (old style... should be updated).  This was pulled out of the old 4.2
  * version of <netinet/in.h>, since it's still useful.
@@ -221,16 +262,18 @@ struct in_addr_42 {
 /*
  * Global configuration variables.
  */
+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 cacheStatEntries = 300;      /*Number of stat cache entries */
+afs_int32 cacheFiles;          /*Optimal # of files in workstation cache */
+afs_int32 rwpct = 0;
+afs_int32 ropct = 0;
+afs_int32 cacheStatEntries;    /*Number of stat cache entries */
 char cacheBaseDir[1024];       /*Where the workstation AFS cache lives */
 char confDir[1024];            /*Where the workstation AFS configuration lives */
 char fullpn_DCacheFile[1024];  /*Full pathname of DCACHEFILE */
 char fullpn_VolInfoFile[1024]; /*Full pathname of VOLINFOFILE */
 char fullpn_CellInfoFile[1024];        /*Full pathanem of CELLINFOFILE */
-char fullpn_AFSLogFile[1024];  /*Full pathname of AFSLOGFILE */
 char fullpn_CacheInfo[1024];   /*Full pathname of CACHEINFO */
 char fullpn_VFile[1024];       /*Full pathname of data cache files */
 char *vFilePtr;                        /*Ptr to the number part of above pathname */
@@ -239,9 +282,10 @@ int sawCacheBaseDir = 0;
 int sawCacheBlocks = 0;
 int sawDCacheSize = 0;
 int sawBiod = 0;
+int sawCacheStatEntries = 0;
 char cacheMountDir[1024];      /*Mount directory for AFS */
 char rootVolume[64] = "root.afs";      /*AFS root volume name */
-afs_int32 cacheSetTime = 1;    /*Keep checking time to avoid drift? */
+afs_int32 cacheSetTime = FALSE;        /*Keep checking time to avoid drift? */
 afs_int32 isHomeCell;          /*Is current cell info for the home cell? */
 #ifdef AFS_XBSD_ENV
 int createAndTrunc = O_RDWR | O_CREAT | O_TRUNC;       /*Create & truncate on open */
@@ -251,14 +295,21 @@ int createAndTrunc = O_CREAT | O_TRUNC;   /*Create & truncate on open */
 int ownerRWmode = 0600;                /*Read/write OK by owner */
 static int filesSet = 0;       /*True if number of files explicitly set */
 static int nFilesPerDir = 2048;        /* # files per cache dir */
-static int nDaemons = 2;       /* Number of background daemons */
+#if defined(AFS_CACHE_BYPASS)
+#define AFSD_NDAEMONS 4
+#else
+#define AFSD_NDAEMONS 2
+#endif
+static int nDaemons = AFSD_NDAEMONS;   /* Number of background daemons */
 static int chunkSize = 0;      /* 2^chunkSize bytes per chunk */
-static int dCacheSize = 300;   /* # of dcache entries */
-static int vCacheSize = 50;    /* # of volume cache entries */
+static int dCacheSize;         /* # of dcache entries */
+static int vCacheSize = 200;   /* # of volume cache entries */
 static int rootVolSet = 0;     /*True if root volume name explicitly set */
 int addrNum;                   /*Cell server address index being printed */
 static int cacheFlags = 0;     /*Flags to cache manager */
+#ifdef AFS_AIX32_ENV
 static int nBiods = 5;         /* AIX3.1 only */
+#endif
 static int preallocs = 400;    /* Def # of allocated memory blocks */
 static int enable_peer_stats = 0;      /* enable rx stats */
 static int enable_process_stats = 0;   /* enable rx stats */
@@ -269,12 +320,15 @@ 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
+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? */
+int rxmaxmtu = 0;       /* Are we forcing a limit on the mtu? */
 
 #ifdef AFS_SGI62_ENV
 #define AFSD_INO_T ino64_t
@@ -292,15 +346,171 @@ int *dir_for_V = NULL;           /* Array: dir of each cache file.
                                 * -2: file exists in top-level
                                 * >=0: file exists in Dxxx
                                 */
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
 AFSD_INO_T *inode_for_V;       /* Array of inodes for desired
                                 * cache files */
+#endif
 int missing_DCacheFile = 1;    /*Is the DCACHEFILE missing? */
 int missing_VolInfoFile = 1;   /*Is the VOLINFOFILE missing? */
 int missing_CellInfoFile = 1;  /*Is the CELLINFOFILE missing? */
 int afsd_rmtsys = 0;           /* Default: don't support rmtsys */
 struct afs_cacheParams cparams;        /* params passed to cache manager */
 
-static int HandleMTab();
+static int HandleMTab(void);
+int PartSizeOverflow(char *path, int cs);
+
+#ifdef AFS_DARWIN_ENV
+static void
+afsd_sleep_callback(void * refCon, io_service_t service, 
+                   natural_t messageType, void * messageArgument )
+{
+    switch (messageType) {
+    case kIOMessageCanSystemSleep:
+       /* Idle sleep is about to kick in; can 
+          prevent sleep by calling IOCancelPowerChange, otherwise 
+          if we don't ack in 30s the system sleeps anyway */
+       
+       /* allow it */
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillSleep:
+       /* The system WILL go to sleep. Ack or suffer delay */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillRestart:
+       /* The system WILL restart. Ack or suffer delay */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillPowerOn:
+    case kIOMessageSystemHasPoweredOn:
+       /* coming back from sleep */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    default:
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+    }
+}
+
+static void
+afsd_update_addresses(CFRunLoopTimerRef timer, void *info)
+{
+    /* parse multihomed address files */
+    afs_uint32 addrbuf[MAXIPADDRS], maskbuf[MAXIPADDRS],
+       mtubuf[MAXIPADDRS];
+    char reason[1024];
+    afs_int32 code;
+
+    code =
+       parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS, reason,
+                     AFSDIR_CLIENT_NETINFO_FILEPATH,
+                     AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
+
+    if (code > 0) {
+       /* Note we're refreshing */
+       code = code | 0x40000000;
+       call_syscall(AFSOP_ADVISEADDR, code, addrbuf, maskbuf, mtubuf);
+    } else
+       printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
+              reason);
+}
+
+/* This function is called when the system's ip addresses may have changed. */
+static void
+afsd_ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
+{
+      CFRunLoopTimerRef timer;
+
+      timer = CFRunLoopTimerCreate (NULL, CFAbsoluteTimeGetCurrent () + 1.0,
+                                   0.0, 0, 0, afsd_update_addresses, NULL);
+      CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
+                        kCFRunLoopDefaultMode);
+      CFRelease (timer);
+}
+
+static void 
+afsd_event_cleanup(int signo) {
+
+    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
+    CFRelease (source);
+    IODeregisterForSystemPower(&iterator);
+    IOServiceClose(root_port);
+    IONotificationPortDestroy(notify);
+
+    exit(0);
+}
+
+/* Adapted from "Living in a Dynamic TCP/IP Environment" technote. */
+static void
+afsd_install_events(void)
+{
+    SCDynamicStoreContext ctx = {0};
+    SCDynamicStoreRef store;
+
+    root_port = IORegisterForSystemPower(0,&notify,afsd_sleep_callback,&iterator);
+    
+    if (root_port) {
+       CFRunLoopAddSource(CFRunLoopGetCurrent(),
+                          IONotificationPortGetRunLoopSource(notify),
+                          kCFRunLoopDefaultMode);
+    }
+    
+    
+    store = SCDynamicStoreCreate (NULL,
+                                 CFSTR ("AddIPAddressListChangeCallbackSCF"),
+                                 afsd_ipaddr_callback, &ctx);
+    
+    if (store) {
+       const void *keys[1];
+       
+       /* Request IPV4 address change notification */
+       keys[0] = (SCDynamicStoreKeyCreateNetworkServiceEntity
+                  (NULL, kSCDynamicStoreDomainState,
+                   kSCCompAnyRegex, kSCEntNetIPv4));
+       
+#if 0
+       /* This should tell us when the hostname(s) change. do we care? */
+       keys[N] = SCDynamicStoreKeyCreateHostNames (NULL);
+#endif
+       
+       if (keys[0] != NULL) {
+           CFArrayRef pattern_array;
+           
+           pattern_array = CFArrayCreate (NULL, keys, 1,
+                                          &kCFTypeArrayCallBacks);
+           
+           if (pattern_array != NULL)
+           {
+               SCDynamicStoreSetNotificationKeys (store, NULL, pattern_array);
+               source = SCDynamicStoreCreateRunLoopSource (NULL, store, 0);
+               
+               CFRelease (pattern_array);
+           }
+           
+           if (keys[0] != NULL)
+               CFRelease (keys[0]);
+       }
+       
+       CFRelease (store); 
+    }
+    
+    if (source != NULL) {
+       CFRunLoopAddSource (CFRunLoopGetCurrent(),
+                           source, kCFRunLoopDefaultMode);
+    }
+    
+    signal(SIGTERM, afsd_event_cleanup);
+
+    CFRunLoopRun();
+}
+#endif
 
 /* ParseArgs is now obsolete, being handled by cmd */
 
@@ -328,7 +538,7 @@ static int HandleMTab();
   *---------------------------------------------------------------------------*/
 
 int
-ParseCacheInfoFile()
+ParseCacheInfoFile(void)
 {
     static char rn[] = "ParseCacheInfoFile";   /*This routine's name */
     FILE *cachefd;             /*Descriptor for cache info file */
@@ -390,8 +600,9 @@ ParseCacheInfoFile()
            ("\tcacheMountDir: '%s'\n\tcacheBaseDir: '%s'\n\tcacheBlocks: %d\n",
             tmd, tbd, tCacheBlocks);
     }
-    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
-       PartSizeOverflow(tbd, cacheBlocks);
+    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
+       return (PartSizeOverflow(tbd, cacheBlocks));
+    }
 
     return (0);
 }
@@ -401,10 +612,13 @@ ParseCacheInfoFile()
  * isn't a mounted partition it's also ignored since we can't guarantee 
  * what will be stored afterwards. Too many if's. This is now purely
  * advisory. ODS with over 2G partition also gives warning message.
+ *
+ * Returns:
+ *     0 if everything went well,
+ *     1 otherwise.
  */
-PartSizeOverflow(path, cs)
-     char *path;
-     int cs;
+int
+PartSizeOverflow(char *path, int cs)
 {
     int bsize = -1, totalblks, mint;
 #if AFS_HAVE_STATVFS
@@ -419,7 +633,15 @@ PartSizeOverflow(path, cs)
     }
     totalblks = statbuf.f_blocks;
     bsize = statbuf.f_frsize;
-#else
+#if AFS_AIX51_ENV
+    if (strcmp(statbuf.f_basetype, "jfs")) {
+       fprintf(stderr, "Cache filesystem '%s' must be jfs (now %s)\n",
+               path, statbuf.f_basetype);
+       return 1;
+    }
+#endif /* AFS_AIX51_ENV */
+
+#else /* AFS_HAVE_STATVFS */
     struct statfs statbuf;
 
     if (statfs(path, &statbuf) < 0) {
@@ -442,12 +664,15 @@ PartSizeOverflow(path, cs)
        totalblks /= (1024 / bsize);
     }
 
-    mint = totalblks - ((totalblks * 5) / 100);
+    mint = totalblks / 100 * 95;
     if (cs > mint) {
        printf
            ("Cache size (%d) must be less than 95%% of partition size (which is %d). Lower cache size\n",
             cs, mint);
+       return 1;
     }
+
+    return 0;
 }
 
 /*-----------------------------------------------------------------------------
@@ -475,10 +700,7 @@ PartSizeOverflow(path, cs)
   *---------------------------------------------------------------------------*/
 
 static int
-doGetXFileNumber(fname, filechar, maxNum)
-     char *fname;
-     char filechar;
-     int maxNum;
+doGetXFileNumber(char *fname, char filechar, int maxNum)
 {
     int computedVNumber;       /*The computed file number we return */
     int filenameLen;           /*Number of chars in filename */
@@ -516,17 +738,13 @@ doGetXFileNumber(fname, filechar, maxNum)
 }
 
 int
-GetVFileNumber(fname, maxFile)
-     char *fname;
-     int maxFile;
+GetVFileNumber(char *fname, int maxFile)
 {
     return doGetXFileNumber(fname, 'V', maxFile);
 }
 
 int
-GetDDirNumber(fname, maxDir)
-     char *fname;
-     int maxDir;
+GetDDirNumber(char *fname, int maxDir)
 {
     return doGetXFileNumber(fname, 'D', maxDir);
 }
@@ -556,9 +774,7 @@ GetDDirNumber(fname, maxDir)
   *---------------------------------------------------------------------------*/
 
 static int
-CreateCacheSubDir(basename, dirNum)
-     char *basename;
-     int dirNum;
+CreateCacheSubDir(char *basename, int dirNum)
 {
     static char rn[] = "CreateCacheSubDir";    /* Routine Name */
     char dir[1024];
@@ -567,7 +783,7 @@ CreateCacheSubDir(basename, dirNum)
     /* Build the new cache subdirectory */
     sprintf(dir, "%s/D%d", basename, dirNum);
 
-    if (afsd_verbose)
+    if (afsd_debug)
        printf("%s: Creating cache subdir '%s'\n", rn, dir);
 
     if ((ret = mkdir(dir, 0700)) != 0) {
@@ -585,9 +801,8 @@ CreateCacheSubDir(basename, dirNum)
 }
 
 static int
-MoveCacheFile(basename, fromDir, toDir, cacheFile, maxDir)
-     char *basename;
-     int fromDir, toDir, cacheFile, maxDir;
+MoveCacheFile(char *basename, int fromDir, int toDir, int cacheFile, 
+             int maxDir)
 {
     static char rn[] = "MoveCacheFile";
     char from[1024], to[1024];
@@ -629,15 +844,13 @@ MoveCacheFile(basename, fromDir, toDir, cacheFile, maxDir)
 }
 
 int
-CreateCacheFile(fname, statp)
-     char *fname;
-     struct stat *statp;
+CreateCacheFile(char *fname, struct stat *statp)
 {
     static char rn[] = "CreateCacheFile";      /*Routine name */
     int cfd;                   /*File descriptor to AFS cache file */
     int closeResult;           /*Result of close() */
 
-    if (afsd_verbose)
+    if (afsd_debug)
        printf("%s: Creating cache file '%s'\n", rn, fname);
     cfd = open(fname, createAndTrunc, ownerRWmode);
     if (cfd <= 0) {
@@ -669,13 +882,26 @@ static void
 CreateFileIfMissing(char *fullpn, int missing)
 {
     if (missing) {
-       if (afsd_verbose)
-           printf("CreateFileIfMissing: Creating '%s'\n", fullpn);
        if (CreateCacheFile(fullpn, NULL))
            printf("CreateFileIfMissing: Can't create '%s'\n", fullpn);
     }
 }
 
+static void
+UnlinkUnwantedFile(char *rn, char *fullpn_FileToDelete, char *fileToDelete)
+{
+    if (unlink(fullpn_FileToDelete)) {
+       if ((errno == EISDIR || errno == EPERM) && *fileToDelete == 'D') {
+           if (rmdir(fullpn_FileToDelete)) {
+               printf("%s: Can't rmdir '%s', errno is %d\n", rn,
+                      fullpn_FileToDelete, errno);
+           }
+       } else
+           printf("%s: Can't unlink '%s', errno is %d\n", rn,
+                  fullpn_FileToDelete, errno);
+    }
+}
+
 /*-----------------------------------------------------------------------------
   * SweepAFSCache
   *
@@ -706,11 +932,10 @@ CreateFileIfMissing(char *fullpn, int missing)
 
 
 static int
-doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
-     int *vFilesFound;
-     char *directory;          /* /path/to/cache/directory */
-     int dirNum;               /* current directory number */
-     int maxDir;               /* maximum directory number */
+doSweepAFSCache(int *vFilesFound, 
+               char *directory,        /* /path/to/cache/directory */
+               int dirNum,             /* current directory number */
+               int maxDir)             /* maximum directory number */
 {
     static char rn[] = "doSweepAFSCache";      /* Routine Name */
     char fullpn_FileToDelete[1024];    /*File to be deleted from cache */
@@ -758,8 +983,10 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
        if (afsd_debug) {
            printf("%s: Current directory entry:\n", rn);
 #ifdef AFS_SGI62_ENV
-           printf("\tinode=%lld, reclen=%d, name='%s'\n", currp->d_ino,
+           printf("\tinode=%" AFS_INT64_FMT ", reclen=%d, name='%s'\n", currp->d_ino,
                   currp->d_reclen, currp->d_name);
+#elif defined(AFS_DFBSD_ENV)
+           printf("\tinode=%d, name='%s'\n", currp->d_ino, currp->d_name);
 #else
            printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
                   currp->d_reclen, currp->d_name);
@@ -781,7 +1008,9 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
             * file's inode, directory, and bump the number of files found
             * total and in this directory.
             */
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
            inode_for_V[vFileNum] = currp->d_ino;
+#endif
            dir_for_V[vFileNum] = dirNum;       /* remember this directory */
 
            if (!maxDir) {
@@ -882,16 +1111,7 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
            sprintf(fileToDelete, "%s", currp->d_name);
            if (afsd_verbose)
                printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
-           if (unlink(fullpn_FileToDelete)) {
-               if (errno == EISDIR && *fileToDelete == 'D') {
-                   if (rmdir(fullpn_FileToDelete)) {
-                       printf("%s: Can't rmdir '%s', errno is %d\n", rn,
-                              fullpn_FileToDelete, errno);
-                   }
-               } else
-                   printf("%s: Can't unlink '%s', errno is %d\n", rn,
-                          fullpn_FileToDelete, errno);
-           }
+           UnlinkUnwantedFile(rn, fullpn_FileToDelete, fileToDelete);
        }
     }
 
@@ -927,7 +1147,9 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
                           vFileNum);
                else {
                    struct stat statb;
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
                    assert(inode_for_V[vFileNum] == (AFSD_INO_T) 0);
+#endif
                    sprintf(vFilePtr, "D%d/V%d", thisDir, vFileNum);
                    if (afsd_verbose)
                        printf("%s: Creating '%s'\n", rn, fullpn_VFile);
@@ -938,7 +1160,9 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
                    if (CreateCacheFile(fullpn_VFile, &statb))
                        printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
                    else {
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
                        inode_for_V[vFileNum] = statb.st_ino;
+#endif
                        dir_for_V[vFileNum] = thisDir;
                        cache_dir_list[thisDir]++;
                        (*vFilesFound)++;
@@ -1001,16 +1225,7 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
        /* Remove any directories >= maxDir -- they should be empty */
        for (; highDir >= maxDir; highDir--) {
            sprintf(fileToDelete, "D%d", highDir);
-           if (unlink(fullpn_FileToDelete)) {
-               if (errno == EISDIR && *fileToDelete == 'D') {
-                   if (rmdir(fullpn_FileToDelete)) {
-                       printf("%s: Can't rmdir '%s', errno is %d\n", rn,
-                              fullpn_FileToDelete, errno);
-                   }
-               } else
-                   printf("%s: Can't unlink '%s', errno is %d\n", rn,
-                          fullpn_FileToDelete, errno);
-           }
+           UnlinkUnwantedFile(rn, fullpn_FileToDelete, fileToDelete);
        }
     }
 
@@ -1047,11 +1262,17 @@ CheckCacheBaseDir(char *dir)
        if (res != 0) {
            return "unable to statfs cache base directory";
        }
+#if !defined(LINUX_USE_FH)
        if (statfsbuf.f_type == 0x52654973) {   /* REISERFS_SUPER_MAGIC */
            return "cannot use reiserfs as cache partition";
-       } else if  (statfsbuf.f_type == 0x58465342) { /* XFS_SUPER_MAGIC */
+       } else if (statfsbuf.f_type == 0x58465342) {    /* XFS_SUPER_MAGIC */
            return "cannot use xfs as cache partition";
+       } else if (statfsbuf.f_type == 0x01021994) {    /* TMPFS_SUPER_MAGIC */
+            return "cannot use tmpfs as cache partition";
+        } else if (statfsbuf.f_type != 0xEF53) {
+            return "must use ext2 or ext3 for cache partition";
        }
+#endif
     }
 #endif
 
@@ -1116,8 +1337,7 @@ CheckCacheBaseDir(char *dir)
 }
 
 int
-SweepAFSCache(vFilesFound)
-     int *vFilesFound;
+SweepAFSCache(int *vFilesFound)
 {
     static char rn[] = "SweepAFSCache";        /*Routine name */
     int maxDir = (cacheFiles + nFilesPerDir - 1) / nFilesPerDir;
@@ -1171,14 +1391,11 @@ SweepAFSCache(vFilesFound)
     return doSweepAFSCache(vFilesFound, cacheBaseDir, -2, maxDir);
 }
 
-static
-ConfigCell(aci, arock, adir)
-     register struct afsconf_cell *aci;
-     char *arock;
-     struct afsconf_dir *adir;
+static int
+ConfigCell(struct afsconf_cell *aci, void *arock, struct afsconf_dir *adir)
 {
-    register int isHomeCell;
-    register int i, code;
+    int isHomeCell;
+    int i, code;
     afs_int32 cellFlags = 0;
     afs_int32 hosts[MAXHOSTSPERCELL];
 
@@ -1205,11 +1422,9 @@ ConfigCell(aci, arock, adir)
     return 0;
 }
 
-static
-ConfigCellAlias(aca, arock, adir)
-     register struct afsconf_cellalias *aca;
-     char *arock;
-     struct afsconf_dir *adir;
+static int
+ConfigCellAlias(struct afsconf_cellalias *aca,
+               void *arock, struct afsconf_dir *adir)
 {
     /* push the alias into the kernel */
     call_syscall(AFSOP_ADDCELLALIAS, aca->aliasName, aca->realName);
@@ -1217,8 +1432,8 @@ ConfigCellAlias(aca, arock, adir)
 }
 
 #ifdef AFS_AFSDB_ENV
-static
-AfsdbLookupHandler()
+static void
+AfsdbLookupHandler(void)
 {
     afs_int32 kernelMsg[64];
     char acellName[128];
@@ -1230,6 +1445,16 @@ AfsdbLookupHandler()
     kernelMsg[1] = 0;
     acellName[0] = '\0';
 
+#ifdef AFS_DARWIN_ENV
+    /* Fork the event handler also. */
+    code = fork();
+    if (code == 0) {
+       afsd_install_events();
+       exit(1);
+    } else if (code != -1) {
+       event_pid = code;
+    }
+#endif
     while (1) {
        /* On some platforms you only get 4 args to an AFS call */
        int sizeArg = ((sizeof acellName) << 16) | (sizeof kernelMsg);
@@ -1259,7 +1484,9 @@ AfsdbLookupHandler()
            acellName[sizeof(acellName) - 1] = '\0';
        }
     }
-
+#ifdef AFS_DARWIN_ENV
+    kill(event_pid, SIGTERM);
+#endif
     exit(1);
 }
 #endif
@@ -1290,25 +1517,22 @@ AfsdbLookupHandler()
 #endif
 #endif
 
-mainproc(as, arock)
-     register struct cmd_syndesc *as;
-     char *arock;
+int
+mainproc(struct cmd_syndesc *as, void *arock)
 {
     static char rn[] = "afsd"; /*Name of this routine */
-    register afs_int32 code;   /*Result of fork() */
-    register int i;
+    afs_int32 code;            /*Result of fork() */
+    int i;
     int currVFile;             /*Current AFS cache file number passed in */
     int mountFlags;            /*Flags passed to mount() */
     int lookupResult;          /*Result of GetLocalCellName() */
     int cacheIteration;                /*How many times through cache verification */
     int vFilesFound;           /*How many data cache files were found in sweep */
     struct afsconf_dir *cdir;  /* config dir */
-    FILE *logfd;
     char *fsTypeMsg = NULL;
 #ifdef AFS_SUN5_ENV
     struct stat st;
 #endif
-    afs_int32 vfs1_type = -1;
 #ifdef AFS_SGI65_ENV
     struct sched_param sp;
 #endif
@@ -1339,14 +1563,13 @@ mainproc(as, arock)
     if (as->parms[3].items) {
        /* -stat */
        cacheStatEntries = atoi(as->parms[3].items->data);
+       sawCacheStatEntries = 1;
     }
     if (as->parms[4].items) {
        /* -memcache */
        cacheBaseDir[0] = '\0';
        sawCacheBaseDir = 1;
        cacheFlags |= AFSCALL_INIT_MEMCACHE;
-       if (chunkSize == 0)
-           chunkSize = 13;
     }
     if (as->parms[5].items) {
        /* -cachedir */
@@ -1383,7 +1606,8 @@ mainproc(as, arock)
        /* -chunksize */
        chunkSize = atoi(as->parms[12].items->data);
        if (chunkSize < 0 || chunkSize > 30) {
-           printf("afsd:invalid chunk size spec'd, using default\n");
+           printf
+               ("afsd:invalid chunk size (not in range 0-30), using default\n");
            chunkSize = 0;
        }
     }
@@ -1422,10 +1646,9 @@ mainproc(as, arock)
        strcpy(confDir, as->parms[17].items->data);
     }
     sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
-    sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
     if (as->parms[18].items) {
        /* -logfile */
-       strcpy(fullpn_AFSLogFile, as->parms[18].items->data);
+        printf("afsd: Ignoring obsolete -logfile flag\n");
     }
     if (as->parms[19].items) {
        /* -waitclose */
@@ -1468,7 +1691,7 @@ mainproc(as, arock)
     if (as->parms[25].items) {
        /* -files_per_subdir */
        int res = atoi(as->parms[25].items->data);
-       if (res < 10 || res > 2 ^ 30) {
+       if (res < 10 || res > (1 << 30)) {
            printf
                ("afsd:invalid number of files per subdir, \"%s\". Ignored\n",
                 as->parms[25].items->data);
@@ -1496,6 +1719,66 @@ mainproc(as, arock)
        /* -backuptree */
        enable_backuptree = 1;
     }
+    if (as->parms[31].items) {
+       /* -rxbind */
+       enable_rxbind = 1;
+    }
+    if (as->parms[32].items) {
+       /* -settime */
+       cacheSetTime = TRUE;
+    }
+
+    /* set rx_extraPackets */
+    if (as->parms[33].items) {
+       /* -rxpck */
+       int rxpck = atoi(as->parms[33].items->data);
+       printf("afsd: set rxpck = %d\n", rxpck);
+       code = call_syscall(AFSOP_SET_RXPCK, rxpck);
+       if (code) {
+           printf("afsd: failed to set rxpck\n");
+           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;
+           }
+       }
+    }
+    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
+
+    /* set -rxmaxmtu */
+    if (as->parms[35].items) {
+        /* -rxmaxmtu */
+        rxmaxmtu = atoi(as->parms[35].items->data);
+    }
 
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
@@ -1522,18 +1805,6 @@ mainproc(as, arock)
        exit(1);
     }
 
-    if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
-       if (afsd_verbose)
-           printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
-       if (CreateCacheFile(fullpn_AFSLogFile, NULL)) {
-           printf
-               ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
-                rn, fullpn_AFSLogFile);
-           exit(1);
-       }
-    } else
-       fclose(logfd);
-
     /* do some random computations in memcache case to get things to work
      * reasonably no matter which parameters you set.
      */
@@ -1541,7 +1812,13 @@ mainproc(as, arock)
        /* memory cache: size described either as blocks or dcache entries, but
         * not both.
         */
+       if (filesSet) {
+           fprintf(stderr, "%s: -files ignored with -memcache\n", rn);
+       }
        if (sawDCacheSize) {
+           if (chunkSize == 0) {
+               chunkSize = 13; /* 8k default chunksize for memcache */
+           }
            if (sawCacheBlocks) {
                printf
                    ("%s: can't set cache blocks and dcache size simultaneously when diskless.\n",
@@ -1549,18 +1826,26 @@ mainproc(as, arock)
                exit(1);
            }
            /* compute the cache size based on # of chunks times the chunk size */
-           i = (chunkSize == 0 ? 13 : chunkSize);
-           i = (1 << i);       /* bytes per chunk */
+           i = (1 << chunkSize);       /* bytes per chunk */
            cacheBlocks = i * dCacheSize;
            sawCacheBlocks = 1; /* so that ParseCacheInfoFile doesn't overwrite */
        } else {
+           if (chunkSize == 0) {
+               /* Try to autotune the memcache chunksize based on size
+                * of memcache. This is done on the assumption that approx
+                * 1024 chunks is suitable, it's a balance between enough
+                * chunks to be useful and ramping up nicely when using larger
+                * memcache to improve bulk read/write performance
+                */
+               for (i = 14;
+                    i <= 21 && (1 << i) / 1024 < (cacheBlocks / 1024); i++);
+               chunkSize = i - 1;
+           }
            /* compute the dcache size from overall cache size and chunk size */
-           i = (chunkSize == 0 ? 13 : chunkSize);
-           /* dCacheSize = (cacheBlocks << 10) / (1<<i); */
-           if (i > 10) {
-               dCacheSize = (cacheBlocks >> (i - 10));
-           } else if (i < 10) {
-               dCacheSize = (cacheBlocks << (10 - i));
+           if (chunkSize > 10) {
+               dCacheSize = (cacheBlocks >> (chunkSize - 10));
+           } else if (chunkSize < 10) {
+               dCacheSize = (cacheBlocks << (10 - chunkSize));
            } else {
                dCacheSize = cacheBlocks;
            }
@@ -1568,8 +1853,11 @@ mainproc(as, arock)
             * by ParseCacheInfoFile.
             */
        }
-       /* kernel computes # of dcache entries as min of cacheFiles and dCacheSize,
-        * so we now make them equal.
+       if (afsd_verbose)
+           printf("%s: chunkSize autotuned to %d\n", rn, chunkSize);
+
+       /* kernel computes # of dcache entries as min of cacheFiles and
+        * dCacheSize, so we now make them equal.
         */
        cacheFiles = dCacheSize;
     } else {
@@ -1578,44 +1866,96 @@ mainproc(as, arock)
         * but only if -files isn't given on the command line.
         * Don't let # files be so small as to prevent full utilization 
         * of the cache unless user has explicitly asked for it.
-        * average V-file is ~10K, according to tentative empirical studies.
         */
+       if (chunkSize == 0) {
+           /* Set chunksize to 256kB - 1MB depending on cache size */
+           if (cacheBlocks < 500000) {
+               chunkSize = 18;
+           } else if (cacheBlocks < 1000000) {
+               chunkSize = 19;
+           } else {
+               chunkSize = 20;
+           }
+       }
        if (!filesSet) {
-           cacheFiles = cacheBlocks / 10;
-           if (cacheFiles < 100)
-               cacheFiles = 100;
+           cacheFiles = cacheBlocks / 32;      /* Assume 32k avg filesize */
+
+           cacheFiles = max(cacheFiles, 1000);
+
            /* Always allow more files than chunks.  Presume average V-file 
             * is ~67% of a chunk...  (another guess, perhaps Honeyman will
             * have a grad student write a paper).  i is KILOBYTES.
             */
-           i = 1 << (chunkSize ==
-                     0 ? 6 : (chunkSize < 10 ? 0 : chunkSize - 10));
+           i = 1 << (chunkSize < 10 ? 0 : chunkSize - 10);
            cacheFiles = max(cacheFiles, 1.5 * (cacheBlocks / i));
+
            /* never permit more files than blocks, while leaving space for
             * VolumeInfo and CacheItems files.  VolumeInfo is usually 20K,
             * CacheItems is 50 Bytes / file (== 1K/20)
             */
-#define VOLINFOSZ 20
 #define CACHEITMSZ (cacheFiles / 20)
-#ifdef AFS_AIX_ENV
-           cacheFiles =
-               min(cacheFiles, (cacheBlocks - VOLINFOSZ - CACHEITMSZ) / 4);
-#else
-           cacheFiles =
-               min(cacheFiles, cacheBlocks - VOLINFOSZ - CACHEITMSZ);
-#endif
+#define VOLINFOSZ 50           /* 40kB has been seen, be conservative */
+#define CELLINFOSZ 4           /* Assuming disk block size is 4k ... */
+#define INFOSZ (VOLINFOSZ+CELLINFOSZ+CACHEITMSZ)
+
+           /* Sanity check: If the obtained number of disk cache files
+            * is larger than the number of available (4k) disk blocks, we're
+            * doing something wrong. Fail hard so we can fix the bug instead
+            * of silently hiding it like before */
+
+           if (cacheFiles > (cacheBlocks - INFOSZ) / 4) {
+               fprintf(stderr,
+                       "%s: ASSERT: cacheFiles %d  diskblocks %d\n",
+                       rn, cacheFiles, (cacheBlocks - INFOSZ) / 4);
+               exit(1);
+           }
            if (cacheFiles < 100)
                fprintf(stderr, "%s: WARNING: cache probably too small!\n",
                        rn);
+
+           if (afsd_verbose)
+               printf("%s: cacheFiles autotuned to %d\n", rn, cacheFiles);
        }
+#if 0
+       /* This actually needs to
+          1) use powers of 2
+          2) not second-guess when a chunksize comes from the command line
+          3) be less, um, small. 2^2?? 
+       */
+       /* Sanity check chunkSize */
+       i = max(cacheBlocks / 1000, cacheBlocks / cacheFiles);
+       chunkSize = min(chunkSize, i);
+       chunkSize = max(chunkSize, 2);
+       if (afsd_verbose)
+           printf("%s: chunkSize autotuned to %d\n", rn, chunkSize);
+#endif
+
        if (!sawDCacheSize) {
-           if ((cacheFiles / 2) > dCacheSize)
-               dCacheSize = cacheFiles / 2;
-           if (dCacheSize > 2000)
+           dCacheSize = cacheFiles / 2;
+           if (dCacheSize > 10000) {
+               dCacheSize = 10000;
+           }
+           if (dCacheSize < 2000) {
                dCacheSize = 2000;
+           }
+           if (afsd_verbose)
+               printf("%s: dCacheSize autotuned to %d\n", rn, dCacheSize);
        }
     }
+    if (!sawCacheStatEntries) {
+       if (chunkSize <= 13) {
+           cacheStatEntries = dCacheSize / 4;
+       } else if (chunkSize >= 16) {
+           cacheStatEntries = dCacheSize * 1.5;
+       } else {
+           cacheStatEntries = dCacheSize;
+       }
+       if (afsd_verbose)
+           printf("%s: cacheStatEntries autotuned to %d\n", rn,
+                  cacheStatEntries);
+    }
 
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
     /*
      * Create and zero the inode table for the desired cache files.
      */
@@ -1628,8 +1968,9 @@ mainproc(as, arock)
     }
     memset(inode_for_V, '\0', (cacheFiles * sizeof(AFSD_INO_T)));
     if (afsd_debug)
-       printf("%s: %d inode_for_V entries at 0x%x, %d bytes\n", rn,
+       printf("%s: %d inode_for_V entries at 0x%x, %lu bytes\n", rn,
               cacheFiles, inode_for_V, (cacheFiles * sizeof(AFSD_INO_T)));
+#endif
 
     /*
      * Set up all the pathnames we'll need for later.
@@ -1640,13 +1981,15 @@ mainproc(as, arock)
     sprintf(fullpn_VFile, "%s/", cacheBaseDir);
     vFilePtr = fullpn_VFile + strlen(fullpn_VFile);
 
-    if  (!(cacheFlags & AFSCALL_INIT_MEMCACHE) && (fsTypeMsg = CheckCacheBaseDir(cacheBaseDir))) {
+    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)
+       && (fsTypeMsg = CheckCacheBaseDir(cacheBaseDir))) {
+#ifdef AFS_SUN5_ENV
        printf("%s: WARNING: Cache dir check failed (%s)\n", rn, fsTypeMsg);
-    }
-#if 0
-    fputs(AFS_GOVERNMENT_MESSAGE, stdout);
-    fflush(stdout);
+#else
+       printf("%s: ERROR: Cache dir check failed (%s)\n", rn, fsTypeMsg);
+       exit(1);
 #endif
+    }
 
     /*
      * Set up all the kernel processes needed for AFS.
@@ -1660,16 +2003,18 @@ mainproc(as, arock)
     /* initialize the rx random number generator from user space */
     {
        /* parse multihomed address files */
-       afs_int32 addrbuf[MAXIPADDRS], maskbuf[MAXIPADDRS],
+       afs_uint32 addrbuf[MAXIPADDRS], maskbuf[MAXIPADDRS],
            mtubuf[MAXIPADDRS];
        char reason[1024];
        code =
            parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS, reason,
                          AFSDIR_CLIENT_NETINFO_FILEPATH,
                          AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
-       if (code > 0)
+       if (code > 0) {
+           if (enable_rxbind)
+               code = code | 0x80000000;
            call_syscall(AFSOP_ADVISEADDR, code, addrbuf, maskbuf, mtubuf);
-       else
+       } else
            printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
                   reason);
     }
@@ -1706,6 +2051,9 @@ mainproc(as, arock)
                     enable_process_stats);
        exit(1);
     }
+#ifdef AFS_SUN510_ENV
+    waitpid((pid_t) -1, NULL, 0);
+#endif
 #endif
     if (afsd_verbose)
        printf("%s: Forking rx callback listener.\n", rn);
@@ -1733,6 +2081,14 @@ mainproc(as, arock)
            printf("%s: Forking AFSDB lookup handler.\n", rn);
        code = fork();
        if (code == 0) {
+           /* Since the AFSDB lookup handler runs as a user process, 
+            * need to drop the controlling TTY, etc.
+            */
+           if (daemon(0, 0) == -1) {
+               printf("Error starting AFSDB lookup handler: %s\n",
+                      strerror(errno));
+               exit(1);
+           }
            AfsdbLookupHandler();
            exit(1);
        }
@@ -1740,8 +2096,10 @@ mainproc(as, arock)
 #endif
 
     code = call_syscall(AFSOP_BASIC_INIT, 1);
-    if (code)
+    if (code) {
        printf("%s: Error %d in basic initialization.\n", rn, code);
+        exit(1);
+    }
 
     /*
      * Tell the kernel some basic information about the workstation's cache.
@@ -1760,10 +2118,18 @@ mainproc(as, arock)
     cparams.chunkSize = chunkSize;
     cparams.setTimeFlag = cacheSetTime;
     cparams.memCacheFlag = cacheFlags;
+    cparams.dynamic_vcaches = afsd_dynamic_vcaches;
 #ifdef notdef
     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);
 
@@ -1794,6 +2160,23 @@ mainproc(as, arock)
                     rn, vFilesFound, cacheFiles, cacheIteration);
        } while ((vFilesFound < cacheFiles)
                 && (cacheIteration < MAX_CACHE_LOOPS));
+#ifdef AFS_CACHE_VNODE_PATH
+       if (afsd_debug)
+           printf
+               ("%s: Calling AFSOP_CACHEBASEDIR with '%s'\n",
+                rn, cacheBaseDir);
+       call_syscall(AFSOP_CACHEBASEDIR, cacheBaseDir);
+       if (afsd_debug)
+           printf
+               ("%s: Calling AFSOP_CACHEDIRS with %d dirs\n",
+                rn, nFilesPerDir);
+       call_syscall(AFSOP_CACHEDIRS, nFilesPerDir);
+       if (afsd_debug)
+           printf
+               ("%s: Calling AFSOP_CACHEFILES with %d files\n",
+                rn, cacheFiles);
+       call_syscall(AFSOP_CACHEFILES, cacheFiles);
+#endif
     } else if (afsd_verbose)
        printf("%s: Using memory cache, not swept\n", rn);
 
@@ -1817,6 +2200,14 @@ mainproc(as, arock)
               fullpn_CellInfoFile);
     call_syscall(AFSOP_CELLINFO, fullpn_CellInfoFile);
 
+    if (rxmaxmtu) {
+    if (afsd_verbose)
+        printf("%s: Setting rxmaxmtu in kernel = %d\n", rn, rxmaxmtu);
+    code = call_syscall(AFSOP_SET_RXMAXMTU, rxmaxmtu);
+    if (code)
+        printf("%s: Error seting rxmaxmtu\n", rn);
+    }
+
     if (enable_dynroot) {
        if (afsd_verbose)
            printf("%s: Enabling dynroot support in kernel.\n", rn);
@@ -1924,23 +2315,11 @@ mainproc(as, arock)
     if (afsd_debug)
        printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
               fullpn_VolInfoFile);
-    call_syscall(AFSOP_VOLUMEINFO, fullpn_VolInfoFile);
-
-    /*
-     * Pass the kernel the name of the afs logging file holding the volume
-     * information.
-     */
-    if (afsd_debug)
-       printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
-              fullpn_AFSLogFile);
-#if defined(AFS_SGI_ENV)
-    /* permit explicit -logfile argument to enable logging on memcache systems */
-    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE) || as->parms[18].items)
-#else
-    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
-#endif
-       call_syscall(AFSOP_AFSLOG, fullpn_AFSLogFile);
+    /* once again, meaningless for a memory-based cache. */
+    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
+       call_syscall(AFSOP_VOLUMEINFO, fullpn_VolInfoFile);
 
+#ifndef AFS_CACHE_VNODE_PATH
     /*
      * Give the kernel the names of the AFS files cached on the workstation's
      * disk.
@@ -1956,10 +2335,15 @@ mainproc(as, arock)
                         (afs_uint32) (inode_for_V[currVFile] >> 32),
                         (afs_uint32) (inode_for_V[currVFile] & 0xffffffff));
 #else
+#if defined(LINUX_USE_FH)
+           sprintf(fullpn_VFile, "%s/D%d/V%d", cacheBaseDir, dir_for_V[currVFile], currVFile);
+           call_syscall(AFSOP_CACHEFILE, fullpn_VFile);
+#else
            call_syscall(AFSOP_CACHEINODE, inode_for_V[currVFile]);
 #endif
+#endif
        }
-
+#endif
 
     /*end for */
     /*
@@ -2004,69 +2388,27 @@ mainproc(as, arock)
        if (afsd_verbose)
            printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn,
                   cacheMountDir, mountFlags);
-#ifdef AFS_DEC_ENV
-       if ((mount("AFS", cacheMountDir, mountFlags, GT_AFS, (caddr_t) 0)) <
-           0) {
-#else
-#ifdef AFS_FBSD_ENV
+#if defined(AFS_FBSD60_ENV)
+       /* data must be non-NULL but is otherwise ignored */
+       if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, rn)) < 0) {
+#elif defined(AFS_FBSD_ENV)
        if ((mount("AFS", cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
-#else
-#ifdef AFS_AUX_ENV
-       if ((fsmount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
-#else
-#ifdef AFS_AIX_ENV
+#elif defined(AFS_AIX_ENV)
        if (aix_vmount()) {
-#else
-#if defined(AFS_HPUX100_ENV)
+#elif defined(AFS_HPUX100_ENV)
        if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
-#else
-#ifdef AFS_HPUX_ENV
-#if    defined(AFS_HPUX90_ENV)
-       {
-           char buffer[80];
-           int code;
-
-           strcpy(buffer, "afs");
-           code = vfsmount(-1, cacheMountDir, mountFlags, (caddr_t) buffer);
-           sscanf(buffer, "%d", &vfs1_type);
-           if (code < 0) {
-               printf
-                   ("Can't find 'afs' type in the registered filesystem table!\n");
-               exit(1);
-           }
-           sscanf(buffer, "%d", &vfs1_type);
-           if (afsd_verbose)
-               printf("AFS vfs slot number is %d\n", vfs1_type);
-       }
-       if ((vfsmount(vfs1_type, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
-#else
-       if (call_syscall
-           (AFSOP_AFS_VFSMOUNT, MOUNT_AFS, cacheMountDir, mountFlags,
-            (caddr_t) NULL) < 0) {
-#endif
-#else
-#ifdef AFS_SUN5_ENV
+#elif defined(AFS_SUN5_ENV)
        if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
-#else
-#if defined(AFS_SGI_ENV)
+#elif defined(AFS_SGI_ENV)
        mountFlags = MS_FSS;
        if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS))
            < 0) {
-#else
-#ifdef AFS_LINUX20_ENV
+#elif defined(AFS_LINUX20_ENV)
        if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) {
 #else
 /* This is the standard mount used by the suns and rts */
        if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
-#endif /* AFS_LINUX20_ENV */
-#endif /* AFS_SGI_ENV */
-#endif /* AFS_SUN5_ENV */
-#endif /* AFS_HPUX100_ENV */
-#endif /* AFS_HPUX_ENV */
-#endif /* AFS_AIX_ENV */
-#endif /* AFS_AUX_ENV */
-#endif /* AFS_FBSD_ENV */
-#endif /* AFS_DEC_ENV */
+#endif
            printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir,
                   errno);
            exit(1);
@@ -2095,12 +2437,10 @@ mainproc(as, arock)
 #include "AFS_component_version_number.c"
 
 
-
-main(argc, argv)
-     int argc;
-     char **argv;
+int
+main(int argc, char **argv)
 {
-    register struct cmd_syndesc *ts;
+    struct cmd_syndesc *ts;
 
     ts = cmd_CreateSyntax(NULL, mainproc, NULL, "start AFS");
     cmd_AddParm(ts, "-blocks", CMD_SINGLE, CMD_OPTIONAL,
@@ -2168,6 +2508,17 @@ main(argc, argv)
     cmd_AddParm(ts, "-nomount", CMD_FLAG, CMD_OPTIONAL, "Do not mount AFS");
     cmd_AddParm(ts, "-backuptree", CMD_FLAG, CMD_OPTIONAL,
                "Prefer backup volumes for mointpoints in backup volumes");
+    cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL,
+               "Bind the Rx socket (one interface only)");
+    cmd_AddParm(ts, "-settime", CMD_FLAG, CMD_OPTIONAL, "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)");
+    cmd_AddParm(ts, "-disable-dynamic-vcaches", CMD_FLAG, CMD_OPTIONAL, 
+               "disable stat/vcache cache growing as needed");
+    cmd_AddParm(ts, "-rxmaxmtu", CMD_SINGLE, CMD_OPTIONAL, "set rx max MTU to use");
+    
     return (cmd_Dispatch(argc, argv));
 }
 
@@ -2183,7 +2534,7 @@ main(argc, argv)
 #endif
 
 static int
-HandleMTab()
+HandleMTab(void)
 {
 #if (defined (AFS_SUN_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)) && !defined(AFS_SUN58_ENV)
     FILE *tfilep;
@@ -2263,15 +2614,17 @@ HandleMTab()
 
 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
 
-call_syscall(param1, param2, param3, param4, param5, param6, param7)
-     long param1, param2, param3, param4, param5, param6, param7;
+int
+call_syscall(long param1, long param2, long param3, long param4, long param5, 
+            long param6, long  param7)
 {
     int error;
 #ifdef AFS_LINUX20_ENV
     long eparm[4];
     struct afsprocdata syscall_data;
-    int fd = open(PROC_SYSCALL_FNAME,O_RDWR);
-
+    int fd = open(PROC_SYSCALL_FNAME, O_RDWR);
+    if (fd < 0)
+       fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
     eparm[0] = param4;
     eparm[1] = param5;
     eparm[2] = param6;
@@ -2284,18 +2637,37 @@ call_syscall(param1, param2, param3, param4, param5, param6, param7)
     syscall_data.param2 = param2;
     syscall_data.param3 = param3;
     syscall_data.param4 = param4;
-    if(fd > 0) {
+    if (fd > 0) {
+       error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
+       close(fd);
+    } else
+#endif
+#ifdef AFS_DARWIN80_ENV
+    struct afssysargs syscall_data;
+    int fd = open(SYSCALL_DEV_FNAME,O_RDWR);
+    syscall_data.syscall = AFSCALL_CALL;
+    syscall_data.param1 = param1;
+    syscall_data.param2 = param2;
+    syscall_data.param3 = param3;
+    syscall_data.param4 = param4;
+    syscall_data.param5 = param5;
+    syscall_data.param6 = param6;
+    if(fd >= 0) {
        error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
        close(fd);
+    } else {
+       error = -1;
     }
-    else
-#endif
+    if (!error)
+      error=syscall_data.retval;
+#else
     error =
        syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4,
                param5, param6, param7);
+#endif
 
-    if (afsd_verbose)
-       printf("SScall(%d, %d, %d)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1,
+    if (afsd_debug)
+       printf("SScall(%d, %d, %ld)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1,
               error);
     return (error);
 }
@@ -2361,15 +2733,14 @@ aix_vmount()
     return (error);
 }
 
-vmountdata(vmtp, obj, stub, host, hostsname, info, args)
-     struct vmount *vmtp;
-     char *obj, *stub, *host, *hostsname, *info, *args;
+vmountdata(struct vmount * vmtp, char *obj, char *stub, char *host,
+          char *hostsname, char *info, char *args)
 {
-    register struct data {
+    struct data {
        short vmt_off;
        short vmt_size;
     } *vdp, *vdprev;
-    register int size;
+    int size;
 
     vdp = (struct data *)vmtp->vmt_data;
     vdp->vmt_off = sizeof(struct vmount);