]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-afsd-dirop-20070830
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 31 Aug 2007 03:56:59 +0000 (03:56 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 31 Aug 2007 03:56:59 +0000 (03:56 +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.

(cherry picked from commit 084ade0a987589593e2066394f35ebd98ee2137f)

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 608788bd53dc63db41e05345e280eb79eaf1bb04..f2b38a84041c2833b18e9f7dae507fadd5fbc2d4 100644 (file)
@@ -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
index 4b71b568d6804b9083a078391fc71c8ce5f62959..cb7fd4aa7739549a8419dcd8631dce1ad173ea70 100644 (file)
@@ -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);
 
index 4af06f8d951dfe1a2271e1683adad8f1da3c077f..3a337c2ef7c9b2bbac6a740b3b2be39f3ae8fb83 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 835e0753314659dd34982d85af300c736882d06a..553849af244b6abb69fdc619fdd478560d40efd5 100644 (file)
@@ -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)
index 121388f2ad1de93551255d73309af18811cbff5a..a09ac2f45eae0c63cf47fa97cf1eeb717db95b97 100644 (file)
@@ -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;
index eba779addb45dbb76bee3755d18054b7a52aea44..6bea94b15d6ecdfb595f083656cbc0bd78caf56a 100644 (file)
@@ -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);