windows-afs-execute-only-20080309
[openafs.git] / src / WINNT / afsd / smb3.c
index 6aa394b..27c6e1a 100644 (file)
@@ -2415,9 +2415,9 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     /* save a pointer to the vnode */
     osi_Log2(smb_logp,"smb_ReceiveTran2Open fidp 0x%p scp 0x%p", fidp, scp);
     fidp->scp = scp;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     
     /* and the user */
     fidp->userp = userp;
@@ -2441,7 +2441,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     /* copy out remainder of the parms */
     parmSlot = 0;
     outp->parmsp[parmSlot++] = fidp->fid;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainRead(&scp->rw);
     if (extraInfo) {
         outp->parmsp[parmSlot++] = smb_Attributes(scp);
         smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
@@ -2463,7 +2463,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         outp->parmsp[parmSlot++] = 0; 
         outp->parmsp[parmSlot++] = 0; 
     }   
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseRead(&scp->rw);
     outp->totalData = 0;               /* total # of data bytes */
     outp->totalParms = parmSlot * 2;   /* shorts are two bytes */
 
@@ -2857,7 +2857,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
 #endif /* DFS_SUPPORT */
 
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp_mx_held = 1;
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -2865,6 +2865,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         
+    lock_ConvertWToR(&scp->rw);
+
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
      */
@@ -2923,7 +2925,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         qpi.u.QPfileStandardInfo.reserved = 0;
 
        if (fidp) {
-           lock_ReleaseMutex(&scp->mx);
+           lock_ReleaseRead(&scp->rw);
            scp_mx_held = 0;
            lock_ObtainMutex(&fidp->mx);
            delonclose = fidp->flags & SMB_FID_DELONCLOSE;
@@ -2969,7 +2971,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     /* send and free the packets */
   done:
     if (scp_mx_held)
-       lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseRead(&scp->rw);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     if (code == 0) {
@@ -3143,19 +3145,19 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         /* lock the vnode with a callback; we need the current status
          * to determine what the new status is, in some cases.
          */
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_GETSTATUS
                          | CM_SCACHESYNC_NEEDCALLBACK);
         if (code) {
-           lock_ReleaseMutex(&scp->mx);
+           lock_ReleaseWrite(&scp->rw);
             goto done;
         }
        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
-       lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseWrite(&scp->rw);
        lock_ObtainMutex(&fidp->mx);
-       lock_ObtainMutex(&scp->mx);
+       lock_ObtainRead(&scp->rw);
 
         /* prepare for setattr call */
         attr.mask = CM_ATTRMASK_LENGTH;
@@ -3182,7 +3184,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                 attr.unixModeBits = scp->unixModeBits | 0222;
             }
         }
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseRead(&scp->rw);
        lock_ReleaseMutex(&fidp->mx);
 
         /* call setattr */
@@ -3224,6 +3226,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_scache_t *scp;
     smb_tran2QFileInfo_t qfi;
     long code = 0;
+    int  readlock = 0;
     cm_req_t req;
 
     cm_InitReq(&req);
@@ -3282,7 +3285,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     osi_Log2(smb_logp,"smb_ReleaseTran2QFileInfo fidp 0x%p scp 0x%p", fidp, scp);
     cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) 
@@ -3290,6 +3293,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
+    lock_ConvertWToR(&scp->rw);
+    readlock = 1;
+
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
      */
@@ -3319,9 +3325,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         unsigned long len;
         char *name;
 
-       lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseRead(&scp->rw);
        lock_ObtainMutex(&fidp->mx);
-       lock_ObtainMutex(&scp->mx);
+       lock_ObtainRead(&scp->rw);
         if (fidp->NTopen_wholepathp)
             name = fidp->NTopen_wholepathp;
         else
@@ -3335,7 +3341,10 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     /* send and free the packets */
   done:
-    lock_ReleaseMutex(&scp->mx);
+    if (readlock)
+        lock_ReleaseRead(&scp->rw);
+    else
+        lock_ReleaseWrite(&scp->rw);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
@@ -3437,20 +3446,20 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        /* lock the vnode with a callback; we need the current status
          * to determine what the new status is, in some cases.
          */
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_GETSTATUS
                          | CM_SCACHESYNC_NEEDCALLBACK);
         if (code) {
-           lock_ReleaseMutex(&scp->mx);
+           lock_ReleaseWrite(&scp->rw);
             goto done;
        }
 
        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
-       lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseWrite(&scp->rw);
        lock_ObtainMutex(&fidp->mx);
-       lock_ObtainMutex(&scp->mx);
+       lock_ObtainRead(&scp->rw);
 
         /* prepare for setattr call */
         attr.mask = 0;
@@ -3482,7 +3491,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                 attr.unixModeBits = scp->unixModeBits | 0222;
             }
         }
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseRead(&scp->rw);
        lock_ReleaseMutex(&fidp->mx);
 
         /* call setattr */
@@ -3837,10 +3846,10 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
     if (code == 0 && !(rights & PRSFS_READ))
         mustFake = 1;
     else if (code == -1) {
-        lock_ObtainMutex(&dscp->mx);
+        lock_ObtainWrite(&dscp->rw);
         code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-        lock_ReleaseMutex(&dscp->mx);
+        lock_ReleaseWrite(&dscp->rw);
         if (code == CM_ERROR_NOACCESS) {
             mustFake = 1;
             code = 0;
@@ -3860,12 +3869,12 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
         if (code) 
             continue;
 
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         if (mustFake == 0)
             code = cm_SyncOp(scp, NULL, userp, reqp, 0,
                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         if (mustFake || code) { 
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
 
             dptr = patchp->dptr;
 
@@ -3979,7 +3988,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
         /* now watch for a symlink */
         code = 0;
         while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
             snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
             reqp->relPathp = path;
             reqp->tidPathp = tidPathp;
@@ -3995,9 +4004,11 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
                 cm_ReleaseSCache(scp);
                 scp = targetScp;
             }
-            lock_ObtainMutex(&scp->mx);
+            lock_ObtainWrite(&scp->rw);
         }
 
+        lock_ConvertWToR(&scp->rw);
+
         dptr = patchp->dptr;
 
         if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
@@ -4099,7 +4110,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
             *dptr++ = (attr >> 8) & 0xff;
         }
 
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseRead(&scp->rw);
         cm_ReleaseSCache(scp);
     }
         
@@ -4918,13 +4929,13 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
              * and so we do another hold now.
              */
             cm_HoldSCache(scp);
-            lock_ObtainMutex(&scp->mx);
+            lock_ObtainWrite(&scp->rw);
             if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
                  LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
                 scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
                 dsp->flags |= SMB_DIRSEARCH_BULKST;
             }
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
         } 
     }
     lock_ReleaseMutex(&dsp->mx);
@@ -4937,11 +4948,11 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
 
     /* get the directory size */
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) {
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
@@ -5023,7 +5034,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 buf_Release(bufferp);
                 bufferp = NULL;
             }       
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
             code = buf_Get(scp, &thyper, &bufferp);
             lock_ObtainMutex(&dsp->mx);
 
@@ -5033,7 +5044,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             if (starPattern) {
                 code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, infoLevel, userp, &req);
                 
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
                 if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                     LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
                     /* Don't bulk stat if risking timeout */
@@ -5046,7 +5057,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                         code = cm_TryBulkStat(scp, &thyper, userp, &req);
                 }
             } else {
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
             }
             lock_ReleaseMutex(&dsp->mx);
             if (code) {
@@ -5327,7 +5338,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
 
     /* release the mutex */
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     if (bufferp) {
         buf_Release(bufferp);
        bufferp = NULL;
@@ -5692,9 +5703,9 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     osi_Log2(smb_logp,"smb_ReceiveV3OpenX fidp 0x%p scp 0x%p", fidp, scp);
     /* also the user */
     fidp->userp = userp;
@@ -5720,7 +5731,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* copy out remainder of the parms */
     parmSlot = 2;
     smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainRead(&scp->rw);
     if (extraInfo) {
         smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
         smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
@@ -5738,7 +5749,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
     smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
     smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseRead(&scp->rw);
     smb_SetSMBDataLength(outp, 0);
 
     osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
@@ -5827,7 +5838,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     userp = smb_GetUserFromVCP(vcp, inp);
 
 
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK
                         | CM_SCACHESYNC_GETSTATUS
@@ -6060,7 +6071,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
 
   doneSync:
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
@@ -6077,6 +6088,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     afs_uint32 searchTime;
     cm_user_t *userp;
     cm_req_t req;
+    int readlock = 0;
 
     cm_InitReq(&req);
 
@@ -6108,7 +6120,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         
         
     /* otherwise, stat the file */
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) 
@@ -6116,6 +6128,8 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
+    lock_ConvertWToR(&scp->rw);
+
     /* decode times.  We need a search time, but the response to this
      * call provides the date first, not the time, as returned in the
      * searchTime variable.  So we take the high-order bits first.
@@ -6142,7 +6156,10 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     code = 0;
 
   done:
-    lock_ReleaseMutex(&scp->mx);
+    if (readlock) 
+        lock_ReleaseRead(&scp->rw);
+    else
+        lock_ReleaseWrite(&scp->rw);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
@@ -6225,6 +6242,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     unsigned short fd;
     unsigned pid;
     smb_fid_t *fidp;
+    smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
     char *op;
@@ -6289,7 +6307,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LARGE_INTEGER LLength;
         cm_scache_t * scp;
 
-        pid = ((smb_t *) inp)->pid;
+        pid = smbp->pid;
         key = cm_GenerateKey(vcp->vcID, pid, fd);
 
         LOffset.HighPart = offset.HighPart;
@@ -6298,9 +6316,9 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.LowPart = count;
 
         scp = fidp->scp;
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_LockCheckWrite(scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
 
         if (code)
             goto done;
@@ -6359,6 +6377,7 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     unsigned short fd;
     unsigned pid;
     smb_fid_t *fidp;
+    smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
     cm_key_t key;
@@ -6405,7 +6424,7 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return CM_ERROR_NOSUCHFILE;
     }
 
-    pid = ((smb_t *) inp)->pid;
+    pid = smbp->pid;
     key = cm_GenerateKey(vcp->vcID, pid, fd);
     {
         LARGE_INTEGER LOffset, LLength;
@@ -6417,9 +6436,9 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.LowPart = count;
 
         scp = fidp->scp;
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_LockCheckRead(scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
     }
 
     if (code) {
@@ -6717,7 +6736,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidflags = 0;
     if (desiredAccess & DELETE)
         fidflags |= SMB_FID_OPENDELETE;
-    if (desiredAccess & AFS_ACCESS_READ)
+    if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
         fidflags |= SMB_FID_OPENREAD_LISTDIR;
     if (desiredAccess & AFS_ACCESS_WRITE)
         fidflags |= SMB_FID_OPENWRITE;
@@ -7230,9 +7249,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
         
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
 
         if (code) {
            if (ldp)
@@ -7256,9 +7275,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     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);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     osi_Log2(smb_logp,"smb_ReceiveNTCreateX fidp 0x%p scp 0x%p", fidp, scp);
 
     fidp->flags = fidflags;
@@ -7291,7 +7310,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     /* out parms */
     parmSlot = 2;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainRead(&scp->rw);
     smb_SetSMBParmByte(outp, parmSlot, 0);     /* oplock */
     smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
     smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
@@ -7319,7 +7338,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                            fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                            userp);
     }
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseRead(&scp->rw);
 
     osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid,
               osi_LogSaveString(smb_logp, realPathp));
@@ -7521,7 +7540,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fidflags = 0;
     if (desiredAccess & DELETE)
         fidflags |= SMB_FID_OPENDELETE;
-    if (desiredAccess & AFS_ACCESS_READ)
+    if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
         fidflags |= SMB_FID_OPENREAD_LISTDIR;
     if (desiredAccess & AFS_ACCESS_WRITE)
         fidflags |= SMB_FID_OPENWRITE;
@@ -7898,9 +7917,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
         key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
         
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
 
         if (code) {
            if (ldp)
@@ -7922,9 +7941,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     osi_Log2(smb_logp,"smb_ReceiveNTTranCreate fidp 0x%p scp 0x%p", fidp, scp);
 
     fidp->flags = fidflags;
@@ -7981,7 +8000,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
         smb_SetSMBDataLength(outp, 70);
 
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainRead(&scp->rw);
         outData = smb_GetSMBData(outp, NULL);
         outData++;                     /* round to get to parmOffset */
         *outData = 0; outData++;       /* oplock */
@@ -8003,7 +8022,6 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                                scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
                                scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
         outData += 2;  /* is a dir? */
-        lock_ReleaseMutex(&scp->mx);
     } else {
         /* out parms */
         parmOffset = 8*4 + 39;
@@ -8031,7 +8049,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
         smb_SetSMBDataLength(outp, 105);
         
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainRead(&scp->rw);
         outData = smb_GetSMBData(outp, NULL);
         outData++;                     /* round to get to parmOffset */
         *outData = 0; outData++;       /* oplock */
@@ -8056,10 +8074,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         memset(outData,0,24); outData += 24; /* Volume ID and file ID */
         *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
         *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
-        lock_ReleaseMutex(&scp->mx);
     }
 
-    lock_ObtainMutex(&scp->mx);
     if ((fidp->flags & SMB_FID_EXECUTABLE) && 
          LargeIntegerGreaterThanZero(fidp->scp->length) && 
          !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
@@ -8067,7 +8083,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                            fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                            userp);
     }
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseRead(&scp->rw);
 
     osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
 
@@ -8150,12 +8166,12 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
     if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE)
        osi_Log0(smb_logp, "      Notify Change Stream Write");
 
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     if (watchtree)
         scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
     else
         scp->flags |= CM_SCACHEFLAG_WATCHED;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     smb_ReleaseFID(fidp);
 
     outp->flags |= SMB_PACKETFLAG_NOSEND;
@@ -8403,12 +8419,12 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
             lastWatch->nextp = nextWatch;
 
         /* Turn off WATCHED flag in dscp */
-        lock_ObtainMutex(&dscp->mx);
+        lock_ObtainWrite(&dscp->rw);
         if (wtree)
             dscp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
         else
             dscp->flags &= ~CM_SCACHEFLAG_WATCHED;
-        lock_ReleaseMutex(&dscp->mx);
+        lock_ReleaseWrite(&dscp->rw);
 
         /* Convert to response packet */
         ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT;
@@ -8553,12 +8569,12 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
                 scp = fidp->scp;
                osi_Log2(smb_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
                 if (watchtree)
                     scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
                 else
                     scp->flags &= ~CM_SCACHEFLAG_WATCHED;
-                lock_ReleaseMutex(&scp->mx);
+                lock_ReleaseWrite(&scp->rw);
                 smb_ReleaseFID(fidp);
             } else {
                 osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);