windows-smb_vc_t-refcounts-20050117
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 18 Jan 2005 07:36:25 +0000 (07:36 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 18 Jan 2005 07:36:25 +0000 (07:36 +0000)
Rework the reference counting of the smb_vc_t objects to use
smb_ReleaseVC and smb_HoldVC.  Add missing counts for references
from waiting locks.

Fix cm_ioctl.c to allow it to compile once again.

src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c

index b3c47b0..c73951d 100644 (file)
@@ -89,8 +89,8 @@ void cm_ResetACLCache(cm_user_t *userp)
     int hash;
 
     lock_ObtainWrite(&cm_scacheLock);
-    for (hash=0; hash < cm_data.hashTableSize; hash++) {
-        for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
+    for (hash=0; hash < cm_hashTableSize; hash++) {
+        for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
             cm_HoldSCacheNoLock(scp);
             lock_ReleaseWrite(&cm_scacheLock);
             lock_ObtainMutex(&scp->mx);
@@ -179,7 +179,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
         if ( shareFound ) {
             /* we found a sharename, therefore use the resulting path */
-            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, sharePath, reqp, &substRootp);
             free(sharePath);
@@ -208,7 +208,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             shareName[i] = 0;       /* terminate string */
 
 
-            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, shareName, reqp, &substRootp);
             if (code) 
@@ -220,7 +220,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
                 return code;
         }
     } else {
-        code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                          CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                          userp, ioctlp->tidPathp, reqp, &substRootp);
         if (code) 
@@ -347,7 +347,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
         if ( shareFound ) {
             /* we found a sharename, therefore use the resulting path */
-            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, sharePath, reqp, &substRootp);
             free(sharePath);
@@ -373,7 +373,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             shareName[i++] = '/';      /* add trailing slash */
             shareName[i] = 0;       /* terminate string */
 
-            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, shareName, reqp, &substRootp);
             if (code) return code;
@@ -383,7 +383,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             if (code) return code;
         }
     } else {
-        code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
+        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                         userp, ioctlp->tidPathp, reqp, &substRootp);
         if (code) return code;
@@ -472,7 +472,7 @@ long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
     {
         cellp = cm_FindCellByID(scp->fid.cell);
         if (cellp) {
-            StringCbCopyA(ioctlp->outDatap, 999999, cellp->name);
+            StringCbCopyA(ioctlp->outDatap, 999999, cellp->namep);
             ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
             code = 0;
         }
@@ -545,8 +545,8 @@ long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_ReleaseSCache(scp);
 
     lock_ObtainWrite(&cm_scacheLock);
-    for (i=0; i<cm_data.hashTableSize; i++) {
-        for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+    for (i=0; i<cm_hashTableSize; i++) {
+        for (scp = cm_hashTablep[i]; scp; scp = scp->nextp) {
             if (scp->fid.volume == volume) {
                 cm_HoldSCacheNoLock(scp);
                 lock_ReleaseWrite(&cm_scacheLock);
@@ -974,10 +974,10 @@ long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     memcpy(&temp, ioctlp->inDatap, sizeof(temp));
     if (temp == 0) 
-        temp = cm_data.buf_nOrigBuffers;
+        temp = buf_nOrigBuffers;
     else {
         /* temp is in 1K units, convert to # of buffers */
-        temp = temp / (cm_data.buf_blockSize / 1024);
+        temp = temp / (buf_bufferSize / 1024);
     }       
 
     /* now adjust the cache size */
@@ -1031,12 +1031,12 @@ long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
     memset(&parms, 0, sizeof(parms));
 
     /* first we get, in 1K units, the cache size */
-    parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
+    parms.parms[0] = buf_nbuffers * (buf_bufferSize / 1024);
 
     /* and then the actual # of buffers in use (not in the free list, I guess,
      * will be what we do).
      */
-    parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
+    parms.parms[1] = (buf_nbuffers - buf_CountFreeList()) * (buf_bufferSize / 1024);
 
     memcpy(ioctlp->outDatap, &parms, sizeof(parms));
     ioctlp->outDatap += sizeof(parms);
@@ -1069,7 +1069,7 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
     }
 
     lock_ObtainRead(&cm_cellLock);
-    for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
+    for (tcellp = cm_allCellsp; tcellp; tcellp = tcellp->nextp) {
         if (whichCell == 0) break;
         whichCell--;
     }
@@ -1097,8 +1097,8 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
         }
         lock_ReleaseRead(&cm_serverLock);
         cp = basep + max * sizeof(afs_int32);
-        StringCbCopyA(cp, 999999, tcellp->name);
-        cp += strlen(tcellp->name)+1;
+        StringCbCopyA(cp, 999999, tcellp->namep);
+        cp += strlen(tcellp->namep)+1;
         ioctlp->outDatap = cp;
     }
 
@@ -1126,18 +1126,18 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_SkipIoctlPath(ioctlp);
     lock_ObtainWrite(&cm_cellLock);
   
-    for (cp = cm_data.allCellsp; cp; cp=cp->nextp) 
+    for (cp = cm_allCellsp; cp; cp=cp->nextp) 
     {
         long code;
         /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
         cm_FreeServerList(&cp->vlServersp);
         cp->vlServersp = NULL;
-        code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
+        code = cm_SearchCellFile(cp->namep, cp->namep, cm_AddCellProc, cp);
 #ifdef AFS_AFSDB_ENV
         if (code) {
             if (cm_dnsEnabled) {
                 int ttl;
-                code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
+                code = cm_SearchCellByDNS(cp->namep, cp->namep, &ttl, cm_AddCellProc, cp);
                 if ( code == 0 ) { /* got cell from DNS */
                     cp->flags |= CM_CELLFLAG_DNS;
                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
@@ -1169,9 +1169,9 @@ long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
        if (cm_freelanceEnabled) {
            StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
                ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
-       } else if (cm_data.rootCellp) {
+       } else if (cm_rootCellp) {
            /* return the default cellname to the caller */
-           StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
+           StringCbCopyA(ioctlp->outDatap, 999999, cm_rootCellp->namep);
            ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
        } else {
            /* if we don't know our default cell, return failure */
@@ -1481,7 +1481,7 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
     }
 
 #ifdef AFS_FREELANCE_CLIENT
-    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
+    if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
         /* we are adding the mount point to the root dir., so call
          * the freelance code to do the add. */
         osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
@@ -1530,7 +1530,7 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp = ioctlp->inDatap;              /* contents of link */
 
 #ifdef AFS_FREELANCE_CLIENT
-    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
+    if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
         /* we are adding the symlink to the root dir., so call
          * the freelance code to do the add. */
         if (cp[0] == cp[1] && cp[1] == '\\' && 
@@ -1595,7 +1595,7 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
     cm_ReleaseSCache(scp);
-    if (code == 0 || code == CM_ERROR_PATH_NOT_COVERED) {
+    if (code == 0) {
         cp = ioctlp->outDatap;
         if (newRootScp != NULL) {
             StringCbCopyA(cp, 999999, cm_mountRoot);
@@ -1657,7 +1657,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp = ioctlp->inDatap;
 
 #ifdef AFS_FREELANCE_CLIENT
-    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
+    if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
         /* we are adding the mount point to the root dir., so call
          * the freelance code to do the add. */
         osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
@@ -1785,7 +1785,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
             return CM_ERROR_INVAL;
 #endif /* !DJGPP */
     } else {
-        cellp = cm_data.rootCellp;
+        cellp = cm_rootCellp;
         osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
     }
 
@@ -1904,7 +1904,7 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp += sizeof(temp);
 
     /* cell name */
-    StringCbCopyA(cp, 999999, ucellp->cellp->name);
+    StringCbCopyA(cp, 999999, ucellp->cellp->namep);
     cp += strlen(cp) + 1;
 
     /* user name */
@@ -1993,7 +1993,7 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp += sizeof(temp);
 
     /* cell name */
-    StringCbCopyA(cp, 999999, ucellp->cellp->name);
+    StringCbCopyA(cp, 999999, ucellp->cellp->namep);
     cp += strlen(cp) + 1;
 
     /* user name */
index 573b974..365ca1b 100644 (file)
@@ -779,9 +779,9 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
     smb_vc_t *vcp;
 
     lock_ObtainWrite(&smb_rctLock);
-    for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
+    for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
         if (lsn == vcp->lsn && lana == vcp->lana) {
-            vcp->refCount++;
+            smb_HoldVCNoLock(vcp);
             break;
         }
     }
@@ -842,6 +842,11 @@ int smb_IsStarMask(char *maskp)
     return 0;
 }
 
+void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+{
+    osi_assert(vcp->refCount-- > 0);
+}       
+
 void smb_ReleaseVC(smb_vc_t *vcp)
 {
     lock_ObtainWrite(&smb_rctLock);
@@ -849,6 +854,11 @@ void smb_ReleaseVC(smb_vc_t *vcp)
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
+void smb_HoldVCNoLock(smb_vc_t *vcp)
+{
+    vcp->refCount++;
+}       
+
 void smb_HoldVC(smb_vc_t *vcp)
 {
     lock_ObtainWrite(&smb_rctLock);
@@ -873,7 +883,7 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
         tidp->nextp = vcp->tidsp;
         tidp->refCount = 1;
         tidp->vcp = vcp;
-        vcp->refCount++;
+        smb_HoldVCNoLock(vcp);
         vcp->tidsp = tidp;
         lock_InitializeMutex(&tidp->mx, "tid_t mutex");
         tidp->tid = tid;
@@ -887,30 +897,27 @@ void smb_ReleaseTID(smb_tid_t *tidp)
     smb_tid_t *tp;
     smb_tid_t **ltpp;
     cm_user_t *userp;
-    smb_vc_t  *vcp;
 
     userp = NULL;
-    vcp = NULL;
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(tidp->refCount-- > 0);
     if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
         ltpp = &tidp->vcp->tidsp;
-        for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
-            if (tp == tidp) break;
+        for (tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
+            if (tp == tidp) 
+                break;
         }
         osi_assert(tp != NULL);
         *ltpp = tp->nextp;
         lock_FinalizeMutex(&tidp->mx);
         userp = tidp->userp;   /* remember to drop ref later */
-        vcp = tidp->vcp;
+        tidp->userp = NULL;
+        smb_ReleaseVCNoLock(tidp->vcp);
+        tidp->vcp = NULL;
     }
     lock_ReleaseWrite(&smb_rctLock);
-    if (userp) {
+    if (userp)
         cm_ReleaseUser(userp);
-    }  
-    if (vcp) {
-        smb_ReleaseVC(vcp);
-    }   
 }              
 
 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
@@ -933,7 +940,7 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
         uidp->nextp = vcp->usersp;
         uidp->refCount = 1;
         uidp->vcp = vcp;
-        vcp->refCount++;
+        smb_HoldVCNoLock(vcp);
         vcp->usersp = uidp;
         lock_InitializeMutex(&uidp->mx, "user_t mutex");
         uidp->userID = uid;
@@ -992,10 +999,8 @@ void smb_ReleaseUID(smb_user_t *uidp)
     smb_user_t *up;
     smb_user_t **lupp;
     cm_user_t *userp;
-    smb_vc_t  *vcp;
 
     userp = NULL;
-    vcp = NULL;
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(uidp->refCount-- > 0);
     if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
@@ -1007,10 +1012,10 @@ void smb_ReleaseUID(smb_user_t *uidp)
         *lupp = up->nextp;
         lock_FinalizeMutex(&uidp->mx);
         if (uidp->unp) {
-            userp = uidp->unp->userp;  /* remember to drop ref later */
-            uidp->unp->userp = NULL;
+            userp = uidp->unp->userp;  /* avoid deadlock by releasing */
+            uidp->unp->userp = NULL;    /* after releasing the lock */
         }       
-        vcp = uidp->vcp;
+        smb_ReleaseVCNoLock(uidp->vcp);
         uidp->vcp = NULL;
     }          
     lock_ReleaseWrite(&smb_rctLock);
@@ -1018,9 +1023,6 @@ void smb_ReleaseUID(smb_user_t *uidp)
         cm_ReleaseUserVCRef(userp);
         cm_ReleaseUser(userp);
     }  
-    if (vcp) {
-        smb_ReleaseVC(vcp);
-    }
 }      
 
 /* retrieve a held reference to a user structure corresponding to an incoming
@@ -1110,7 +1112,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
     }
 
   retry:
-    for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+    for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
         if (fid == fidp->fid) {
             if (newFid) {
                 fid++;
@@ -1141,7 +1143,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
         osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
         fidp->refCount = 1;
         fidp->vcp = vcp;
-        vcp->refCount++;
+        smb_HoldVCNoLock(vcp);
         lock_InitializeMutex(&fidp->mx, "fid_t mutex");
         fidp->fid = fid;
         fidp->curr_chunk = fidp->prev_chunk = -2;
@@ -1170,24 +1172,30 @@ void smb_ReleaseFID(smb_fid_t *fidp)
     osi_assert(fidp->refCount-- > 0);
     if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
         vcp = fidp->vcp;
-        if (!(fidp->flags & SMB_FID_IOCTL))
+        fidp->vcp = NULL;
+        if (!(fidp->flags & SMB_FID_IOCTL)) {
             scp = fidp->scp;
+            fidp->scp = NULL;
+        }
+
         osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
         thrd_CloseHandle(fidp->raw_write_event);
 
         /* and see if there is ioctl stuff to free */
         ioctlp = fidp->ioctlp;
         if (ioctlp) {
-            if (ioctlp->prefix) cm_FreeSpace(ioctlp->prefix);
-            if (ioctlp->inAllocp) free(ioctlp->inAllocp);
-            if (ioctlp->outAllocp) free(ioctlp->outAllocp);
+            if (ioctlp->prefix) 
+                cm_FreeSpace(ioctlp->prefix);
+            if (ioctlp->inAllocp) 
+                free(ioctlp->inAllocp);
+            if (ioctlp->outAllocp) 
+                free(ioctlp->outAllocp);
             free(ioctlp);
         }       
 
         free(fidp);
 
-        /* do not call smb_ReleaseVC() because we already have the lock */
-        vcp->refCount--;
+        smb_ReleaseVCNoLock(vcp);
     }
     lock_ReleaseWrite(&smb_rctLock);
 
@@ -1854,6 +1862,8 @@ static NCB *GetNCB(void)
 
 void smb_FreePacket(smb_packet_t *tbp)
 {
+    smb_vc_t * vcp = NULL;
+
     osi_assert(tbp->magic == SMB_PACKETMAGIC);
         
     lock_ObtainWrite(&smb_globalLock);
@@ -1861,6 +1871,7 @@ void smb_FreePacket(smb_packet_t *tbp)
     smb_packetFreeListp = tbp;
     tbp->magic = SMB_PACKETMAGIC;
     tbp->ncbp = NULL;
+    vcp = tbp->vcp;
     tbp->vcp = NULL;
     tbp->resumeCode = 0;
     tbp->inCount = 0;
@@ -1871,6 +1882,9 @@ void smb_FreePacket(smb_packet_t *tbp)
     tbp->ncb_length = 0;
     tbp->flags = 0;
     lock_ReleaseWrite(&smb_globalLock);
+
+    if (vcp)
+        smb_ReleaseVC(vcp);
 }
 
 static void FreeNCB(NCB *bufferp)
@@ -2966,6 +2980,8 @@ void smb_WaitingLocksDaemon()
             cm_FreeSpace(inp->spacep);
             smb_FreePacket(inp);
             smb_FreePacket(outp);
+            if (vcp)
+                smb_ReleaseVC(vcp);
             FreeNCB(ncbp);
             free(wL);
         } while (nwL);
@@ -3404,10 +3420,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         memcpy(dsp->mask, mask, 11);
 
         /* track if this is likely to match a lot of entries */
-        if (smb_IsStarMask(mask)) starPattern = 1;
-        else starPattern = 0;
-    }  
-    else {
+        if (smb_IsStarMask(mask)) 
+            starPattern = 1;
+        else 
+            starPattern = 0;
+    } else {
         /* pull the next cookie value out of the search status block */
         nextCookie = inCookiep[13] + (inCookiep[14]<<8) + (inCookiep[15]<<16)
             + (inCookiep[16]<<24);
@@ -3837,7 +3854,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     caseFold = CM_FLAG_CASEFOLD;
 
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
-    if(code) {
+    if (code) {
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
index 4774e39..d98fa59 100644 (file)
@@ -436,6 +436,8 @@ extern smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana);
 
 extern void smb_ReleaseVC(smb_vc_t *vcp);
 
+extern void smb_ReleaseVCNoLock(smb_vc_t *vcp);
+
 extern smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags);
 
 extern void smb_ReleaseTID(smb_tid_t *tidp);
@@ -513,6 +515,8 @@ extern void smb_MapNTError(long code, unsigned long *NTStatusp);
 
 extern void smb_HoldVC(smb_vc_t *vcp);
 
+extern void smb_HoldVCNoLock(smb_vc_t *vcp);
+
 /* some globals, too */
 extern char *smb_localNamep;
 extern int loggedOut;
index 3f614c6..f8b221a 100644 (file)
@@ -1145,7 +1145,8 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
 /* free a tran2 packet; must be called with smb_globalLock held */
 void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
 {
-    if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
+    if (t2p->vcp) 
+        smb_ReleaseVC(t2p->vcp);
     if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
         if (t2p->parmsp)
             free(t2p->parmsp);
@@ -3742,10 +3743,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         smb_StripLastComponent(spacep->data, NULL, pathp);
         code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
         if (code) {
-            lock_ReleaseMutex(&dsp->mx);
             cm_ReleaseUser(userp);
             smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES);
             smb_FreeTran2Packet(outp);
+            lock_ReleaseMutex(&dsp->mx);
             smb_DeleteDirSearch(dsp);
             smb_ReleaseDirSearch(dsp);
             return 0;
@@ -4371,8 +4372,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
          * and truncate the file if we find it, otherwise we create the
          * file.
          */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
+        if (!lastNamep) 
+            lastNamep = pathp;
+        else 
+            lastNamep++;
         code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
                           &req, &scp);
         if (code && code != CM_ERROR_NOSUCHFILE) {
@@ -4390,7 +4393,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (code == 0) {
         code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
         if (code) {
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             return code;
@@ -4398,7 +4402,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         if (excl) {
             /* oops, file shouldn't be there */
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             return CM_ERROR_EXISTS;
@@ -4557,7 +4562,8 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                       CM_SCACHESYNC_NEEDCALLBACK
                         | CM_SCACHESYNC_GETSTATUS
                         | CM_SCACHESYNC_LOCK);
-       if (code) goto doneSync;
+       if (code) 
+            goto doneSync;
 
        LockType = smb_GetSMBParm(inp, 3) & 0xff;
        Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
@@ -4619,6 +4625,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 /* Put on waiting list */
                 waitingLock = malloc(sizeof(smb_waitingLock_t));
                 waitingLock->vcp = vcp;
+                smb_HoldVC(vcp);
                 waitingLock->inp = smb_CopyPacket(inp);
                 waitingLock->outp = smb_CopyPacket(outp);
                 waitingLock->timeRemaining = Timeout;
@@ -4631,7 +4638,8 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 /* don't send reply immediately */
                 outp->flags |= SMB_PACKETFLAG_NOSEND;
             }
-            if (code) break;
+            if (code) 
+                break;
        }       
 
     if (code) {
@@ -4886,9 +4894,14 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     cm_InitReq(&req);
 
+    /* This code is very long and has a lot of if-then-else clauses
+     * scp and dscp get reused frequently and we need to ensure that 
+     * we don't lose a reference.  Start by ensuring that they are NULL.
+     */
+    scp = NULL;
+    dscp = NULL;
     treeCreate = FALSE;
     foundscp = FALSE;
-    scp = NULL;
 
     nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
     flags = smb_GetSMBOffsetParm(inp, 3, 1)
@@ -5035,8 +5048,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (desiredAccess & AFS_ACCESS_WRITE)
         fidflags |= SMB_FID_OPENWRITE;
 
-    dscp = NULL;
     code = 0;
+
     /* For an exclusive create, we want to do a case sensitive match for the last component. */
     if ( createDisp == FILE_CREATE || 
          createDisp == FILE_OVERWRITE ||
@@ -5057,15 +5070,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     return CM_ERROR_EXISTS;
                 }
             }
-        } else
-            dscp = NULL;
+        }
+        /* we have both scp and dscp */
     } else {
         code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
+        /* we might have scp but not dscp */
     }
-    if (code == 0) 
-        foundscp = TRUE;
 
+    if (scp)
+        foundscp = TRUE;
+    
     if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
         /* look up parent directory */
         /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
@@ -5073,8 +5088,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
          * recognize.
          */
 
-        if ( !dscp ) {
-            while (1) {
+        /* we might or might not have scp */
+
+        if (dscp == NULL) {
+            do {
                 char *tp;
 
                 code = cm_NameI(baseDirp, spacep->data,
@@ -5094,20 +5111,27 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                             smb_ReleaseFID(baseFidp);
                         cm_ReleaseUser(userp);
                         free(realPathp);
+                        if (scp)
+                            cm_ReleaseSCache(scp);
                         return CM_ERROR_BADNTFILENAME;
                     }
+                    code = 0;
                 }
-                else
-                    break;
-            }
+            } while (dscp == NULL && code == 0);
         } else
-            code = 0;
+                       code = 0;
+
+        /* we might have scp and we might have dscp */
 
         if (baseFid != 0) 
             smb_ReleaseFID(baseFidp);
 
         if (code) {
             osi_Log0(smb_logp,"NTCreateX parent not found");
+            if (scp)
+                cm_ReleaseSCache(scp);
+            if (dscp)
+                cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
             return code;
@@ -5115,6 +5139,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         if (treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
             /* A file exists where we want a directory. */
+            if (scp)
+                cm_ReleaseSCache(scp);
             cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5127,6 +5153,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             lastNamep++;
 
         if (!smb_IsLegalFilename(lastNamep)) {
+            if (scp)
+                cm_ReleaseSCache(scp);
+                       if (dscp)
             cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5152,196 +5181,206 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 return code;
             }
         }
-    }
-    else {
+        /* we have scp and dscp */
+    } else {
+        /* we have scp but not dscp */
         if (baseFid != 0) 
             smb_ReleaseFID(baseFidp);
-       }       
+    }       
 
-       /* if we get here, if code is 0, the file exists and is represented by
-        * scp.  Otherwise, we have to create it.  The dir may be represented
-        * by dscp, or we may have found the file directly.  If code is non-zero,
-        * scp is NULL.
-        */
-       if (code == 0 && !treeCreate) {
-            if (createDisp == FILE_CREATE) {
-                /* oops, file shouldn't be there */
-                if (dscp) cm_ReleaseSCache(dscp);
-                cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                free(realPathp);
-                return CM_ERROR_EXISTS;
-            }
+    /* if we get here, if code is 0, the file exists and is represented by
+     * scp.  Otherwise, we have to create it.  The dir may be represented
+     * by dscp, or we may have found the file directly.  If code is non-zero,
+     * scp is NULL.
+     */
+    if (code == 0 && !treeCreate) {
+        if (createDisp == FILE_CREATE) {
+            /* oops, file shouldn't be there */
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_EXISTS;
+        }
 
-            if ( createDisp == FILE_OVERWRITE || 
-                 createDisp == FILE_OVERWRITE_IF) {
-                setAttr.mask = CM_ATTRMASK_LENGTH;
-                setAttr.length.LowPart = 0;
-                setAttr.length.HighPart = 0;
-                /* now watch for a symlink */
-                code = 0;
-                while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
-                    targetScp = 0;
-                    code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
-                    if (code == 0) {
-                        /* we have a more accurate file to use (the
-                        * target of the symbolic link).  Otherwise,
-                        * we'll just use the symlink anyway.
-                        */
-                        osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                                  scp, targetScp);
-                        cm_ReleaseSCache(scp);
-                        scp = targetScp;
-                    }
+        if ( createDisp == FILE_OVERWRITE || 
+             createDisp == FILE_OVERWRITE_IF) {
+            setAttr.mask = CM_ATTRMASK_LENGTH;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
+            /* now watch for a symlink */
+            code = 0;
+            while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+                targetScp = 0;
+                osi_assert(dscp != NULL);
+                code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+                if (code == 0) {
+                    /* we have a more accurate file to use (the
+                     * target of the symbolic link).  Otherwise,
+                     * we'll just use the symlink anyway.
+                     */
+                    osi_Log2(smb_logp, "symlink vp %x to vp %x",
+                              scp, targetScp);
+                    cm_ReleaseSCache(scp);
+                    scp = targetScp;
                 }
-                code = cm_SetAttr(scp, &setAttr, userp, &req);
-                openAction = 3;        /* truncated existing file */
             }
-            else 
-                openAction = 1;        /* found existing file */
+            code = cm_SetAttr(scp, &setAttr, userp, &req);
+            openAction = 3;    /* truncated existing file */
+        }
+        else 
+            openAction = 1;    /* found existing file */
 
-            code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
-                                  &req);
-            if (code) {
-                if (dscp) cm_ReleaseSCache(dscp);
-                cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                free(realPathp);
-                return code;
-            }
-       }       
-       else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
-            /* don't create if not found */
-            if (dscp) cm_ReleaseSCache(dscp);
+        code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
+        if (code) {
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
-            return CM_ERROR_NOSUCHFILE;
-       }       
-       else if (realDirFlag == 0 || realDirFlag == -1) {
-            osi_assert(dscp != NULL);
-            osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
-                      osi_LogSaveString(smb_logp, lastNamep));
-            openAction = 2;            /* created file */
-            setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-            setAttr.clientModTime = time(NULL);
-            code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                              &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+            return code;
+        }
+    } else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
+        /* don't create if not found */
+        if (dscp)
+            cm_ReleaseSCache(dscp);
+               if (scp)
+                       cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        free(realPathp);
+        return CM_ERROR_NOSUCHFILE;
+    } else if (realDirFlag == 0 || realDirFlag == -1) {
+        osi_assert(dscp != NULL);
+        osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
+                  osi_LogSaveString(smb_logp, lastNamep));
+        openAction = 2;                /* created file */
+        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+        setAttr.clientModTime = time(NULL);
+        code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
+        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+            smb_NotifyChange(FILE_ACTION_ADDED,
+                              FILE_NOTIFY_CHANGE_FILE_NAME,
+                              dscp, lastNamep, NULL, TRUE);
+        if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+            /* Not an exclusive create, and someone else tried
+             * creating it already, then we open it anyway.  We
+             * don't bother retrying after this, since if this next
+             * fails, that means that the file was deleted after we
+             * started this call.
+             */
+            code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+                              userp, &req, &scp);
+            if (code == 0) {
+                if (createDisp == FILE_OVERWRITE_IF) {
+                    setAttr.mask = CM_ATTRMASK_LENGTH;
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+
+                    /* now watch for a symlink */
+                    code = 0;
+                    while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+                        targetScp = 0;
+                        code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+                        if (code == 0) {
+                            /* we have a more accurate file to use (the
+                             * target of the symbolic link).  Otherwise,
+                             * we'll just use the symlink anyway.
+                             */
+                            osi_Log2(smb_logp, "symlink vp %x to vp %x",
+                                      scp, targetScp);
+                            cm_ReleaseSCache(scp);
+                            scp = targetScp;
+                        }
+                    }
+                    code = cm_SetAttr(scp, &setAttr, userp, &req);
+                }
+            }  /* lookup succeeded */
+        }
+    } else {
+        char *tp, *pp;
+        char *cp; /* This component */
+        int clen = 0; /* length of component */
+        cm_scache_t *tscp1, *tscp2;
+        int isLast = 0;
+
+        /* create directory */
+        if ( !treeCreate ) 
+            treeStartp = lastNamep;
+        osi_assert(dscp != NULL);
+        osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+                  osi_LogSaveString(smb_logp, treeStartp));
+        openAction = 2;                /* created directory */
+
+        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+        setAttr.clientModTime = time(NULL);
+
+        pp = treeStartp;
+        cp = spacep->data;
+        tscp1 = dscp;
+        cm_HoldSCache(tscp1);
+        tscp2 = NULL;
+
+        while (pp && *pp) {
+            tp = strchr(pp, '\\');
+            if (!tp) {
+                strcpy(cp,pp);
+                clen = strlen(cp);
+                isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
+            } else {
+                clen = tp - pp;
+                strncpy(cp,pp,clen);
+                *(cp + clen) = 0;
+                tp++;
+            }
+            pp = tp;
+
+            if (clen == 0) 
+                continue; /* the supplied path can't have consecutive slashes either , but */
+
+            /* cp is the next component to be created. */
+            code = cm_MakeDir(tscp1, cp, 0, &setAttr, userp, &req);
+            if (code == 0 && (tscp1->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_ADDED,
-                                  FILE_NOTIFY_CHANGE_FILE_NAME,
-                                  dscp, lastNamep, NULL, TRUE);
-            if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+                                  FILE_NOTIFY_CHANGE_DIR_NAME,
+                                  tscp1, cp, NULL, TRUE);
+            if (code == 0 || 
+                 (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
                 /* Not an exclusive create, and someone else tried
                  * creating it already, then we open it anyway.  We
                  * don't bother retrying after this, since if this next
                  * fails, that means that the file was deleted after we
                  * started this call.
                  */
-                code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                  userp, &req, &scp);
-                if (code == 0) {
-                    if (createDisp == FILE_OVERWRITE_IF) {
-                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                        setAttr.length.LowPart = 0;
-                        setAttr.length.HighPart = 0;
-
-                        /* now watch for a symlink */
-                        code = 0;
-                        while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
-                            targetScp = 0;
-                            code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
-                            if (code == 0) {
-                                /* we have a more accurate file to use (the
-                                * target of the symbolic link).  Otherwise,
-                                * we'll just use the symlink anyway.
-                                */
-                                osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                                          scp, targetScp);
-                                cm_ReleaseSCache(scp);
-                                scp = targetScp;
-                            }
-                        }
-                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                    }
-                }      /* lookup succeeded */
-            }
-       }       
-       else {
-            char *tp, *pp;
-            char *cp; /* This component */
-            int clen = 0; /* length of component */
-            cm_scache_t *tscp;
-            int isLast = 0;
-               
-            /* create directory */
-            if ( !treeCreate ) 
-                treeStartp = lastNamep;
-            osi_assert(dscp != NULL);
-            osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
-                      osi_LogSaveString(smb_logp, treeStartp));
-            openAction = 2;            /* created directory */
-
-            setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-            setAttr.clientModTime = time(NULL);
-               
-            pp = treeStartp;
-            cp = spacep->data;
-            tscp = dscp;
-
-            while (pp && *pp) {
-                tp = strchr(pp, '\\');
-                if (!tp) {
-                    strcpy(cp,pp);
-                    clen = strlen(cp);
-                    isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
-                }
-                else {
-                    clen = tp - pp;
-                    strncpy(cp,pp,clen);
-                    *(cp + clen) = 0;
-                    tp++;
-                }
-                pp = tp;
-
-                if (clen == 0) 
-                    continue; /* the supplied path can't have consecutive slashes either , but */
-
-                /* cp is the next component to be created. */
-                code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
-                if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                    smb_NotifyChange(FILE_ACTION_ADDED,
-                                      FILE_NOTIFY_CHANGE_DIR_NAME,
-                                      tscp, cp, NULL, TRUE);
-                if (code == 0 || 
-                     (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
-                    /* Not an exclusive create, and someone else tried
-                     * creating it already, then we open it anyway.  We
-                     * don't bother retrying after this, since if this next
-                     * fails, that means that the file was deleted after we
-                     * started this call.
-                     */
-                    code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
-                                      userp, &req, &scp);
-                }
-                if (code) break;
+                code = cm_Lookup(tscp1, cp, CM_FLAG_CASEFOLD,
+                                  userp, &req, &tscp2);
+            }       
+            if (code) 
+                break;
 
-                if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
-                    cm_ReleaseSCache(tscp);
-                    tscp = scp; /* Newly created directory will be next parent */
-                }
+            if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
+                cm_ReleaseSCache(tscp1);
+                tscp1 = tscp2; /* Newly created directory will be next parent */
+                /* the hold is transfered to tscp1 from tscp2 */
             }
+        }
 
-            /* 
-             * if we get here and code == 0, then scp is the last directory created, and tscp is the
-             * parent of scp.  dscp got released if dscp != tscp. both tscp and scp are held.
-             */
-            dscp = tscp;
-       }
+        cm_ReleaseSCache(dscp);
+        dscp = tscp1;
+        cm_ReleaseSCache(scp);
+        scp = tscp2;
+        /* 
+         * if we get here and code == 0, then scp is the last directory created, and dscp is the
+         * parent of scp.
+         */
+    }
 
     if (code) {
         /* something went wrong creating or truncating the file */
-        if (scp) cm_ReleaseSCache(scp);
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (scp) 
+            cm_ReleaseSCache(scp);
+        if (dscp) 
+            cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return code;
@@ -5359,14 +5398,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 * target of the symbolic link).  Otherwise,
                 * we'll just use the symlink anyway.
                 */
-                osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                          scp, targetScp);
+                osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
                 cm_ReleaseSCache(scp);
                 scp = targetScp;
             }
         }
 
         if (scp->fileType != CM_SCACHETYPE_FILE) {
+                       if (dscp)
+            cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5377,7 +5417,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* (only applies to single component case) */
     if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
         cm_ReleaseSCache(scp);
-        if (dscp) cm_ReleaseSCache(dscp);
+        cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return CM_ERROR_NOTDIR;
@@ -5387,7 +5427,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
     /* save a pointer to the vnode */
-    fidp->scp = scp;
+    fidp->scp = scp;    /* Hold transfered to fidp->scp and no longer needed */
 
     fidp->flags = fidflags;
 
@@ -5401,7 +5441,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp->NTopen_wholepathp = realPathp;
 
     /* we don't need this any longer */
-    if (dscp) cm_ReleaseSCache(dscp);
+    if (dscp) {
+        cm_ReleaseSCache(dscp);
+        dscp = NULL;
+    }
     cm_Open(scp, 0, userp);
 
     /* set inp->fid so that later read calls in same msg can find fid */
@@ -5442,6 +5485,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return 0;
 }       
 
+
 /*
  * A lot of stuff copied verbatim from NT Create&X to NT Tran Create.
  * Instead, ultimately, would like to use a subroutine for common code.
@@ -6352,7 +6396,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         }
 
         smb_SendPacket(vcp, watch);
-        smb_ReleaseVC(vcp);
         smb_FreePacket(watch);
         watch = nextWatch;
     }
@@ -6419,8 +6462,6 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             ((smb_t *)watch)->errHigh = 0xC0;
             ((smb_t *)watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
             smb_SendPacket(vcp, watch);
-            if (watch->vcp)
-                smb_ReleaseVC(watch->vcp);
             smb_FreePacket(watch);
             return 0;
         }
@@ -6445,7 +6486,6 @@ long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     char *oldPathp, *newPathp;
     long code = 0;
-    cm_user_t *userp;
     char * tp;
     int attrs;
     int rename_type;