mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 15:30:14 +00:00
Windows: buf_CleanAsync scp->fid == bp->fid
If buf_CleanAsync or buf_CleanAsyncLocked are called with a non-NULL cm_scache_t parameter, that status object's fid must be the same as the associated cm_buf_t object. If not, the wrong locks will be held. If the cm_scache_t parameter is NULL and cm_FindSCache() returns NULL, it means that the cm_scache_t object associated with the bp->fid has been flushed from the cache. cm_GetSCache() must therefore be called to allocate a new status object for the FID. If the status object cannot be allocated, then any dirty data stored in the buffer will be discarded. Change-Id: Ie5d4eb8a1090d4b3c0753b7ddee2de0799485a2e Reviewed-on: http://gerrit.openafs.org/3604 Tested-by: BuildBot <buildbot@rampaginggeek.com> Tested-by: Jeffrey Altman <jaltman@openafs.org> Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
parent
4e32073357
commit
b6576d8cb5
@ -18,7 +18,6 @@
|
||||
#include <windows.h>
|
||||
#include <osi.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <strsafe.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -743,6 +742,9 @@ cm_buf_t *buf_FindAll(struct cm_scache *scp, osi_hyper_t *offsetp, afs_uint32 fl
|
||||
* if this buffer contains logged data.
|
||||
*
|
||||
* Returns non-zero if the buffer was dirty.
|
||||
*
|
||||
* 'scp' may or may not be NULL. If it is not NULL, the FID for both cm_scache_t
|
||||
* and cm_buf_t must match.
|
||||
*/
|
||||
afs_uint32 buf_CleanAsyncLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
|
||||
afs_uint32 flags, afs_uint32 *pisdirty)
|
||||
@ -753,35 +755,54 @@ afs_uint32 buf_CleanAsyncLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
|
||||
int release_scp = 0;
|
||||
|
||||
osi_assertx(bp->magic == CM_BUF_MAGIC, "invalid cm_buf_t magic");
|
||||
osi_assertx(scp == NULL || cm_FidCmp(&scp->fid, &bp->fid) == 0, "scp fid != bp fid");
|
||||
|
||||
if (scp = cm_FindSCache(&bp->fid))
|
||||
release_scp = 1;
|
||||
|
||||
if (!scp) {
|
||||
osi_Log1(buf_logp, "buf_CleanAsyncLocked unable to start I/O - scp not found buf 0x%p", bp);
|
||||
code = CM_ERROR_NOSUCHFILE;
|
||||
/*
|
||||
* If the matching cm_scache_t was not provided as a parameter
|
||||
* we must either find one or allocate a new one. It is possible
|
||||
* that the cm_scache_t was recycled out of the cache even though
|
||||
* a cm_buf_t with the same FID is in the cache.
|
||||
*/
|
||||
if (scp == NULL) {
|
||||
if ((scp = cm_FindSCache(&bp->fid)) ||
|
||||
(cm_GetSCache(&bp->fid, &scp,
|
||||
bp->userp ? bp->userp : cm_rootUserp,
|
||||
reqp) == 0)) {
|
||||
release_scp = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
|
||||
isdirty = 1;
|
||||
lock_ReleaseMutex(&bp->mx);
|
||||
|
||||
osi_Log2(buf_logp, "buf_CleanAsyncLocked starts I/O on scp 0x%p buf 0x%p", scp, bp);
|
||||
if (!scp) {
|
||||
/*
|
||||
* If we didn't find a cm_scache_t object for bp->fid it means
|
||||
* that we no longer have that FID in the cache. It does not
|
||||
* mean that the object does not exist in the cell. That may
|
||||
* in fact be the case but we don't know that until we attempt
|
||||
* a FetchStatus on the FID.
|
||||
*/
|
||||
osi_Log1(buf_logp, "buf_CleanAsyncLocked unable to start I/O - scp not found buf 0x%p", bp);
|
||||
code = CM_ERROR_NOSUCHFILE;
|
||||
} else {
|
||||
osi_Log2(buf_logp, "buf_CleanAsyncLocked starts I/O on scp 0x%p buf 0x%p", scp, bp);
|
||||
|
||||
offset = bp->offset;
|
||||
LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset));
|
||||
code = (*cm_buf_opsp->Writep)(scp, &offset,
|
||||
offset = bp->offset;
|
||||
LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset));
|
||||
code = (*cm_buf_opsp->Writep)(scp, &offset,
|
||||
#if 1
|
||||
/* we might as well try to write all of the contiguous
|
||||
* dirty buffers in one RPC
|
||||
*/
|
||||
cm_chunkSize,
|
||||
/* we might as well try to write all of the contiguous
|
||||
* dirty buffers in one RPC
|
||||
*/
|
||||
cm_chunkSize,
|
||||
#else
|
||||
bp->dirty_length,
|
||||
bp->dirty_length,
|
||||
#endif
|
||||
flags, bp->userp, reqp);
|
||||
osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
|
||||
|
||||
flags, bp->userp, reqp);
|
||||
osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
|
||||
}
|
||||
lock_ObtainMutex(&bp->mx);
|
||||
/* if the Write routine returns No Such File, clear the dirty flag
|
||||
* because we aren't going to be able to write this data to the file
|
||||
@ -1024,7 +1045,10 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
|
||||
* have the WRITING flag set, so we won't get
|
||||
* back here.
|
||||
*/
|
||||
buf_CleanAsync(scp, bp, reqp, 0, NULL);
|
||||
if (cm_FidCmp(&scp->fid, &bp->fid) == 0)
|
||||
buf_CleanAsync(scp, bp, reqp, 0, NULL);
|
||||
else
|
||||
buf_CleanAsync(NULL, bp, reqp, 0, NULL);
|
||||
|
||||
/* now put it back and go around again */
|
||||
buf_Release(bp);
|
||||
|
Loading…
Reference in New Issue
Block a user