replace all DebugBreak() calls with osi_panic.
remove calls to cm_RecycleSCache from VNOVNODE handler as its not
lock safe to drop and re-obtain locks to adhere to the locking
hierarchy
restore reference to CM_SCACHESYNC_STOREDATA that should
not have been removed.
remove attempts to adhere to locking hierarching from cm_GetNewSCache.
dropping the cm_scacheLock is too dangerous
add a check to ensure that the scache refcount is not zero if there
is a valid smb_fid_t pointing to it.
more debug logging
/* first, start by finding out whether we have a directory or something
* else, so we can find what object's ACL we need.
*/
- if (scp->fileType == CM_SCACHETYPE_DIRECTORY || !cm_HaveCallback(scp)) {
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY ) {
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
- if (code)
- return code;
-
- got_cb = 1;
- }
-
- if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ if (!code)
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ } else {
/* not a dir, use parent dir's acl */
tfid.cell = scp->fid.cell;
tfid.volume = scp->fid.volume;
}
osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
- if (!cm_HaveCallback(aclScp)) {
- lock_ObtainMutex(&aclScp->mx);
- code = cm_SyncOp(aclScp, NULL, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (!code) {
-#if 0
- /* cm_GetCallback was called by cm_SyncOp */
- code = cm_GetCallback(aclScp, userp, reqp, 1);
-#endif
- cm_SyncOpDone(aclScp, NULL,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
- }
- lock_ReleaseMutex(&aclScp->mx);
- }
+ lock_ObtainMutex(&aclScp->mx);
+ code = cm_SyncOp(aclScp, NULL, userp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
+ if (!code)
+ cm_SyncOpDone(aclScp, NULL,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseMutex(&aclScp->mx);
cm_ReleaseSCache(aclScp);
lock_ObtainMutex(&scp->mx);
}
-#if 0
- else if (!got_cb) {
- /* cm_GetCallback was called by cm_SyncOp */
- code = cm_GetCallback(scp, userp, reqp, 1);
- }
-#endif
_done:
- if (got_cb)
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-
return code;
}
osi_assert(bp->magic == CM_BUF_MAGIC);
#ifdef DEBUG
if (bp->refCount == 0)
- DebugBreak();
+ osi_panic("buf refcount 0",__FILE__,__LINE__);;
#else
osi_assert(bp->refCount > 0);
#endif
lock_ObtainRead(&buf_globalLock);
for (bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) {
if (bp->magic != CM_BUF_MAGIC)
- DebugBreak();
+ osi_panic("buf magic error",__FILE__,__LINE__);
countb++;
bpb = bp;
}
for (bp = cm_data.buf_freeListp; bp; bp=(cm_buf_t *) osi_QNext(&bp->q)) {
if (bp->magic != CM_BUF_MAGIC)
- DebugBreak();
+ osi_panic("buf magic error",__FILE__,__LINE__);
countf++;
bpf = bp;
}
for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
if (bp->magic != CM_BUF_MAGIC)
- DebugBreak();
+ osi_panic("buf magic error",__FILE__,__LINE__);
counta++;
bpa = bp;
}
lock_ReleaseRead(&buf_globalLock);
if (countb != countf)
- DebugBreak();
+ osi_panic("buf magic error",__FILE__,__LINE__);
if (counta != cm_data.buf_nbuffers)
- DebugBreak();
+ osi_panic("buf magic error",__FILE__,__LINE__);
}
#endif /* TESTING */
if (scp->fileType != CM_SCACHETYPE_DIRECTORY)
pscp = cm_FindSCacheParent(scp);
+
+ lock_ObtainMutex(&scp->mx);
lock_ObtainWrite(&cm_scacheLock);
- cm_RecycleSCache(scp, CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS);
- cm_ReleaseSCacheNoLock(scp);
+ cm_RemoveSCacheFromHashTable(scp);
lock_ReleaseWrite(&cm_scacheLock);
+ scp->flags |= CM_SCACHEFLAG_DELETED;
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseSCache(scp);
if (pscp) {
- if (pscp->cbExpires > 0 && pscp->cbServerp != NULL) {
+ if (cm_HaveCallback(pscp)) {
lock_ObtainMutex(&pscp->mx);
cm_DiscardSCache(pscp);
lock_ReleaseMutex(&pscp->mx);
lock_ObtainMutex(&bufp->mx);
lock_ObtainMutex(&scp->mx);
- flags = CM_SCACHESYNC_GETSTATUS
- | CM_SCACHESYNC_STOREDATA
- | CM_SCACHESYNC_BUFLOCKED;
+ flags = CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_BUFLOCKED;
code = cm_SyncOp(scp, bufp, userp, reqp, 0, flags);
if (code) {
lock_ReleaseMutex(&bufp->mx);
cm_data.scacheLRULastp = scp;
}
-/* called with cm_scacheLock write-locked; recycles an existing scp.
- *
- * this function ignores all of the locking hierarchy.
- */
-long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
+/* call with scache write-locked and mutex held */
+void cm_RemoveSCacheFromHashTable(cm_scache_t *scp)
{
cm_scache_t **lscpp;
cm_scache_t *tscp;
int i;
-
- if (scp->refCount != 0) {
- return -1;
- }
-
+
if (scp->flags & CM_SCACHEFLAG_INHASH) {
/* hash it out first */
i = CM_SCACHE_HASH(&scp->fid);
for (lscpp = &cm_data.hashTablep[i], tscp = cm_data.hashTablep[i];
- tscp;
- lscpp = &tscp->nextp, tscp = tscp->nextp) {
+ tscp;
+ lscpp = &tscp->nextp, tscp = tscp->nextp) {
if (tscp == scp) {
*lscpp = scp->nextp;
scp->flags &= ~CM_SCACHEFLAG_INHASH;
}
}
}
+}
+
+/* called with cm_scacheLock write-locked; recycles an existing scp.
+ *
+ * this function ignores all of the locking hierarchy.
+ */
+long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
+{
+ if (scp->refCount != 0) {
+ return -1;
+ }
+
+ if (scp->flags & CM_SCACHEFLAG_SMB_FID) {
+ osi_Log1(afsd_logp,"cm_RecycleSCache CM_SCACHEFLAG_SMB_FID detected scp 0x%p", scp);
+#ifdef DEBUG
+ osi_panic("cm_RecycleSCache CM_SCACHEFLAG_SMB_FID detected",__FILE__,__LINE__);
+#endif
+ return -1;
+ }
+
+ cm_RemoveSCacheFromHashTable(scp);
#if 0
if (flags & CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS) {
| CM_SCACHEFLAG_RO
| CM_SCACHEFLAG_PURERO
| CM_SCACHEFLAG_OVERQUOTA
- | CM_SCACHEFLAG_OUTOFSPACE);
+ | CM_SCACHEFLAG_OUTOFSPACE
+ | CM_SCACHEFLAG_EACCESS);
scp->serverModTime = 0;
scp->dataVersion = 0;
scp->bulkStatProgress = hzero;
return CM_ERROR_WOULDBLOCK;
}
+#if not_too_dangerous
+ /* dropping the cm_scacheLock is dangerous */
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainMutex(&scp->mx);
lock_ObtainWrite(&cm_scacheLock);
+#endif
scp->fid = *fidp;
scp->volp = cm_data.rootSCachep->volp;
scp->dotdotFid.cell=AFS_FAKE_ROOT_CELL_ID;
scp->group=0;
scp->dataVersion=cm_data.fakeDirVersion;
scp->lockDataVersion=-1; /* no lock yet */
+#if not_too_dangerous
lock_ReleaseMutex(&scp->mx);
- *outScpp = scp;
+#endif
+ *outScpp = scp;
lock_ReleaseWrite(&cm_scacheLock);
return 0;
}
osi_Log2(afsd_logp,"cm_GetNewSCache returns scp 0x%x flags 0x%x", scp, scp->flags);
osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH));
+
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainMutex(&scp->mx);
lock_ObtainWrite(&cm_scacheLock);
/* lookup this first */
bufLocked = flags & CM_SCACHESYNC_BUFLOCKED;
- /* some minor assertions */
- if (flags & (CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_FETCHDATA
- | CM_SCACHESYNC_READ | CM_SCACHESYNC_WRITE
- | CM_SCACHESYNC_SETSIZE)) {
- if (bufp) {
- osi_assert(bufp->refCount > 0);
- /*
- osi_assert(cm_FidCmp(&bufp->fid, &scp->fid) == 0);
- */
- }
- }
- else osi_assert(bufp == NULL);
+ if (bufp)
+ osi_assert(bufp->refCount > 0);
+
/* Do the access check. Now we don't really do the access check
* atomically, since the caller doesn't expect the parent dir to be
(CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
#define CM_SCACHEFLAG_EACCESS 0x200000 /* Bulk Stat returned EACCES */
-#define CM_SCACHEFLAG_RECYCLING 0x400000
+#define CM_SCACHEFLAG_SMB_FID 0x400000
/* sync flags for calls to the server. The CM_SCACHEFLAG_FETCHING,
* CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
+extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
#endif /* __CM_SCACHE_H_ENV__ */
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;
+ }
userp = fidp->userp;
fidp->userp = NULL;
lock_ReleaseMutex(&dsp->mx);
lock_FinalizeMutex(&dsp->mx);
scp = dsp->scp;
+ osi_Log2(afsd_logp,"smb_ReleaseDirSearch dsp 0x%p scp 0x%p", dsp, scp);
free(dsp);
} else {
lock_ReleaseMutex(&dsp->mx);
wlRequest);
scp = wlRequest->scp;
+ osi_Log2(afsd_logp,"smb_WaitingLocksDaemon wlRequest 0x%p scp 0x%p", wlRequest, scp);
cm_InitReq(&req);
lock_ObtainMutex(&dsp->mx);
if (dsp->scp) {
scp = dsp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveCoreSearchDir (1) dsp 0x%p scp 0x%p", dsp, scp);
cm_HoldSCache(scp);
code = 0;
} else {
#endif /* DFS_SUPPORT */
dsp->scp = scp;
+ osi_Log2(afsd_logp,"smb_ReceiveCoreSearchDir (2) dsp 0x%p scp 0x%p", dsp, scp);
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done with this
* function, we'll drop the one for our own processing.
/* save a pointer to the vnode */
fidp->scp = scp;
+ osi_Log2(afsd_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+
/* and the user */
cm_HoldUser(userp);
fidp->userp = userp;
int deleted = 0;
int nullcreator = 0;
- osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
- fidp, fidp->fid, vcp);
+ osi_Log4(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d scp=0x%x vcp=0x%x)",
+ fidp, fidp->fid, scp, vcp);
if (!userp) {
lock_ObtainMutex(&fidp->mx);
free(fidp->NTopen_wholepathp);
fidp->NTopen_wholepathp = NULL;
}
+
fidp->scp = NULL;
lock_ReleaseMutex(&fidp->mx);
scp->flags |= CM_SCACHEFLAG_DELETED;
lock_ReleaseMutex(&scp->mx);
}
+ lock_ObtainMutex(&scp->mx);
+ scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
cm_ReleaseSCache(scp);
}
lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
+ cm_HoldSCache(scp);
lock_ObtainMutex(&scp->mx);
if (offset.HighPart == 0) {
if (code == 0 && sequential)
cm_ConsiderPrefetch(scp, &lastByte, userp, &req);
+ cm_ReleaseSCache(scp);
+
return code;
}
if (created)
fidp->flags |= SMB_FID_CREATED;
+ osi_Log2(afsd_logp,"smb_ReceiveCoreCreate fidp 0x%p scp 0x%p", fidp, scp);
+
/* save a pointer to the vnode */
fidp->scp = scp;
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+
/* and the user */
fidp->userp = userp;
lock_ReleaseMutex(&fidp->mx);
if (fidp->scp != NULL) {
scp = fidp->scp;
fidp->scp = NULL;
+ lock_ObtainMutex(&scp->mx);
+ scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+ osi_Log2(afsd_logp,"smb_Shutdown fidp 0x%p scp 0x%p", fidp, scp);
cm_ReleaseSCache(scp);
}
lock_ReleaseMutex(&fidp->mx);
cm_HoldUser(userp);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
+ osi_Log2(afsd_logp,"smb_ReceiveTran2Open fidp 0x%p scp 0x%p", fidp, scp);
fidp->scp = scp;
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+
/* and the user */
fidp->userp = userp;
lock_ObtainMutex(&fidp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReleaseTran2QFileInfo fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
}
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveTran2SetFileInfo fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&dsp->mx);
if (dsp->scp) {
scp = dsp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveTran2SearchDir dsp 0x%p scp 0x%p", dsp, scp);
cm_HoldSCache(scp);
code = 0;
} else {
}
#endif /* DFS_SUPPORT */
dsp->scp = scp;
+ osi_Log2(afsd_logp,"smb_ReceiveTran2SearchDir dsp 0x%p scp 0x%p", dsp, scp);
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done
* with this function, we'll drop the one for our own
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp;
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+ osi_Log2(afsd_logp,"smb_ReceiveV3OpenX fidp 0x%p scp 0x%p", fidp, scp);
/* also the user */
fidp->userp = userp;
return CM_ERROR_BADFD;
}
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveV3LockingX fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
wlRequest->vcp = vcp;
smb_HoldVC(vcp);
wlRequest->scp = scp;
+ osi_Log2(afsd_logp,"smb_ReceiveV3LockingX wlRequest 0x%p scp 0x%p", wlRequest, scp);
cm_HoldSCache(scp);
wlRequest->inp = smb_CopyPacket(inp);
wlRequest->outp = smb_CopyPacket(outp);
return CM_ERROR_BADFD;
}
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveV3GetAttributes fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
return CM_ERROR_BADFD;
}
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveV3SetAttributes fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp; /* Hold transfered to fidp->scp and no longer needed */
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+ osi_Log2(afsd_logp,"smb_ReceiveNTCreateX fidp 0x%p scp 0x%p", fidp, scp);
fidp->flags = fidflags;
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;
fidp->NTopen_dscp = dscp;
+ osi_Log2(afsd_logp,"smb_ReceiveNTCreateX fidp 0x%p dscp 0x%p", fidp, dscp);
cm_HoldSCache(dscp);
fidp->NTopen_pathp = strdup(lastNamep);
}
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp;
+ lock_ObtainMutex(&scp->mx);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseMutex(&scp->mx);
+ osi_Log2(afsd_logp,"smb_ReceiveNTTranCreate fidp 0x%p scp 0x%p", fidp, scp);
fidp->flags = fidflags;
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;
fidp->NTopen_dscp = dscp;
+ osi_Log2(afsd_logp,"smb_ReceiveNTTranCreate fidp 0x%p dscp 0x%p", fidp, dscp);
cm_HoldSCache(dscp);
fidp->NTopen_pathp = strdup(lastNamep);
}
filter, fid, watchtree, osi_LogSaveString(smb_logp, fidp->NTopen_wholepathp));
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveNTTranNotifyChange fidp 0x%p scp 0x%p", fidp, scp);
lock_ObtainMutex(&scp->mx);
if (watchtree)
scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
osi_LogSaveString(smb_logp, (fidp)?fidp->NTopen_wholepathp:""));
scp = fidp->scp;
+ osi_Log2(afsd_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
lock_ObtainMutex(&scp->mx);
if (watchtree)
scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;