From 4e39cbc91734d3e552bdfaceede6aa09141a74ee Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 31 Aug 2007 03:56:59 +0000 Subject: [PATCH] DEVEL15-windows-afsd-dirop-20070830 Do not attempt to obtain a write lock on a directory if we already know that we aren't going to perform any local directory updates. Add the CM_ERROR_BPLUS_NOMATCH error which has the same meaning as CM_ERROR_NOSUCHFILE except that it indicates that we came to that conclusion as the result of a bplus search. This provides us the ability to short circuit additional directory searches since we know the answer is final. (cherry picked from commit 084ade0a987589593e2066394f35ebd98ee2137f) --- src/WINNT/afsd/cm.h | 1 + src/WINNT/afsd/cm_dir.c | 5 ++- src/WINNT/afsd/cm_dir.h | 2 ++ src/WINNT/afsd/cm_vnodeops.c | 68 ++++++++++++++++++++++++------------ src/WINNT/afsd/smb.c | 18 ++++++---- src/WINNT/afsd/smb3.c | 25 +++++++------ 6 files changed, 80 insertions(+), 39 deletions(-) diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index 608788bd5..f2b38a840 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -302,6 +302,7 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_BAD_LEVEL (CM_ERROR_BASE+52) #define CM_ERROR_NOT_A_DFSLINK (CM_ERROR_BASE+53) #define CM_ERROR_INEXACT_MATCH (CM_ERROR_BASE+54) +#define CM_ERROR_BPLUS_NOMATCH (CM_ERROR_BASE+55) /* Used by cm_FollowMountPoint and cm_GetVolumeByName */ #define RWVOL 0 diff --git a/src/WINNT/afsd/cm_dir.c b/src/WINNT/afsd/cm_dir.c index 4b71b568d..cb7fd4aa7 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -34,12 +34,15 @@ afs_uint64 dir_lookup_time = 0; afs_uint64 dir_create_time = 0; afs_uint64 dir_remove_time = 0; -afs_int32 cm_BPlusTrees = 0; +afs_uint64 dir_enums = 0; + +afs_int32 cm_BPlusTrees = 1; void cm_DirDumpStats(void) { afsi_log("Dir Lookup Hits: %-8d", dir_lookup_hits); afsi_log(" Misses: %-8d", dir_lookup_misses); + afsi_log(" Enums: %-8d", dir_enums); afsi_log(" Create: %-8d", dir_create_entry); afsi_log(" Remove: %-8d", dir_remove_entry); diff --git a/src/WINNT/afsd/cm_dir.h b/src/WINNT/afsd/cm_dir.h index 4af06f8d9..3a337c2ef 100644 --- a/src/WINNT/afsd/cm_dir.h +++ b/src/WINNT/afsd/cm_dir.h @@ -182,4 +182,6 @@ cm_DirEntryListFree(cm_dirEntryList_t ** list); extern void cm_DirDumpStats(void); + +extern afs_int64 dir_enums; #endif /* __CM_DIR_ENV__ */ diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 835e07533..553849af2 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -666,7 +666,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp, return 0; } - return CM_ERROR_NOSUCHFILE; + return CM_ERROR_BPLUS_NOMATCH; } #endif } @@ -1224,7 +1224,7 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us goto haveFid; } - return CM_ERROR_NOSUCHFILE; + return CM_ERROR_BPLUS_NOMATCH; } #endif } @@ -1621,8 +1621,10 @@ long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp) else osi_Log0(afsd_logp, "CALL RemoveFile SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_dnlcRemove(dscp, namep); cm_SyncOpDone(dscp, NULL, sflags); @@ -1930,7 +1932,9 @@ long cm_NameI(cm_scache_t *rootSCachep, char *pathp, long flags, cm_ReleaseSCache(dirScp); if (psp) cm_FreeSpace(psp); - if (code == CM_ERROR_NOSUCHFILE && tscp->fileType == CM_SCACHETYPE_SYMLINK) { + if ((code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) && + tscp->fileType == CM_SCACHETYPE_SYMLINK) + { osi_Log0(afsd_logp,"cm_NameI code CM_ERROR_NOSUCHPATH"); return CM_ERROR_NOSUCHPATH; } else { @@ -2136,7 +2140,7 @@ long cm_EvaluateSymLink(cm_scache_t *dscp, cm_scache_t *linkScp, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW | CM_FLAG_DIRSEARCH, userp, NULL, reqp, outScpp); - if (code == CM_ERROR_NOSUCHFILE) + if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) code = CM_ERROR_NOSUCHPATH; /* this stuff is allocated no matter what happened on the namei call, @@ -2688,8 +2692,10 @@ long cm_Create(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp, else osi_Log0(afsd_logp, "CALL CreateFile SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) { @@ -2836,8 +2842,10 @@ long cm_MakeDir(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp, else osi_Log0(afsd_logp, "CALL MakeDir SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) { @@ -2944,12 +2952,18 @@ long cm_Link(cm_scache_t *dscp, char *namep, cm_scache_t *sscp, long flags, else osi_Log0(afsd_logp, "CALL Link SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) { cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0); + } + lock_ReleaseMutex(&dscp->mx); + + if (code == 0) { if (cm_CheckDirOpForSingleChange(&dirop)) { cm_DirCreateEntry(&dirop, namep, &sscp->fid); #ifdef USE_BPLUS @@ -2958,7 +2972,6 @@ long cm_Link(cm_scache_t *dscp, char *namep, cm_scache_t *sscp, long flags, } } cm_EndDirOp(&dirop); - lock_ReleaseMutex(&dscp->mx); return code; } @@ -3021,12 +3034,18 @@ long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags, else osi_Log0(afsd_logp, "CALL Symlink SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) { cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0); + } + lock_ReleaseMutex(&dscp->mx); + + if (code == 0) { if (cm_CheckDirOpForSingleChange(&dirop)) { newFid.cell = dscp->fid.cell; newFid.volume = dscp->fid.volume; @@ -3040,7 +3059,6 @@ long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags, } } cm_EndDirOp(&dirop); - lock_ReleaseMutex(&dscp->mx); /* now try to create the new dir's entry, too, but be careful to * make sure that we don't merge in old info. Since we weren't locking @@ -3119,8 +3137,10 @@ long cm_RemoveDir(cm_scache_t *dscp, char *namep, cm_user_t *userp, else osi_Log0(afsd_logp, "CALL RemoveDir SUCCESS"); - lock_ObtainWrite(&dscp->dirlock); - dirop.lockType = CM_DIRLOCK_WRITE; + if (dirop.scp) { + lock_ObtainWrite(&dirop.scp->dirlock); + dirop.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&dscp->mx); cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) { @@ -3311,8 +3331,10 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp, osi_Log0(afsd_logp, "CALL Rename SUCCESS"); /* update the individual stat cache entries for the directories */ - lock_ObtainWrite(&oldDscp->dirlock); - oldDirOp.lockType = CM_DIRLOCK_WRITE; + if (oldDirOp.scp) { + lock_ObtainWrite(&oldDirOp.scp->dirlock); + oldDirOp.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&oldDscp->mx); cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_STOREDATA); @@ -3353,8 +3375,10 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp, /* and update it for the new one, too, if necessary */ if (!oneDir) { - lock_ObtainWrite(&newDscp->dirlock); - newDirOp.lockType = CM_DIRLOCK_WRITE; + if (newDirOp.scp) { + lock_ObtainWrite(&newDirOp.scp->dirlock); + newDirOp.lockType = CM_DIRLOCK_WRITE; + } lock_ObtainMutex(&newDscp->mx); cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_STOREDATA); if (code == 0) diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 121388f2a..a09ac2f45 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -2744,7 +2744,8 @@ void smb_MapNTError(long code, unsigned long *NTStatusp) else if (code == CM_ERROR_READONLY) { NTStatus = 0xC00000A2L; /* Write protected */ } - else if (code == CM_ERROR_NOSUCHFILE) { + else if (code == CM_ERROR_NOSUCHFILE || + code == CM_ERROR_BPLUS_NOMATCH) { NTStatus = 0xC000000FL; /* No such file */ } else if (code == CM_ERROR_NOSUCHPATH) { @@ -2918,7 +2919,8 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep, class = 3; error = 19; /* read only */ } - else if (code == CM_ERROR_NOSUCHFILE) { + else if (code == CM_ERROR_NOSUCHFILE || + code == CM_ERROR_BPLUS_NOMATCH) { class = 1; error = 2; /* ENOENT! */ } @@ -5503,7 +5505,9 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i /* Check if the file already exists; if so return error */ code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp); - if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) { + if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) && + (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) + { osi_Log2(smb_logp, " lookup returns %ld for [%s]", code, osi_LogSaveString(smb_logp, newLastNamep)); @@ -5701,7 +5705,9 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) /* Check if the file already exists; if so return error */ code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp); - if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) { + if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) && + (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) + { osi_Log2(smb_logp, " lookup returns %ld for [%s]", code, osi_LogSaveString(smb_logp, newLastNamep)); @@ -7227,7 +7233,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp lastNamep++; code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp); if (scp) cm_ReleaseSCache(scp); - if (code != CM_ERROR_NOSUCHFILE) { + if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { if (code == 0) code = CM_ERROR_EXISTS; cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); @@ -7364,7 +7370,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #endif code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp); - if (code && code != CM_ERROR_NOSUCHFILE) { + if (code && code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); return code; diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index eba779add..6bea94b15 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -2219,7 +2219,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) lastNamep++; code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp, &req, &scp); - if (code && code != CM_ERROR_NOSUCHFILE) { + if (code && code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); smb_FreeTran2Packet(outp); @@ -4385,7 +4385,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op /* if a case sensitive match failed, we try a case insensitive one next. */ - if (code == CM_ERROR_NOSUCHFILE) { + if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) { code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE | CM_FLAG_CASEFOLD, userp, &req, &targetscp); } @@ -4400,7 +4400,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op smb_ReceiveTran2SearchDir(). */ cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if (code != CM_ERROR_NOSUCHFILE) { + if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { smb_SendTran2Error(vcp, p, opx, code); code = 0; } @@ -4593,7 +4593,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op osi_Log0(smb_logp, "T2SDSingle done."); - if (code != CM_ERROR_NOSUCHFILE) { + if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { if (code) smb_SendTran2Error(vcp, p, opx, code); else @@ -4695,10 +4695,15 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t /* we only failover if we see a CM_ERROR_NOSUCHFILE */ if (code != CM_ERROR_NOSUCHFILE) { +#ifdef USE_BPLUS + if (code == CM_ERROR_BPLUS_NOMATCH) + code = CM_ERROR_NOSUCHFILE; +#endif return code; } } #endif + dir_enums++; dsp = smb_NewDirSearch(1); dsp->attribute = attribute; @@ -5526,7 +5531,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) lastNamep++; code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp, &req, &scp); - if (code && code != CM_ERROR_NOSUCHFILE) { + if (code && code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); return code; @@ -6646,7 +6651,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #endif /* DFS_SUPPORT */ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW, userp, &req, &scp); - if (code == CM_ERROR_NOSUCHFILE) { + if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) { code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); if (code == 0 && realDirFlag == 1) { @@ -6792,7 +6797,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); } - if (code && code != CM_ERROR_NOSUCHFILE) { + if (code && (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH)) { if (dscp) cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); @@ -6953,7 +6958,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * it will appear as a directory name of the nul-string * and a code of CM_ERROR_NOSUCHFILE */ - if ( !*treeStartp && code == CM_ERROR_NOSUCHFILE) + if ( !*treeStartp && (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)) code = CM_ERROR_EXISTS; setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; @@ -7426,7 +7431,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out #endif /* DFS_SUPPORT */ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW, userp, &req, &scp); - if (code == CM_ERROR_NOSUCHFILE) { + if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) { code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); if (code == 0 && realDirFlag == 1) { @@ -7512,7 +7517,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); } - if (code && code != CM_ERROR_NOSUCHFILE) { + if (code && code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); -- 2.39.5