vol: Use FDH_SIZE more consistently
[openafs.git] / src / viced / afsfileprocs.c
index 914024e..0ac27e9 100644 (file)
@@ -173,13 +173,13 @@ struct afs_FSStats {
 
 struct afs_FSStats afs_fsstats;
 
-int LogLevel = 0;
 int supported = 1;
 int Console = 0;
 afs_int32 BlocksSpare = 1024;  /* allow 1 MB overruns */
 afs_int32 PctSpare;
 extern afs_int32 implicitAdminRights;
 extern afs_int32 readonlyServer;
+extern afs_int32 adminwriteServer;
 extern int CopyOnWrite_calls, CopyOnWrite_off0, CopyOnWrite_size0;
 extern afs_fsize_t CopyOnWrite_maxsize;
 
@@ -851,8 +851,6 @@ GetVolumePackageWithCall(struct rx_call *acall, struct VCallByVol *cbv,
     Error errorCode = 0;               /* return code to caller */
     struct rx_connection *tcon = rx_ConnectionOf(acall);
 
-    rx_KeepAliveOff(acall);
-
     if ((errorCode = CheckVnodeWithCall(Fid, volptr, cbv, targetptr, locktype)))
        goto gvpdone;
 
@@ -904,8 +902,6 @@ GetVolumePackageWithCall(struct rx_call *acall, struct VCallByVol *cbv,
 #endif /* ADMIN_IMPLICIT_LOOKUP */
     }
 gvpdone:
-    if (errorCode)
-       rx_KeepAliveOn(acall);
     return errorCode;
 
 }                              /*GetVolumePackage */
@@ -957,7 +953,6 @@ PutVolumePackageWithCall(struct rx_call *acall, Vnode *
 {
     Error fileCode = 0;                /* Error code returned by the volume package */
 
-    rx_KeepAliveOff(acall);
     if (parentwhentargetnotdir) {
        VPutVnode(&fileCode, parentwhentargetnotdir);
        assert_vnode_success_or_salvaging(fileCode);
@@ -973,7 +968,6 @@ PutVolumePackageWithCall(struct rx_call *acall, Vnode *
     if (volptr) {
        VPutVolumeWithCall(volptr, cbv);
     }
-    rx_KeepAliveOn(acall);
 
     if (*client) {
        PutClient(client);
@@ -1014,6 +1008,30 @@ VolumeRootVnode(Vnode * targetptr)
 
 }                              /*VolumeRootVnode */
 
+/**
+ * Check if server can perform writes.
+ *
+ * This functions checks if the fileserver is read-only for the client received
+ * as an argument. Read-only fileservers allow write requests for members of
+ * system:administrators when started with both -readonly and -admin-write.
+ *
+ * @param[in]  client  calling user
+ *
+ * @return 1 if not read-only for this user; 0 otherwise
+ */
+static int
+IsWriteAllowed(struct client *client)
+{
+    if (readonlyServer) {
+       if (adminwriteServer && !VanillaUser(client)) {
+           /* admins can write */
+           return 1;
+       }
+       return 0;
+    }
+    return 1;
+}
+
 /*
  * Check if target file has the proper access permissions for the Fetch
  * (FetchData, FetchACL, FetchStatus) and Store (StoreData, StoreACL,
@@ -1084,6 +1102,9 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
                      AUD_END);
        }
     } else {                   /* a store operation */
+       if (!IsWriteAllowed(client)) {
+           return (VREADONLY);
+       }
        if ((rights & PRSFS_INSERT) && OWNSp(client, targetptr)
            && (CallingRoutine != CHK_STOREACL)
            && (targetptr->disk.type == vFile)) {
@@ -1092,9 +1113,7 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
             * unless you are a system administrator */
          /******  InStatus->Owner && UnixModeBits better be SET!! */
            if (CHOWN(InStatus, targetptr) || CHGRP(InStatus, targetptr)) {
-               if (readonlyServer)
-                   return (VREADONLY);
-               else if (VanillaUser(client))
+               if (VanillaUser(client))
                    return (EPERM);     /* Was EACCES */
                else
                    osi_audit(PrivilegeEvent, 0, AUD_ID,
@@ -1107,9 +1126,6 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
                          (client ? client->z.ViceId : 0), AUD_INT,
                          CallingRoutine, AUD_END);
            } else {
-               if (readonlyServer) {
-                   return (VREADONLY);
-               }
                if (CallingRoutine == CHK_STOREACL) {
                    if (!(rights & PRSFS_ADMINISTER)
                        && !VolumeOwner(client, targetptr))
@@ -1118,9 +1134,7 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
                    /* watch for chowns and chgrps */
                    if (CHOWN(InStatus, targetptr)
                        || CHGRP(InStatus, targetptr)) {
-                       if (readonlyServer)
-                           return (VREADONLY);
-                       else if (VanillaUser(client))
+                       if (VanillaUser(client))
                            return (EPERM);     /* Was EACCES */
                        else
                            osi_audit(PrivilegeEvent, 0, AUD_ID,
@@ -1134,8 +1148,6 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
 #else
                        (InStatus->UnixModeBits & (S_ISUID | S_ISGID)) != 0) {
 #endif
-                       if (readonlyServer)
-                           return (VREADONLY);
                        if (VanillaUser(client))
                            return (EACCES);
                        else
@@ -1144,8 +1156,6 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
                                      CallingRoutine, AUD_END);
                    }
                    if (CallingRoutine == CHK_STOREDATA) {
-                       if (readonlyServer)
-                           return (VREADONLY);
                        if (!(rights & PRSFS_WRITE))
                            return (EACCES);
                        /* Next thing is tricky.  We want to prevent people
@@ -1173,8 +1183,6 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
 #endif
                            if ((targetptr->disk.type != vDirectory)
                                && (!(targetptr->disk.modeBits & OWNERWRITE))) {
-                           if (readonlyServer)
-                               return (VREADONLY);
                            if (VanillaUser(client))
                                return (EACCES);
                            else
@@ -1183,8 +1191,6 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
                                          AUD_INT, CallingRoutine, AUD_END);
                        }
                    } else {    /* a status store */
-                       if (readonlyServer)
-                           return (VREADONLY);
                        if (targetptr->disk.type == vDirectory) {
                            if (!(rights & PRSFS_DELETE)
                                && !(rights & PRSFS_INSERT))
@@ -1490,8 +1496,13 @@ DeleteTarget(Vnode * parentptr, Volume * volptr, Vnode ** targetptr,
 
     /* check that the file is in the directory */
     SetDirHandle(dir, parentptr);
-    if (afs_dir_Lookup(dir, Name, fileFid))
-       return (ENOENT);
+    errorCode = afs_dir_Lookup(dir, Name, fileFid);
+    if (errorCode && errorCode != ENOENT) {
+        errorCode = EIO;
+    }
+    if (errorCode) {
+       return errorCode;
+    }
     fileFid->Volume = V_id(volptr);
 
     /* just-in-case check for something causing deadlock */
@@ -2027,9 +2038,10 @@ HandleLocking(Vnode * targetptr, struct client *client, afs_int32 rights, ViceLo
 /* Checks if caller has the proper AFS and Unix (WRITE) access permission to the target directory; Prfs_Mode refers to the AFS Mode operation while rights contains the caller's access permissions to the directory. */
 
 static afs_int32
-CheckWriteMode(Vnode * targetptr, afs_int32 rights, int Prfs_Mode)
+CheckWriteMode(Vnode * targetptr, afs_int32 rights, int Prfs_Mode,
+              struct client *client)
 {
-    if (readonlyServer)
+    if (!IsWriteAllowed(client))
        return (VREADONLY);
     if (!(rights & Prfs_Mode))
        return (EACCES);
@@ -2360,8 +2372,6 @@ common_FetchData64(struct rx_call *acall, struct AFSFid *Fid,
     GetStatus(targetptr, OutStatus, rights, anyrights,
              &tparentwhentargetnotdir);
 
-    rx_KeepAliveOn(acall); /* I/O done */
-
     /* if a r/w volume, promise a callback to the caller */
     if (VolumeWriteable(volptr))
        SetCallBackStruct(AddCallBack(client->z.host, Fid), CallBack);
@@ -2540,8 +2550,6 @@ SAFSS_FetchStatus(struct rx_call *acall, struct AFSFid *Fid,
                          &rights, &anyrights)))
        goto Bad_FetchStatus;
 
-    rx_KeepAliveOn(acall);
-
     /* set volume synchronization information */
     SetVolumeSync(Sync, volptr);
 
@@ -2639,8 +2647,6 @@ SRXAFS_BulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
                              &rights, &anyrights)))
            goto Bad_BulkStatus;
 
-       rx_KeepAliveOn(acall);
-
        /* set volume synchronization information, but only once per call */
        if (i == 0)
            SetVolumeSync(Sync, volptr);
@@ -2766,6 +2772,7 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
                              &rights, &anyrights))) {
            tstatus = &OutStats->AFSBulkStats_val[i];
 
+           tstatus->InterfaceVersion = 1;
            if (thost->z.hostFlags & HERRORTRANS) {
                tstatus->errorCode = sys_error_to_et(errorCode);
            } else {
@@ -2781,8 +2788,6 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
            continue;
        }
 
-       rx_KeepAliveOn(acall);
-
        /* set volume synchronization information, but only once per call */
        if (!VolSync_set) {
            SetVolumeSync(Sync, volptr);
@@ -2796,6 +2801,7 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
                                        CHK_FETCHSTATUS, 0))) {
                tstatus = &OutStats->AFSBulkStats_val[i];
 
+               tstatus->InterfaceVersion = 1;
                if (thost->z.hostFlags & HERRORTRANS) {
                    tstatus->errorCode = sys_error_to_et(errorCode);
                } else {
@@ -2947,8 +2953,6 @@ common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
        goto Bad_StoreData;
     }
 
-    rx_KeepAliveOn(acall);
-
     /* set volume synchronization information */
     SetVolumeSync(Sync, volptr);
 
@@ -2971,9 +2975,7 @@ common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
      */
     if (parentwhentargetnotdir != NULL) {
        tparentwhentargetnotdir = *parentwhentargetnotdir;
-       rx_KeepAliveOff(acall);
        VPutVnode(&fileCode, parentwhentargetnotdir);
-       rx_KeepAliveOn(acall);
        assert_vnode_success_or_salvaging(fileCode);
        parentwhentargetnotdir = NULL;
     }
@@ -2991,11 +2993,9 @@ common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
     if (errorCode && (!targetptr->changed_newTime))
        goto Bad_StoreData;
 
-    rx_KeepAliveOff(acall);
     /* Update the status of the target's vnode */
     Update_TargetVnodeStatus(targetptr, TVS_SDATA, client, InStatus,
                             targetptr, volptr, 0, 0);
-    rx_KeepAliveOn(acall);
 
     /* Get the updated File's status back to the caller */
     GetStatus(targetptr, OutStatus, rights, anyrights,
@@ -3120,8 +3120,6 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     VVnodeWriteToRead(&errorCode, targetptr);
     assert_vnode_success_or_salvaging(errorCode);
 
-    rx_KeepAliveOn(acall);
-
     /* break call backs on the directory  */
     BreakCallBack(client->z.host, Fid, 0);
 
@@ -3208,8 +3206,6 @@ SAFSS_StoreStatus(struct rx_call *acall, struct AFSFid *Fid,
                             (parentwhentargetnotdir ? parentwhentargetnotdir
                              : targetptr), volptr, 0, 0);
 
-    rx_KeepAliveOn(acall);
-
     /* convert the write lock to a read lock before breaking callbacks */
     VVnodeWriteToRead(&errorCode, targetptr);
     assert_vnode_success_or_salvaging(errorCode);
@@ -3311,7 +3307,7 @@ SAFSS_RemoveFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     SetVolumeSync(Sync, volptr);
 
     /* Does the caller has delete (& write) access to the parent directory? */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE, client))) {
        goto Bad_RemoveFile;
     }
 
@@ -3327,8 +3323,6 @@ SAFSS_RemoveFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
                             parentptr->disk.linkCount,
                             client->z.InSameNetwork);
 
-    rx_KeepAliveOn(acall);
-
     /* Return the updated parent dir's status back to caller */
     GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
 
@@ -3452,7 +3446,7 @@ SAFSS_CreateFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     SetVolumeSync(Sync, volptr);
 
     /* Can we write (and insert) onto the parent directory? */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
        goto Bad_CreateFile;
     }
 
@@ -3471,8 +3465,6 @@ SAFSS_CreateFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     Update_TargetVnodeStatus(targetptr, TVS_CFILE, client, InStatus,
                             parentptr, volptr, 0, 0);
 
-    rx_KeepAliveOn(acall);
-
     /* set up the return status for the parent dir and the newly created file, and since the newly created file is owned by the creator, give it PRSFS_ADMINISTER to tell the client its the owner of the file */
     GetStatus(targetptr, OutFidStatus, rights | PRSFS_ADMINISTER, anyrights, parentptr);
     GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
@@ -3648,10 +3640,11 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
     /* set volume synchronization information */
     SetVolumeSync(Sync, volptr);
 
-    if ((errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE))) {
+    if ((errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE, client))) {
        goto Bad_Rename;
     }
-    if ((errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT))) {
+    if ((errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT,
+                                   client))) {
        goto Bad_Rename;
     }
 
@@ -3682,8 +3675,11 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
     SetDirHandle(&newdir, newvptr);
 
     /* Lookup the file to delete its vnode */
-    if (afs_dir_Lookup(&olddir, OldName, &fileFid)) {
-       errorCode = ENOENT;
+    errorCode = afs_dir_Lookup(&olddir, OldName, &fileFid);
+    if (errorCode && errorCode != ENOENT) {
+        errorCode = EIO;
+    }
+    if (errorCode) {
        goto Bad_Rename;
     }
     if (fileFid.Vnode == oldvptr->vnodeNumber
@@ -3722,8 +3718,13 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
     }
 
     /* Lookup the new file  */
-    if (!(afs_dir_Lookup(&newdir, NewName, &newFileFid))) {
-       if (readonlyServer) {
+    code = afs_dir_Lookup(&newdir, NewName, &newFileFid);
+    if (code && code != ENOENT) {
+        errorCode = EIO;
+        goto Bad_Rename;
+    }
+    if (!code) {
+       if (!IsWriteAllowed(client)) {
            errorCode = VREADONLY;
            goto Bad_Rename;
        }
@@ -3831,6 +3832,10 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
            struct AFSFid unused;
 
            code = afs_dir_Lookup(&filedir, "..", &unused);
+            if (code && code != ENOENT) {
+                errorCode = EIO;
+                goto Bad_Rename;
+            }
            if (code == ENOENT) {
                /* only update .. if it doesn't already exist */
                updatefile = 1;
@@ -3877,7 +3882,7 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
                             NewName, errno));
                    if ((errno != ENOENT) && (errno != EIO)
                        && (errno != ENXIO))
-                       ViceLog(0, ("Do we need to fsck?"));
+                       ViceLog(0, ("Do we need to fsck?\n"));
                }
            }
            VN_SET_INO(newfileptr, (Inode) 0);
@@ -3960,8 +3965,6 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
        assert_vnode_success_or_salvaging(errorCode);
     }
 
-    rx_KeepAliveOn(acall);
-
     /* break call back on NewDirFid, OldDirFid, NewDirFid and newFileFid  */
     BreakCallBack(client->z.host, NewDirFid, 0);
     if (oldvptr != newvptr) {
@@ -3988,7 +3991,6 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
 
   Bad_Rename:
     if (newfileptr) {
-       rx_KeepAliveOff(acall);
        VPutVnode(&fileCode, newfileptr);
        assert_vnode_success_or_salvaging(fileCode);
     }
@@ -4098,7 +4100,7 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     SetVolumeSync(Sync, volptr);
 
     /* Does the caller has insert (and write) access to the parent directory? */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)))
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client)))
        goto Bad_SymLink;
 
     /*
@@ -4107,7 +4109,7 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
      * to do this.
      */
     if ((InStatus->Mask & AFS_SETMODE) && !(InStatus->UnixModeBits & 0111)) {
-       if (readonlyServer) {
+       if (!IsWriteAllowed(client)) {
            errorCode = VREADONLY;
            goto Bad_SymLink;
        }
@@ -4164,8 +4166,6 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     VVnodeWriteToRead(&errorCode, parentptr);
     assert_vnode_success_or_salvaging(errorCode);
 
-    rx_KeepAliveOn(acall);
-
     /* break call back on the parent dir */
     BreakCallBack(client->z.host, DirFid, 0);
 
@@ -4280,7 +4280,7 @@ SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     SetVolumeSync(Sync, volptr);
 
     /* Can the caller insert into the parent directory? */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
        goto Bad_Link;
     }
 
@@ -4342,8 +4342,6 @@ SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     VVnodeWriteToRead(&errorCode, parentptr);
     assert_vnode_success_or_salvaging(errorCode);
 
-    rx_KeepAliveOn(acall);
-
     /* break call back on DirFid */
     BreakCallBack(client->z.host, DirFid, 0);
     /*
@@ -4466,10 +4464,11 @@ SAFSS_MakeDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
      * implcit a access that goes with dir ownership, and proceed to
      * subvert quota in the volume.
      */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))
-       || (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))
+       || (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE,
+                                      client))) {
 #else
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
 #endif /* DIRCREATE_NEED_WRITE */
        goto Bad_MakeDir;
     }
@@ -4511,8 +4510,6 @@ SAFSS_MakeDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     VVnodeWriteToRead(&errorCode, parentptr);
     assert_vnode_success_or_salvaging(errorCode);
 
-    rx_KeepAliveOn(acall);
-
     /* break call back on DirFid */
     BreakCallBack(client->z.host, DirFid, 0);
 
@@ -4617,7 +4614,7 @@ SAFSS_RemoveDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     SetVolumeSync(Sync, volptr);
 
     /* Does the caller has delete (&write) access to the parent dir? */
-    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
+    if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE, client))) {
        goto Bad_RemoveDir;
     }
 
@@ -4647,8 +4644,6 @@ SAFSS_RemoveDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
     VVnodeWriteToRead(&errorCode, parentptr);
     assert_vnode_success_or_salvaging(errorCode);
 
-    rx_KeepAliveOn(acall);
-
     /* break call back on DirFid and fileFid */
     BreakCallBack(client->z.host, DirFid, 0);
 
@@ -4946,7 +4941,6 @@ SAFSS_ReleaseLock(struct rx_call *acall, struct AFSFid *Fid,
 
     /* if no more locks left, a callback would be triggered here */
     if (targetptr->disk.lock.lockCount <= 0) {
-       rx_KeepAliveOn(acall);
        /* convert the write lock to a read lock before breaking callbacks */
        VVnodeWriteToRead(&errorCode, targetptr);
        assert_vnode_success_or_salvaging(errorCode);
@@ -5392,82 +5386,54 @@ SRXAFS_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
                 afs_int32 * a_timeP, AFS_CollData * a_dataP)
 {                              /*SRXAFS_GetXStats */
 
+    struct client *t_client = NULL;    /* tmp ptr to client data */
+    struct rx_connection *tcon = rx_ConnectionOf(a_call);
     int code;          /*Return value */
     afs_int32 *dataBuffP;      /*Ptr to data to be returned */
     afs_int32 dataBytes;       /*Bytes in data buffer */
     struct fsstats fsstats;
 
-    fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_GETXSTATS);
-
     /*
-     * Record the time of day and the server version number.
+     * Note: This function intentionally omits CallPreamble()
+     *       to avoid issuing TellMeAboutYourself() calls to
+     *       simple clients which are only gathering stats.
      */
+
+    fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_GETXSTATS);
+
+    t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
+
+    /* Return the server's time of day and xstat version number. */
     *a_srvVersionNumP = AFS_XSTAT_VERSION;
     *a_timeP = (afs_int32) time(NULL);
-
-    /*
-     * Stuff the appropriate data in there (assume victory)
-     */
     code = 0;
 
-    ViceLog(1,
-           ("Received GetXStats call for collection %d\n",
-            a_collectionNumber));
-
-#if 0
-    /*
-     * We're not keeping stats, so just return successfully with
-     * no data.
-     */
-    a_dataP->AFS_CollData_len = 0;
-    a_dataP->AFS_CollData_val = NULL;
-#endif /* 0 */
+    osi_auditU(a_call, GetXStatsEvent,
+              AUD_ID, t_client ? t_client->z.ViceId : 0,
+              AUD_INT, a_clientVersionNum,
+              AUD_INT, a_collectionNumber, AUD_END);
 
     switch (a_collectionNumber) {
     case AFS_XSTATSCOLL_CALL_INFO:
-       /*
-        * Pass back all the call-count-related data.
-        *
-        * >>> We are forced to allocate a separate area in which to
-        * >>> put this stuff in by the RPC stub generator, since it
-        * >>> will be freed at the tail end of the server stub code.
-        */
-#if 0
-       /*
-        * I don't think call-level stats are being collected yet
-        * for the File Server.
-        */
-       dataBytes = sizeof(struct afs_Stats);
-       dataBuffP = malloc(dataBytes);
-       memcpy(dataBuffP, &afs_cmstats, dataBytes);
-       a_dataP->AFS_CollData_len = dataBytes >> 2;
-       a_dataP->AFS_CollData_val = dataBuffP;
-#else
+       /*  The call info collection type is not implemented. */
        a_dataP->AFS_CollData_len = 0;
        a_dataP->AFS_CollData_val = NULL;
-#endif /* 0 */
        break;
 
     case AFS_XSTATSCOLL_PERF_INFO:
        /*
         * Pass back all the regular performance-related data.
         *
-        * >>> We are forced to allocate a separate area in which to
-        * >>> put this stuff in by the RPC stub generator, since it
-        * >>> will be freed at the tail end of the server stub code.
+        * Allocate a separate area in which to put this stuff in
+        * by the RPC stub generator, since it will be freed at the
+        * tail end of the server stub code.
         */
-
        afs_perfstats.numPerfCalls++;
        FillPerfValues(&afs_perfstats);
-
-       /*
-        * Don't overwrite the spares at the end.
-        */
-
        dataBytes = sizeof(struct afs_PerfStats);
-       dataBuffP = malloc(dataBytes);
+       dataBuffP = calloc(1, dataBytes);
        memcpy(dataBuffP, &afs_perfstats, dataBytes);
-       a_dataP->AFS_CollData_len = dataBytes >> 2;
+       a_dataP->AFS_CollData_len = dataBytes / sizeof(afs_int32);
        a_dataP->AFS_CollData_val = dataBuffP;
        break;
 
@@ -5477,23 +5443,17 @@ SRXAFS_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
         * We have to stuff the basic, overall numbers in, but the
         * detailed numbers are kept in the structure already.
         *
-        * >>> We are forced to allocate a separate area in which to
-        * >>> put this stuff in by the RPC stub generator, since it
-        * >>> will be freed at the tail end of the server stub code.
+        * Allocate a separate area in which to put this stuff in
+        * by the RPC stub generator, since it will be freed at the
+        * tail end of the server stub code.
         */
-
        afs_perfstats.numPerfCalls++;
        afs_FullPerfStats.overall.numPerfCalls = afs_perfstats.numPerfCalls;
        FillPerfValues(&afs_FullPerfStats.overall);
-
-       /*
-        * Don't overwrite the spares at the end.
-        */
-
        dataBytes = sizeof(struct fs_stats_FullPerfStats);
-       dataBuffP = malloc(dataBytes);
+       dataBuffP = calloc(1, dataBytes);
        memcpy(dataBuffP, &afs_FullPerfStats, dataBytes);
-       a_dataP->AFS_CollData_len = dataBytes >> 2;
+       a_dataP->AFS_CollData_len = dataBytes / sizeof(afs_int32);
        a_dataP->AFS_CollData_val = dataBuffP;
        break;
 
@@ -5501,7 +5461,7 @@ SRXAFS_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
        afs_perfstats.numPerfCalls++;
 
        dataBytes = sizeof(struct cbcounters);
-       dataBuffP = malloc(dataBytes);
+       dataBuffP = calloc(1, dataBytes);
        {
            extern struct cbcounters cbstuff;
            dataBuffP[0]=cbstuff.DeleteFiles;
@@ -5522,15 +5482,12 @@ SRXAFS_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
            dataBuffP[15]=cbstuff.GSS5;
        }
 
-       a_dataP->AFS_CollData_len = dataBytes >> 2;
+       a_dataP->AFS_CollData_len = dataBytes / sizeof(afs_int32);
        a_dataP->AFS_CollData_val = dataBuffP;
        break;
 
-
     default:
-       /*
-        * Illegal collection number.
-        */
+       /* Illegal collection number. */
        a_dataP->AFS_CollData_len = 0;
        a_dataP->AFS_CollData_val = NULL;
        code = 1;
@@ -6015,7 +5972,7 @@ SRXAFS_SetVolumeStatus(struct rx_call * acall, afs_int32 avolid,
                          &rights, &anyrights)))
        goto Bad_SetVolumeStatus;
 
-    if (readonlyServer) {
+    if (!IsWriteAllowed(client)) {
        errorCode = VREADONLY;
        goto Bad_SetVolumeStatus;
     }
@@ -6048,14 +6005,6 @@ SRXAFS_SetVolumeStatus(struct rx_call * acall, afs_int32 avolid,
 afs_int32
 SRXAFS_GetRootVolume(struct rx_call * acall, char **VolumeName)
 {
-#ifdef notdef
-    int fd;
-    int len;
-    char *temp;
-    struct rx_connection *tcon;
-    struct host *thost;
-    Error errorCode = 0;
-#endif
     struct fsstats fsstats;
 
     fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_GETROOTVOLUME);
@@ -6102,7 +6051,6 @@ SRXAFS_GetRootVolume(struct rx_call * acall, char **VolumeName)
 }                              /*SRXAFS_GetRootVolume */
 
 
-/* still works because a struct CBS is the same as a struct AFSOpaque */
 afs_int32
 SRXAFS_CheckToken(struct rx_call * acall, afs_int32 AfsId,
                  struct AFSOpaque * Token)
@@ -6367,7 +6315,7 @@ GetLinkCountAndSize(Volume * vp, FdHandle_t * fdP, int *lc,
     FDH_CLOSE(lhp);
     if (*lc < 0)
        return -1;
-    *size = OS_SIZE(fdP->fd_fd);
+    *size = FDH_SIZE(fdP);
     return (*size == -1) ? -1 : 0;
 #else
     struct afs_stat status;
@@ -6450,7 +6398,6 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
                 inet_ntoa(logHostAddr), ntohs(rxr_PortOf(rx_ConnectionOf(Call)))));
        return ENOENT;          /* is this proper error code? */
     } else {
-       rx_KeepAliveOff(Call);
        /*
         * See if the file has several links (from other volumes).  If it
         * does, then we have to make a copy before changing it to avoid
@@ -6808,6 +6755,13 @@ init_sys_error_to_et(void)
     sys2et[EDQUOT] = UAEDQUOT;
     sys2et[ENOMEDIUM] = UAENOMEDIUM;
     sys2et[EMEDIUMTYPE] = UAEMEDIUMTYPE;
+    sys2et[ECANCELED] = UAECANCELED;
+    sys2et[ENOTRECOVERABLE] = UAENOTRECOVERABLE;
+    sys2et[ENOTSUP] = UAENOTSUP;
+    sys2et[EOTHER] = UAEOTHER;
+    sys2et[EOWNERDEAD] = UAEOWNERDEAD;
+    sys2et[EPROCLIM] = UAEPROCLIM;
+    sys2et[EDISCON] = UAEDISCON;
 
     sys2et[EIO] = UAEIO;
 }