windows-afsd-dirop-20070830
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 31 Aug 2007 03:55:53 +0000 (03:55 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 31 Aug 2007 03:55:53 +0000 (03:55 +0000)
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
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_dir.h
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb3.c

index 5a8d473..6d8be09 100644 (file)
@@ -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
index 4f42432..01de142 100644 (file)
@@ -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);
 
index 4af06f8..3a337c2 100644 (file)
@@ -182,4 +182,6 @@ cm_DirEntryListFree(cm_dirEntryList_t ** list);
 
 extern void
 cm_DirDumpStats(void);
+
+extern afs_int64 dir_enums;
 #endif /*  __CM_DIR_ENV__ */
index efbf2b3..51bba40 100644 (file)
@@ -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)
index 90d1dc0..3d36254 100644 (file)
@@ -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;
index 981725b..ff8ff13 100644 (file)
@@ -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);