From 084ade0a987589593e2066394f35ebd98ee2137f Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 31 Aug 2007 03:55:53 +0000 Subject: [PATCH] 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. --- 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 5a8d47342..6d8be092d 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -298,6 +298,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 4f4243252..01de1426c 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -32,12 +32,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 efbf2b3c6..51bba40c8 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -664,7 +664,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 } @@ -1222,7 +1222,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 } @@ -1619,8 +1619,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); @@ -1928,7 +1930,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 { @@ -2134,7 +2138,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, @@ -2686,8 +2690,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) { @@ -2834,8 +2840,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) { @@ -2942,12 +2950,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 @@ -2956,7 +2970,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; } @@ -3019,12 +3032,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; @@ -3038,7 +3057,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 @@ -3117,8 +3135,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) { @@ -3309,8 +3329,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); @@ -3351,8 +3373,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 90d1dc096..3d36254bd 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -2498,7 +2498,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) { @@ -2672,7 +2673,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! */ } @@ -5223,7 +5225,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)); @@ -5421,7 +5425,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)); @@ -6890,7 +6896,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); @@ -7027,7 +7033,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 981725bb7..ff8ff13f9 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -2213,7 +2213,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); @@ -4379,7 +4379,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); } @@ -4394,7 +4394,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; } @@ -4587,7 +4587,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 @@ -4689,10 +4689,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; @@ -5520,7 +5525,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; @@ -6632,7 +6637,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) { @@ -6778,7 +6783,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); @@ -6939,7 +6944,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; @@ -7412,7 +7417,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) { @@ -7498,7 +7503,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