DEVEL15-windows-smb_fid_t-deadlock-20061022

smb_ReleaseFID cannot be called while a cm_scache_t->mx is held

shuffle the order of the smb_ReleaseFID calls so they are always after
cm_XXXRelease calls for performance.


(cherry picked from commit c484781531ce29d3d1b5c3753322be4a87dd0841)
This commit is contained in:
Jeffrey Altman 2006-10-22 13:25:38 +00:00
parent 7f2c4c5cac
commit 12d5ed1afe
2 changed files with 27 additions and 28 deletions

View File

@ -1547,6 +1547,9 @@ void smb_HoldFIDNoLock(smb_fid_t *fidp)
fidp->refCount++;
}
/* smb_ReleaseFID cannot be called while an cm_scache_t mutex lock is held */
/* the sm_fid_t->mx and smb_rctLock must not be held */
void smb_ReleaseFID(smb_fid_t *fidp)
{
cm_scache_t *scp = NULL;
@ -1561,13 +1564,13 @@ void smb_ReleaseFID(smb_fid_t *fidp)
vcp = fidp->vcp;
fidp->vcp = NULL;
scp = fidp->scp; /* release after lock is released */
if (scp) {
lock_ObtainMutex(&scp->mx);
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
lock_ReleaseMutex(&scp->mx);
osi_Log2(afsd_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
fidp->scp = NULL;
}
if (scp) {
lock_ObtainMutex(&scp->mx);
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
lock_ReleaseMutex(&scp->mx);
osi_Log2(afsd_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
fidp->scp = NULL;
}
userp = fidp->userp;
fidp->userp = NULL;

View File

@ -2654,6 +2654,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
cm_user_t *userp;
cm_space_t *spacep;
cm_scache_t *scp, *dscp;
int scp_mx_held = 0;
int delonclose = 0;
long code = 0;
char *pathp;
@ -2814,6 +2815,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
#endif /* DFS_SUPPORT */
lock_ObtainMutex(&scp->mx);
scp_mx_held = 1;
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code) goto done;
@ -2879,8 +2881,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
if (fidp) {
lock_ReleaseMutex(&scp->mx);
scp_mx_held = 0;
lock_ObtainMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
@ -2923,7 +2925,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
/* send and free the packets */
done:
lock_ReleaseMutex(&scp->mx);
if (scp_mx_held)
lock_ReleaseMutex(&scp->mx);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (code == 0) {
@ -3064,8 +3067,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
fidp = smb_FindFIDByScache(vcp, scp);
if (!fidp) {
cm_ReleaseUser(userp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, code);
return 0;
}
@ -3073,9 +3076,9 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
lock_ObtainMutex(&fidp->mx);
if (!(fidp->flags & SMB_FID_OPENWRITE)) {
lock_ReleaseMutex(&fidp->mx);
cm_ReleaseSCache(scp);
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
cm_ReleaseSCache(scp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
return 0;
}
@ -5737,8 +5740,8 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_SetSMBDataLength(outp, 0);
done:
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
return code;
}
@ -5860,9 +5863,8 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_SetSMBParm(outp, 5, finalCount);
smb_SetSMBDataLength(outp, finalCount);
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
return code;
}
@ -6213,9 +6215,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
treeStartp = realPathp + (tp - spacep->data);
if (*tp && !smb_IsLegalFilename(tp)) {
cm_ReleaseUser(userp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
cm_ReleaseUser(userp);
free(realPathp);
if (scp)
cm_ReleaseSCache(scp);
@ -6580,16 +6582,14 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
lock_ReleaseMutex(&scp->mx);
if (code) {
/* shouldn't this be smb_CloseFID() fidp->flags = SMB_FID_DELETE; */
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
cm_ReleaseSCache(scp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
/* shouldn't this be smb_CloseFID() fidp->flags = SMB_FID_DELETE; */
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
free(realPathp);
return code;
}
}
@ -6657,9 +6657,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid,
osi_LogSaveString(smb_logp, realPathp));
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
/* Can't free realPathp if we get here since
fidp->NTopen_wholepathp is pointing there */
@ -7200,14 +7199,12 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
lock_ReleaseMutex(&scp->mx);
if (code) {
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
/* Shouldn't this be smb_CloseFID()? fidp->flags = SMB_FID_DELETE; */
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_SHARING_VIOLATION;
}
}
@ -7354,9 +7351,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
/* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
/* leave scp held since we put it in fidp->scp */