afsd missing close brace
[openafs.git] / src / afsd / afsd.c
index a258aa1..87f1615 100644 (file)
   *    -confdir    The configuration directory .
   *    -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.
   *     -dcache    The number of data cache entries.
   *     -biods     Number of bkg I/O daemons (AIX3.1 only)
   *    -prealloc  Number of preallocated "small" memory blocks
-  *     -pininodes Number of inodes which can be spared from inode[] for 
-  *                pointing at Vfiles.  If this is set too high, you may have
-  *                system problems, which can only be ameliorated by changing
-  *                NINODE (or equivalent) and rebuilding the kernel.
-  *               This option is now disabled.
   *    -logfile   [OBSOLETE] Place where to put the logfile (default in
   *                <cache>/etc/AFSLog.
   *    -waitclose make close calls always synchronous (slows em down, tho)
@@ -57,8 +56,9 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#ifdef IGNORE_SOME_GCC_WARNINGS
+# pragma GCC diagnostic warning "-Wdeprecated-declarations"
+#endif
 
 #define VFS 1
 
@@ -133,10 +133,10 @@ 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>
+#include <afs/sys_prototypes.h>
 
 #ifdef AFS_SGI61_ENV
 #include <unistd.h>
@@ -158,13 +158,44 @@ void set_staticaddrs(void);
 #ifdef AFS_DARWIN_ENV
 #ifdef AFS_DARWIN80_ENV
 #include <sys/ioctl.h>
+#include <sys/xattr.h>
 #endif
 #include <mach/mach.h>
+#ifndef AFS_DARWIN100_ENV
 /* 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
+#endif
+#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
@@ -263,31 +294,35 @@ 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;         /* # 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 */
-#ifdef AFS_AFSDB_ENV
 static int enable_afsdb = 0;   /* enable AFSDB support */
-#endif
 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
@@ -305,15 +340,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 */
 
@@ -423,7 +614,8 @@ ParseCacheInfoFile(void)
 int
 PartSizeOverflow(char *path, int cs)
 {
-    int bsize = -1, totalblks, mint;
+  int bsize = -1;
+  afs_int64 totalblks, mint;
 #if AFS_HAVE_STATVFS
     struct statvfs statbuf;
 
@@ -458,7 +650,7 @@ PartSizeOverflow(char *path, int cs)
     bsize = statbuf.f_bsize;
 #endif
     if (bsize == -1)
-       return 0;               /* sucess */
+       return 0;               /* success */
 
     /* now free and totalblks are in fragment units, but we want them in 1K units */
     if (bsize >= 1024) {
@@ -470,7 +662,7 @@ PartSizeOverflow(char *path, int cs)
     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",
+           ("Cache size (%d) must be less than 95%% of partition size (which is %lld). Lower cache size\n",
             cs, mint);
        return 1;
     }
@@ -503,10 +695,7 @@ PartSizeOverflow(char *path, int 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 */
@@ -544,17 +733,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);
 }
@@ -584,9 +769,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];
@@ -612,10 +795,27 @@ CreateCacheSubDir(basename, dirNum)
     return (0);
 }
 
+static void
+SetNoBackupAttr(char *fullpn)
+{
+#ifdef AFS_DARWIN80_ENV
+    int ret;
+
+    ret = setxattr(fullpn, "com.apple.metadata:com_apple_backup_excludeItem",
+                  "com.apple.backupd", strlen("com.apple.backupd"), 0,
+                  XATTR_CREATE);
+    if(ret < 0)
+    {
+       if(errno != EEXIST)
+           fprintf(stderr, "afsd: Warning: failed to set attribute to preclude cache backup: %s\n", strerror(errno));
+    }
+#endif
+    return;
+}
+
 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];
@@ -646,6 +846,7 @@ MoveCacheFile(basename, fromDir, toDir, cacheFile, maxDir)
               from, to, ret, errno);
        return -1;
     }
+    SetNoBackupAttr(to);
 
     /* Reset directory pointer; fix file counts */
     dir_for_V[cacheFile] = toDir;
@@ -657,9 +858,7 @@ 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 */
@@ -747,11 +946,10 @@ UnlinkUnwantedFile(char *rn, char *fullpn_FileToDelete, char *fileToDelete)
 
 
 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 */
@@ -799,8 +997,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);
@@ -822,7 +1022,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) {
@@ -890,16 +1092,19 @@ doSweepAFSCache(vFilesFound, directory, dirNum, maxDir)
             * Found the file holding the dcache entries.
             */
            missing_DCacheFile = 0;
+           SetNoBackupAttr(fullpn_DCacheFile);
        } else if (dirNum < 0 && strcmp(currp->d_name, VOLINFOFILE) == 0) {
            /*
             * Found the file holding the volume info.
             */
            missing_VolInfoFile = 0;
+           SetNoBackupAttr(fullpn_VolInfoFile);
        } else if (dirNum < 0 && strcmp(currp->d_name, CELLINFOFILE) == 0) {
            /*
             * Found the file holding the cell info.
             */
            missing_CellInfoFile = 0;
+           SetNoBackupAttr(fullpn_CellInfoFile);
        } else if ((strcmp(currp->d_name, ".") == 0)
                   || (strcmp(currp->d_name, "..") == 0) ||
 #ifdef AFS_DECOSF_ENV
@@ -959,7 +1164,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);
@@ -970,11 +1177,14 @@ 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)++;
                    }
+                   SetNoBackupAttr(fullpn_VFile);
                }
 
            } else if (dir_for_V[vFileNum] >= maxDir
@@ -1070,11 +1280,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 */
            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
 
@@ -1139,8 +1355,7 @@ CheckCacheBaseDir(char *dir)
 }
 
 int
-SweepAFSCache(vFilesFound)
-     int *vFilesFound;
+SweepAFSCache(int *vFilesFound)
 {
     static char rn[] = "SweepAFSCache";        /*Routine name */
     int maxDir = (cacheFiles + nFilesPerDir - 1) / nFilesPerDir;
@@ -1194,8 +1409,8 @@ SweepAFSCache(vFilesFound)
     return doSweepAFSCache(vFilesFound, cacheBaseDir, -2, maxDir);
 }
 
-static
-ConfigCell(struct afsconf_cell *aci, char *arock, struct afsconf_dir *adir)
+static int
+ConfigCell(struct afsconf_cell *aci, void *arock, struct afsconf_dir *adir)
 {
     int isHomeCell;
     int i, code;
@@ -1225,18 +1440,17 @@ ConfigCell(struct afsconf_cell *aci, char *arock, struct afsconf_dir *adir)
     return 0;
 }
 
-static
+static int
 ConfigCellAlias(struct afsconf_cellalias *aca,
-               char *arock, struct afsconf_dir *adir)
+               void *arock, struct afsconf_dir *adir)
 {
     /* push the alias into the kernel */
     call_syscall(AFSOP_ADDCELLALIAS, aca->aliasName, aca->realName);
     return 0;
 }
 
-#ifdef AFS_AFSDB_ENV
-static
-AfsdbLookupHandler()
+static void
+AfsdbLookupHandler(void)
 {
     afs_int32 kernelMsg[64];
     char acellName[128];
@@ -1248,6 +1462,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);
@@ -1277,10 +1501,11 @@ AfsdbLookupHandler()
            acellName[sizeof(acellName) - 1] = '\0';
        }
     }
-
+#ifdef AFS_DARWIN_ENV
+    kill(event_pid, SIGTERM);
+#endif
     exit(1);
 }
-#endif
 
 #ifdef mac2
 #include <sys/ioctl.h>
@@ -1308,7 +1533,8 @@ AfsdbLookupHandler()
 #endif
 #endif
 
-mainproc(struct cmd_syndesc *as, char *arock)
+int
+mainproc(struct cmd_syndesc *as, void *arock)
 {
     static char rn[] = "afsd"; /*Name of this routine */
     afs_int32 code;            /*Result of fork() */
@@ -1319,12 +1545,10 @@ mainproc(struct cmd_syndesc *as, char *arock)
     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
@@ -1426,12 +1650,6 @@ mainproc(struct cmd_syndesc *as, char *arock)
        /* -prealloc */
        preallocs = atoi(as->parms[16].items->data);
     }
-#ifdef notdef
-    if (as->parms[17].items) {
-       /* -pininodes */
-       inodes = atoi(as->parms[17].items->data);
-    }
-#endif
     strcpy(confDir, AFSDIR_CLIENT_ETC_DIRPATH);
     if (as->parms[17].items) {
        /* -confdir */
@@ -1470,20 +1688,16 @@ mainproc(struct cmd_syndesc *as, char *arock)
     }
     if (as->parms[23].items) {
        /* -mem_alloc_sleep */
-       cacheFlags |= AFSCALL_INIT_MEMCACHE_SLEEP;
+       printf("afsd: -mem_alloc_sleep is deprecated -- ignored\n");
     }
     if (as->parms[24].items) {
        /* -afsdb */
-#ifdef AFS_AFSDB_ENV
        enable_afsdb = 1;
-#else
-       printf("afsd: No AFSDB support; ignoring -afsdb");
-#endif
     }
     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);
@@ -1547,6 +1761,31 @@ mainproc(struct cmd_syndesc *as, char *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
+
+    /* set -rxmaxmtu */
+    if (as->parms[36].items) {
+        /* -rxmaxmtu */
+        rxmaxmtu = atoi(as->parms[36].items->data);
+    }
+
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
      * the cellular community we're willing to let our users see.
@@ -1683,12 +1922,19 @@ mainproc(struct cmd_syndesc *as, char *arock)
            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) {
            dCacheSize = cacheFiles / 2;
@@ -1715,6 +1961,7 @@ mainproc(struct cmd_syndesc *as, char *arock)
                   cacheStatEntries);
     }
 
+#if !defined(AFS_CACHE_VNODE_PATH) && !defined(LINUX_USE_FH)
     /*
      * Create and zero the inode table for the desired cache files.
      */
@@ -1727,8 +1974,9 @@ mainproc(struct cmd_syndesc *as, char *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.
@@ -1741,12 +1989,13 @@ mainproc(struct cmd_syndesc *as, char *arock)
 
     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.
@@ -1760,7 +2009,7 @@ mainproc(struct cmd_syndesc *as, char *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 =
@@ -1832,7 +2081,6 @@ mainproc(struct cmd_syndesc *as, char *arock)
     }
 #endif
 
-#ifdef AFS_AFSDB_ENV
     if (enable_afsdb) {
        if (afsd_verbose)
            printf("%s: Forking AFSDB lookup handler.\n", rn);
@@ -1850,7 +2098,6 @@ mainproc(struct cmd_syndesc *as, char *arock)
            exit(1);
        }
     }
-#endif
 
     code = call_syscall(AFSOP_BASIC_INIT, 1);
     if (code) {
@@ -1875,9 +2122,7 @@ mainproc(struct cmd_syndesc *as, char *arock)
     cparams.chunkSize = chunkSize;
     cparams.setTimeFlag = cacheSetTime;
     cparams.memCacheFlag = cacheFlags;
-#ifdef notdef
-    cparams.inodes = inodes;
-#endif
+    cparams.dynamic_vcaches = afsd_dynamic_vcaches;
     call_syscall(AFSOP_CACHEINIT, &cparams);
 
     /* do it before we init the cache inodes */
@@ -1939,6 +2184,14 @@ mainproc(struct cmd_syndesc *as, char *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);
@@ -2056,20 +2309,47 @@ mainproc(struct cmd_syndesc *as, char *arock)
      */
     if (afsd_debug)
        printf
-           ("%s: Calling AFSOP_CACHEINODE for each of the %d files in '%s'\n",
+           ("%s: Calling AFSOP_CACHEFILE for each of the %d files in '%s'\n",
             rn, cacheFiles, cacheBaseDir);
-    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
+    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
+       /* ... and again ... */
+       int nocachefile = 0;
        for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
+           if (!nocachefile) {
+               sprintf(fullpn_VFile, "%s/D%d/V%d", cacheBaseDir, dir_for_V[currVFile], currVFile);
+               code = call_syscall(AFSOP_CACHEFILE, fullpn_VFile);
+               if (code) {
+                   if (currVFile == 0) {
+                       if (afsd_debug)
+                           printf
+                               ("%s: Calling AFSOP_CACHEINODE for each of the %d files in '%s'\n",
+                                rn, cacheFiles, cacheBaseDir);
+                       nocachefile = 1;
+                   } else {
+                       printf
+                           ("%s: Error calling AFSOP_CACHEFILE for '%s'\n",
+                            rn, fullpn_VFile);
+                       exit(1);
+                   }
+               } else {
+                   continue;
+               }
+               /* fall through to setup-by-inode */
+           }
 #ifdef AFS_SGI62_ENV
            call_syscall(AFSOP_CACHEINODE,
                         (afs_uint32) (inode_for_V[currVFile] >> 32),
                         (afs_uint32) (inode_for_V[currVFile] & 0xffffffff));
-#else
+#elif !(defined(LINUX_USE_FH) || defined(AFS_CACHE_VNODE_PATH))
            call_syscall(AFSOP_CACHEINODE, inode_for_V[currVFile]);
+#else
+           printf
+               ("%s: Error calling AFSOP_CACHEINODE: not configured\n",
+                rn);
+           exit(1);
 #endif
        }
-
-
+    }
     /*end for */
     /*
      * All the necessary info has been passed into the kernel to run an AFS
@@ -2162,12 +2442,14 @@ mainproc(struct cmd_syndesc *as, char *arock)
 #include "AFS_component_version_number.c"
 
 
-
+int
 main(int argc, char **argv)
 {
     struct cmd_syndesc *ts;
 
     ts = cmd_CreateSyntax(NULL, mainproc, NULL, "start AFS");
+
+    /* 0 - 10 */
     cmd_AddParm(ts, "-blocks", CMD_SINGLE, CMD_OPTIONAL,
                "1024 byte blocks in cache");
     cmd_AddParm(ts, "-files", CMD_SINGLE, CMD_OPTIONAL, "files in cache");
@@ -2186,6 +2468,8 @@ main(int argc, char **argv)
                "display lots of information");
     cmd_AddParm(ts, "-rmtsys", CMD_FLAG, CMD_OPTIONAL,
                "start NFS rmtsysd program");
+
+    /* 11 - 20 */
     cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL, "display debug info");
     cmd_AddParm(ts, "-chunksize", CMD_SINGLE, CMD_OPTIONAL,
                "log(2) of chunk size");
@@ -2195,13 +2479,8 @@ main(int argc, char **argv)
                "number of volume entries");
     cmd_AddParm(ts, "-biods", CMD_SINGLE, CMD_OPTIONAL,
                "number of bkg I/O daemons (aix vm)");
-
     cmd_AddParm(ts, "-prealloc", CMD_SINGLE, CMD_OPTIONAL,
                "number of 'small' preallocated blocks");
-#ifdef notdef
-    cmd_AddParm(ts, "-pininodes", CMD_SINGLE, CMD_OPTIONAL,
-               "number of inodes to hog");
-#endif
     cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL,
                "configuration directory");
     cmd_AddParm(ts, "-logfile", CMD_SINGLE, CMD_OPTIONAL,
@@ -2210,6 +2489,7 @@ main(int argc, char **argv)
                "make close calls synchronous");
     cmd_AddParm(ts, "-shutdown", CMD_FLAG, CMD_OPTIONAL,
                "Shutdown all afs state");
+    /* 21 - 30 */
     cmd_AddParm(ts, "-enable_peer_stats", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE,
                "Collect rpc statistics by peer");
     cmd_AddParm(ts, "-enable_process_stats", CMD_FLAG,
@@ -2217,11 +2497,8 @@ main(int argc, char **argv)
                "Collect rpc statistics for this process");
     cmd_AddParm(ts, "-mem_alloc_sleep", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
                "Allow sleeps when allocating memory cache");
-    cmd_AddParm(ts, "-afsdb", CMD_FLAG, (CMD_OPTIONAL
-#ifndef AFS_AFSDB_ENV
-                                        | CMD_HIDE
-#endif
-               ), "Enable AFSDB support");
+    cmd_AddParm(ts, "-afsdb", CMD_FLAG, (CMD_OPTIONAL),
+               "Enable AFSDB support");
     cmd_AddParm(ts, "-files_per_subdir", CMD_SINGLE, CMD_OPTIONAL,
                "log(2) of the number of cache files per cache subdirectory");
     cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL,
@@ -2233,6 +2510,7 @@ main(int argc, char **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");
+    /* 31 - 40 */
     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");
@@ -2240,7 +2518,10 @@ 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");
+    cmd_AddParm(ts, "-rxmaxmtu", CMD_SINGLE, CMD_OPTIONAL, "set rx max MTU to use");
+    
     return (cmd_Dispatch(argc, argv));
 }
 
@@ -2256,7 +2537,7 @@ main(int argc, char **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;
@@ -2318,6 +2599,7 @@ HandleMTab()
 #endif /* AFS_SUN5_ENV */
 #endif /* unreasonable systems */
 #ifdef AFS_DARWIN_ENV
+#ifndef AFS_DARWIN100_ENV
     mach_port_t diskarb_port;
     kern_return_t status;
 
@@ -2330,14 +2612,15 @@ HandleMTab()
     }
 
     return status;
+#endif
 #endif /* AFS_DARWIN_ENV */
     return 0;
 }
 
 #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
@@ -2365,30 +2648,59 @@ call_syscall(param1, param2, param3, param4, param5, param6, param7)
 #endif
 #ifdef AFS_DARWIN80_ENV
     struct afssysargs syscall_data;
+    void *ioctldata;
     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;
+    int syscallnum;
+#ifdef AFS_DARWIN100_ENV
+    int is64 = 0;
+    struct afssysargs64 syscall64_data;
+    if (sizeof(param1) == 8) {
+       syscallnum = VIOC_SYSCALL64;
+       is64 = 1;
+       ioctldata = &syscall64_data;
+       syscall64_data.syscall = (int)AFSCALL_CALL;
+       syscall64_data.param1 = param1;
+       syscall64_data.param2 = param2;
+       syscall64_data.param3 = param3;
+       syscall64_data.param4 = param4;
+       syscall64_data.param5 = param5;
+       syscall64_data.param6 = param6;
+    } else {
+#endif
+       syscallnum = VIOC_SYSCALL;
+       ioctldata = &syscall_data;
+       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;
+#ifdef AFS_DARWIN100_ENV
+    }
+#endif
     if(fd >= 0) {
-       error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
-       close(fd);
+       error = ioctl(fd, syscallnum, ioctldata);
+       close(fd);
     } else {
-       error = -1;
+       error = -1;
+    }
+    if (!error) {
+#ifdef AFS_DARWIN100_ENV
+       if (is64)
+           error=syscall64_data.retval;
+       else
+#endif
+           error=syscall_data.retval;
     }
-    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);
 }