#include <windows.h>
#include <osi.h>
#include <stdio.h>
-#include <assert.h>
#include <strsafe.h>
#include <math.h>
* 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)
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
* 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);