Windows: cm_CheckNTDelete missing SyncDone call
[openafs.git] / src / WINNT / afsd / cm_vnodeops.c
index 6044a78..f1f691b 100644 (file)
@@ -360,7 +360,7 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
         return code;
 
     thyper.HighPart = 0; thyper.LowPart = 0;
-    code = buf_Get(scp, &thyper, reqp, &bufferp);
+    code = buf_Get(scp, &thyper, reqp, 0, &bufferp);
     if (code)
         return code;
 
@@ -375,8 +375,10 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
         if (code)
             goto done;
 
-        if (cm_HaveBuffer(scp, bufferp, 1))
+       if (cm_HaveBuffer(scp, bufferp, 1)) {
+           cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ | CM_SCACHESYNC_BUFLOCKED);
             break;
+       }
 
         /* otherwise, load the buffer and try again */
         lock_ReleaseMutex(&bufferp->mx);
@@ -603,7 +605,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
                 bufferp = NULL;
             }
 
-            code = buf_Get(scp, &thyper, reqp, &bufferp);
+            code = buf_Get(scp, &thyper, reqp, 0, &bufferp);
             if (code) {
                 /* if buf_Get() fails we do not have a buffer object to lock */
                 bufferp = NULL;
@@ -860,10 +862,11 @@ long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
     {
         char temp[MOUNTPOINTLEN];
         osi_hyper_t offset;
+        afs_uint32 bytesRead = 0;
 
         /* otherwise, we have to read it in */
         offset.LowPart = offset.HighPart = 0;
-        code = cm_GetData(scp, &offset, temp, MOUNTPOINTLEN, userp, reqp);
+        code = cm_GetData(scp, &offset, temp, MOUNTPOINTLEN, &bytesRead, userp, reqp);
         if (code)
             goto done;
 
@@ -979,7 +982,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
     if (targetType == BACKVOL
          && (scp->flags & (CM_SCACHEFLAG_RO | CM_SCACHEFLAG_PURERO))
          == CM_SCACHEFLAG_RO) {
-        code = CM_ERROR_NOSUCHVOLUME;
+       code = CM_ERROR_TOO_MANY_SYMLINKS;
         goto done;
     }
 
@@ -1743,10 +1746,9 @@ long cm_Unlink(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t * cnamep,
         if (code == 0) {
            lock_ObtainWrite(&scp->rw);
             if (--scp->linkCount == 0) {
-                scp->flags |= CM_SCACHEFLAG_DELETED;
+               _InterlockedOr(&scp->flags, CM_SCACHEFLAG_DELETED);
                lock_ObtainWrite(&cm_scacheLock);
                 cm_AdjustScacheLRU(scp);
-                cm_RemoveSCacheFromHashTable(scp);
                lock_ReleaseWrite(&cm_scacheLock);
             }
             cm_DiscardSCache(scp);
@@ -1789,10 +1791,11 @@ long cm_HandleLink(cm_scache_t *linkScp, cm_user_t *userp, cm_req_t *reqp)
         {
             char temp[MOUNTPOINTLEN];
             osi_hyper_t offset;
+            afs_uint32 bytesRead = 0;
 
             /* read the link data from the file server */
             offset.LowPart = offset.HighPart = 0;
-            code = cm_GetData(linkScp, &offset, temp, MOUNTPOINTLEN, userp, reqp);
+            code = cm_GetData(linkScp, &offset, temp, MOUNTPOINTLEN, &bytesRead, userp, reqp);
             if (code)
                 return code;
 
@@ -2495,16 +2498,27 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
                 continue;
 
             rxconnp = cm_GetRxConn(connp);
-           if (!(connp->serverp->flags & CM_SERVERFLAG_NOINLINEBULK)) {
+           if (SERVERHASINLINEBULK(connp)) {
                code = RXAFS_InlineBulkStatus(rxconnp, &fidStruct,
                                               &statStruct, &callbackStruct, &volSync);
                if (code == RXGEN_OPCODE) {
-                   cm_SetServerNoInlineBulk(connp->serverp, 1);
+                   SET_SERVERHASNOINLINEBULK(connp);
                } else {
                    inlinebulk = 1;
                }
            }
            if (!inlinebulk) {
+                /*
+                 * It is important to note that RXAFS_BulkStatus is quite braindead.
+                 * The AFS 3.6 file server implementation returns arrays that are
+                 * sized to hold responses for all of the requested FIDs but it only
+                 * populates their contents up to the point where it detects an error.
+                 * Unfortunately, it does inform the caller which entries were filled
+                 * and which were not.  The caller has no ability to determine which
+                 * FID the RPC return code applies to or which of the FIDs valid status
+                 * info and callbacks have been issued for.  As a result, when an
+                 * error is returned, none of the data received can be trusted.
+                 */
                code = RXAFS_BulkStatus(rxconnp, &fidStruct,
                                        &statStruct, &callbackStruct, &volSync);
            }
@@ -2548,6 +2562,17 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
         if (code) {
             osi_Log2(afsd_logp, "CALL %sBulkStatus FAILURE code 0x%x",
                      inlinebulk ? "Inline" : "", code);
+            if (!inlinebulk) {
+                /*
+                 * Since an error occurred and it is impossible to determine
+                 * the context in which the returned error code should be
+                 * interpreted, we return the CM_ERROR_BULKSTAT_FAILURE error
+                 * which indicates that Bulk Stat cannot be used for the
+                 * current request.  The caller should fallback to using
+                 * individual RXAFS_FetchStatus calls.
+                 */
+                code = CM_ERROR_BULKSTAT_FAILURE;
+            }
             cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
             break;
         }
@@ -2616,9 +2641,10 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
                                                           &bbp->callbacks[j],
                                                           &volSync,
                                                           CM_CALLBACK_MAINTAINCOUNT|CM_CALLBACK_BULKSTAT);
-                    InterlockedIncrement(&scp->activeRPCs);
-                    if (!lostRace)
+                   if (!lostRace) {
+                       InterlockedIncrement(&scp->activeRPCs);
                         code = cm_MergeStatus(dscp, scp, &bbp->stats[j], &volSync, userp, reqp, CM_MERGEFLAG_BULKSTAT);
+                   }
                     lock_ReleaseWrite(&scp->rw);
                 } else {
                     lock_ReleaseRead(&scp->rw);
@@ -2738,7 +2764,7 @@ cm_IsSpaceAvailable(cm_fid_t * fidp, osi_hyper_t *sizep, cm_user_t *userp, cm_re
         goto _done;
     }
 
-    volp = cm_GetVolumeByFID(fidp);
+    volp = cm_FindVolumeByFID(fidp, userp, reqp);
     if (!volp) {
         spaceAvail = 0;
         goto _done;
@@ -2806,6 +2832,7 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
 {
     long code;
     int shrinking;
+    int available;
 
     /* start by locking out buffer creation */
     lock_ObtainWrite(&scp->bufCreateLock);
@@ -2864,8 +2891,12 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
          * than where we're truncating the file, set truncPos to this
          * new value.
          */
-        if (!shrinking)
+       if (!shrinking) {
+           cm_SyncOpDone(scp, NULL,
+                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS
+                         | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_SETSIZE);
             goto startover;
+       }
         if (!(scp->mask & CM_SCACHEMASK_TRUNCPOS)
              || LargeIntegerLessThan(*sizep, scp->length)) {
             /* set trunc pos */
@@ -2877,9 +2908,32 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
         scp->mask |= CM_SCACHEMASK_LENGTH;
     }
     else if (LargeIntegerGreaterThan(*sizep, scp->length)) {
-        /* really extending the file */
-        /* Check to see if we have sufficient quota */
-        if (cm_IsSpaceAvailable(&scp->fid, sizep, userp, reqp)) {
+        /*
+         * Really extending the file so must check to see if we
+         * have sufficient quota.  cm_IsSpaceAvailable() obtains
+         * the cm_scache.rw lock on the volume root directory.
+         * vnode 1 < scp->fid.vnode therefore calling cm_IsSpaceAvailable
+         * while holding scp->rw is a lock order violation.
+         * Dropping it is ok because we are holding scp->bufCreateLock
+         * which prevents the size of the file from changing.
+         */
+        afs_uint64 nextChunk = scp->length.QuadPart;
+
+        nextChunk -= (nextChunk & 0xFFFFF);
+        nextChunk += 0x100000;
+
+        if (sizep->QuadPart > nextChunk) {
+            lock_ReleaseWrite(&scp->rw);
+            available = cm_IsSpaceAvailable(&scp->fid, sizep, userp, reqp);
+            lock_ObtainWrite(&scp->rw);
+        } else {
+            /*
+             * The file server permits 1MB quota overruns so only check
+             * when the file size increases by at least that much.
+             */
+            available = 1;
+        }
+        if (available) {
             scp->length = *sizep;
             scp->mask |= CM_SCACHEMASK_LENGTH;
         } else {
@@ -3115,10 +3169,11 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
             if (!cm_HaveCallback(scp)) {
                 lostRace = cm_EndCallbackGrantingCall(scp, &cbReq,
                                                       &newFileCallback, &volSync, 0);
-                InterlockedIncrement(&scp->activeRPCs);
-                if (!lostRace)
+               if (!lostRace) {
+                   InterlockedIncrement(&scp->activeRPCs);
                     code = cm_MergeStatus( dscp, scp, &newFileStatus, &volSync,
                                            userp, reqp, 0);
+               }
                 didEnd = 1;
             }
             lock_ReleaseWrite(&scp->rw);
@@ -3306,10 +3361,11 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
             if (!cm_HaveCallback(scp)) {
                 lostRace = cm_EndCallbackGrantingCall(scp, &cbReq,
                                                       &newDirCallback, &volSync, 0);
-                InterlockedIncrement(&scp->activeRPCs);
-                if (!lostRace)
+               if (!lostRace) {
+                   InterlockedIncrement(&scp->activeRPCs);
                     code = cm_MergeStatus( dscp, scp, &newDirStatus, &volSync,
                                            userp, reqp, 0);
+               }
                 didEnd = 1;
             }
             lock_ReleaseWrite(&scp->rw);
@@ -3703,10 +3759,9 @@ long cm_RemoveDir(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t *cnamep, cm_
     if (scp) {
         if (code == 0) {
            lock_ObtainWrite(&scp->rw);
-            scp->flags |= CM_SCACHEFLAG_DELETED;
+           _InterlockedOr(&scp->flags, CM_SCACHEFLAG_DELETED);
             lock_ObtainWrite(&cm_scacheLock);
             cm_AdjustScacheLRU(scp);
-            cm_RemoveSCacheFromHashTable(scp);
             lock_ReleaseWrite(&cm_scacheLock);
            lock_ReleaseWrite(&scp->rw);
             if (RDR_Initialized && !(reqp->flags & CM_REQ_SOURCE_REDIR))
@@ -5725,9 +5780,7 @@ void cm_CheckLocks()
                     goto post_syncopdone;
 
                 code = cm_SyncOp(scp, NULL, fileLock->userp, &req, 0,
-                                 CM_SCACHESYNC_NEEDCALLBACK
-                                 | CM_SCACHESYNC_GETSTATUS
-                                 | CM_SCACHESYNC_LOCK);
+                                CM_SCACHESYNC_LOCK);
 
                 if (code) {
                     osi_Log1(afsd_logp,
@@ -6052,9 +6105,7 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
         cm_user_t * userp;
 
         code = cm_SyncOp(scp, NULL, oldFileLock->userp, &req, 0,
-                         CM_SCACHESYNC_NEEDCALLBACK
-                        | CM_SCACHESYNC_GETSTATUS
-                        | CM_SCACHESYNC_LOCK);
+                        CM_SCACHESYNC_LOCK);
         if (code) {
             osi_Log1(afsd_logp, "cm_RetryLock SyncOp failure code 0x%x", code);
             lock_ReleaseWrite(&cm_scacheLock);