Fix fs bypassthreshold to accept a size of -1 to disable
[openafs.git] / src / venus / fs.c
index 8a93420..a8c1712 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -11,6 +11,7 @@
 #include <afs/param.h>
 
 
+#include <afs/afs_consts.h>
 #include <afs/afs_args.h>
 #include <rx/xdr.h>
 #include <sys/ioctl.h>
 #include <netdb.h>
 #include <errno.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <netinet/in.h>
 #include <sys/stat.h>
 #include <afs/stds.h>
 #include <afs/vice.h>
 #include <afs/venus.h>
 #include <afs/com_err.h>
+#include <afs/afs_consts.h>
 #ifdef AFS_AIX32_ENV
 #include <signal.h>
 #endif
 #include <afs/ptuser.h>
 #include <afs/afsutil.h>
 #include <afs/sys_prototypes.h>
-    
-#define        MAXHOSTS 13
-#define        OMAXHOSTS 8
-#define MAXCELLHOSTS 8
+
 #define MAXNAME 100
-#define        MAXSIZE 2048
 #define MAXINSIZE 1300         /* pioctl complains if data is larger than this */
 #define VMSGSIZE 128           /* size of msg buf in volume hdr */
 
-static char space[MAXSIZE];
+static char space[AFS_PIOCTL_MAXSIZE];
 static char tspace[1024];
 static struct ubik_client *uclient;
 
@@ -291,7 +290,7 @@ InAFS(char *apath)
     afs_int32 code;
 
     blob.in_size = 0;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.out = space;
 
     code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1);
@@ -641,8 +640,30 @@ PrintStatus(VolumeStatus * status, char *name, char *offmsg)
     return 0;
 }
 
+static const char power_letter[] = {
+  'K',  /* kibi */
+  'M',  /* mebi */
+  'G',  /* gibi */
+  'T',  /* tebi */
+  'P',  /* pebi */
+};
+
+static void
+HumanPrintSpace(afs_int32 int_space)
+{
+    int exponent = 0;
+    int exponent_max = sizeof(power_letter) - 1;
+    float space = int_space;
+
+    while (space >= 1024 && exponent < exponent_max) {
+       exponent++;
+       space /= 1024;
+    }
+    printf("%9.1f%c", space, power_letter[exponent]);
+}
+
 static int
-QuickPrintStatus(VolumeStatus * status, char *name)
+QuickPrintStatus(VolumeStatus * status, char *name, int human)
 {
     double QuotaUsed = 0.0;
     double PartUsed = 0.0;
@@ -650,11 +671,22 @@ QuickPrintStatus(VolumeStatus * status, char *name)
     printf("%-25.25s", name);
 
     if (status->MaxQuota != 0) {
-       printf(" %10d %10d", status->MaxQuota, status->BlocksInUse);
+       if (human) {
+           printf(" ");
+           HumanPrintSpace(status->MaxQuota);
+           printf(" ");
+           HumanPrintSpace(status->BlocksInUse);
+       }
+       else
+           printf(" %10d %10d", status->MaxQuota, status->BlocksInUse);
        QuotaUsed =
            ((((double)status->BlocksInUse) / status->MaxQuota) * 100.0);
     } else {
-       printf("   no limit %10d", status->BlocksInUse);
+       printf("   no limit ");
+       if (human)
+           HumanPrintSpace(status->BlocksInUse);
+       else
+           printf("%10d", status->BlocksInUse);
     }
     if (QuotaUsed > 90.0) {
        printf("%5.0f%%<<", QuotaUsed);
@@ -678,15 +710,21 @@ QuickPrintStatus(VolumeStatus * status, char *name)
 }
 
 static int
-QuickPrintSpace(VolumeStatus * status, char *name)
+QuickPrintSpace(VolumeStatus * status, char *name, int human)
 {
     double PartUsed = 0.0;
     int WARN = 0;
     printf("%-25.25s", name);
 
-    printf("%10d%10d%10d", status->PartMaxBlocks,
-          status->PartMaxBlocks - status->PartBlocksAvail,
-          status->PartBlocksAvail);
+    if (human) {
+       HumanPrintSpace(status->PartMaxBlocks);
+       HumanPrintSpace(status->PartMaxBlocks - status->PartBlocksAvail);
+       HumanPrintSpace(status->PartBlocksAvail);
+    }
+    else
+       printf("%10d%10d%10d", status->PartMaxBlocks,
+               status->PartMaxBlocks - status->PartBlocksAvail,
+               status->PartBlocksAvail);
 
     PartUsed =
        (100.0 -
@@ -707,8 +745,8 @@ QuickPrintSpace(VolumeStatus * status, char *name)
 static char *
 AclToString(struct Acl *acl)
 {
-    static char mydata[MAXSIZE];
-    char tstring[MAXSIZE];
+    static char mydata[AFS_PIOCTL_MAXSIZE];
+    char tstring[AFS_PIOCTL_MAXSIZE];
     char dfsstring[30];
     struct AclEntry *tp;
 
@@ -747,7 +785,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock)
        clear = 0;
     plusp = !(as->parms[3].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = idf;
        blob.in = blob.out = space;
        code = pioctl(ti->data, VIOCGETAL, &blob, 1);
@@ -878,7 +916,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock)
        clear = 1;
     else
        clear = 0;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.in_size = idf;
     blob.in = blob.out = space;
     code = pioctl(as->parms[0].items->data, VIOCGETAL, &blob, 1);
@@ -889,7 +927,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock)
     fa = ParseAcl(space);
     CleanAcl(fa, as->parms[0].items->data);
     for (ti = as->parms[1].items; ti; ti = ti->next) {
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = idf;
        blob.in = blob.out = space;
        code = pioctl(ti->data, VIOCGETAL, &blob, 1);
@@ -1053,7 +1091,7 @@ CleanACLCmd(struct cmd_syndesc *as, void *arock)
 
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        code = pioctl(ti->data, VIOCGETAL, &blob, 1);
@@ -1140,7 +1178,7 @@ ListACLCmd(struct cmd_syndesc *as, void *arock)
 
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = idf;
        blob.in = blob.out = space;
        code = pioctl(ti->data, VIOCGETAL, &blob, 1);
@@ -1150,42 +1188,61 @@ ListACLCmd(struct cmd_syndesc *as, void *arock)
            continue;
        }
        ta = ParseAcl(space);
-       switch (ta->dfs) {
-       case 0:
-           printf("Access list for %s is\n", ti->data);
-           break;
-       case 1:
-           printf("DFS access list for %s is\n", ti->data);
-           break;
-       case 2:
-           printf("DFS initial directory access list of %s is\n", ti->data);
-           break;
-       case 3:
-           printf("DFS initial file access list of %s is\n", ti->data);
-           break;
-       }
-       if (ta->dfs) {
-           printf("  Default cell = %s\n", ta->cell);
-       }
-       if (ta->nplus > 0) {
-           if (!ta->dfs)
-               printf("Normal rights:\n");
-           for (te = ta->pluslist; te; te = te->next) {
-               printf("  %s ", te->name);
-               PRights(te->rights, ta->dfs);
-               printf("\n");
+        if (as->parms[3].items) {                      /* -cmd */
+            printf("fs setacl -dir %s -acl ", ti->data);
+            if (ta->nplus > 0) {
+                for (te = ta->pluslist; te; te = te->next) {
+                    printf("  %s ", te->name);
+                    PRights(te->rights, ta->dfs);
+                }
+            }
+            printf("\n");
+            if (ta->nminus > 0) {
+                printf("fs setacl -dir %s -acl ", ti->data);
+                for (te = ta->minuslist; te; te = te->next) {
+                    printf("  %s ", te->name);
+                    PRights(te->rights, ta->dfs);
+                }
+                printf(" -negative\n");
+            }
+        } else {
+           switch (ta->dfs) {
+           case 0:
+               printf("Access list for %s is\n", ti->data);
+               break;
+           case 1:
+               printf("DFS access list for %s is\n", ti->data);
+               break;
+           case 2:
+               printf("DFS initial directory access list of %s is\n", ti->data);
+               break;
+           case 3:
+               printf("DFS initial file access list of %s is\n", ti->data);
+               break;
            }
-       }
-       if (ta->nminus > 0) {
-           printf("Negative rights:\n");
-           for (te = ta->minuslist; te; te = te->next) {
-               printf("  %s ", te->name);
-               PRights(te->rights, ta->dfs);
-               printf("\n");
+           if (ta->dfs) {
+               printf("  Default cell = %s\n", ta->cell);
+           }
+           if (ta->nplus > 0) {
+               if (!ta->dfs)
+                   printf("Normal rights:\n");
+               for (te = ta->pluslist; te; te = te->next) {
+                   printf("  %s ", te->name);
+                   PRights(te->rights, ta->dfs);
+                   printf("\n");
+               }
            }
+           if (ta->nminus > 0) {
+               printf("Negative rights:\n");
+               for (te = ta->minuslist; te; te = te->next) {
+                   printf("  %s ", te->name);
+                   PRights(te->rights, ta->dfs);
+                   printf("\n");
+               }
+           }
+           if (ti->next)
+               printf("\n");
        }
-       if (ti->next)
-           printf("\n");
        ZapAcl(ta);
     }
     return error;
@@ -1240,11 +1297,11 @@ FlushVolumeCmd(struct cmd_syndesc *as, void *arock)
     return error;
 }
 
-/* 
+/*
  * The Windows version of UuidCmd displays the UUID.
  * When the UNIX version is updated to do the same
  * be sure to replace the CMD_REQUIRED flag with
- * CMD_OPTIONAL in the cmd_AddParam(-generate) call 
+ * CMD_OPTIONAL in the cmd_AddParam(-generate) call
  */
 static int
 UuidCmd(struct cmd_syndesc *as, void *arock)
@@ -1254,7 +1311,7 @@ UuidCmd(struct cmd_syndesc *as, void *arock)
 
     blob.in_size = 0;
     blob.out_size = 0;
-    
+
     if (as->parms[0].items) {
         if (geteuid()) {
             fprintf (stderr, "Permission denied: requires root access.\n");
@@ -1283,41 +1340,45 @@ UuidCmd(struct cmd_syndesc *as, void *arock)
  * With a threshold of 0, the cache is always bypassed.  With a threshold of -1,
  * cache bypass is disabled.
  */
+
 static int
-BypassThresholdCmd(struct cmd_syndesc *as, char *arock)
+BypassThresholdCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
-    afs_int32 size;
     struct ViceIoctl blob;
     afs_int32 threshold_i, threshold_o;
-    char *tp;  
-    
+    char *tp;
+
     /* if new threshold supplied, then set and confirm, else,
      * get current threshold and print
      */
-        
+
     if(as->parms[0].items) {
        int digit, ix, len;
-                               
+
        tp = as->parms[0].items->data;
        len = strlen(tp);
-       digit = 1; 
-       for(ix = 0; ix < len; ++ix) {
-           if(!isdigit(tp[0])) {
-               digit = 0;
-               break;
-           }
-       }
-       if (digit == 0) {
-           fprintf(stderr, "fs bypassthreshold -size: %s must be an undecorated digit string.\n", tp);
-           return EINVAL;
-       }
-       threshold_i = atoi(tp);
-       if(ix > 9 && threshold_i < 2147483647) 
-           threshold_i = 2147483647;
-       blob.in = (char *) &threshold_i;
-       blob.in_size = sizeof(threshold_i);
+
+        if (!strcmp(tp,"-1")) {
+            threshold_i = -1;
+        } else {
+            digit = 1;
+            for(ix = 0; ix < len; ++ix) {
+                if(!isdigit(tp[0])) {
+                    digit = 0;
+                    break;
+                }
+            }
+            if (digit == 0) {
+                fprintf(stderr, "fs bypassthreshold -size: %s must be an integer between -1 and 2^31\n", tp);
+                return EINVAL;
+            }
+            threshold_i = atoi(tp);
+            if(ix > 9 && threshold_i < 2147483647)
+                threshold_i = 2147483647;
+        }
+        blob.in = (char *) &threshold_i;
+        blob.in_size = sizeof(threshold_i);
     } else {
        blob.in = NULL;
        blob.in_size = 0;
@@ -1329,7 +1390,7 @@ BypassThresholdCmd(struct cmd_syndesc *as, char *arock)
     if (code) {
        Die(errno, NULL);
        return 1;
-    } else {           
+    } else {
        printf("Cache bypass threshold %d", threshold_o);
        if(threshold_o ==  -1)
            printf(" (disabled)");
@@ -1391,7 +1452,7 @@ SetVolCmd(struct cmd_syndesc *as, void *arock)
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = sizeof(*status) + 3;     /* for the three terminating nulls */
        blob.out = space;
        blob.in = space;
@@ -1399,7 +1460,7 @@ SetVolCmd(struct cmd_syndesc *as, void *arock)
        status->MinQuota = status->MaxQuota = -1;
        offmsg = NULL;
        if (as->parms[1].items) {
-           code = util_GetInt32(as->parms[1].items->data, &status->MaxQuota);
+           code = util_GetHumanInt32(as->parms[1].items->data, &status->MaxQuota);
            if (code) {
                fprintf(stderr, "%s: bad integer specified for quota.\n", pn);
                error = 1;
@@ -1457,7 +1518,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
        struct VenusFid vfid;
 
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
@@ -1492,13 +1553,17 @@ ListQuotaCmd(struct cmd_syndesc *as, void *arock)
     struct VolumeStatus *status;
     char *name;
     int error = 0;
+    int human = 0;
+
+    if (as->parms[1].items)
+       human = 1;
 
     printf("%-25s%-11s%-11s%-7s%-11s\n", "Volume Name", "      Quota",
           "       Used", " %Used", "  Partition");
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
@@ -1509,7 +1574,7 @@ ListQuotaCmd(struct cmd_syndesc *as, void *arock)
        }
        status = (VolumeStatus *) space;
        name = (char *)status + sizeof(*status);
-       QuickPrintStatus(status, name);
+       QuickPrintStatus(status, name, human);
     }
     return error;
 }
@@ -1528,7 +1593,7 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock)
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        memset(space, 0, sizeof(space));
@@ -1541,7 +1606,7 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock)
        hosts = (afs_int32 *) space;
        printf("File %s is on host%s ", ti->data,
               (hosts[0] && !hosts[1]) ? "" : "s");
-       for (j = 0; j < MAXHOSTS; j++) {
+       for (j = 0; j < AFS_MAXHOSTS; j++) {
            if (hosts[j] == 0)
                break;
            tp = hostutil_GetNameByINet(hosts[j]);
@@ -1562,13 +1627,17 @@ DiskFreeCmd(struct cmd_syndesc *as, void *arock)
     char *name;
     struct VolumeStatus *status;
     int error = 0;
+    int human = 0;
 
-    printf("%-25s%-10s%-10s%-10s%-6s\n", "Volume Name", "    kbytes",
-          "      used", "     avail", " %used");
+    if (as->parms[1].items)
+       human = 1;
+
+    printf("%-25s%10s%10s%10s%6s\n", "Volume Name",
+          human ? "total" : "kbytes", "used", "avail", "%used");
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
@@ -1579,7 +1648,7 @@ DiskFreeCmd(struct cmd_syndesc *as, void *arock)
        }
        status = (VolumeStatus *) space;
        name = (char *)status + sizeof(*status);
-       QuickPrintSpace(status, name);
+       QuickPrintSpace(status, name, human);
     }
     return error;
 }
@@ -1597,7 +1666,7 @@ QuotaCmd(struct cmd_syndesc *as, void *arock)
     SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
        /* once per file */
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = 0;
        blob.out = space;
        code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
@@ -1720,9 +1789,9 @@ ListMountCmd(struct cmd_syndesc *as, void *arock)
 
        blob.in = last_component;
        blob.in_size = strlen(last_component) + 1;
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.out = space;
-       memset(space, 0, MAXSIZE);
+       memset(space, 0, AFS_PIOCTL_MAXSIZE);
 
        code = pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
 
@@ -1797,7 +1866,7 @@ defect #3069
 
     if (!cellName) {
        blob.in_size = 0;
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.out = space;
        code =
            pioctl(Parent(as->parms[0].items->data), VIOC_FILE_CELL_NAME,
@@ -1876,7 +1945,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock)
        blob.in_size = strlen(tp) + 1;
        blob.out = lsbuffer;
        blob.out_size = sizeof(lsbuffer);
-       code = pioctl(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0);
+       code = pioctl(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 1);
        if (code) {
            if (errno == EINVAL) {
                fprintf(stderr, "%s: '%s' is not a mount point.\n", pn,
@@ -1890,7 +1959,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock)
        blob.out_size = 0;
        blob.in = tp;
        blob.in_size = strlen(tp) + 1;
-       code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0);
+       code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 1);
        if (code) {
            Die(errno, ti->data);
            error = 1;
@@ -1917,7 +1986,7 @@ CheckServersCmd(struct cmd_syndesc *as, void *arock)
     blob.in_size = sizeof(struct chservinfo);
     blob.in = (caddr_t) & checkserv;
 
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.out = space;
     memset(space, 0, sizeof(afs_int32));       /* so we assure zero when nothing is copied back */
 
@@ -2010,7 +2079,7 @@ MessagesCmd(struct cmd_syndesc *as, void *arock)
     memset(&gagflags, 0, sizeof(struct gaginfo));
     blob.in_size = sizeof(struct gaginfo);
     blob.in = (caddr_t) & gagflags;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.out = space;
     memset(space, 0, sizeof(afs_int32));       /* so we assure zero when nothing is copied back */
 
@@ -2067,7 +2136,7 @@ PreCacheCmd(struct cmd_syndesc *as, void *arock)
     afs_int32 code;
     struct ViceIoctl blob;
     afs_int32 temp;
-    
+
     if (!as->parms[0].items && !as->parms[1].items) {
        fprintf(stderr, "%s: syntax error in precache cmd.\n", pn);
        return 1;
@@ -2089,7 +2158,7 @@ PreCacheCmd(struct cmd_syndesc *as, void *arock)
        Die(errno, NULL);
        return 1;
     }
-    
+
     printf("New precache size set.\n");
     return 0;
 }
@@ -2106,7 +2175,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock)
        return 1;
     }
     if (as->parms[0].items) {
-       code = util_GetInt32(as->parms[0].items->data, &temp);
+       code = util_GetHumanInt32(as->parms[0].items->data, &temp);
        if (code) {
            fprintf(stderr, "%s: bad integer specified for cache size.\n",
                    pn);
@@ -2187,26 +2256,26 @@ GetCacheParmsCmd(struct cmd_syndesc *as, void *arock)
            percentFiles, filesUsed, parms[2]);
     if (flags == 2){
        printf("        afs_cacheFiles: %10d\n", parms[2]);
-       printf("        IFFree:         %10d\n", parms[3]); 
-       printf("        IFEverUsed:     %10d\n", parms[4]); 
-       printf("        IFDataMod:      %10d\n", parms[5]); 
+       printf("        IFFree:         %10d\n", parms[3]);
+       printf("        IFEverUsed:     %10d\n", parms[4]);
+       printf("        IFDataMod:      %10d\n", parms[5]);
        printf("        IFDirtyPages:   %10d\n", parms[6]);
-       printf("        IFAnyPages:     %10d\n", parms[7]); 
+       printf("        IFAnyPages:     %10d\n", parms[7]);
        printf("        IFDiscarded:    %10d\n", parms[8]);
        printf("        DCentries:  %10d\n", parms[9]);
-       printf("          0k-   4K: %10d\n", parms[10]); 
-       printf("          4k-  16k: %10d\n", parms[11]); 
-       printf("         16k-  64k: %10d\n", parms[12]); 
-       printf("         64k- 256k: %10d\n", parms[13]); 
-       printf("        256k-   1M: %10d\n", parms[14]); 
-       printf("              >=1M: %10d\n", parms[15]); 
+       printf("          0k-   4K: %10d\n", parms[10]);
+       printf("          4k-  16k: %10d\n", parms[11]);
+       printf("         16k-  64k: %10d\n", parms[12]);
+       printf("         64k- 256k: %10d\n", parms[13]);
+       printf("        256k-   1M: %10d\n", parms[14]);
+       printf("              >=1M: %10d\n", parms[15]);
     }
 
     if (percentBlocks > 90)
        printf("[cache size usage over 90%%, consider increasing cache size]\n");
     if (percentFiles > 90)
        printf("[cache file usage over 90%%, consider increasing '-files' argument to afsd]\n");
-        
+
     return 0;
 }
 
@@ -2224,7 +2293,7 @@ ListCellsCmd(struct cmd_syndesc *as, void *arock)
     for (i = 0;; i++) {
        tp = space;
        memcpy(tp, &i, sizeof(afs_int32));
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = sizeof(afs_int32);
        blob.in = space;
        blob.out = space;
@@ -2236,8 +2305,8 @@ ListCellsCmd(struct cmd_syndesc *as, void *arock)
            return 1;
        }
        tp = space;
-       printf("Cell %s on hosts", tp + MAXCELLHOSTS * sizeof(afs_int32));
-       for (j = 0; j < MAXCELLHOSTS; j++) {
+       printf("Cell %s on hosts", tp + AFS_MAXCELLHOSTS * sizeof(afs_int32));
+       for (j = 0; j < AFS_MAXCELLHOSTS; j++) {
            afs_int32 addr;
            char *name, tbuffer[20];
 
@@ -2270,7 +2339,7 @@ ListAliasesCmd(struct cmd_syndesc *as, void *arock)
     for (i = 0;; i++) {
        tp = space;
        memcpy(tp, &i, sizeof(afs_int32));
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.in_size = sizeof(afs_int32);
        blob.in = space;
        blob.out = space;
@@ -2299,7 +2368,7 @@ CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
     afs_int32 hostAddr;
     struct hostent *thp;
     int setp;
-    
+
     ti = as->parms[0].items;
     setp = 1;
     if (ti) {
@@ -2313,13 +2382,13 @@ CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
         hostAddr = 0;   /* means don't set host */
        setp = 0;       /* aren't setting host */
     }
-    
+
     /* now do operation */
     blob.in_size = sizeof(afs_int32);
     blob.out_size = sizeof(afs_int32);
     blob.in = (char *) &hostAddr;
     blob.out = (char *) &hostAddr;
-    
+
     code = pioctl(0, VIOC_CBADDR, &blob, 1);
     if (code < 0) {
        Die(errno, 0);
@@ -2336,7 +2405,7 @@ NukeNFSCredsCmd(struct cmd_syndesc *as, void *arock)
     struct cmd_item *ti;
     afs_int32 hostAddr;
     struct hostent *thp;
-    
+
     ti = as->parms[0].items;
     thp = hostutil_GetHostByName(ti->data);
     if (!thp) {
@@ -2344,13 +2413,13 @@ NukeNFSCredsCmd(struct cmd_syndesc *as, void *arock)
        return 1;
     }
     else memcpy(&hostAddr, thp->h_addr, sizeof(afs_int32));
-    
+
     /* now do operation */
     blob.in_size = sizeof(afs_int32);
     blob.out_size = sizeof(afs_int32);
     blob.in = (char *) &hostAddr;
     blob.out = (char *) &hostAddr;
-    
+
     code = pioctl(0, VIOC_NFS_NUKE_CREDS, &blob, 1);
     if (code < 0) {
        Die(errno, 0);
@@ -2372,8 +2441,8 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
 
     /* Yuck!
      * With the NEWCELL pioctl call, 3.4 clients take an array of
-     * MAXHOSTS (13) servers while 3.5 clients take an array of
-     * MAXCELLHOSTS (8) servers. To determine which we are talking to,
+     * AFS_MAXHOSTS (13) servers while 3.5 clients take an array of
+     * AFS_MAXCELLHOSTS (8) servers. To determine which we are talking to,
      * do a GETCELL pioctl and pass it a magic number. If an array of
      * 8 comes back, its a 3.5 client. If not, its a 3.4 client.
      * If we get back EDOM, there are no cells in the kernel yet,
@@ -2383,7 +2452,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
     lp = (afs_int32 *) tp;
     *lp++ = 0;                 /* first cell entry */
     *lp = 0x12345678;          /* magic */
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.in_size = sizeof(afs_int32) + sizeof(afs_int32);
     blob.in = space;
     blob.out = space;
@@ -2393,11 +2462,11 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
        return 1;
     }
     if (code < 1 && errno == EDOM) {
-       scount = MAXHOSTS;
+       scount = AFS_MAXHOSTS;
     } else {
        tp = space;
-       cellname = tp + MAXCELLHOSTS * sizeof(afs_int32);
-       scount = ((cellname[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
+       cellname = tp + AFS_MAXCELLHOSTS * sizeof(afs_int32);
+       scount = ((cellname[0] != '\0') ? AFS_MAXCELLHOSTS : AFS_MAXHOSTS);
     }
 
     /* Now setup and do the NEWCELL pioctl call */
@@ -2539,7 +2608,7 @@ WSCellCmd(struct cmd_syndesc *as, void *arock)
 
     blob.in_size = 0;
     blob.in = NULL;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.out = space;
 
     code = pioctl(NULL, VIOC_GET_WS_CELL, &blob, 1);
@@ -2634,13 +2703,13 @@ SysNameCmd(struct cmd_syndesc *as, void *arock)
     ti = as->parms[0].items;
     blob.in = space;
     blob.out = space;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.in_size = sizeof(afs_int32);
     input += sizeof(afs_int32);
     for (; ti; ti = ti->next) {
        setp++;
        blob.in_size += strlen(ti->data) + 1;
-       if (blob.in_size > MAXSIZE) {
+       if (blob.in_size > AFS_PIOCTL_MAXSIZE) {
            fprintf(stderr, "%s: sysname%s too long.\n", pn,
                    setp > 1 ? "s" : "");
            return 1;
@@ -2933,8 +3002,8 @@ VLDBInit(int noAuthFlag, struct afsconf_cell *info)
 {
     afs_int32 code;
 
-    code = ugen_ClientInit(noAuthFlag, AFSDIR_CLIENT_ETC_DIRPATH, 
-                          info->name, 0, &uclient, 
+    code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
+                          info->name, 0, &uclient,
                            NULL, pn, rxkad_clear,
                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
                            0, 0, USER_SERVICE_ID);
@@ -3055,7 +3124,7 @@ SetPrefCmd(struct cmd_syndesc *as, void *arock)
     gblob.in_size = ((char *)&(ssp->servers[0])) - (char *)ssp;
     gblob.in = space;
     gblob.out = space;
-    gblob.out_size = MAXSIZE;
+    gblob.out_size = AFS_PIOCTL_MAXSIZE;
 
 
     if (geteuid()) {
@@ -3181,17 +3250,26 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock)
        blob.in_size = sizeof(struct sprefrequest);
        blob.in = (char *)in;
        blob.out = space;
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
 
        in->num_servers =
-           (MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
+           (AFS_PIOCTL_MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
        in->flags = vlservers;
 
-       code = pioctl(0, VIOC_GETSPREFS, &blob, 1);
-       if (code) {
-           perror("getserverprefs pioctl");
-           return 1;
-       }
+       do {
+           code = pioctl(0, VIOC_GETSPREFS, &blob, 1);
+           if (code) {
+               if ((errno != E2BIG) || (2 * blob.out_size > 0x7FFF)) {
+                   perror("getserverprefs pioctl");
+                   return 1;
+               }
+               blob.out_size *= 2;
+               if (blob.out == space)
+                   blob.out = malloc(blob.out_size);
+               else
+                   blob.out = realloc(blob.out, blob.out_size);
+           }
+       } while (code != 0);
 
        out = (struct sprefinfo *)blob.out;
 
@@ -3210,6 +3288,9 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock)
        in->offset = out->next_offset;
     } while (out->next_offset > 0);
 
+    if (blob.out != space)
+       free(blob.out);
+
     return 0;
 }
 
@@ -3259,13 +3340,14 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
        verbose = 1;
 
     blob.in = (char *)&tsb;
-    blob.out = (char *)&tsb2;
-    blob.in_size = blob.out_size = sizeof(struct sbstruct);
-    memset(&tsb2, 0, sizeof(tsb2));
+    blob.in_size = sizeof(struct sbstruct);
 
     /* once per -file */
     for (ti = as->parms[1].items; ti; ti = ti->next) {
        /* Do this solely to see if the file is there */
+
+        blob.out = space;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
        code = pioctl(ti->data, VIOCWHEREIS, &blob, 1);
        if (code) {
            Die(errno, ti->data);
@@ -3273,6 +3355,9 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
            continue;
        }
 
+       memset(&tsb2, 0, sizeof(tsb2));
+       blob.out = (char *)&tsb2;
+       blob.out_size = sizeof(struct sbstruct);
        code = pioctl(ti->data, VIOC_STORBEHIND, &blob, 1);
        if (code) {
            Die(errno, ti->data);
@@ -3297,6 +3382,9 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
      */
     if (!as->parms[1].items || (allfiles != -1)) {
        tsb.sb_default = allfiles;
+        memset(&tsb2, 0, sizeof(tsb2));
+       blob.out = (char *)&tsb2;
+       blob.out_size = sizeof(struct sbstruct);
        code = pioctl(0, VIOC_STORBEHIND, &blob, 1);
        if (code) {
            Die(errno, ((allfiles == -1) ? 0 : "-allfiles"));
@@ -3305,7 +3393,7 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
     }
 
     /* Having no arguments also reports the default store asynchrony */
-    if (verbose && (blob.out_size == sizeof(tsb2))) {
+    if (!error && verbose && (blob.out_size == sizeof(tsb2))) {
        fprintf(stdout, "Default store asynchrony is %d kbytes.\n",
                (tsb2.sb_default / 1024));
     }
@@ -3369,7 +3457,6 @@ GetCryptCmd(struct cmd_syndesc *as, void *arock)
     return 0;
 }
 
-#ifdef AFS_DISCON_ENV
 static char *modenames[] = {
     "offline",
     "online",
@@ -3394,13 +3481,13 @@ DisconCmd(struct cmd_syndesc *as, void *arock)
     char *modename;
     char *policyname;
     int modelen, policylen;
-    afs_int32 mode, policy, code;
+    afs_int32 mode, policy, code, unixuid = 0;
     struct ViceIoctl blob;
 
     blob.in = NULL;
     blob.in_size = 0;
 
-    space[0] = space[1] = space[2] = 0;
+    space[0] = space[1] = space[2] = space[3] = 0;
 
     ti = as->parms[0].items;
     if (ti) {
@@ -3434,8 +3521,19 @@ DisconCmd(struct cmd_syndesc *as, void *arock)
        printf("force on\n");
     }
 
+    ti = as->parms[3].items;
+    if (ti) {
+       code = util_GetInt32(ti->data, &unixuid);
+       if (code) {
+           fprintf(stderr, "%s: bad integer specified for uid.\n", pn);
+            return 1;
+        }
+       space[3] = unixuid;
+    } else
+       space[3] = 0;
+
     blob.in = space;
-    blob.in_size = 3 * sizeof(afs_int32);
+    blob.in_size = 4 * sizeof(afs_int32);
 
     blob.out_size = sizeof(mode);
     blob.out = space;
@@ -3452,7 +3550,6 @@ DisconCmd(struct cmd_syndesc *as, void *arock)
 
     return 0;
 }
-#endif
 
 #include "AFS_component_version_number.c"
 
@@ -3527,6 +3624,7 @@ main(int argc, char **argv)
     parm_listacl_id = ts->nParms;
     cmd_AddParm(ts, "-id", CMD_FLAG, CMD_OPTIONAL, "initial directory acl");
     cmd_AddParm(ts, "-if", CMD_FLAG, CMD_OPTIONAL, "initial file acl");
+    cmd_AddParm(ts, "-cmd", CMD_FLAG, CMD_OPTIONAL, "output as 'fs setacl' command");
     cmd_CreateAlias(ts, "la");
 
     ts = cmd_CreateSyntax("getcalleraccess", GetCallerAccess, NULL,
@@ -3583,11 +3681,13 @@ main(int argc, char **argv)
 
     ts = cmd_CreateSyntax("listquota", ListQuotaCmd, NULL, "list volume quota");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-human", CMD_FLAG, CMD_OPTIONAL, "human-readable listing");
     cmd_CreateAlias(ts, "lq");
 
     ts = cmd_CreateSyntax("diskfree", DiskFreeCmd, NULL,
                          "show server disk space usage");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-human", CMD_FLAG, CMD_OPTIONAL, "human-readable listing");
     cmd_CreateAlias(ts, "df");
 
     ts = cmd_CreateSyntax("quota", QuotaCmd, NULL, "show volume quota usage");
@@ -3777,13 +3877,12 @@ defect 3069
                          "get fid for file(s)");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
 
-#ifdef AFS_DISCON_ENV
     ts = cmd_CreateSyntax("discon", DisconCmd, NULL,
                          "disconnection mode");
     cmd_AddParm(ts, "-mode", CMD_SINGLE, CMD_REQUIRED, "offline | online");
     cmd_AddParm(ts, "-policy", CMD_SINGLE, CMD_OPTIONAL, "client | server");
     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "Force reconnection, despite any synchronization issues.");
-#endif
+    cmd_AddParm(ts, "-uid", CMD_SINGLE, CMD_OPTIONAL, "Numeric UID of user whose tokens to use at reconnect.");
 
     ts = cmd_CreateSyntax("nukenfscreds", NukeNFSCredsCmd, NULL, "nuke credentials for NFS client");
     cmd_AddParm(ts, "-addr", CMD_SINGLE, 0, "host name or address");
@@ -3862,10 +3961,10 @@ GetClientAddrsCmd(struct cmd_syndesc *as, void *arock)
        blob.in_size = sizeof(struct sprefrequest);
        blob.in = (char *)in;
        blob.out = space;
-       blob.out_size = MAXSIZE;
+       blob.out_size = AFS_PIOCTL_MAXSIZE;
 
        in->num_servers =
-           (MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
+           (AFS_PIOCTL_MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
        /* returns addr in network byte order */
        code = pioctl(0, VIOC_GETCPREFS, &blob, 1);
        if (code) {
@@ -3907,7 +4006,7 @@ SetClientAddrsCmd(struct cmd_syndesc *as, void *arock)
     ssp->num_servers = 0;
     blob.in = space;
     blob.out = space;
-    blob.out_size = MAXSIZE;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
 
     if (geteuid()) {
        fprintf(stderr, "Permission denied: requires root access.\n");
@@ -4068,7 +4167,7 @@ FlushMountCmd(struct cmd_syndesc *as, void *arock)
        blob.in = last_component;
        blob.in_size = strlen(last_component) + 1;
        blob.out_size = 0;
-       memset(space, 0, MAXSIZE);
+       memset(space, 0, AFS_PIOCTL_MAXSIZE);
 
        code = pioctl(parent_dir, VIOC_AFS_FLUSHMOUNT, &blob, 1);
 
@@ -4157,20 +4256,42 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
 {
     struct ViceIoctl blob;
     struct cmd_item *ti;
+
+    afs_int32 code;
+    int error = 0;
+    char cell[MAXCELLCHARS];
+
+    SetDotDefault(&as->parms[0].items);
     for (ti = as->parms[0].items; ti; ti = ti->next) {
-      struct VenusFid vfid;
-      
-      blob.out_size = sizeof(struct VenusFid);
-      blob.out = (char *) &vfid;
-      blob.in_size = 0;
-      
-      if (0 == pioctl(ti->data, VIOCGETFID, &blob, 1)) {
-       printf("File %s (%u.%u.%u) contained in volume %u\n",
-              ti->data, vfid.Fid.Volume, vfid.Fid.Vnode, vfid.Fid.Unique,
-              vfid.Fid.Volume);
-      }
+        struct VenusFid vfid;
+
+        blob.out_size = sizeof(struct VenusFid);
+        blob.out = (char *) &vfid;
+        blob.in_size = 0;
+
+        code = pioctl(ti->data, VIOCGETFID, &blob, 1);
+        if (code) {
+            Die(errno,ti->data);
+            error = 1;
+            continue;
+        }
+
+        code = GetCell(ti->data, cell);
+        if (code) {
+           if (errno == ENOENT)
+               fprintf(stderr, "%s: no such cell as '%s'\n", pn, ti->data);
+           else
+               Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        printf("File %s (%u.%u.%u) located in cell %s\n",
+               ti->data, vfid.Fid.Volume, vfid.Fid.Vnode, vfid.Fid.Unique,
+               cell);
+
     }
 
-    return 0;
+    return error;
 }