DEVEL15-windows-buf-deadlock-20080228

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)
This commit is contained in:
Jeffrey Altman 2008-02-28 18:22:58 +00:00
parent a709dbf9ef
commit 7e6a650ce5

View 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);
}