diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index e40332355b..2994f91968 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -2804,10 +2804,16 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a return code; } -long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) +/* + * locked if TRUE means write-locked + * else the cm_scache_t rw must not be held + */ +long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked) { long code; + if (locked) + lock_ReleaseWrite(&scp->rw); code = buf_CleanVnode(scp, userp, reqp); if (code == 0) { lock_ObtainWrite(&scp->rw); @@ -2822,7 +2828,10 @@ long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) scp->flags &= ~(CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE); } - lock_ReleaseWrite(&scp->rw); + if (!locked) + lock_ReleaseWrite(&scp->rw); + } else if (locked) { + lock_ObtainWrite(&scp->rw); } return code; } @@ -4847,10 +4856,12 @@ long cm_UnlockByKey(cm_scache_t * scp, if (scp->serverLock == LockWrite && scp->exclusiveLocks == 0 && scp->sharedLocks > 0) { - /* The serverLock should be downgraded to LockRead */ osi_Log0(afsd_logp, " DOWNGRADE lock from LockWrite to LockRead"); + /* Make sure there are no dirty buffers left. */ + code = cm_FSync(scp, userp, reqp, TRUE); + /* since scp->serverLock looked sane, we are going to assume that we have a valid server lock. */ scp->lockDataVersion = scp->dataVersion; @@ -4902,6 +4913,11 @@ long cm_UnlockByKey(cm_scache_t * scp, scp->sharedLocks == 0) { /* The serverLock should be released entirely */ + if (scp->serverLock == LockWrite) { + /* Make sure there are no dirty buffers left. */ + code = cm_FSync(scp, userp, reqp, TRUE); + } + code = cm_IntReleaseLock(scp, userp, reqp); if (code == 0) @@ -5052,6 +5068,9 @@ long cm_Unlock(cm_scache_t *scp, /* The serverLock should be downgraded to LockRead */ osi_Log0(afsd_logp, " DOWNGRADE lock from LockWrite to LockRead"); + /* Make sure there are no dirty buffers left. */ + code = cm_FSync(scp, userp, reqp, TRUE); + /* Since we already had a lock, we assume that there is a valid server lock. */ scp->lockDataVersion = scp->dataVersion; @@ -5116,6 +5135,11 @@ long cm_Unlock(cm_scache_t *scp, scp->sharedLocks == 0) { /* The serverLock should be released entirely */ + if (scp->serverLock == LockWrite) { + /* Make sure there are no dirty buffers left. */ + code = cm_FSync(scp, userp, reqp, TRUE); + } + code = cm_IntReleaseLock(scp, userp, reqp); if (code == 0) { diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index 0c3a8a4029..da22ded6b2 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -110,7 +110,7 @@ extern long cm_Create(cm_scache_t *scp, clientchar_t *namep, long flags, cm_attr_t *attrp, cm_scache_t **scpp, cm_user_t *userp, cm_req_t *reqp); -extern long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp); +extern long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked); extern void cm_StatusFromAttr(struct AFSStoreStatus *statusp, struct cm_scache *scp, struct cm_attr *attrp); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 154964dd2f..8a86680365 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -6686,7 +6686,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) cm_scache_t * scp = fidp->scp; cm_HoldSCache(scp); lock_ReleaseMutex(&fidp->mx); - code = cm_FSync(scp, userp, &req); + code = cm_FSync(scp, userp, &req, FALSE); cm_ReleaseSCache(scp); } else { lock_ReleaseMutex(&fidp->mx); @@ -6834,7 +6834,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp, } if (smb_AsyncStore != 2) { lock_ReleaseMutex(&fidp->mx); - code = cm_FSync(scp, userp, &req); + code = cm_FSync(scp, userp, &req, FALSE); lock_ObtainMutex(&fidp->mx); } }