]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-buf-deadlock-20080228
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 28 Feb 2008 18:22:58 +0000 (18:22 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 28 Feb 2008 18:22:58 +0000 (18:22 +0000)
LICENSE MIT

avoid deadlock in buf_FlushCleanPages().
cannot obtain buffer mutex after a successful
Stabilize call because the scp will be be locked
and obtaining buffer mutex after scache mutex
is a lock order violation.

(cherry picked from commit 0546641c0da59289d03a9417984fe5f7e5636a75)

src/WINNT/afsd/cm_buf.c

index 3b0d35b88e2471d5ab50968c3fa22e10e55f361b..434558500c905120687f0b1b689332b74d273c50 100644 (file)
@@ -1548,19 +1548,21 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
             if (code && code != CM_ERROR_BADFD) 
                 goto skip;
 
-           /* if the scp's FID is bad its because we received VNOVNODE 
-            * when attempting to FetchStatus before the write.  This
-            * page therefore contains data that can no longer be stored.
-            */
-           lock_ObtainMutex(&bp->mx);
-           bp->flags &= ~CM_BUF_DIRTY;
-           bp->flags |= CM_BUF_ERROR;
-           bp->error = code;
-            bp->dirty_offset = 0;
-            bp->dirty_length = 0;
-            bp->dataVersion = -1;      /* known bad */
-            bp->dirtyCounter++;
-           lock_ReleaseMutex(&bp->mx);
+            if (code == CM_ERROR_BADFD) {
+                /* if the scp's FID is bad its because we received VNOVNODE 
+                 * when attempting to FetchStatus before the write.  This
+                 * page therefore contains data that can no longer be stored.
+                 */
+                lock_ObtainMutex(&bp->mx);
+                bp->flags &= ~CM_BUF_DIRTY;
+                bp->flags |= CM_BUF_ERROR;
+                bp->error = CM_ERROR_BADFD;
+                bp->dirty_offset = 0;
+                bp->dirty_length = 0;
+                bp->dataVersion = -1;  /* known bad */
+                bp->dirtyCounter++;
+                lock_ReleaseMutex(&bp->mx);
+            }
 
             /* actually, we only know that buffer is clean if ref
              * count is 1, since we don't have buffer itself locked.
@@ -1578,7 +1580,7 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
                 lock_ReleaseWrite(&buf_globalLock);
             }
 
-           if (code != CM_ERROR_BADFD)
+           if (code == 0)
                (*cm_buf_opsp->Unstabilizep)(scp, userp);
         }