viced: avoid crash if missing volume header
[openafs.git] / src / viced / afsfileprocs.c
index 864a28c..7702c6a 100644 (file)
@@ -244,7 +244,7 @@ SetVolumeSync(struct AFSVolSync *async, Volume * avol)
     FS_LOCK;
     /* date volume instance was created */
     if (async) {
-       if (avol)
+       if (avol && avol->header)
            async->spare1 = avol->header->diskstuff.creationDate;
        else
            async->spare1 = 0;
@@ -790,6 +790,7 @@ VanillaUser(struct client *client)
  *      locktype            : indicates what kind of lock to take on vnodes
  *      rights              : returns a pointer to caller's rights
  *      anyrights           : returns a pointer to anonymous' rights
+ *      remote             : indicates that the volume is a remote RW replica
  *
  * Returns:
  *      0 on success
@@ -807,7 +808,7 @@ GetVolumePackageWithCall(struct rx_call *acall, struct VCallByVol *cbv,
                          AFSFid * Fid, Volume ** volptr, Vnode ** targetptr,
                          int chkforDir, Vnode ** parent,
                         struct client **client, int locktype,
-                        afs_int32 * rights, afs_int32 * anyrights)
+                        afs_int32 * rights, afs_int32 * anyrights, int remote)
 {
     struct acl_accessList *aCL;        /* Internal access List */
     int aCLSize;               /* size of the access list */
@@ -831,38 +832,43 @@ GetVolumePackageWithCall(struct rx_call *acall, struct VCallByVol *cbv,
            goto gvpdone;
        }
     }
-    if ((errorCode =
-        SetAccessList(targetptr, volptr, &aCL, &aCLSize, parent,
-                      (chkforDir == MustBeDIR ? (AFSFid *) 0 : Fid),
-                      (chkforDir == MustBeDIR ? 0 : locktype))) != 0)
-       goto gvpdone;
-    if (chkforDir == MustBeDIR)
-       osi_Assert((*parent) == 0);
-    if (!(*client)) {
-       if ((errorCode = GetClient(tcon, client)) != 0)
+    /*
+     * If the remote flag is set, the current call is dealing with a remote RW
+     * replica, and it can be assumed that the appropriate access checks were
+     * done by the calling server hosting the master volume.
+     */
+    if (!remote) {
+       if ((errorCode = SetAccessList(targetptr, volptr, &aCL, &aCLSize, parent,
+               (chkforDir == MustBeDIR ? (AFSFid *) 0 : Fid),
+               (chkforDir == MustBeDIR ? 0 : locktype))) != 0)
            goto gvpdone;
+       if (chkforDir == MustBeDIR)
+           osi_Assert((*parent) == 0);
        if (!(*client)) {
-           errorCode = EINVAL;
-           goto gvpdone;
+           if ((errorCode = GetClient(tcon, client)) != 0)
+               goto gvpdone;
+           if (!(*client))
+               errorCode = EINVAL;
+               goto gvpdone;
+       }
+       GetRights(*client, aCL, rights, anyrights);
+       /* ok, if this is not a dir, set the PRSFS_ADMINISTER bit iff we're the owner */
+       if ((*targetptr)->disk.type != vDirectory) {
+           /* anyuser can't be owner, so only have to worry about rights, not anyrights */
+           if ((*targetptr)->disk.owner == (*client)->ViceId)
+               (*rights) |= PRSFS_ADMINISTER;
+           else
+               (*rights) &= ~PRSFS_ADMINISTER;
        }
-    }
-    GetRights(*client, aCL, rights, anyrights);
-    /* ok, if this is not a dir, set the PRSFS_ADMINISTER bit iff we're the owner */
-    if ((*targetptr)->disk.type != vDirectory) {
-       /* anyuser can't be owner, so only have to worry about rights, not anyrights */
-       if ((*targetptr)->disk.owner == (*client)->ViceId)
-           (*rights) |= PRSFS_ADMINISTER;
-       else
-           (*rights) &= ~PRSFS_ADMINISTER;
-    }
 #ifdef ADMIN_IMPLICIT_LOOKUP
-    /* admins get automatic lookup on everything */
-    if (!VanillaUser(*client))
-       (*rights) |= PRSFS_LOOKUP;
+       /* admins get automatic lookup on everything */
+       if (!VanillaUser(*client))
+           (*rights) |= PRSFS_LOOKUP;
 #endif /* ADMIN_IMPLICIT_LOOKUP */
 gvpdone:
     if (errorCode)
        rx_KeepAliveOn(acall);
+    }
     return errorCode;
 
 }                              /*GetVolumePackage */
@@ -875,7 +881,7 @@ GetVolumePackage(struct rx_call *acall, AFSFid * Fid, Volume ** volptr,
 {
     return GetVolumePackageWithCall(acall, NULL, Fid, volptr, targetptr,
                                     chkforDir, parent, client, locktype,
-                                    rights, anyrights);
+                                    rights, anyrights, 0);
 }
 
 
@@ -1326,7 +1332,7 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr, afs_foff_t off, afs_fsize_t len)
                IH_RELEASE(newH);
                FDH_REALLYCLOSE(targFdP);
                rc = IH_DEC(V_linkHandle(volptr), ino, V_parentId(volptr));
-               if (!rc) {
+               if (rc) {
                    ViceLog(0,
                            ("CopyOnWrite failed: error %u after i_dec on disk full, volume %u in partition %s needs salvage\n",
                             rc, V_id(volptr), volptr->partition->name));
@@ -1586,6 +1592,8 @@ Update_ParentVnodeStatus(Vnode * parentptr, Volume * volptr, DirHandle * dir,
  * Update the target file's (or dir's) status block after the specified
  * operation is complete. Note that some other fields maybe updated by
  * the individual module.
+ * If remote is set, the volume is a RW replica and access checks can
+ * be skipped.
  */
 
 /* XXX INCOMPLETE - More attention is needed here! */
@@ -1593,7 +1601,7 @@ static void
 Update_TargetVnodeStatus(Vnode * targetptr, afs_uint32 Caller,
                         struct client *client, AFSStoreStatus * InStatus,
                         Vnode * parentptr, Volume * volptr,
-                        afs_fsize_t length)
+                        afs_fsize_t length, int remote)
 {
     Date currDate;             /*Current date */
     int writeIdx;              /*Write index to bump */
@@ -1654,7 +1662,7 @@ Update_TargetVnodeStatus(Vnode * targetptr, afs_uint32 Caller,
        targetptr->disk.author = client->ViceId;
     if (Caller & TVS_SDATA) {
        targetptr->disk.dataVersion++;
-       if (VanillaUser(client)) {
+       if (!remote && VanillaUser(client)) {
            targetptr->disk.modeBits &= ~04000; /* turn off suid for file. */
 #ifdef CREATE_SGUID_ADMIN_ONLY
            targetptr->disk.modeBits &= ~02000; /* turn off sgid for file. */
@@ -1672,7 +1680,7 @@ Update_TargetVnodeStatus(Vnode * targetptr, afs_uint32 Caller,
     }
     if (InStatus->Mask & AFS_SETOWNER) {
        /* admin is allowed to do chmod, chown as well as chown, chmod. */
-       if (VanillaUser(client)) {
+       if (!remote && VanillaUser(client)) {
            targetptr->disk.modeBits &= ~04000; /* turn off suid for file. */
 #ifdef CREATE_SGUID_ADMIN_ONLY
            targetptr->disk.modeBits &= ~02000; /* turn off sgid for file. */
@@ -1690,10 +1698,10 @@ Update_TargetVnodeStatus(Vnode * targetptr, afs_uint32 Caller,
        int modebits = InStatus->UnixModeBits;
 #define        CREATE_SGUID_ADMIN_ONLY 1
 #ifdef CREATE_SGUID_ADMIN_ONLY
-       if (VanillaUser(client))
+       if (!remote && VanillaUser(client))
            modebits = modebits & 0777;
 #endif
-       if (VanillaUser(client)) {
+       if (!remote && VanillaUser(client)) {
            targetptr->disk.modeBits = modebits;
        } else {
            targetptr->disk.modeBits = modebits;
@@ -1806,7 +1814,7 @@ Alloc_NewVnode(Vnode * parentptr, DirHandle * dir, Volume * volptr,
        return VSALVAGE;
     }
 
-    *targetptr = VAllocVnode(&errorCode, volptr, FileType);
+    *targetptr = VAllocVnode(&errorCode, volptr, FileType, 0, 0);
     if (errorCode != 0) {
        VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
        return (errorCode);
@@ -2003,8 +2011,8 @@ RXGetVolumeStatus(AFSFetchVolumeStatus * status, char **name, char **offMsg,
     status->MinQuota = V_minquota(volptr);
     status->MaxQuota = V_maxquota(volptr);
     status->BlocksInUse = V_diskused(volptr);
-    status->PartBlocksAvail = RoundInt64ToInt32(volptr->partition->free);
-    status->PartMaxBlocks = RoundInt64ToInt32(volptr->partition->totalUsable);
+    status->PartBlocksAvail = RoundInt64ToInt31(volptr->partition->free);
+    status->PartMaxBlocks = RoundInt64ToInt31(volptr->partition->totalUsable);
 
     /* now allocate and copy these things; they're freed by the RXGEN stub */
     temp = strlen(V_name(volptr)) + 1;
@@ -2228,7 +2236,7 @@ common_FetchData64(struct rx_call *acall, struct AFSFid *Fid,
     if ((errorCode =
         GetVolumePackageWithCall(acall, cbv, Fid, &volptr, &targetptr, DONTCHECK,
                          &parentwhentargetnotdir, &client, READ_LOCK,
-                         &rights, &anyrights)))
+                         &rights, &anyrights, 0)))
        goto Bad_FetchData;
 
     SetVolumeSync(Sync, volptr);
@@ -2688,7 +2696,13 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
                              &parentwhentargetnotdir, &client, READ_LOCK,
                              &rights, &anyrights))) {
            tstatus = &OutStats->AFSBulkStats_val[i];
-           tstatus->errorCode = errorCode;
+
+           if (thost->hostFlags & HERRORTRANS) {
+               tstatus->errorCode = sys_error_to_et(errorCode);
+           } else {
+               tstatus->errorCode = errorCode;
+           }
+
            PutVolumePackage(acall, parentwhentargetnotdir, targetptr,
                             (Vnode *) 0, volptr, &client);
            parentwhentargetnotdir = (Vnode *) 0;
@@ -2712,7 +2726,13 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
                 Check_PermissionRights(targetptr, client, rights,
                                        CHK_FETCHSTATUS, 0))) {
                tstatus = &OutStats->AFSBulkStats_val[i];
-               tstatus->errorCode = errorCode;
+
+               if (thost->hostFlags & HERRORTRANS) {
+                   tstatus->errorCode = sys_error_to_et(errorCode);
+               } else {
+                   tstatus->errorCode = errorCode;
+               }
+
                (void)PutVolumePackage(acall, parentwhentargetnotdir,
                                       targetptr, (Vnode *) 0, volptr,
                                       &client);
@@ -2863,7 +2883,7 @@ common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
     /* set volume synchronization information */
     SetVolumeSync(Sync, volptr);
 
-    if ((targetptr->disk.type == vSymlink)) {
+    if (targetptr->disk.type == vSymlink) {
        /* Should we return a better error code here??? */
        errorCode = EISDIR;
        goto Bad_StoreData;
@@ -2905,7 +2925,7 @@ common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
     rx_KeepAliveOff(acall);
     /* Update the status of the target's vnode */
     Update_TargetVnodeStatus(targetptr, TVS_SDATA, client, InStatus,
-                            targetptr, volptr, 0);
+                            targetptr, volptr, 0, 0);
     rx_KeepAliveOn(acall);
 
     /* Get the updated File's status back to the caller */
@@ -3117,7 +3137,7 @@ SAFSS_StoreStatus(struct rx_call *acall, struct AFSFid *Fid,
     /* Update the status of the target's vnode */
     Update_TargetVnodeStatus(targetptr, TVS_SSTATUS, client, InStatus,
                             (parentwhentargetnotdir ? parentwhentargetnotdir
-                             : targetptr), volptr, 0);
+                             : targetptr), volptr, 0, 0);
 
     rx_KeepAliveOn(acall);
 
@@ -3380,7 +3400,7 @@ SAFSS_CreateFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
 
     /* update the status of the new file's vnode */
     Update_TargetVnodeStatus(targetptr, TVS_CFILE, client, InStatus,
-                            parentptr, volptr, 0);
+                            parentptr, volptr, 0, 0);
 
     rx_KeepAliveOn(acall);
 
@@ -4047,7 +4067,7 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
 
     /* update the status of the new symbolic link file vnode */
     Update_TargetVnodeStatus(targetptr, TVS_SLINK, client, InStatus,
-                            parentptr, volptr, strlen((char *)LinkContents));
+                            parentptr, volptr, strlen((char *)LinkContents), 0);
 
     /* Write the contents of the symbolic link name into the target inode */
     fdP = IH_OPEN(targetptr->handle);
@@ -4406,7 +4426,7 @@ SAFSS_MakeDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
 
     /* update the status for the target vnode */
     Update_TargetVnodeStatus(targetptr, TVS_MKDIR, client, InStatus,
-                            parentptr, volptr, 0);
+                            parentptr, volptr, 0, 0);
 
     /* Actually create the New directory in the directory package */
     SetDirHandle(&dir, targetptr);
@@ -4760,7 +4780,7 @@ SAFSS_ExtendLock(struct rx_call *acall, struct AFSFid *Fid,
     (void)PutVolumePackage(acall, parentwhentargetnotdir, targetptr,
                           (Vnode *) 0, volptr, &client);
 
-    if ((errorCode == VREADONLY))      /* presumably, we already granted this lock */
+    if (errorCode == VREADONLY)        /* presumably, we already granted this lock */
        errorCode = 0;          /* under our generous policy re RO vols */
 
     ViceLog(2, ("SAFS_ExtendLock returns %d\n", errorCode));
@@ -4869,7 +4889,7 @@ SAFSS_ReleaseLock(struct rx_call *acall, struct AFSFid *Fid,
     (void)PutVolumePackage(acall, parentwhentargetnotdir, targetptr,
                           (Vnode *) 0, volptr, &client);
 
-    if ((errorCode == VREADONLY))      /* presumably, we already granted this lock */
+    if (errorCode == VREADONLY)        /* presumably, we already granted this lock */
        errorCode = 0;          /* under our generous policy re RO vols */
 
     ViceLog(2, ("SAFS_ReleaseLock returns %d\n", errorCode));
@@ -4982,8 +5002,8 @@ SetVolumeStats(struct AFSStatistics *stats)
 
     for (part = DiskPartitionList; part && i < AFS_MSTATDISKS;
         part = part->next) {
-       stats->Disks[i].TotalBlocks = RoundInt64ToInt32(part->totalUsable);
-       stats->Disks[i].BlocksAvailable = RoundInt64ToInt32(part->free);
+       stats->Disks[i].TotalBlocks = RoundInt64ToInt31(part->totalUsable);
+       stats->Disks[i].BlocksAvailable = RoundInt64ToInt31(part->free);
        memset(stats->Disks[i].Name, 0, AFS_DISKNAMESIZE);
        strncpy(stats->Disks[i].Name, part->name, AFS_DISKNAMESIZE);
        i++;
@@ -5493,7 +5513,7 @@ common_GiveUpCallBacks(struct rx_call *acall, struct AFSCBFids *FidArray,
     if (!FidArray && !CallBackArray) {
        ViceLog(1,
                ("SAFS_GiveUpAllCallBacks: host=%x\n",
-                (rx_PeerOf(tcon) ? rx_PeerOf(tcon)->host : 0)));
+                (rx_PeerOf(tcon) ? rx_HostOf(rx_PeerOf(tcon)) : 0)));
        errorCode = GetClient(tcon, &client);
        if (!errorCode) {
            H_LOCK;
@@ -5506,7 +5526,7 @@ common_GiveUpCallBacks(struct rx_call *acall, struct AFSCBFids *FidArray,
            ViceLog(0,
                    ("GiveUpCallBacks: #Fids %d < #CallBacks %d, host=%x\n",
                     FidArray->AFSCBFids_len, CallBackArray->AFSCBs_len,
-                    (rx_PeerOf(tcon) ? rx_PeerOf(tcon)->host : 0)));
+                    (rx_PeerOf(tcon) ? rx_HostOf(rx_PeerOf(tcon)) : 0)));
            errorCode = EINVAL;
            goto Bad_GiveUpCallBacks;
        }
@@ -6543,7 +6563,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
     FreeSendBuffer((struct afs_buffer *)tbuffer);
 #endif /* HAVE_PIOV */
     if (sync) {
-       FDH_SYNC(fdP);
+       (void) FDH_SYNC(fdP);
     }
     if (errorCode) {
        Error tmp_errorCode = 0;