afsd-no-logfile-20051015
[openafs.git] / src / afsd / afsd.c
index bfc60b6..a258aa1 100644 (file)
@@ -47,7 +47,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
@@ -78,6 +79,7 @@ RCSID
 #include <errno.h>
 #include <sys/time.h>
 #include <dirent.h>
+#include <sys/wait.h>
 
 
 #ifdef HAVE_SYS_PARAM_H
@@ -154,6 +156,9 @@ 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 *);
@@ -184,7 +189,6 @@ kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
 
 
 #define CACHEINFOFILE   "cacheinfo"
-#define        AFSLOGFILE      "AFSLog"
 #define        DCACHEFILE      "CacheItems"
 #define        VOLINFOFILE     "VolumeItems"
 #define CELLINFOFILE   "CellItems"
@@ -229,14 +233,15 @@ struct in_addr_42 {
 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 */
@@ -245,6 +250,7 @@ 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 = FALSE;        /*Keep checking time to avoid drift? */
@@ -259,8 +265,8 @@ 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 */
 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 */
@@ -275,6 +281,7 @@ static int enable_dynroot = 0;      /* enable dynroot support */
 static int enable_fakestat = 0;        /* enable fakestat support */
 static int enable_backuptree = 0;      /* enable backup tree support */
 static int enable_nomount = 0; /* do not mount */
+static int enable_splitcache = 0;
 #ifdef notdef
 static int inodes = 60;                /* VERY conservative, but has to be */
 #endif
@@ -334,7 +341,7 @@ static int HandleMTab();
   *---------------------------------------------------------------------------*/
 
 int
-ParseCacheInfoFile()
+ParseCacheInfoFile(void)
 {
     static char rn[] = "ParseCacheInfoFile";   /*This routine's name */
     FILE *cachefd;             /*Descriptor for cache info file */
@@ -396,8 +403,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);
 }
@@ -407,10 +415,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
@@ -425,7 +436,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) {
@@ -448,12 +467,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;
 }
 
 /*-----------------------------------------------------------------------------
@@ -573,7 +595,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) {
@@ -643,7 +665,7 @@ CreateCacheFile(fname, statp)
     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) {
@@ -675,13 +697,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
   *
@@ -888,16 +923,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);
        }
     }
 
@@ -1007,16 +1033,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);
        }
     }
 
@@ -1055,7 +1072,7 @@ CheckCacheBaseDir(char *dir)
        }
        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";
        }
     }
@@ -1178,13 +1195,10 @@ SweepAFSCache(vFilesFound)
 }
 
 static
-ConfigCell(aci, arock, adir)
-     register struct afsconf_cell *aci;
-     char *arock;
-     struct afsconf_dir *adir;
+ConfigCell(struct afsconf_cell *aci, char *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];
 
@@ -1212,10 +1226,8 @@ ConfigCell(aci, arock, adir)
 }
 
 static
-ConfigCellAlias(aca, arock, adir)
-     register struct afsconf_cellalias *aca;
-     char *arock;
-     struct afsconf_dir *adir;
+ConfigCellAlias(struct afsconf_cellalias *aca,
+               char *arock, struct afsconf_dir *adir)
 {
     /* push the alias into the kernel */
     call_syscall(AFSOP_ADDCELLALIAS, aca->aliasName, aca->realName);
@@ -1296,13 +1308,11 @@ AfsdbLookupHandler()
 #endif
 #endif
 
-mainproc(as, arock)
-     struct cmd_syndesc *as;
-     char *arock;
+mainproc(struct cmd_syndesc *as, char *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() */
@@ -1345,14 +1355,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 */
@@ -1389,7 +1398,8 @@ mainproc(as, arock)
        /* -chunksize */
        chunkSize = atoi(as->parms[12].items->data);
        if (chunkSize < 0 || chunkSize > 30) {
-           printf("afsd:invalid chunk size (not in range 0-30), using default\n");
+           printf
+               ("afsd:invalid chunk size (not in range 0-30), using default\n");
            chunkSize = 0;
        }
     }
@@ -1428,10 +1438,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 */
@@ -1507,22 +1516,37 @@ mainproc(as, arock)
        enable_rxbind = 1;
     }
     if (as->parms[32].items) {
-       /* -settime */
-       cacheSetTime = TRUE;
+       /* -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);
+       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);
+           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;
+           }
        }
     }
-    
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
      * the cellular community we're willing to let our users see.
@@ -1548,18 +1572,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.
      */
@@ -1567,7 +1579,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",
@@ -1575,18 +1593,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;
            }
@@ -1594,8 +1620,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 {
@@ -1604,43 +1633,87 @@ 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);
        }
+       /* 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);
+
        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);
+    }
 
     /*
      * Create and zero the inode table for the desired cache files.
@@ -1666,7 +1739,8 @@ 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))) {
        printf("%s: WARNING: Cache dir check failed (%s)\n", rn, fsTypeMsg);
     }
 #if 0
@@ -1734,6 +1808,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);
@@ -1761,6 +1838,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);
        }
@@ -1768,8 +1853,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.
@@ -1792,6 +1879,13 @@ mainproc(as, arock)
     cparams.inodes = inodes;
 #endif
     call_syscall(AFSOP_CACHEINIT, &cparams);
+
+    /* do it before we init the cache inodes */
+    if (enable_splitcache) {
+       call_syscall(AFSOP_BUCKETPCT, 1, rwpct);
+       call_syscall(AFSOP_BUCKETPCT, 2, ropct);
+    }
+
     if (afsd_CloseSynch)
        call_syscall(AFSOP_CLOSEWAIT);
 
@@ -1953,25 +2047,10 @@ mainproc(as, arock)
        printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
               fullpn_VolInfoFile);
     /* once again, meaningless for a memory-based cache. */
-    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) 
+    if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
        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);
-
-    /*
      * Give the kernel the names of the AFS files cached on the workstation's
      * disk.
      */
@@ -2034,69 +2113,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);
@@ -2126,9 +2163,7 @@ mainproc(as, arock)
 
 
 
-main(argc, argv)
-     int argc;
-     char **argv;
+main(int argc, char **argv)
 {
     struct cmd_syndesc *ts;
 
@@ -2198,10 +2233,14 @@ 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,
-               "don't set the time");
-    cmd_AddParm(ts, "-rxpck", CMD_SINGLE, CMD_OPTIONAL, "set rx_extraPackets to this value");
+    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)");
+
     return (cmd_Dispatch(argc, argv));
 }
 
@@ -2304,9 +2343,9 @@ call_syscall(param1, param2, param3, param4, param5, param6, param7)
 #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);
+       fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
     eparm[0] = param4;
     eparm[1] = param5;
     eparm[2] = param6;
@@ -2319,15 +2358,34 @@ 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,
@@ -2396,15 +2454,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);