From 49329541a13cdee3361d0246256a27d2a5ee8bef Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 25 Jan 2013 02:21:27 -0500 Subject: [PATCH] Windows: Add flag BUF_GET_FLAG_BUFCREATE_LOCKED Modify the buf_Get() and buf_GetNewLocked() interfaces to permit the cm_scache.bufCreateLocked lock to be held prior to calling to buf_Get(). Holding the cm_scache.bufCreateLocked lock before the buf_Get() call prevents a race with another thread that attempts to set the file size. Change-Id: I54b13c83801a4d9a2078552d5be7ada6f4607850 Reviewed-on: http://gerrit.openafs.org/9209 Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- src/WINNT/afsd/cm_buf.c | 32 +++++++++++++++++++---------- src/WINNT/afsd/cm_buf.h | 6 ++++-- src/WINNT/afsd/cm_dcache.c | 4 ++-- src/WINNT/afsd/cm_dir.c | 4 ++-- src/WINNT/afsd/cm_vnodeops.c | 4 ++-- src/WINNT/afsd/rawops.c | 4 ++-- src/WINNT/afsd/smb.c | 6 +++--- src/WINNT/afsd/smb3.c | 2 +- src/WINNT/afsrdr/user/RDRFunction.c | 4 ++-- 9 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index bea66082d..0a5a3d241 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -1258,12 +1258,14 @@ buf_ExistsLocked(struct cm_scache *scp, osi_hyper_t *offsetp) * space from the buffer pool. In that case, the buffer will be returned * without being hashed into the hash table. */ -long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf_t **bufpp) +long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, + afs_uint32 flags, cm_buf_t **bufpp) { cm_buf_t *bp; /* buffer we're dealing with */ cm_buf_t *nextBp; /* next buffer in file hash chain */ afs_uint32 i; /* temp */ afs_uint64 n_bufs, n_nonzero, n_busy, n_dirty, n_own, n_redir; + int bufCreateLocked = !!(flags & BUF_GET_FLAG_BUFCREATE_LOCKED); #ifdef TESTING buf_ValidateBufQueues(); @@ -1278,12 +1280,14 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req n_dirty = 0; n_redir = 0; - lock_ObtainRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ObtainRead(&scp->bufCreateLock); lock_ObtainWrite(&buf_globalLock); /* check to see if we lost the race */ if (buf_ExistsLocked(scp, offsetp)) { lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); return CM_BUF_EXISTS; } @@ -1291,7 +1295,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req if (!cm_data.buf_freeListEndp) { lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); if ( RDR_Initialized ) goto rdr_release; @@ -1375,7 +1380,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req */ buf_HoldLocked(bp); lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); /* * grab required lock and clean. @@ -1395,7 +1401,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req /* but first obtain the locks we gave up * before the buf_CleanAsync() call */ - lock_ObtainRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ObtainRead(&scp->bufCreateLock); lock_ObtainWrite(&buf_globalLock); /* @@ -1404,7 +1411,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req */ if (buf_ExistsLocked(scp, offsetp)) { lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); return CM_BUF_EXISTS; } @@ -1488,7 +1496,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req buf_IncrementUsedCount(); lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); *bufpp = bp; @@ -1498,7 +1507,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req return 0; } /* for all buffers in lru queue */ lock_ReleaseWrite(&buf_globalLock); - lock_ReleaseRead(&scp->bufCreateLock); + if (!bufCreateLocked) + lock_ReleaseRead(&scp->bufCreateLock); osi_Log2(afsd_logp, "buf_GetNewLocked: Free Buffer List has %u buffers none free; redir %u", n_bufs, n_redir); osi_Log4(afsd_logp, "... nonzero %u; own %u; busy %u; dirty %u", n_nonzero, n_own, n_busy, n_dirty); @@ -1527,7 +1537,7 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req * * The scp must be unlocked when passed in unlocked. */ -long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf_t **bufpp) +long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, afs_uint32 flags, cm_buf_t **bufpp) { cm_buf_t *bp; long code; @@ -1561,7 +1571,7 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf } /* otherwise, we have to create a page */ - code = buf_GetNewLocked(scp, &pageOffset, reqp, &bp); + code = buf_GetNewLocked(scp, &pageOffset, reqp, flags, &bp); switch (code) { case 0: /* the requested buffer was created */ diff --git a/src/WINNT/afsd/cm_buf.h b/src/WINNT/afsd/cm_buf.h index 1243c2280..a316cb10c 100644 --- a/src/WINNT/afsd/cm_buf.h +++ b/src/WINNT/afsd/cm_buf.h @@ -170,9 +170,11 @@ extern cm_buf_t *buf_FindAllLocked(struct cm_fid *, osi_hyper_t *, afs_uint32 fl extern cm_buf_t *buf_FindAll(struct cm_fid *, osi_hyper_t *, afs_uint32 flags); -extern long buf_GetNewLocked(struct cm_scache *, osi_hyper_t *, cm_req_t *, cm_buf_t **); +extern long buf_GetNewLocked(struct cm_scache *, osi_hyper_t *, cm_req_t *, afs_uint32, cm_buf_t **); -extern long buf_Get(struct cm_scache *, osi_hyper_t *, cm_req_t *, cm_buf_t **); +extern long buf_Get(struct cm_scache *, osi_hyper_t *, cm_req_t *, afs_uint32, cm_buf_t **); + +#define BUF_GET_FLAG_BUFCREATE_LOCKED 1 extern afs_uint32 buf_CleanLocked(cm_scache_t *, cm_buf_t *, cm_req_t *, afs_uint32 flags, afs_uint32 *); diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index 873e79292..aff45e5f0 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -879,7 +879,7 @@ cm_BkgPrefetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp) rxheld = 0; } - code = buf_Get(scp, &offset, reqp, &bp); + code = buf_Get(scp, &offset, reqp, 0, &bp); if (code) break; @@ -1324,7 +1324,7 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp, if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize)) break; - code = buf_Get(scp, &pageBase, reqp, &tbp); + code = buf_Get(scp, &pageBase, reqp, 0, &tbp); if (code) { lock_ObtainWrite(&scp->rw); cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); diff --git a/src/WINNT/afsd/cm_dir.c b/src/WINNT/afsd/cm_dir.c index 534b85ffb..7430bd4d2 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -1538,7 +1538,7 @@ cm_DirPrefetchBuffers(cm_dirOp_t * op) offset.HighPart, offset.LowPart); lock_ReleaseWrite(&op->scp->rw); - code = buf_Get(op->scp, &offset, &op->req, &bufferp); + code = buf_Get(op->scp, &offset, &op->req, 0, &bufferp); lock_ObtainWrite(&op->scp->rw); @@ -1685,7 +1685,7 @@ cm_DirGetPage(cm_dirOp_t * op, goto _has_buffer; } - code = buf_Get(op->scp, &bufferOffset, &op->req, &bufferp); + code = buf_Get(op->scp, &bufferOffset, &op->req, 0, &bufferp); if (code) { osi_Log1(afsd_logp, " buf_Get returned code 0x%x", code); bufferp = NULL; diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 84446ee8b..512289483 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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; @@ -603,7 +603,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; diff --git a/src/WINNT/afsd/rawops.c b/src/WINNT/afsd/rawops.c index 14f672eb7..882082eca 100644 --- a/src/WINNT/afsd/rawops.c +++ b/src/WINNT/afsd/rawops.c @@ -80,7 +80,7 @@ raw_ReadData( cm_scache_t *scp, osi_hyper_t *offsetp, } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, reqp, &bufp); + code = buf_Get(scp, &thyper, reqp, 0, &bufp); lock_ObtainWrite(&scp->rw); if (code) goto done; @@ -211,7 +211,7 @@ raw_WriteData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char * } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, reqp, &bufp); + code = buf_Get(scp, &thyper, reqp, 0, &bufp); if (bufp) lock_ObtainMutex(&bufp->mx); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 31a49a863..651f8ac35 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -5124,7 +5124,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou bufferp = NULL; } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, &req, &bufferp); + code = buf_Get(scp, &thyper, &req, 0, &bufferp); lock_ObtainMutex(&dsp->mx); /* now, if we're doing a star match, do bulk fetching of all of @@ -7249,7 +7249,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, &req, &bufferp); + code = buf_Get(scp, &thyper, &req, 0, &bufferp); lock_ObtainWrite(&scp->rw); if (code) goto done; @@ -7439,7 +7439,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, &req, &bufferp); + code = buf_Get(scp, &thyper, &req, 0, &bufferp); lock_ObtainMutex(&bufferp->mx); lock_ObtainWrite(&scp->rw); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index d8a956b7a..290b1e715 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -5903,7 +5903,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t bufferp = NULL; } lock_ReleaseWrite(&scp->rw); - code = buf_Get(scp, &thyper, &req, &bufferp); + code = buf_Get(scp, &thyper, &req, 0, &bufferp); lock_ObtainWrite(&scp->rw); if (code) { osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code); diff --git a/src/WINNT/afsrdr/user/RDRFunction.c b/src/WINNT/afsrdr/user/RDRFunction.c index 36894c196..fcc26af88 100644 --- a/src/WINNT/afsrdr/user/RDRFunction.c +++ b/src/WINNT/afsrdr/user/RDRFunction.c @@ -3420,7 +3420,7 @@ RDR_BkgFetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp) rwheld = 0; } - code = buf_Get(scp, &offset, reqp, &bufp); + code = buf_Get(scp, &offset, reqp, 0, &bufp); if (code) { /* * any error from buf_Get() is non-fatal. @@ -3657,7 +3657,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp, QueueLength = 0; thyper.QuadPart = ByteOffset.QuadPart; - code = buf_Get(scp, &thyper, &req, &bufp); + code = buf_Get(scp, &thyper, &req, 0, &bufp); if (code == 0) { lock_ObtainMutex(&bufp->mx); bBufRelease = TRUE; -- 2.39.5