Index: openafs/src/WINNT/afsd/afsd_eventmessages.mc
diff -c openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.1 openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.1.2.1
*** openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.1	Thu Feb 26 14:22:44 2004
--- openafs/src/WINNT/afsd/afsd_eventmessages.mc	Sun Jan 15 21:06:58 2006
***************
*** 106,109 ****
--- 106,127 ----
  .
  
  
+ MessageId=
+ Severity=Warning
+ Facility=System
+ SymbolicName=MSG_SMB_SEND_PACKET_FAILURE
+ Language=English
+ Unable to Send SMB Packet: %1.
+ .
+ 
+ 
+ MessageId=
+ Severity=Warning
+ Facility=System
+ SymbolicName=MSG_UNEXPECTED_SMB_SESSION_CLOSE
+ Language=English
+ Unexpected SMB Session Close: %1.
+ .
+ 
+ 
  ;#endif /* __AFSD_EVENTMESSAGES_H_ 1 */
Index: openafs/src/WINNT/afsd/afsd_init.c
diff -c openafs/src/WINNT/afsd/afsd_init.c:1.40.2.27 openafs/src/WINNT/afsd/afsd_init.c:1.40.2.28
*** openafs/src/WINNT/afsd/afsd_init.c:1.40.2.27	Wed Dec 14 00:33:46 2005
--- openafs/src/WINNT/afsd/afsd_init.c	Tue Jan 24 12:16:05 2006
***************
*** 729,758 ****
      dummyLen = sizeof(ltt);
      code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
                              (BYTE *) &ltt, &dummyLen);
!     if (code == ERROR_SUCCESS)
!         afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
!     else {
          ltt = 1;
-         afsi_log("Logoff token transfer on by default");
-     }
      smb_LogoffTokenTransfer = ltt;
!     afsi_log("Logoff token transfer is currently ignored");
  
      if (ltt) {
          dummyLen = sizeof(ltto);
          code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
                                  NULL, NULL, (BYTE *) &ltto, &dummyLen);
!         if (code == ERROR_SUCCESS)
!             afsi_log("Logoff token tranfer timeout %d seconds", ltto);
!         else {
!             ltto = 10;
!             afsi_log("Default logoff token transfer timeout 10 seconds");
!         }
      } else {
          ltto = 0;
      }   
      smb_LogoffTransferTimeout = ltto;
!     afsi_log("Default logoff token is currently ignored");
  
      dummyLen = sizeof(cm_rootVolumeName);
      code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
--- 729,750 ----
      dummyLen = sizeof(ltt);
      code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
                              (BYTE *) &ltt, &dummyLen);
!     if (code != ERROR_SUCCESS)
          ltt = 1;
      smb_LogoffTokenTransfer = ltt;
!     afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
  
      if (ltt) {
          dummyLen = sizeof(ltto);
          code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
                                  NULL, NULL, (BYTE *) &ltto, &dummyLen);
!         if (code != ERROR_SUCCESS)
!             ltto = 120;
      } else {
          ltto = 0;
      }   
      smb_LogoffTransferTimeout = ltto;
!     afsi_log("Logoff token transfer timeout %d seconds", ltto);
  
      dummyLen = sizeof(cm_rootVolumeName);
      code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
Index: openafs/src/WINNT/afsd/afslogon.c
diff -c openafs/src/WINNT/afsd/afslogon.c:1.24.2.15 openafs/src/WINNT/afsd/afslogon.c:1.24.2.16
*** openafs/src/WINNT/afsd/afslogon.c:1.24.2.15	Mon Aug 29 15:40:59 2005
--- openafs/src/WINNT/afsd/afslogon.c	Thu Jan 19 18:08:44 2006
***************
*** 801,807 ****
          {			
              if ( KFW_is_available() ) {
                  code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
!                 DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",uname,opt.smbName,cell,code);
                  if (code == 0 && opt.theseCells) { 
                      char * principal, *p;
  
--- 801,808 ----
          {			
              if ( KFW_is_available() ) {
                  code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
!                 DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
! 			    uname,opt.smbName,cell,code);
                  if (code == 0 && opt.theseCells) { 
                      char * principal, *p;
  
***************
*** 830,837 ****
                  code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
                                                      uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
                                                      &reason);
!                 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s]",
!                             code,uname,cell);
              }       
              if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
                  for ( ctemp = uname; *ctemp ; ctemp++) {
--- 831,838 ----
                  code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
                                                      uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
                                                      &reason);
!                 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
!                             code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
              }       
              if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
                  for ( ctemp = uname; *ctemp ; ctemp++) {
Index: openafs/src/WINNT/afsd/cm_callback.c
diff -c openafs/src/WINNT/afsd/cm_callback.c:1.20.2.12 openafs/src/WINNT/afsd/cm_callback.c:1.20.2.13
*** openafs/src/WINNT/afsd/cm_callback.c:1.20.2.12	Sun Jun  5 02:45:31 2005
--- openafs/src/WINNT/afsd/cm_callback.c	Sun Jan 15 21:06:59 2006
***************
*** 1668,1675 ****
          lock_ReleaseMutex(&scp->mx);
  		
          /* now make the RPC */
!         osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%x cell %d vol %d uniq %d", 
!                  (long) scp, scp->fid.cell, scp->fid.volume, scp->fid.unique);
          do {
              code = cm_Conn(&sfid, userp, reqp, &connp);
              if (code) 
--- 1668,1675 ----
          lock_ReleaseMutex(&scp->mx);
  		
          /* now make the RPC */
!         osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%x vol %u vn %u uniq %u", 
!                  (long) scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
          do {
              code = cm_Conn(&sfid, userp, reqp, &connp);
              if (code) 
***************
*** 1684,1694 ****
                              &cbr, code));
          code = cm_MapRPCError(code, reqp);
          if (code)
!             osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%x cell %d vol %d", 
!                      code, (long) scp, scp->fid.cell, scp->fid.volume);
          else
!             osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%x cell %d vol %d uniq %d", 
!                      (long) scp, scp->fid.cell, scp->fid.volume, scp->fid.unique);
  
          lock_ObtainMutex(&scp->mx);
          if (code == 0) {
--- 1684,1694 ----
                              &cbr, code));
          code = cm_MapRPCError(code, reqp);
          if (code)
!             osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%x vol %u vn %u", 
!                      code, (long) scp, scp->fid.volume, scp->fid.vnode);
          else
!             osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%x vol %u vn %u uniq %u", 
!                      (long) scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
  
          lock_ObtainMutex(&scp->mx);
          if (code == 0) {
***************
*** 1702,1708 ****
          /* now check to see if we got an error */
          if (code) {
              osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%x -->",code, scp);
!             osi_Log4(afsd_logp, "            cell %d vol %d vn %d uniq %d",
                       scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
              return code;
          }
--- 1702,1708 ----
          /* now check to see if we got an error */
          if (code) {
              osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%x -->",code, scp);
!             osi_Log4(afsd_logp, "            cell %u vol %u vn %u uniq %u",
                       scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
              return code;
          }
Index: openafs/src/WINNT/afsd/cm_conn.c
diff -c openafs/src/WINNT/afsd/cm_conn.c:1.25.2.18 openafs/src/WINNT/afsd/cm_conn.c:1.25.2.19
*** openafs/src/WINNT/afsd/cm_conn.c:1.25.2.18	Wed Dec  7 07:02:41 2005
--- openafs/src/WINNT/afsd/cm_conn.c	Sun Jan 15 21:06:59 2006
***************
*** 90,96 ****
  {
  	memset((char *)reqp, 0, sizeof(cm_req_t));
  #ifndef DJGPP
! 	reqp->startTime = GetCurrentTime();
  #else
          gettimeofday(&reqp->startTime, NULL);
  #endif
--- 90,96 ----
  {
  	memset((char *)reqp, 0, sizeof(cm_req_t));
  #ifndef DJGPP
! 	reqp->startTime = GetTickCount();
  #else
          gettimeofday(&reqp->startTime, NULL);
  #endif
***************
*** 189,195 ****
      
      /* timeleft - get if from reqp the same way as cmXonnByMServers does */
  #ifndef DJGPP
!     timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
  #else
      gettimeofday(&now, NULL);
      timeUsed = sub_time(now, reqp->startTime) / 1000;
--- 189,195 ----
      
      /* timeleft - get if from reqp the same way as cmXonnByMServers does */
  #ifndef DJGPP
!     timeUsed = (GetTickCount() - reqp->startTime) / 1000;
  #else
      gettimeofday(&now, NULL);
      timeUsed = sub_time(now, reqp->startTime) / 1000;
***************
*** 536,542 ****
      *connpp = NULL;
  
  #ifndef DJGPP
!     timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
  #else
      gettimeofday(&now, NULL);
      timeUsed = sub_time(now, reqp->startTime) / 1000;
--- 536,542 ----
      *connpp = NULL;
  
  #ifndef DJGPP
!     timeUsed = (GetTickCount() - reqp->startTime) / 1000;
  #else
      gettimeofday(&now, NULL);
      timeUsed = sub_time(now, reqp->startTime) / 1000;
Index: openafs/src/WINNT/afsd/cm_daemon.c
diff -c openafs/src/WINNT/afsd/cm_daemon.c:1.4.2.9 openafs/src/WINNT/afsd/cm_daemon.c:1.4.2.10
*** openafs/src/WINNT/afsd/cm_daemon.c:1.4.2.9	Sat Oct 29 16:15:07 2005
--- openafs/src/WINNT/afsd/cm_daemon.c	Sat Jan 21 15:58:39 2006
***************
*** 49,54 ****
--- 49,56 ----
  #ifndef DJGPP
  void cm_IpAddrDaemon(long parm)
  {
+     extern void smb_CheckVCs(void);
+ 
      rx_StartClientThread();
  
      while (daemon_ShutdownFlag == 0) {
***************
*** 57,63 ****
  	    osi_Log0(afsd_logp, "cm_IpAddrDaemon CheckDownServers");
  	    Sleep(2500);
              cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
! 	}
      }
  }
  #endif
--- 59,66 ----
  	    osi_Log0(afsd_logp, "cm_IpAddrDaemon CheckDownServers");
  	    Sleep(2500);
              cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
! 	    smb_CheckVCs();
! 	}	
      }
  }
  #endif
Index: openafs/src/WINNT/afsd/cm_ioctl.c
diff -c openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.23 openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.24
*** openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.23	Tue Jan 10 08:28:01 2006
--- openafs/src/WINNT/afsd/cm_ioctl.c	Thu Jan 19 18:08:44 2006
***************
*** 1951,1957 ****
      }
  
      if (flags & PIOCTL_LOGON) {
!         userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
  	release_userp = 1;
      }
  
--- 1951,1958 ----
      }
  
      if (flags & PIOCTL_LOGON) {
!         userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
! 				     SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
  	release_userp = 1;
      }
  
Index: openafs/src/WINNT/afsd/cm_server.h
diff -c openafs/src/WINNT/afsd/cm_server.h:1.5.2.5 openafs/src/WINNT/afsd/cm_server.h:1.5.2.6
*** openafs/src/WINNT/afsd/cm_server.h:1.5.2.5	Mon Nov 21 19:30:01 2005
--- openafs/src/WINNT/afsd/cm_server.h	Sun Jan 15 21:06:59 2006
***************
*** 25,31 ****
      struct sockaddr_in addr;		/* by mx */
      int type;				/* by mx */
      struct cm_conn *connsp;		/* locked by cm_connLock */
!     long flags;				/* by mx */
      struct cm_cell *cellp;		/* cell containing this server */
      unsigned long refCount;		/* locked by cm_serverLock */
      osi_mutex_t mx;
--- 25,31 ----
      struct sockaddr_in addr;		/* by mx */
      int type;				/* by mx */
      struct cm_conn *connsp;		/* locked by cm_connLock */
!     long flags; 			/* by mx */
      struct cm_cell *cellp;		/* cell containing this server */
      unsigned long refCount;		/* locked by cm_serverLock */
      osi_mutex_t mx;
Index: openafs/src/WINNT/afsd/cm_user.c
diff -c openafs/src/WINNT/afsd/cm_user.c:1.5.2.1 openafs/src/WINNT/afsd/cm_user.c:1.5.2.2
*** openafs/src/WINNT/afsd/cm_user.c:1.5.2.1	Tue Dec  7 00:58:20 2004
--- openafs/src/WINNT/afsd/cm_user.c	Thu Jan 19 18:08:44 2006
***************
*** 39,52 ****
  
  cm_user_t *cm_NewUser(void)
  {
!     cm_user_t *up;
          
!     up = malloc(sizeof(*up));
!     memset(up, 0, sizeof(*up));
!     up->refCount = 1;
!     up->vcRefs = 1;		/* from caller */
!     lock_InitializeMutex(&up->mx, "cm_user_t");
!     return up;
  }
  
  /* must be called with locked userp */
--- 39,51 ----
  
  cm_user_t *cm_NewUser(void)
  {
!     cm_user_t *userp;
          
!     userp = malloc(sizeof(*userp));
!     memset(userp, 0, sizeof(*userp));
!     userp->refCount = 1;
!     lock_InitializeMutex(&userp->mx, "cm_user_t");
!     return userp;
  }
  
  /* must be called with locked userp */
***************
*** 98,128 ****
      lock_ReleaseWrite(&cm_userLock);
  }
  
! void cm_ReleaseUser(cm_user_t *up)
  {
      cm_ucell_t *ucp;
      cm_ucell_t *ncp;
  
!     if (up == NULL) 
          return;
  
      lock_ObtainWrite(&cm_userLock);
!     osi_assert(up->refCount-- > 0);
!     if (up->refCount == 0) {
!         lock_FinalizeMutex(&up->mx);
!         for (ucp = up->cellInfop; ucp; ucp = ncp) {
              ncp = ucp->nextp;
              if (ucp->ticketp) 
                  free(ucp->ticketp);
              free(ucp);
          }
!         free(up);
      }
      lock_ReleaseWrite(&cm_userLock);
  }
  
  /* release the count of the # of connections that use this user structure.
!  * When this hits zero, we know we won't be getting an new requests from
   * this user, and thus we can start GC'ing connections.  Ref count on user
   * won't hit zero until all cm_conn_t's have been GC'd, since they hold
   * refCount references to userp.
--- 97,135 ----
      lock_ReleaseWrite(&cm_userLock);
  }
  
! void cm_ReleaseUser(cm_user_t *userp)
  {
      cm_ucell_t *ucp;
      cm_ucell_t *ncp;
  
!     if (userp == NULL) 
          return;
  
      lock_ObtainWrite(&cm_userLock);
!     osi_assert(userp->refCount-- > 0);
!     if (userp->refCount == 0) {
!         lock_FinalizeMutex(&userp->mx);
!         for (ucp = userp->cellInfop; ucp; ucp = ncp) {
              ncp = ucp->nextp;
              if (ucp->ticketp) 
                  free(ucp->ticketp);
              free(ucp);
          }
!         free(userp);
      }
      lock_ReleaseWrite(&cm_userLock);
  }
  
+ 
+ void cm_HoldUserVCRef(cm_user_t *userp)
+ {
+     lock_ObtainMutex(&userp->mx);
+     userp->vcRefs++;
+     lock_ReleaseMutex(&userp->mx);
+ }       
+ 
  /* release the count of the # of connections that use this user structure.
!  * When this hits zero, we know we won't be getting any new requests from
   * this user, and thus we can start GC'ing connections.  Ref count on user
   * won't hit zero until all cm_conn_t's have been GC'd, since they hold
   * refCount references to userp.
Index: openafs/src/WINNT/afsd/cm_user.h
diff -c openafs/src/WINNT/afsd/cm_user.h:1.2.20.2 openafs/src/WINNT/afsd/cm_user.h:1.2.20.3
*** openafs/src/WINNT/afsd/cm_user.h:1.2.20.2	Tue Dec  7 00:58:20 2004
--- openafs/src/WINNT/afsd/cm_user.h	Thu Jan 19 18:08:44 2006
***************
*** 48,54 ****
  } cm_user_t;
  
  #define CM_USERFLAG_DELETE	1	/* delete on last reference */
- #define CM_USERFLAG_WASLOGON	2	/* was logon DLL user */
  
  extern void cm_InitUser(void);
  
--- 48,53 ----
***************
*** 60,65 ****
--- 59,66 ----
  
  extern void cm_HoldUser(cm_user_t *up);
  
+ extern void cm_HoldUserVCRef(cm_user_t *up);
+ 
  extern void cm_ReleaseUser(cm_user_t *up);
  
  extern void cm_ReleaseUserVCRef(cm_user_t *up);
Index: openafs/src/WINNT/afsd/cm_vnodeops.c
diff -c openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.32 openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.33
*** openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.32	Sun Jan  8 23:49:17 2006
--- openafs/src/WINNT/afsd/cm_vnodeops.c	Sun Jan 15 21:06:59 2006
***************
*** 3558,3566 ****
  
          fileLock->lastUpdate = (code == 0) ? time(NULL) : 0;
  
-         osi_QAddT(&scp->fileLocksH, &scp->fileLocksT, &fileLock->fileq);
- 
          lock_ObtainWrite(&cm_scacheLock);
          cm_HoldSCacheNoLock(scp);
          fileLock->scp = scp;
          osi_QAdd(&cm_allFileLocks, &fileLock->q);
--- 3558,3565 ----
  
          fileLock->lastUpdate = (code == 0) ? time(NULL) : 0;
  
          lock_ObtainWrite(&cm_scacheLock);
+         osi_QAddT(&scp->fileLocksH, &scp->fileLocksT, &fileLock->fileq);
          cm_HoldSCacheNoLock(scp);
          fileLock->scp = scp;
          osi_QAdd(&cm_allFileLocks, &fileLock->q);
***************
*** 3899,3918 ****
          return 0;
      }
  
      /* discard lock record */
      if (scp->fileLocksT == q)
          scp->fileLocksT = osi_QPrev(q);
      osi_QRemove(&scp->fileLocksH, q);
  
-     lock_ReleaseRead(&cm_scacheLock);
- 
      /*
       * Don't delete it here; let the daemon delete it, to simplify
       * the daemon's traversal of the list.
       */
  
-     lock_ObtainWrite(&cm_scacheLock);
- 
      if(IS_LOCK_ACCEPTED(fileLock)) {
          if(fileLock->lockType == LockRead)
              scp->sharedLocks--;
--- 3898,3916 ----
          return 0;
      }
  
+     lock_ReleaseRead(&cm_scacheLock);
+ 
      /* discard lock record */
+     lock_ObtainWrite(&cm_scacheLock);
      if (scp->fileLocksT == q)
          scp->fileLocksT = osi_QPrev(q);
      osi_QRemove(&scp->fileLocksH, q);
  
      /*
       * Don't delete it here; let the daemon delete it, to simplify
       * the daemon's traversal of the list.
       */
  
      if(IS_LOCK_ACCEPTED(fileLock)) {
          if(fileLock->lockType == LockRead)
              scp->sharedLocks--;
***************
*** 4511,4519 ****
--- 4509,4519 ----
  
    handleCode:
      if (code != 0 && code != CM_ERROR_WOULDBLOCK) {
+ 	lock_ObtainWrite(&cm_scacheLock);
          if (scp->fileLocksT == &oldFileLock->fileq)
              scp->fileLocksT = osi_QPrev(&oldFileLock->fileq);
          osi_QRemove(&scp->fileLocksH, &oldFileLock->fileq);
+ 	lock_ReleaseWrite(&cm_scacheLock);
      } else if (code == 0 && IS_LOCK_WAITLOCK(oldFileLock)) {
          scp->serverLock = newLock;
      }
Index: openafs/src/WINNT/afsd/smb.c
diff -c openafs/src/WINNT/afsd/smb.c:1.55.2.35 openafs/src/WINNT/afsd/smb.c:1.55.2.41
*** openafs/src/WINNT/afsd/smb.c:1.55.2.35	Tue Jan 10 08:28:01 2006
--- openafs/src/WINNT/afsd/smb.c	Tue Jan 24 12:16:06 2006
***************
*** 41,51 ****
  smb_vc_t *dead_vcp = NULL;
  smb_vc_t *active_vcp = NULL;
  
- /* TODO; logout mechanism needs to be thread-safe */
- char *loggedOutName = NULL;
- smb_user_t *loggedOutUserp = NULL;
- time_t loggedOutTime;
- int loggedOut = 0;
  int smbShutdownFlag = 0;
  
  int smb_LogoffTokenTransfer;
--- 41,46 ----
***************
*** 94,113 ****
  ULONG smb_lsaSecPackage;
  LSA_STRING smb_lsaLogonOrigin;
  
! #define NCBmax MAXIMUM_WAIT_OBJECTS
! EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
  EVENT_HANDLE **NCBreturns;
  EVENT_HANDLE **NCBShutdown;
  EVENT_HANDLE *smb_ServerShutdown;
! DWORD NCBsessions[NCBmax];
! NCB *NCBs[NCBmax];
! struct smb_packet *bufs[NCBmax];
! 
! #define Sessionmax MAXIMUM_WAIT_OBJECTS - 4
! EVENT_HANDLE SessionEvents[Sessionmax];
! unsigned short LSNs[Sessionmax];
! int lanas[Sessionmax];
! BOOL dead_sessions[Sessionmax];
  LANA_ENUM lana_list;
  
  /* for raw I/O */
--- 89,108 ----
  ULONG smb_lsaSecPackage;
  LSA_STRING smb_lsaLogonOrigin;
  
! #define NCB_MAX MAXIMUM_WAIT_OBJECTS
! EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX];
  EVENT_HANDLE **NCBreturns;
  EVENT_HANDLE **NCBShutdown;
  EVENT_HANDLE *smb_ServerShutdown;
! DWORD NCBsessions[NCB_MAX];
! NCB *NCBs[NCB_MAX];
! struct smb_packet *bufs[NCB_MAX];
! 
! #define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4
! EVENT_HANDLE SessionEvents[SESSION_MAX];
! unsigned short LSNs[SESSION_MAX];
! int lanas[SESSION_MAX];
! BOOL dead_sessions[SESSION_MAX];
  LANA_ENUM lana_list;
  
  /* for raw I/O */
***************
*** 172,177 ****
--- 167,173 ----
  char *smb_localNamep = NULL;
  
  smb_vc_t *smb_allVCsp;
+ smb_vc_t *smb_deadVCsp;
  
  smb_username_t *usernamesp = NULL;
  
***************
*** 179,185 ****
  
  /* forward decl */
  void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
! 						NCB *ncbp, raw_write_cont_t *rwcp);
  void smb_NetbiosInit();
  #ifdef DJGPP
  #ifndef AFS_WIN95_ENV
--- 175,181 ----
  
  /* forward decl */
  void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
! 			NCB *ncbp, raw_write_cont_t *rwcp);
  void smb_NetbiosInit();
  #ifdef DJGPP
  #ifndef AFS_WIN95_ENV
***************
*** 820,830 ****
      if (!vcp && (flags & SMB_FLAG_CREATE)) {
          vcp = malloc(sizeof(*vcp));
          memset(vcp, 0, sizeof(*vcp));
!         vcp->vcID = numVCs++;
!         vcp->refCount = 1;
          vcp->tidCounter = 1;
          vcp->fidCounter = 1;
!         vcp->uidCounter = 1;  /* UID 0 is reserved for blank user */
          vcp->nextp = smb_allVCsp;
          smb_allVCsp = vcp;
          lock_InitializeMutex(&vcp->mx, "vc_t mutex");
--- 816,828 ----
      if (!vcp && (flags & SMB_FLAG_CREATE)) {
          vcp = malloc(sizeof(*vcp));
          memset(vcp, 0, sizeof(*vcp));
! 	lock_ObtainWrite(&smb_globalLock);
!         vcp->vcID = ++numVCs;
! 	lock_ReleaseWrite(&smb_globalLock);
!         vcp->refCount = 2; 	/* smb_allVCsp and caller */
          vcp->tidCounter = 1;
          vcp->fidCounter = 1;
!         vcp->uidCounter = 1;  	/* UID 0 is reserved for blank user */
          vcp->nextp = smb_allVCsp;
          smb_allVCsp = vcp;
          lock_InitializeMutex(&vcp->mx, "vc_t mutex");
***************
*** 862,868 ****
--- 860,868 ----
              memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
  
          if (numVCs >= CM_SESSION_RESERVED) {
+ 	    lock_ObtainWrite(&smb_globalLock);
              numVCs = 0;
+ 	    lock_ReleaseWrite(&smb_globalLock);
              osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
          }
      }
***************
*** 882,906 ****
      return 0;
  }
  
! void smb_ReleaseVCNoLock(smb_vc_t *vcp)
  {
!     osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
  #ifdef DEBUG
      osi_assert(vcp->refCount-- != 0);
  #else
      vcp->refCount--;
  #endif
  }       
  
  void smb_ReleaseVC(smb_vc_t *vcp)
  {
      lock_ObtainWrite(&smb_rctLock);
      osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
! #ifdef DEBUG
!     osi_assert(vcp->refCount-- != 0);
! #else
!     vcp->refCount--;
! #endif
      lock_ReleaseWrite(&smb_rctLock);
  }       
  
--- 882,922 ----
      return 0;
  }
  
! void smb_ReleaseVCInternal(smb_vc_t *vcp)
  {
!     smb_vc_t **vcpp;
! 
  #ifdef DEBUG
      osi_assert(vcp->refCount-- != 0);
  #else
      vcp->refCount--;
  #endif
+ 
+     if (vcp->refCount == 0) {
+         /* remove VCP from smb_deadVCsp */
+         for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+             if (*vcpp == vcp) {
+                 *vcpp = vcp->nextp;
+                 break;
+             }
+         }
+ 	
+ 	memset(vcp,0,sizeof(smb_vc_t));
+ 	free(vcp);
+     }
+ }
+ 
+ void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+ {
+     osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+     smb_ReleaseVCInternal(vcp);
  }       
  
  void smb_ReleaseVC(smb_vc_t *vcp)
  {
      lock_ObtainWrite(&smb_rctLock);
      osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
!     smb_ReleaseVCInternal(vcp);
      lock_ReleaseWrite(&smb_rctLock);
  }       
  
***************
*** 922,941 ****
  {
      smb_fid_t *fidpIter;
      smb_fid_t *fidpNext;
-     smb_fid_t *fidp;
      unsigned short fid;
      smb_tid_t *tidpIter;
      smb_tid_t *tidpNext;
-     smb_tid_t *tidp;
      unsigned short tid;
!     smb_user_t *userpIter;
!     smb_user_t *userpNext;
!     smb_user_t *userp;
      unsigned short uid;
  
      osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
  
!     lock_ObtainRead(&smb_rctLock);
      for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
          fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
  
--- 938,955 ----
  {
      smb_fid_t *fidpIter;
      smb_fid_t *fidpNext;
      unsigned short fid;
      smb_tid_t *tidpIter;
      smb_tid_t *tidpNext;
      unsigned short tid;
!     smb_user_t *uidpIter;
!     smb_user_t *uidpNext;
      unsigned short uid;
+     smb_vc_t **vcpp;
  
      osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
  
!     lock_ObtainWrite(&smb_rctLock);
      for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
          fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
  
***************
*** 944,957 ****
  
          fid = fidpIter->fid;
  	osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
-         lock_ReleaseRead(&smb_rctLock);
  
!         fidp = smb_FindFID(vcp, fid, 0);
!         osi_assert(fidp);
!         smb_CloseFID(vcp, fidp, NULL, 0);
!         smb_ReleaseFID(fidp);
  
!         lock_ObtainRead(&smb_rctLock);
      }
  
      for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
--- 958,973 ----
  
          fid = fidpIter->fid;
  	osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
  
! 	smb_HoldFIDNoLock(fidpIter);
! 	lock_ReleaseWrite(&smb_rctLock);
  
! 	/* smb_CloseFID sets SMB_FID_DELETE */
!         if (smb_CloseFID(vcp, fidpIter, NULL, 0) == 0)
! 	    smb_ReleaseFID(fidpIter);
! 
!         lock_ObtainWrite(&smb_rctLock);
! 	fidpNext = vcp->fidsp;
      }
  
      for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
***************
*** 961,1005 ****
  
  	tid = tidpIter->tid;
  	osi_Log2(smb_logp, "  Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
- 	lock_ReleaseRead(&smb_rctLock);
  
! 	tidp = smb_FindTID(vcp, tid, 0);
! 	osi_assert(tidp);
  
! 	lock_ObtainMutex(&tidp->mx);
! 	tidp->flags |= SMB_TIDFLAG_DELETE;
! 	lock_ReleaseMutex(&tidp->mx);
  
! 	smb_ReleaseTID(tidp);
  
! 	lock_ObtainRead(&smb_rctLock);
      }
  
!     for (userpIter = vcp->usersp; userpIter; userpIter = userpNext) {
! 	userpNext = userpIter->nextp;
! 
! 	if (userpIter->flags & SMB_USERFLAG_DELETE)
  	    continue;
  
! 	uid = userpIter->userID;
! 	osi_Log2(smb_logp, "  Cleanup UID %d (userp=0x%x)", uid, userpIter);
! 	lock_ReleaseRead(&smb_rctLock);
! 
! 	userp = smb_FindUID(vcp, uid, 0);
! 	osi_assert(userp);
  
! 	lock_ObtainMutex(&userp->mx);
! 	userp->flags |= SMB_USERFLAG_DELETE;
! 	lock_ReleaseMutex(&userp->mx);
! 
! 	smb_ReleaseUID(userp);
! 
! 	lock_ObtainRead(&smb_rctLock);
      }
! 
!     lock_ReleaseRead(&smb_rctLock);
! 
!     osi_Log0(smb_logp, "Done cleaning up dead vcp");
  }
  
  smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
--- 977,1034 ----
  
  	tid = tidpIter->tid;
  	osi_Log2(smb_logp, "  Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
  
! 	smb_HoldTIDNoLock(tidpIter);
! 	lock_ReleaseWrite(&smb_rctLock);
  
! 	lock_ObtainMutex(&tidpIter->mx);
! 	tidpIter->flags |= SMB_TIDFLAG_DELETE;
! 	lock_ReleaseMutex(&tidpIter->mx);
  
! 	smb_ReleaseTID(tidpIter);
  
! 	lock_ObtainWrite(&smb_rctLock);
! 	tidpNext = vcp->tidsp;
      }
  
!     for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
! 	uidpNext = uidpIter->nextp;
! 	if (uidpIter->flags & SMB_USERFLAG_DELETE)
  	    continue;
  
! 	uid = uidpIter->userID;
! 	osi_Log2(smb_logp, "  Cleanup UID %d (uidp=0x%x)", uid, uidpIter);
  
! 	/* do not add an additional reference count for the smb_user_t 
! 	 * as the smb_vc_t already is holding a reference */
! 	lock_ReleaseWrite(&smb_rctLock);
! 
! 	lock_ObtainMutex(&uidpIter->mx);
! 	uidpIter->flags |= SMB_USERFLAG_DELETE;
! 	lock_ReleaseMutex(&uidpIter->mx);
! 
! 	smb_ReleaseUID(uidpIter);
! 
! 	lock_ObtainWrite(&smb_rctLock);
! 	uidpNext = vcp->usersp;
!     }
! 
!     /* remove VCP from smb_allVCsp */
!     for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
!         if (*vcpp == vcp) {
!             *vcpp = vcp->nextp;
!             vcp->nextp = smb_deadVCsp;
!             smb_deadVCsp = vcp;
!             /* We intentionally do not keep a reference to the
!              * vcp once it is placed on the deadVCsp list.  This
!              * allows the refcount to reach 0 so we can delete
!              * it. */
!             smb_ReleaseVCNoLock(vcp);
!             break;
!         }
      }
!     lock_ReleaseWrite(&smb_rctLock);
!     osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
  }
  
  smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
***************
*** 1028,1033 ****
--- 1057,1067 ----
      return tidp;
  }       	
  
+ void smb_HoldTIDNoLock(smb_tid_t *tidp)
+ {
+     tidp->refCount++;
+ }
+ 
  void smb_ReleaseTID(smb_tid_t *tidp)
  {
      smb_tid_t *tp;
***************
*** 1049,1055 ****
          userp = tidp->userp;	/* remember to drop ref later */
          tidp->userp = NULL;
          smb_ReleaseVCNoLock(tidp->vcp);
!         tidp->vcp = 0;
      }
      lock_ReleaseWrite(&smb_rctLock);
      if (userp)
--- 1083,1089 ----
          userp = tidp->userp;	/* remember to drop ref later */
          tidp->userp = NULL;
          smb_ReleaseVCNoLock(tidp->vcp);
!         tidp->vcp = NULL;
      }
      lock_ReleaseWrite(&smb_rctLock);
      if (userp)
***************
*** 1074,1080 ****
          uidp = malloc(sizeof(*uidp));
          memset(uidp, 0, sizeof(*uidp));
          uidp->nextp = vcp->usersp;
!         uidp->refCount = 1;
          uidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->usersp = uidp;
--- 1108,1114 ----
          uidp = malloc(sizeof(*uidp));
          memset(uidp, 0, sizeof(*uidp));
          uidp->nextp = vcp->usersp;
!         uidp->refCount = 2; /* one for the vcp and one for the caller */
          uidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->usersp = uidp;
***************
*** 1086,1092 ****
      return uidp;
  }       	
  
! smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
  {
      smb_username_t *unp= NULL;
  
--- 1120,1126 ----
      return uidp;
  }       	
  
! smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
  {
      smb_username_t *unp= NULL;
  
***************
*** 1107,1113 ****
--- 1141,1150 ----
          unp->machine = strdup(machine);
          usernamesp = unp;
          lock_InitializeMutex(&unp->mx, "username_t mutex");
+ 	if (flags & SMB_FLAG_AFSLOGON)
+ 	    unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
      }
+ 
      lock_ReleaseWrite(&smb_rctLock);
      return unp;
  }	
***************
*** 1136,1145 ****
      smb_username_t *up;
      smb_username_t **lupp;
      cm_user_t *userp = NULL;
  
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(unp->refCount-- > 0);
!     if (unp->refCount == 0) {
          lupp = &usernamesp;
          for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
              if (up == unp) 
--- 1173,1184 ----
      smb_username_t *up;
      smb_username_t **lupp;
      cm_user_t *userp = NULL;
+     time_t 	now = osi_Time();
  
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(unp->refCount-- > 0);
!     if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
! 	(unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
          lupp = &usernamesp;
          for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
              if (up == unp) 
***************
*** 1147,1152 ****
--- 1186,1192 ----
          }
          osi_assert(up != NULL);
          *lupp = up->nextp;
+ 	up->nextp = NULL;			/* do not remove this */
          lock_FinalizeMutex(&unp->mx);
  	userp = unp->userp;
  	free(unp->name);
***************
*** 1156,1166 ****
      lock_ReleaseWrite(&smb_rctLock);
  
      if (userp) {
-         cm_ReleaseUserVCRef(userp);
          cm_ReleaseUser(userp);
      }	
  }	
  
  void smb_ReleaseUID(smb_user_t *uidp)
  {
      smb_user_t *up;
--- 1196,1210 ----
      lock_ReleaseWrite(&smb_rctLock);
  
      if (userp) {
          cm_ReleaseUser(userp);
      }	
  }	
  
+ void smb_HoldUIDNoLock(smb_user_t *uidp)
+ {
+     uidp->refCount++;
+ }
+ 
  void smb_ReleaseUID(smb_user_t *uidp)
  {
      smb_user_t *up;
***************
*** 1169,1175 ****
  
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(uidp->refCount-- > 0);
!     if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
          lupp = &uidp->vcp->usersp;
          for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
              if (up == uidp) 
--- 1213,1219 ----
  
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(uidp->refCount-- > 0);
!     if (uidp->refCount == 0) {
          lupp = &uidp->vcp->usersp;
          for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
              if (up == uidp) 
***************
*** 1180,1191 ****
          lock_FinalizeMutex(&uidp->mx);
  	unp = uidp->unp;
          smb_ReleaseVCNoLock(uidp->vcp);
  	free(uidp);
      }		
      lock_ReleaseWrite(&smb_rctLock);
  
!     if (unp)
  	smb_ReleaseUsername(unp);
  }	
  
  /* retrieve a held reference to a user structure corresponding to an incoming
--- 1224,1239 ----
          lock_FinalizeMutex(&uidp->mx);
  	unp = uidp->unp;
          smb_ReleaseVCNoLock(uidp->vcp);
+ 	uidp->vcp = NULL;
  	free(uidp);
      }		
      lock_ReleaseWrite(&smb_rctLock);
  
!     if (unp) {
! 	if (unp->userp)
! 	    cm_ReleaseUserVCRef(unp->userp);
  	smb_ReleaseUsername(unp);
+     }
  }	
  
  /* retrieve a held reference to a user structure corresponding to an incoming
***************
*** 1195,1215 ****
  cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
  {
      smb_user_t *uidp;
!     cm_user_t *up;
      smb_t *smbp;
  
      smbp = (smb_t *) inp;
      uidp = smb_FindUID(vcp, smbp->uid, 0);
!     if ((!uidp) ||  (!uidp->unp))
!         return NULL;
! 
      lock_ObtainMutex(&uidp->mx);
!     up = uidp->unp->userp;
!     cm_HoldUser(up);
      lock_ReleaseMutex(&uidp->mx);
  
      smb_ReleaseUID(uidp);
- 
      return up;
  }
  
--- 1243,1264 ----
  cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
  {
      smb_user_t *uidp;
!     cm_user_t *up = NULL;
      smb_t *smbp;
  
      smbp = (smb_t *) inp;
      uidp = smb_FindUID(vcp, smbp->uid, 0);
!     if (!uidp)
! 	return NULL;
!     
      lock_ObtainMutex(&uidp->mx);
!     if (uidp->unp) {
! 	up = uidp->unp->userp;
! 	cm_HoldUser(up);
!     }
      lock_ReleaseMutex(&uidp->mx);
  
      smb_ReleaseUID(uidp);
      return up;
  }
  
***************
*** 1323,1348 ****
                  osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
                           vcp);
                  vcp->fidCounter = 1;
!         }
!     }
      }
  
      lock_ReleaseWrite(&smb_rctLock);
      return fidp;
  }
  
  void smb_ReleaseFID(smb_fid_t *fidp)
  {
!     cm_scache_t *scp;
!     cm_user_t *userp;
      smb_vc_t *vcp = NULL;
      smb_ioctl_t *ioctlp;
  
      if (!fidp)
          return;
  
-     scp = NULL;
-     userp = NULL;
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(fidp->refCount-- > 0);
      if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
--- 1372,1400 ----
                  osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
                           vcp);
                  vcp->fidCounter = 1;
! 	    }
! 	}
      }
  
      lock_ReleaseWrite(&smb_rctLock);
      return fidp;
  }
  
+ void smb_HoldFIDNoLock(smb_fid_t *fidp)
+ {
+     fidp->refCount++;
+ }
+ 
  void smb_ReleaseFID(smb_fid_t *fidp)
  {
!     cm_scache_t *scp = NULL;
!     cm_user_t *userp = NULL;
      smb_vc_t *vcp = NULL;
      smb_ioctl_t *ioctlp;
  
      if (!fidp)
          return;
  
      lock_ObtainWrite(&smb_rctLock);
      osi_assert(fidp->refCount-- > 0);
      if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
***************
*** 1370,1376 ****
  
          free(fidp);
  
!         smb_ReleaseVCNoLock(vcp);
      }
      lock_ReleaseWrite(&smb_rctLock);
  
--- 1422,1429 ----
  
          free(fidp);
  
! 	if (vcp)
! 	    smb_ReleaseVCNoLock(vcp);
      }
      lock_ReleaseWrite(&smb_rctLock);
  
***************
*** 2002,2009 ****
      tbp = GetPacket();
      memcpy(tbp, pkt, sizeof(smb_packet_t));
      tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
! 	if (tbp->vcp)
! 		smb_HoldVC(tbp->vcp);
      return tbp;
  }
  
--- 2055,2062 ----
      tbp = GetPacket();
      memcpy(tbp, pkt, sizeof(smb_packet_t));
      tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
!     if (tbp->vcp)
! 	smb_HoldVC(tbp->vcp);
      return tbp;
  }
  
***************
*** 2425,2430 ****
--- 2478,2504 ----
              s = "unknown error";
          }
          osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
+ 	osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
+ 		  vcp, vcp->usersp);
+ 	smb_HoldVC(vcp);
+ 	lock_ObtainMutex(&vcp->mx);
+ 	vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ 	lock_ReleaseMutex(&vcp->mx);
+ 
+ 	lock_ObtainWrite(&smb_globalLock);
+ 	if (dead_vcp) {
+ 	    smb_vc_t * dvcp = dead_vcp;
+ 	    dead_vcp = vcp;
+ 	    dead_sessions[vcp->session] = TRUE;
+ 	    lock_ReleaseWrite(&smb_globalLock);
+ 	    osi_Log1(smb_logp,"Previous dead_vcp %x", dvcp);
+ 	    smb_CleanupDeadVC(dvcp);
+ 	    smb_ReleaseVC(dvcp);
+ 	} else {
+ 	    dead_vcp = vcp;
+ 	    dead_sessions[vcp->session] = TRUE;
+ 	    lock_ReleaseWrite(&smb_globalLock);
+ 	}
      }
  
      if (localNCB)
***************
*** 2977,3002 ****
  
      osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
  			 ongoingOps - 1);
-     if (!isGateway) {
-         if (active_vcp) {
-             DWORD now = GetCurrentTime();
-             if (now - last_msg_time >= 30000
-                  && now - last_msg_time <= 90000) {
-                 osi_Log1(smb_logp,
-                           "Setting dead_vcp %x", active_vcp);
-                 if (dead_vcp) {
-                     smb_ReleaseVC(dead_vcp);
-                     osi_Log1(smb_logp,
-                              "Previous dead_vcp %x", dead_vcp);
-                 }
-                 smb_HoldVC(active_vcp);
-                 dead_vcp = active_vcp;
-                 dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-             }
-         }
-     }
- 
-     inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
  
      namep = smb_GetSMBData(inp, &dbytes);
      namex = 0;
--- 3051,3056 ----
***************
*** 3187,3195 ****
--- 3241,3281 ----
      return 0;
  }
  
+ void smb_CheckVCs(void)
+ {
+     smb_vc_t * vcp;
+     smb_packet_t * outp = GetPacket();
+     smb_t *smbp;
+             
+     for ( vcp=smb_allVCsp; vcp; vcp = vcp->nextp ) 
+     {
+ 	if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+ 	    continue;
+ 
+ 	smb_FormatResponsePacket(vcp, NULL, outp);
+         smbp = (smb_t *)outp;
+ 	outp->inCom = smbp->com = 0x2b /* Echo */;
+         smbp->tid = 0xFFFF;
+         smbp->pid = 0;
+         smbp->uid = 0;
+         smbp->mid = 0;
+         smbp->res[0] = 0;
+         smbp->res[1] = 0;
+ 
+ 	smb_SetSMBParm(outp, 0, 0);
+ 	smb_SetSMBDataLength(outp, 0);
+ 
+ 	smb_SendPacket(vcp, outp);
+     }
+ 
+     smb_FreePacket(outp);
+ }
+ 
  void smb_Daemon(void *parmp)
  {
      afs_uint32 count = 0;
+     smb_username_t    **unpp;
+     time_t 		now;
  
      while(smbShutdownFlag == 0) {
          count++;
***************
*** 3219,3225 ****
              if ( smb_localZero != old_localZero )
                  cm_noteLocalMountPointChange();
  #endif
!         }
          /* XXX GC dir search entries */
      }
  }
--- 3305,3358 ----
              if ( smb_localZero != old_localZero )
                  cm_noteLocalMountPointChange();
  #endif
! 
! 	    smb_CheckVCs();
! 	}
! 
! 	/* XXX GC the smb_username_t objects with refCount 0 and
! 	 * neither SMB_USERNAMEFLAG_AFSLOGON nor (SMB_USERNAMEFLAG_LOGOFF
! 	 * && smb_LogoffTokenTransfer && 
! 	 * now > last_logoff_t + smb_LogoffTransferTimeout) 
! 	 */
! 	now = osi_Time();
! 	lock_ObtainWrite(&smb_rctLock);
! 	for ( unpp=&usernamesp; *unpp; ) {
! 	    int delete = 0;
! 	    smb_username_t *unp;
! 
! 	    lock_ObtainMutex(&(*unpp)->mx);
! 	    if ( (*unpp)->refCount > 0 )
! 		;
! 	    else if ((*unpp)->flags & SMB_USERNAMEFLAG_AFSLOGON)
! 		;
! 	    else if (!(((*unpp)->flags & SMB_USERNAMEFLAG_LOGOFF) && smb_LogoffTokenTransfer))
! 		delete = 1;
! 	    else if ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now)
! 		delete = 1;
! 	    lock_ReleaseMutex(&(*unpp)->mx);
! 
! 	    if (delete) {
! 		cm_user_t * userp;
! 
! 		unp = *unpp;	
! 		*unpp = unp->nextp;
! 		unp->nextp = NULL;
! 		lock_FinalizeMutex(&unp->mx);
! 		userp = unp->userp;
! 		free(unp->name);
! 		free(unp->machine);
! 		free(unp);
! 		if (userp) {
! 		    lock_ReleaseWrite(&smb_rctLock);
! 		    cm_ReleaseUser(userp);
! 		    lock_ObtainWrite(&smb_rctLock);
! 		}
! 	    } else {
! 		unpp = &(*unpp)->nextp;
! 	    }
! 	}
! 	lock_ReleaseWrite(&smb_rctLock);
! 
          /* XXX GC dir search entries */
      }
  }
***************
*** 3983,3989 ****
                       LargeIntegerGreaterThanOrEqualTo(thyper, 
                                                        scp->bulkStatProgress)) {
                      /* Don't bulk stat if risking timeout */
!                     int now = GetCurrentTime();
                      if (now - req.startTime > 5000) {
                          scp->bulkStatProgress = thyper;
                          scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
--- 4116,4122 ----
                       LargeIntegerGreaterThanOrEqualTo(thyper, 
                                                        scp->bulkStatProgress)) {
                      /* Don't bulk stat if risking timeout */
!                     int now = GetTickCount();
                      if (now - req.startTime > 5000) {
                          scp->bulkStatProgress = thyper;
                          scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
***************
*** 5529,5543 ****
                    afs_uint32 dosTime) {
      long code = 0;
      cm_req_t req;
  
      osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
               fidp, fidp->fid, vcp);
  
      if (!userp) {
!         if (!fidp->userp) {
!             osi_Log0(smb_logp, "  No user specified.  Not closing fid");
!         return CM_ERROR_BADFD;
!     }
          
          userp = fidp->userp;    /* no hold required since fidp is held
                                     throughout the function */
--- 5662,5678 ----
                    afs_uint32 dosTime) {
      long code = 0;
      cm_req_t req;
+     cm_scache_t *dscp = fidp->NTopen_dscp;
+     char *pathp = fidp->NTopen_pathp;
  
      osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
               fidp, fidp->fid, vcp);
  
      if (!userp) {
!         if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
!             osi_Log0(smb_logp, "  No user specified.  Not closing fid.");
! 	    return CM_ERROR_BADFD;
! 	}
          
          userp = fidp->userp;    /* no hold required since fidp is held
                                     throughout the function */
***************
*** 5547,5552 ****
--- 5682,5695 ----
  
      lock_ObtainMutex(&fidp->mx);
  
+     if (fidp->flags & SMB_FID_DELETE) {
+ 	osi_Log0(smb_logp, "  Fid already closed.");
+ 	lock_ReleaseMutex(&fidp->mx);
+ 	return CM_ERROR_BADFD;
+     }
+ 
+     fidp->flags |= SMB_FID_DELETE;
+         
      /* Don't jump the gun on an async raw write */
      while (fidp->raw_writers) {
          lock_ReleaseMutex(&fidp->mx);
***************
*** 5554,5561 ****
          lock_ObtainMutex(&fidp->mx);
      }
  
-     fidp->flags |= SMB_FID_DELETE;
-         
      /* watch for ioctl closes, and read-only opens */
      if (fidp->scp != NULL &&
          (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
--- 5697,5702 ----
***************
*** 5607,5614 ****
      }
  
      if (fidp->flags & SMB_FID_DELONCLOSE) {
-         cm_scache_t *dscp = fidp->NTopen_dscp;
-         char *pathp = fidp->NTopen_pathp;
          char *fullPathp;
  
          smb_FullName(dscp, fidp->scp, pathp, &fullPathp, userp, &req);
--- 5748,5753 ----
***************
*** 5626,5643 ****
                                   dscp, fullPathp, NULL, TRUE);
          }
          free(fullPathp);
      }
-     lock_ReleaseMutex(&fidp->mx);
  
      if (fidp->flags & SMB_FID_NTOPEN) {
!         cm_ReleaseSCache(fidp->NTopen_dscp);
!         free(fidp->NTopen_pathp);
          fidp->NTopen_pathp = NULL;
      }
      if (fidp->NTopen_wholepathp) {
          free(fidp->NTopen_wholepathp);
          fidp->NTopen_wholepathp = NULL;
      }
  
      return code;
  }
--- 5765,5789 ----
                                   dscp, fullPathp, NULL, TRUE);
          }
          free(fullPathp);
+ 	fidp->flags &= ~SMB_FID_DELONCLOSE;
      }
  
      if (fidp->flags & SMB_FID_NTOPEN) {
! 	fidp->NTopen_dscp = NULL;
          fidp->NTopen_pathp = NULL;
+ 	fidp->flags &= ~SMB_FID_NTOPEN;
      }
      if (fidp->NTopen_wholepathp) {
          free(fidp->NTopen_wholepathp);
          fidp->NTopen_wholepathp = NULL;
      }
+     lock_ReleaseMutex(&fidp->mx);
+ 
+     if (dscp)
+ 	cm_ReleaseSCache(dscp);
+ 
+     if (pathp)
+ 	free(pathp);
  
      return code;
  }
***************
*** 6915,6921 ****
  
      /* Remember session generation number and time */
      oldGen = sessionGen;
!     oldTime = GetCurrentTime();
  
      while (inp->inCom != 0xff) {
          dp = &smb_dispatchTable[inp->inCom];
--- 7061,7067 ----
  
      /* Remember session generation number and time */
      oldGen = sessionGen;
!     oldTime = GetTickCount();
  
      while (inp->inCom != 0xff) {
          dp = &smb_dispatchTable[inp->inCom];
***************
*** 6959,6966 ****
  
              if (inp->inCom == 0x1d)
                  /* Raw Write */
!                 code = smb_ReceiveCoreWriteRaw (vcp, inp, outp,
!                                                  rwcp);
              else {
                  osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp 0x%x lana %d lsn %d",(int)vcp,vcp->lana,vcp->lsn);
                  osi_Log4(smb_logp,"Dispatch %s vcp 0x%x lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
--- 7105,7111 ----
  
              if (inp->inCom == 0x1d)
                  /* Raw Write */
!                 code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
              else {
                  osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp 0x%x lana %d lsn %d",(int)vcp,vcp->lana,vcp->lsn);
                  osi_Log4(smb_logp,"Dispatch %s vcp 0x%x lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
***************
*** 6979,6985 ****
                  HANDLE h;
                  char *ptbuf[1];
                  char s[100];
!                 newTime = GetCurrentTime();
                  h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                  sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d",
                           newTime - oldTime, ncbp->ncb_length);
--- 7124,7130 ----
                  HANDLE h;
                  char *ptbuf[1];
                  char s[100];
!                 newTime = GetTickCount();
                  h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                  sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d",
                           newTime - oldTime, ncbp->ncb_length);
***************
*** 7132,7149 ****
          outWctp = tp;
      }	/* while loop over all requests in the packet */
  
-     /* done logging out, turn off logging-out flag */
-     if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) {
-         vcp->justLoggedOut = NULL;
-         if (loggedOut) {
-             loggedOut = 0;
-             free(loggedOutName);
-             loggedOutName = NULL;
-             smb_ReleaseUID(loggedOutUserp);
-             loggedOutUserp = NULL;
-         }
-     }
-  
      /* now send the output packet, and return */
      if (!noSend)
          smb_SendPacket(vcp, outp);
--- 7277,7282 ----
***************
*** 7152,7170 ****
      if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
          if (active_vcp != vcp) {
              if (active_vcp) {
-                 smb_ReleaseVC(active_vcp);
                  osi_Log2(smb_logp,
                        "Replacing active_vcp %x with %x", active_vcp, vcp);
              }
              smb_HoldVC(vcp);
              active_vcp = vcp;
          }
!         last_msg_time = GetCurrentTime();
!     } else if (active_vcp == vcp) {
          smb_ReleaseVC(active_vcp);
          active_vcp = NULL;
      }
- 
      return;
  }
  
--- 7285,7306 ----
      if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
          if (active_vcp != vcp) {
              if (active_vcp) {
                  osi_Log2(smb_logp,
                        "Replacing active_vcp %x with %x", active_vcp, vcp);
+                 smb_ReleaseVC(active_vcp);
              }
              smb_HoldVC(vcp);
+ 	    lock_ObtainWrite(&smb_globalLock);
              active_vcp = vcp;
+ 	    lock_ReleaseWrite(&smb_globalLock);
          }
!         last_msg_time = GetTickCount();
!     } else if (active_vcp == vcp) { 	/* the vcp is dead */
          smb_ReleaseVC(active_vcp);
+ 	lock_ObtainWrite(&smb_globalLock);
          active_vcp = NULL;
+ 	lock_ReleaseWrite(&smb_globalLock);
      }
      return;
  }
  
***************
*** 7377,7382 ****
--- 7513,7522 ----
      outbufp->ncbp = outncbp;
  
      while (1) {
+ 	if (vcp) {
+ 	    smb_ReleaseVC(vcp);
+ 	    vcp = NULL;
+ 	}
          code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                   FALSE, INFINITE);
  
***************
*** 7550,7555 ****
--- 7690,7696 ----
  
          switch (rc) {
          case NRC_GOODRET: 
+             vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
              break;
  
          case NRC_PENDING:
***************
*** 7557,7603 ****
              osi_Log2(smb_logp, "NCBRECV pending lsn %d session %d", ncbp->ncb_lsn, idx_session);
              continue;
  
-         case NRC_SCLOSED:
          case NRC_SNUMOUT:
  	case NRC_SABORT:
              /* Client closed session */
-             dead_sessions[idx_session] = TRUE;
-             if (vcp)
-                 smb_ReleaseVC(vcp);
              vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-             /* Should also release vcp.  [done] 2004-05-11 jaltman
-              * Also, should do
-              * sanity check that all TID's are gone. 
-              *
-              * TODO: check if we could use LSNs[idx_session] instead, 
-              * also cleanup after dead vcp 
-              */
              if (vcp) {
!                 if (dead_vcp == vcp)
                      osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp);
!                 else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
                      osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
                               vcp, vcp->usersp);
-                     smb_HoldVC(vcp);
                      if (dead_vcp) {
!                         smb_ReleaseVC(dead_vcp);
!                         osi_Log1(smb_logp,
!                                   "Previous dead_vcp %x", dead_vcp);
!                     }
!                     dead_vcp = vcp;
                      vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
!                 }
! 
!                 smb_CleanupDeadVC(vcp);
! 
!                 if (vcp->justLoggedOut) {
!                     loggedOut = 1;
!                     loggedOutTime = vcp->logoffTime;
!                     loggedOutName = strdup(vcp->justLoggedOut->unp->name);
!                     loggedOutUserp = vcp->justLoggedOut;
!                     lock_ObtainWrite(&smb_rctLock);
!                     loggedOutUserp->refCount++;
!                     lock_ReleaseWrite(&smb_rctLock);
                  }
              }
              goto doneWithNCB;
--- 7698,7733 ----
              osi_Log2(smb_logp, "NCBRECV pending lsn %d session %d", ncbp->ncb_lsn, idx_session);
              continue;
  
          case NRC_SNUMOUT:
  	case NRC_SABORT:
+ 	case NRC_SCLOSED:
              /* Client closed session */
              vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
              if (vcp) {
! 		lock_ObtainWrite(&smb_globalLock);
! 		if (dead_vcp == vcp) {
                      osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp);
! 		    lock_ReleaseWrite(&smb_globalLock);
! 		} else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
                      osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
                               vcp, vcp->usersp);
                      if (dead_vcp) {
! 			smb_vc_t * dvcp = dead_vcp;
! 			dead_vcp = vcp;		/* transfer the reference */
! 			dead_sessions[vcp->session] = TRUE;
! 			lock_ReleaseWrite(&smb_globalLock);
!                         osi_Log1(smb_logp,"Previous dead_vcp %x", dvcp);
! 			smb_CleanupDeadVC(dvcp);
!                         smb_ReleaseVC(dvcp);
!                     } else {
! 			dead_vcp = vcp;		/* transfer the reference */
! 			dead_sessions[vcp->session] = TRUE;
! 			lock_ReleaseWrite(&smb_globalLock);
! 		    }
! 		    lock_ObtainMutex(&vcp->mx);
                      vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
! 		    lock_ReleaseMutex(&vcp->mx);
! 		    vcp = NULL;
                  }
              }
              goto doneWithNCB;
***************
*** 7633,7647 ****
                   *
                   continue;
                   */
                  break;
              }
  
          default:
!             /* A weird error code.  Log it, sleep, and
!             * continue. */
              if (vcp && vcp->errorCount++ > 3) {
                  osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
!                 dead_sessions[idx_session] = TRUE;
              }
              else {
                  thrd_Sleep(1000);
--- 7763,7800 ----
                   *
                   continue;
                   */
+ 		vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
                  break;
              }
  
          default:
!             /* A weird error code.  Log it, sleep, and continue. */
! 	    vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
              if (vcp && vcp->errorCount++ > 3) {
                  osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
! 		lock_ObtainWrite(&smb_globalLock);
!  		if (dead_vcp == vcp) {
!                      osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp);
! 		    lock_ReleaseWrite(&smb_globalLock);
! 		} else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
! 		    osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
!                               vcp, vcp->usersp);
! 		    if (dead_vcp) {
! 			smb_vc_t * dvcp = dead_vcp;
! 			dead_vcp = vcp;		/* transfer reference */
! 			dead_sessions[vcp->session] = TRUE;
! 			lock_ReleaseWrite(&smb_globalLock);
! 
! 			osi_Log1(smb_logp,"Previous dead_vcp %x", dvcp);
! 			smb_CleanupDeadVC(dvcp);
! 			smb_ReleaseVC(dvcp);
! 		    }
! 		    lock_ObtainMutex(&vcp->mx);
! 		    vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
! 		    lock_ReleaseMutex(&vcp->mx);
! 		    vcp = NULL;
! 		}
!  		goto doneWithNCB;
              }
              else {
                  thrd_Sleep(1000);
***************
*** 7656,7664 ****
          if (smb_concurrentCalls > smb_maxObsConcurrentCalls)
              smb_maxObsConcurrentCalls = smb_concurrentCalls;
  
-         if (vcp)
-             smb_ReleaseVC(vcp);
-         vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
          /*
           * If at this point vcp is NULL (implies that packet was invalid)
           * then we are in big trouble. This means either :
--- 7809,7814 ----
***************
*** 7711,7717 ****
              continue;
          }
  
- 
          vcp->errorCount = 0;
          bufp = (struct smb_packet *) ncbp->ncb_buffer;
  #ifdef DJGPP
--- 7861,7866 ----
***************
*** 7858,7865 ****
      NCB *ncbp;
      long code = 0;
      long len;
!     long i, j;
!     smb_vc_t *vcp = 0;
      int flags = 0;
      char rname[NCBNAMSZ+1];
      char cname[MAX_COMPUTERNAME_LENGTH+1];
--- 8007,8015 ----
      NCB *ncbp;
      long code = 0;
      long len;
!     long i;
!     int  session, thread;
!     smb_vc_t *vcp = NULL;
      int flags = 0;
      char rname[NCBNAMSZ+1];
      char cname[MAX_COMPUTERNAME_LENGTH+1];
***************
*** 7959,8025 ****
              if (strncmp(rname, cname, NCBNAMSZ) != 0)
                  flags |= SMB_VCFLAG_REMOTECONN;
  
-         osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
          /* lock */
          lock_ObtainMutex(&smb_ListenerLock);
  
!         /* New generation */
!         sessionGen++;
  
!         /* Log session startup */
  #ifdef NOTSERVICE
!         fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host "
!                  "%s\n",
!                  ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
  #endif /* NOTSERVICE */
!         osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
!                   ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
  
!         if (reportSessionStartups) {
  #ifndef DJGPP
!             HANDLE h;
!             char *ptbuf[1];
!             char s[100];
! 
!             h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
!             sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
!             ptbuf[0] = s;
!             ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
!                          1, 0, ptbuf, NULL);
!             DeregisterEventSource(h);
  #else /* DJGPP */
!             time(&now);
!             fprintf(stderr, "%s: New session %d starting from host %s\n",
!                     asctime(localtime(&now)), ncbp->ncb_lsn, rname);
!             fflush(stderr);
  #endif /* !DJGPP */
!         }
!         osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname));
!         osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
!                   ongoingOps);
  
!         /* now ncbp->ncb_lsn is the connection ID */
!         vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
!         vcp->flags |= flags;
!         strcpy(vcp->rname, rname);
  
!         /* Allocate slot in session arrays */
!         /* Re-use dead session if possible, otherwise add one more */
!         /* But don't look at session[0], it is reserved */
!         for (i = 1; i < numSessions; i++) {
!             if (dead_sessions[i]) {
!                 osi_Log1(smb_logp, "connecting to dead session [ %d ]", i);
!                 dead_sessions[i] = FALSE;
!                 break;
!             }
!         }
  
!         if (i >= Sessionmax - 1  || numNCBs >= NCBmax - 1) {
              unsigned long code = CM_ERROR_ALLBUSY;
              smb_packet_t * outp = GetPacket();
              unsigned char *outWctp;
              smb_t *smbp;
              
              outp->ncbp = ncbp;
  
              if (vcp->flags & SMB_VCFLAG_STATUS32) {
--- 8109,8213 ----
              if (strncmp(rname, cname, NCBNAMSZ) != 0)
                  flags |= SMB_VCFLAG_REMOTECONN;
  
          /* lock */
          lock_ObtainMutex(&smb_ListenerLock);
  
! 	osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname));
! 	osi_Log1(smb_logp, "SMB session startup, %d ongoing ops", ongoingOps);
!  
! 	/* now ncbp->ncb_lsn is the connection ID */
! 	vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
!  	if (vcp->session == 0) {
!  	    /* New generation */
!  	    osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
!  	    sessionGen++;
  
!  	    /* Log session startup */
  #ifdef NOTSERVICE
! 	    fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
! 		    ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
  #endif /* NOTSERVICE */
! 	    osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
! 		     ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
  
! 	    if (reportSessionStartups) {
  #ifndef DJGPP
! 		HANDLE h;
! 		char *ptbuf[1];
! 		char s[100];
! 
! 		h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
! 		sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
! 		ptbuf[0] = s;
! 		ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
! 			     1, 0, ptbuf, NULL);
! 		DeregisterEventSource(h);
  #else /* DJGPP */
! 		time(&now);
! 		fprintf(stderr, "%s: New session %d starting from host %s\n",
! 			 asctime(localtime(&now)), ncbp->ncb_lsn, rname);
! 		fflush(stderr);
  #endif /* !DJGPP */
! 	    }
  
! 	    strcpy(vcp->rname, rname);
! 	    vcp->flags |= flags;
  
! 	    /* Allocate slot in session arrays */
! 	    /* Re-use dead session if possible, otherwise add one more */
! 	    /* But don't look at session[0], it is reserved */
! 	    lock_ObtainWrite(&smb_globalLock);
! 	    for (session = 1; session < numSessions; session++) {
! 		if (dead_sessions[session]) {
! 		    osi_Log1(smb_logp, "connecting to dead session [ %d ]", session);
! 		    dead_sessions[session] = FALSE;
! 		    break;
! 		}
! 	    }
! 	    lock_ReleaseWrite(&smb_globalLock);
! 	} else {
!  	    /* We are re-using an existing VC because the lsn and lana 
!  	     * were re-used */
!  	    session = vcp->session;
!  
!  	    osi_Log1(smb_logp, "Re-using session lsn %d", ncbp->ncb_lsn);
!  
!  	    /* Log session startup */
! #ifdef NOTSERVICE
! 	    fprintf(stderr, "Re-using session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
! 		    ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
! #endif /* NOTSERVICE */
! 	    osi_Log4(smb_logp, "Re-using session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
! 		     ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
  
! 	    if (reportSessionStartups) {
! #ifndef DJGPP
! 		HANDLE h;
! 		char *ptbuf[1];
! 		char s[100];
! 
! 		h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
! 		sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
! 		ptbuf[0] = s;
! 		ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
! 			     1, 0, ptbuf, NULL);
! 		DeregisterEventSource(h);
! #else /* DJGPP */
! 		time(&now);
! 		fprintf(stderr, "%s: Re-using session %d starting from host %s\n",
! 			asctime(localtime(&now)), ncbp->ncb_lsn, rname);
! 		fflush(stderr);
! #endif /* !DJGPP */
! 	    }
! 	}
! 
!         if (session >= SESSION_MAX - 1  || numNCBs >= NCB_MAX - 1) {
              unsigned long code = CM_ERROR_ALLBUSY;
              smb_packet_t * outp = GetPacket();
              unsigned char *outWctp;
              smb_t *smbp;
              
+ 	    smb_FormatResponsePacket(vcp, NULL, outp);
              outp->ncbp = ncbp;
  
              if (vcp->flags & SMB_VCFLAG_STATUS32) {
***************
*** 8050,8088 ****
              }
              smb_SendPacket(vcp, outp);
              smb_FreePacket(outp);
          } else {
              /* assert that we do not exceed the maximum number of sessions or NCBs.
!             * we should probably want to wait for a session to be freed in case
!             * we run out.
!             */
!             osi_assert(i < Sessionmax - 1);
!             osi_assert(numNCBs < NCBmax - 1);   /* if we pass this test we can allocate one more */
  
!             LSNs[i] = ncbp->ncb_lsn;
!             lanas[i] = ncbp->ncb_lana_num;
  		
!             if (i == numSessions) {
                  /* Add new NCB for new session */
                  char eventName[MAX_PATH];
  
                  osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
  
                  InitNCBslot(numNCBs);
                  numNCBs++;
                  thrd_SetEvent(NCBavails[0]);
                  thrd_SetEvent(NCBevents[0]);
!                 for (j = 0; j < smb_NumServerThreads; j++)
!                     thrd_SetEvent(NCBreturns[j][0]);
                  /* Also add new session event */
!                 sprintf(eventName, "SessionEvents[%d]", i);
!                 SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
                  if ( GetLastError() == ERROR_ALREADY_EXISTS )
                      osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
                  numSessions++;
                  osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
                  thrd_SetEvent(SessionEvents[0]);
              } else {
!                 thrd_SetEvent(SessionEvents[i]);
              }
          }
          
--- 8238,8291 ----
              }
              smb_SendPacket(vcp, outp);
              smb_FreePacket(outp);
+ 
+ 	    lock_ObtainMutex(&vcp->mx);
+ 	    vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ 	    lock_ReleaseMutex(&vcp->mx);
+ 	    smb_CleanupDeadVC(vcp);
+ 	    smb_ReleaseVC(vcp);
          } else {
              /* assert that we do not exceed the maximum number of sessions or NCBs.
!              * we should probably want to wait for a session to be freed in case
!              * we run out.
!              */
!             osi_assert(session < SESSION_MAX - 1);
!             osi_assert(numNCBs < NCB_MAX - 1);   /* if we pass this test we can allocate one more */
  
! 	    lock_ObtainMutex(&vcp->mx);
! 	    vcp->session   = session;
! 	    lock_ReleaseMutex(&vcp->mx);
! 	    lock_ObtainWrite(&smb_globalLock);
!             LSNs[session]  = ncbp->ncb_lsn;
!             lanas[session] = ncbp->ncb_lana_num;
! 	    lock_ReleaseWrite(&smb_globalLock);
  		
!             if (session == numSessions) {
                  /* Add new NCB for new session */
                  char eventName[MAX_PATH];
  
                  osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
  
                  InitNCBslot(numNCBs);
+ 		lock_ObtainWrite(&smb_globalLock);
                  numNCBs++;
+ 		lock_ReleaseWrite(&smb_globalLock);
                  thrd_SetEvent(NCBavails[0]);
                  thrd_SetEvent(NCBevents[0]);
!                 for (thread = 0; thread < smb_NumServerThreads; thread++)
!                     thrd_SetEvent(NCBreturns[thread][0]);
                  /* Also add new session event */
!                 sprintf(eventName, "SessionEvents[%d]", session);
!                 SessionEvents[session] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
                  if ( GetLastError() == ERROR_ALREADY_EXISTS )
                      osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
+ 		lock_ObtainWrite(&smb_globalLock);
                  numSessions++;
+ 		lock_ReleaseWrite(&smb_globalLock);
                  osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
                  thrd_SetEvent(SessionEvents[0]);
              } else {
!                 thrd_SetEvent(SessionEvents[session]);
              }
          }
          
***************
*** 8396,8402 ****
      if ( GetLastError() == ERROR_ALREADY_EXISTS )
          afsi_log("Event Object Already Exists: %s", eventName);
      for (i = 0; i < smb_NumServerThreads; i++) {
!         NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
          NCBreturns[i][0] = retHandle;
      }
  
--- 8599,8605 ----
      if ( GetLastError() == ERROR_ALREADY_EXISTS )
          afsi_log("Event Object Already Exists: %s", eventName);
      for (i = 0; i < smb_NumServerThreads; i++) {
!         NCBreturns[i] = malloc(NCB_MAX * sizeof(EVENT_HANDLE));
          NCBreturns[i][0] = retHandle;
      }
  
***************
*** 8922,8927 ****
--- 9125,9160 ----
      sprintf(output, "done dumping smb_vc_t\n");
      WriteFile(outputFile, output, strlen(output), &zilch, NULL);
    
+     sprintf(output, "begin dumping DEAD smb_vc_t\n");
+     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ 
+     for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp) 
+     {
+         smb_fid_t *fidp;
+       
+         sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+                  cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+       
+         sprintf(output, "begin dumping smb_fid_t\n");
+         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ 
+         for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+         {
+             sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
+                      cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+                      fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
+                      fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+         }
+       
+         sprintf(output, "done dumping smb_fid_t\n");
+         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+     }
+ 
+     sprintf(output, "done dumping DEAD smb_vc_t\n");
+     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+   
      if (lock)
          lock_ReleaseRead(&smb_rctLock);
      return 0;
Index: openafs/src/WINNT/afsd/smb.h
diff -c openafs/src/WINNT/afsd/smb.h:1.14.2.16 openafs/src/WINNT/afsd/smb.h:1.14.2.20
*** openafs/src/WINNT/afsd/smb.h:1.14.2.16	Tue Jan 10 08:28:02 2006
--- openafs/src/WINNT/afsd/smb.h	Tue Jan 24 12:16:07 2006
***************
*** 91,96 ****
--- 91,97 ----
  
  /* flags for functions */
  #define SMB_FLAG_CREATE		1	/* create the structure if necessary */
+ #define SMB_FLAG_AFSLOGON       2       /* operating on behalf of afslogon.dll */
  
  /* max # of bytes we'll receive in an incoming SMB message */
  /* the maximum is 2^18-1 for NBT and 2^25-1 for Raw transport messages */
***************
*** 166,174 ****
  } smb_packet_t;
  
  /* smb_packet flags */
! #define SMB_PACKETFLAG_PROFILE_UPDATE_OK	1
! #define SMB_PACKETFLAG_NOSEND			2
! #define SMB_PACKETFLAG_SUSPENDED		4
  
  /* a structure for making Netbios calls; locked by smb_globalLock */
  #define SMB_NCBMAGIC	0x2334344
--- 167,174 ----
  } smb_packet_t;
  
  /* smb_packet flags */
! #define SMB_PACKETFLAG_NOSEND			1
! #define SMB_PACKETFLAG_SUSPENDED		2
  
  /* a structure for making Netbios calls; locked by smb_globalLock */
  #define SMB_NCBMAGIC	0x2334344
***************
*** 203,210 ****
      struct smb_tid *tidsp;		/* the first child in the tid list */
      struct smb_user *usersp;	        /* the first child in the user session list */
      struct smb_fid *fidsp;		/* the first child in the open file list */
-     struct smb_user *justLoggedOut;	/* ready for profile upload? */
-     time_t logoffTime;	                /* tick count when logged off */
      unsigned char errorCount;
      char rname[17];
      int lana;
--- 203,208 ----
***************
*** 212,217 ****
--- 210,216 ----
      void * secCtx;                      /* security context when negotiating SMB extended auth
                                           * valid when SMB_VCFLAG_AUTH_IN_PROGRESS is set
                                           */
+     unsigned short session;		/* This is the Session Index associated with the NCBs */
  } smb_vc_t;
  
  					/* have we negotiated ... */
***************
*** 235,240 ****
--- 234,241 ----
      struct smb_username *unp;           /* user name struct */
  } smb_user_t;
  
+ #define SMB_USERFLAG_DELETE	    1	/* delete struct when ref count zero */
+ 
  typedef struct smb_username {
      struct smb_username *nextp;		/* next sibling */
      unsigned long refCount;		/* ref count */
***************
*** 243,251 ****
      struct cm_user *userp;		/* CM user structure */
      char *name;			        /* user name */
      char *machine;                      /* machine name */
  } smb_username_t;
  
! #define SMB_USERFLAG_DELETE	1	/* delete struct when ref count zero */
  
  #define SMB_MAX_USERNAME_LENGTH 256
  
--- 244,268 ----
      struct cm_user *userp;		/* CM user structure */
      char *name;			        /* user name */
      char *machine;                      /* machine name */
+     time_t last_logoff_t;		/* most recent logoff time */
  } smb_username_t;
  
! /* The SMB_USERNAMEFLAG_AFSLOGON is used to preserve the existence of an 
!  * smb_username_t even when the refCount is zero.  This is used to ensure
!  * that tokens set to a username during the integrated logon process are 
!  * preserved until the SMB Session that will require the tokens is created.
!  * The cm_IoctlSetTokens() function when executed from the Network Provider
!  * connects to the AFS Client Service using the credentials of the machine
!  * and not the user for whom the tokens are being configured. */
! #define SMB_USERNAMEFLAG_AFSLOGON   1
! 
! /* The SMB_USERNAMEFLAG_LOGOFF is used to indicate that the user most
!  * recently logged off at 'last_logoff_t'.  The smb_username_t should not
!  * be deleted even if the refCount is zero before 'last_logoff_t' + 
!  * 'smb_LogoffTransferTimeout' if 'smb_LogoffTokenTransfer' is non-zero.
!  * The smb_Daemon() thread is responsible for purging the expired objects */
! 
! #define SMB_USERNAMEFLAG_LOGOFF     2
  
  #define SMB_MAX_USERNAME_LENGTH 256
  
***************
*** 487,512 ****
  
  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);
  
  extern smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags);
  
! extern smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags);
  
  extern smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern); 
  
- extern smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags);
- 
- extern smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern);
- 
  extern void smb_ReleaseUsername(smb_username_t *unp);
  
  extern void smb_ReleaseUID(smb_user_t *uidp);
  
  extern cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp);
--- 504,531 ----
  
  extern smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana);
  
+ extern void smb_CleanupDeadVC(smb_vc_t *vcp);
+ 
  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_HoldTIDNoLock(smb_tid_t *tidp);
+ 
  extern void smb_ReleaseTID(smb_tid_t *tidp);
  
  extern smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags);
  
! extern smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags);
  
  extern smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern); 
  
  extern void smb_ReleaseUsername(smb_username_t *unp);
  
+ extern void smb_HoldUIDNoLock(smb_user_t *uidp);
+ 
  extern void smb_ReleaseUID(smb_user_t *uidp);
  
  extern cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp);
***************
*** 515,520 ****
--- 534,541 ----
  
  extern smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags);
  
+ extern void smb_HoldFIDNoLock(smb_fid_t *fidp);
+ 
  extern void smb_ReleaseFID(smb_fid_t *fidp);
  
  extern long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
***************
*** 577,586 ****
  
  /* some globals, too */
  extern char *smb_localNamep;
- extern int loggedOut;
- extern time_t loggedOutTime;
- extern char *loggedOutName;
- extern smb_user_t *loggedOutUserp;
  
  extern osi_log_t *smb_logp;
  
--- 598,603 ----
Index: openafs/src/WINNT/afsd/smb3.c
diff -c openafs/src/WINNT/afsd/smb3.c:1.42.2.35 openafs/src/WINNT/afsd/smb3.c:1.42.2.41
*** openafs/src/WINNT/afsd/smb3.c:1.42.2.35	Tue Jan 10 08:28:02 2006
--- openafs/src/WINNT/afsd/smb3.c	Tue Jan 24 12:16:07 2006
***************
*** 49,55 ****
      cm_user_t *up = NULL;
          
      uidp = smb_FindUID(vcp, inp->uid, 0);
!     if (!uidp) return NULL;
          
      lock_ObtainMutex(&uidp->mx);
      if (uidp->unp) {
--- 49,56 ----
      cm_user_t *up = NULL;
          
      uidp = smb_FindUID(vcp, inp->uid, 0);
!     if (!uidp) 
! 	return NULL;
          
      lock_ObtainMutex(&uidp->mx);
      if (uidp->unp) {
***************
*** 661,667 ****
      smb_user_t *uidp;
      unsigned short newUid;
      unsigned long caps = 0;
-     cm_user_t *userp;
      smb_username_t *unp;
      char *s1 = " ";
      long code = 0; 
--- 662,667 ----
***************
*** 841,860 ****
      uidp = smb_FindUserByNameThisSession(vcp, usern);
      if (uidp) {   /* already there, so don't create a new one */
          unp = uidp->unp;
-         userp = unp->userp;
          newUid = uidp->userID;
!         osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern));
!         osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
          smb_ReleaseUID(uidp);
      }
      else {
!       /* do a global search for the username/machine name pair */
          unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
  
          /* Create a new UID and cm_user_t structure */
          userp = unp->userp;
          if (!userp)
              userp = cm_NewUser();
          lock_ObtainMutex(&vcp->mx);
          if (!vcp->uidCounter)
              vcp->uidCounter++; /* handle unlikely wraparounds */
--- 841,872 ----
      uidp = smb_FindUserByNameThisSession(vcp, usern);
      if (uidp) {   /* already there, so don't create a new one */
          unp = uidp->unp;
          newUid = uidp->userID;
!         osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",
! 		      vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern));
!         osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",
! 		  vcp->lana,vcp->lsn,newUid);
          smb_ReleaseUID(uidp);
      }
      else {
! 	cm_user_t *userp;
! 
! 	/* do a global search for the username/machine name pair */
          unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
+ 	lock_ObtainMutex(&unp->mx);
+ 	if (unp->flags & SMB_USERNAMEFLAG_AFSLOGON) {
+ 	    /* clear the afslogon flag so that the tickets can now 
+ 	     * be freed when the refCount returns to zero.
+ 	     */
+ 	    unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON;
+ 	}
+ 	lock_ReleaseMutex(&unp->mx);
  
          /* Create a new UID and cm_user_t structure */
          userp = unp->userp;
          if (!userp)
              userp = cm_NewUser();
+ 	cm_HoldUserVCRef(userp);
          lock_ObtainMutex(&vcp->mx);
          if (!vcp->uidCounter)
              vcp->uidCounter++; /* handle unlikely wraparounds */
***************
*** 926,956 ****
  {
      smb_user_t *uidp;
  
-     /* don't get tokens from this VC */
-     vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- 
-     inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
- 
      /* find the tree and free it */
      uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-     /* TODO: smb_ReleaseUID() ? */
      if (uidp) {
!         char *s1 = NULL, *s2 = NULL;
! 
!         if (s2 == NULL) s2 = " ";
!         if (s1 == NULL) {s1 = s2; s2 = " ";}
  
!         osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID,
!                   osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), 
!                   osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2));
  
          lock_ObtainMutex(&uidp->mx);
!         uidp->flags |= SMB_USERFLAG_DELETE;
!         /*
!          * it doesn't get deleted right away
!          * because the vcp points to it
!          */
          lock_ReleaseMutex(&uidp->mx);
      }
      else    
          osi_Log0(smb_logp, "SMB3 user logoffX");
--- 938,963 ----
  {
      smb_user_t *uidp;
  
      /* find the tree and free it */
      uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
      if (uidp) {
! 	smb_username_t * unp;
  
!         osi_Log2(smb_logp, "SMB3 user logoffX uid %d name %s", uidp->userID,
!                   osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "));
  
          lock_ObtainMutex(&uidp->mx);
! 	unp = uidp->unp;
          lock_ReleaseMutex(&uidp->mx);
+ 
+ 	if (unp && smb_LogoffTokenTransfer) {
+ 	    lock_ObtainMutex(&unp->mx);
+ 	    unp->flags |= SMB_USERNAMEFLAG_LOGOFF;
+ 	    unp->last_logoff_t = osi_Time() + smb_LogoffTransferTimeout;
+ 	    lock_ReleaseMutex(&unp->mx);
+ 	}
+ 
+ 	smb_ReleaseUID(uidp);
      }
      else    
          osi_Log0(smb_logp, "SMB3 user logoffX");
***************
*** 1128,1134 ****
          
      tp = malloc(sizeof(*tp));
      memset(tp, 0, sizeof(*tp));
!     tp->vcp = NULL;
      tp->curData = tp->curParms = 0;
      tp->totalData = totalData;
      tp->totalParms = totalParms;
--- 1135,1142 ----
          
      tp = malloc(sizeof(*tp));
      memset(tp, 0, sizeof(*tp));
!     smb_HoldVC(vcp);
!     tp->vcp = vcp;
      tp->curData = tp->curParms = 0;
      tp->totalData = totalData;
      tp->totalParms = totalParms;
***************
*** 1162,1169 ****
  /* 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->flags & SMB_TRAN2PFLAG_ALLOC) {
          if (t2p->parmsp)
              free(t2p->parmsp);
--- 1170,1179 ----
  /* 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);
+ 	t2p->vcp = NULL;
+     }
      if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
          if (t2p->parmsp)
              free(t2p->parmsp);
***************
*** 4102,4108 ****
                  if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                      LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
                      /* Don't bulk stat if risking timeout */
!                     int now = GetCurrentTime();
                      if (now - req.startTime > 5000) {
                          scp->bulkStatProgress = thyper;
                          scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
--- 4112,4118 ----
                  if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                      LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
                      /* Don't bulk stat if risking timeout */
!                     int now = GetTickCount();
                      if (now - req.startTime > 5000) {
                          scp->bulkStatProgress = thyper;
                          scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
***************
*** 5691,5697 ****
       * scp is NULL.
       */
      if (code == 0 && !treeCreate) {
!         if (createDisp == FILE_CREATE) {
              /* oops, file shouldn't be there */
              if (dscp)
                  cm_ReleaseSCache(dscp);
--- 5701,5718 ----
       * scp is NULL.
       */
      if (code == 0 && !treeCreate) {
!         code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
!         if (code) {
!             if (dscp)
!                 cm_ReleaseSCache(dscp);
!             if (scp)
!                 cm_ReleaseSCache(scp);
!             cm_ReleaseUser(userp);
!             free(realPathp);
!             return code;
!         }
! 
! 	if (createDisp == FILE_CREATE) {
              /* oops, file shouldn't be there */
              if (dscp)
                  cm_ReleaseSCache(dscp);
***************
*** 5731,5746 ****
          else 
              openAction = 1;	/* found existing file */
  
-         code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
-         if (code) {
-             if (dscp)
-                 cm_ReleaseSCache(dscp);
-             if (scp)
-                 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)
--- 5752,5757 ----
***************
*** 6727,6732 ****
--- 6738,6745 ----
  
      savedPacketp = smb_CopyPacket(inp);
      smb_HoldVC(vcp);
+     if (savedPacketp->vcp)
+ 	smb_ReleaseVC(savedPacketp->vcp);
      savedPacketp->vcp = vcp;
      lock_ObtainMutex(&smb_Dir_Watch_Lock);
      savedPacketp->nextp = smb_Directory_Watches;
***************
*** 6884,6890 ****
      BOOL twoEntries = FALSE;
      ULONG otherNameLen, oldParmCount = 0;
      DWORD otherAction;
-     smb_vc_t *vcp;
      smb_fid_t *fidp;
  
      /* Get ready for rename within directory */
--- 6897,6902 ----
***************
*** 6905,6911 ****
          wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
          maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
              | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
-         vcp = watch->vcp;
  
          /*
           * Strange hack - bug in NT Client and NT Server that we
--- 6917,6922 ----
***************
*** 6914,6920 ****
          if (filter == 3 && wtree)
              filter = 0x17;
  
!         fidp = smb_FindFID(vcp, fid, 0);
          if (!fidp) {
              osi_Log1(smb_logp," no fidp for fid[%d]",fid);
              lastWatch = watch;
--- 6925,6931 ----
          if (filter == 3 && wtree)
              filter = 0x17;
  
!         fidp = smb_FindFID(watch->vcp, fid, 0);
          if (!fidp) {
              osi_Log1(smb_logp," no fidp for fid[%d]",fid);
              lastWatch = watch;
***************
*** 7044,7050 ****
              ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
          }
  
!         smb_SendPacket(vcp, watch);
          smb_FreePacket(watch);
          watch = nextWatch;
      }
--- 7055,7061 ----
              ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
          }
  
!         smb_SendPacket(watch->vcp, watch);
          smb_FreePacket(watch);
          watch = nextWatch;
      }
***************
*** 7173,7183 ****
      lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
  }
  
! cm_user_t *smb_FindCMUserByName(char *usern, char *machine)
  {
      smb_username_t *unp;
  
!     unp = smb_FindUserByName(usern, machine, SMB_FLAG_CREATE);
      if (!unp->userp) {
          lock_ObtainMutex(&unp->mx);
          unp->userp = cm_NewUser();
--- 7184,7195 ----
      lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
  }
  
! cm_user_t *smb_FindCMUserByName(char *usern, char *machine, afs_uint32 flags)
  {
      smb_username_t *unp;
+     cm_user_t *     userp;
  
!     unp = smb_FindUserByName(usern, machine, flags);
      if (!unp->userp) {
          lock_ObtainMutex(&unp->mx);
          unp->userp = cm_NewUser();
***************
*** 7188,7195 ****
          osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
          osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine);
      }
!     cm_HoldUser(unp->userp);
      smb_ReleaseUsername(unp);
!     return unp->userp;
  }
  
--- 7200,7208 ----
          osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
          osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine);
      }
!     userp = unp->userp;
!     cm_HoldUser(userp);
      smb_ReleaseUsername(unp);
!     return userp;
  }
  
Index: openafs/src/WINNT/afsd/smb3.h
diff -c openafs/src/WINNT/afsd/smb3.h:1.7.2.3 openafs/src/WINNT/afsd/smb3.h:1.7.2.4
*** openafs/src/WINNT/afsd/smb3.h:1.7.2.3	Fri Mar 11 01:58:52 2005
--- openafs/src/WINNT/afsd/smb3.h	Thu Jan 19 18:08:46 2006
***************
*** 192,198 ****
  extern int smb_V3MatchMask(char *namep, char *maskp, int flags);
  
  extern void smb3_Init();
! extern cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine);
  
  /* SMB auth related functions */
  extern void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength);
--- 192,198 ----
  extern int smb_V3MatchMask(char *namep, char *maskp, int flags);
  
  extern void smb3_Init();
! extern cm_user_t *smb_FindCMUserByName(char *usern, char *machine, afs_uint32 flags);
  
  /* SMB auth related functions */
  extern void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength);
Index: openafs/src/WINNT/afsd/smb_ioctl.c
diff -c openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.5 openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.6
*** openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.5	Sun Oct  2 02:08:56 2005
--- openafs/src/WINNT/afsd/smb_ioctl.c	Sun Jan 15 21:07:01 2006
***************
*** 31,89 ****
  
  void smb_InitIoctl(void)
  {
!         int i;
!         for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
! 	    smb_ioctlProcsp[i] = NULL;
! 
! 	smb_ioctlProcsp[VIOCGETAL] = cm_IoctlGetACL;
!         smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = cm_IoctlGetFileCellName;
!         smb_ioctlProcsp[VIOCSETAL] = cm_IoctlSetACL;
!         smb_ioctlProcsp[VIOC_FLUSHVOLUME] = cm_IoctlFlushVolume;
!         smb_ioctlProcsp[VIOCFLUSH] = cm_IoctlFlushFile;
!         smb_ioctlProcsp[VIOCSETVOLSTAT] = cm_IoctlSetVolumeStatus;
!         smb_ioctlProcsp[VIOCGETVOLSTAT] = cm_IoctlGetVolumeStatus;
!         smb_ioctlProcsp[VIOCWHEREIS] = cm_IoctlWhereIs;
!         smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = cm_IoctlStatMountPoint;
!         smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = cm_IoctlDeleteMountPoint;
!         smb_ioctlProcsp[VIOCCKSERV] = cm_IoctlCheckServers;
!         smb_ioctlProcsp[VIOC_GAG] = cm_IoctlGag;
!         smb_ioctlProcsp[VIOCCKBACK] = cm_IoctlCheckVolumes;
!         smb_ioctlProcsp[VIOCSETCACHESIZE] = cm_IoctlSetCacheSize;
!         smb_ioctlProcsp[VIOCGETCACHEPARMS] = cm_IoctlGetCacheParms;
!         smb_ioctlProcsp[VIOCGETCELL] = cm_IoctlGetCell;
!         smb_ioctlProcsp[VIOCNEWCELL] = cm_IoctlNewCell;
!         smb_ioctlProcsp[VIOC_GET_WS_CELL] = cm_IoctlGetWsCell;
!         smb_ioctlProcsp[VIOC_AFS_SYSNAME] = cm_IoctlSysName;
!         smb_ioctlProcsp[VIOC_GETCELLSTATUS] = cm_IoctlGetCellStatus;
!         smb_ioctlProcsp[VIOC_SETCELLSTATUS] = cm_IoctlSetCellStatus;
!         smb_ioctlProcsp[VIOC_SETSPREFS] = cm_IoctlSetSPrefs;
!         smb_ioctlProcsp[VIOC_GETSPREFS] = cm_IoctlGetSPrefs;
!         smb_ioctlProcsp[VIOC_STOREBEHIND] = cm_IoctlStoreBehind;
!         smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = cm_IoctlCreateMountPoint;
!         smb_ioctlProcsp[VIOC_TRACECTL] = cm_IoctlTraceControl;
! 	smb_ioctlProcsp[VIOCSETTOK] = cm_IoctlSetToken;
! 	smb_ioctlProcsp[VIOCGETTOK] = cm_IoctlGetTokenIter;
! 	smb_ioctlProcsp[VIOCNEWGETTOK] = cm_IoctlGetToken;
! 	smb_ioctlProcsp[VIOCDELTOK] = cm_IoctlDelToken;
! 	smb_ioctlProcsp[VIOCDELALLTOK] = cm_IoctlDelAllToken;
! 	smb_ioctlProcsp[VIOC_SYMLINK] = cm_IoctlSymlink;
! 	smb_ioctlProcsp[VIOC_LISTSYMLINK] = cm_IoctlListlink;
! 	smb_ioctlProcsp[VIOC_DELSYMLINK] = cm_IoctlDeletelink;
! 	smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = cm_IoctlMakeSubmount;
! 	smb_ioctlProcsp[VIOC_GETRXKCRYPT] = cm_IoctlGetRxkcrypt;
! 	smb_ioctlProcsp[VIOC_SETRXKCRYPT] = cm_IoctlSetRxkcrypt;
! 	smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
  #ifdef DJGPP
! 	smb_ioctlProcsp[VIOC_SHUTDOWN] = cm_IoctlShutdown;
  #endif
! 	smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = cm_IoctlMemoryDump;
! 	smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
!         smb_ioctlProcsp[VIOC_FLUSHALL] = cm_IoctlFlushAllVolumes;
!         smb_ioctlProcsp[VIOCGETFID] = cm_IoctlGetFid;
!         smb_ioctlProcsp[VIOCGETOWNER] = cm_IoctlGetOwner;
!         smb_ioctlProcsp[VIOC_RXSTAT_PROC] = cm_IoctlRxStatProcess;
!         smb_ioctlProcsp[VIOC_RXSTAT_PEER] = cm_IoctlRxStatPeer;
! }
  
  /* called to make a fid structure into an IOCTL fid structure */
  void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
--- 31,89 ----
  
  void smb_InitIoctl(void)
  {
!     int i;
!     for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
! 	smb_ioctlProcsp[i] = NULL;
! 
!     smb_ioctlProcsp[VIOCGETAL] = cm_IoctlGetACL;
!     smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = cm_IoctlGetFileCellName;
!     smb_ioctlProcsp[VIOCSETAL] = cm_IoctlSetACL;
!     smb_ioctlProcsp[VIOC_FLUSHVOLUME] = cm_IoctlFlushVolume;
!     smb_ioctlProcsp[VIOCFLUSH] = cm_IoctlFlushFile;
!     smb_ioctlProcsp[VIOCSETVOLSTAT] = cm_IoctlSetVolumeStatus;
!     smb_ioctlProcsp[VIOCGETVOLSTAT] = cm_IoctlGetVolumeStatus;
!     smb_ioctlProcsp[VIOCWHEREIS] = cm_IoctlWhereIs;
!     smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = cm_IoctlStatMountPoint;
!     smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = cm_IoctlDeleteMountPoint;
!     smb_ioctlProcsp[VIOCCKSERV] = cm_IoctlCheckServers;
!     smb_ioctlProcsp[VIOC_GAG] = cm_IoctlGag;
!     smb_ioctlProcsp[VIOCCKBACK] = cm_IoctlCheckVolumes;
!     smb_ioctlProcsp[VIOCSETCACHESIZE] = cm_IoctlSetCacheSize;
!     smb_ioctlProcsp[VIOCGETCACHEPARMS] = cm_IoctlGetCacheParms;
!     smb_ioctlProcsp[VIOCGETCELL] = cm_IoctlGetCell;
!     smb_ioctlProcsp[VIOCNEWCELL] = cm_IoctlNewCell;
!     smb_ioctlProcsp[VIOC_GET_WS_CELL] = cm_IoctlGetWsCell;
!     smb_ioctlProcsp[VIOC_AFS_SYSNAME] = cm_IoctlSysName;
!     smb_ioctlProcsp[VIOC_GETCELLSTATUS] = cm_IoctlGetCellStatus;
!     smb_ioctlProcsp[VIOC_SETCELLSTATUS] = cm_IoctlSetCellStatus;
!     smb_ioctlProcsp[VIOC_SETSPREFS] = cm_IoctlSetSPrefs;
!     smb_ioctlProcsp[VIOC_GETSPREFS] = cm_IoctlGetSPrefs;
!     smb_ioctlProcsp[VIOC_STOREBEHIND] = cm_IoctlStoreBehind;
!     smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = cm_IoctlCreateMountPoint;
!     smb_ioctlProcsp[VIOC_TRACECTL] = cm_IoctlTraceControl;
!     smb_ioctlProcsp[VIOCSETTOK] = cm_IoctlSetToken;
!     smb_ioctlProcsp[VIOCGETTOK] = cm_IoctlGetTokenIter;
!     smb_ioctlProcsp[VIOCNEWGETTOK] = cm_IoctlGetToken;
!     smb_ioctlProcsp[VIOCDELTOK] = cm_IoctlDelToken;
!     smb_ioctlProcsp[VIOCDELALLTOK] = cm_IoctlDelAllToken;
!     smb_ioctlProcsp[VIOC_SYMLINK] = cm_IoctlSymlink;
!     smb_ioctlProcsp[VIOC_LISTSYMLINK] = cm_IoctlListlink;
!     smb_ioctlProcsp[VIOC_DELSYMLINK] = cm_IoctlDeletelink;
!     smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = cm_IoctlMakeSubmount;
!     smb_ioctlProcsp[VIOC_GETRXKCRYPT] = cm_IoctlGetRxkcrypt;
!     smb_ioctlProcsp[VIOC_SETRXKCRYPT] = cm_IoctlSetRxkcrypt;
!     smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
  #ifdef DJGPP
!     smb_ioctlProcsp[VIOC_SHUTDOWN] = cm_IoctlShutdown;
  #endif
!     smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = cm_IoctlMemoryDump;
!     smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
!     smb_ioctlProcsp[VIOC_FLUSHALL] = cm_IoctlFlushAllVolumes;
!     smb_ioctlProcsp[VIOCGETFID] = cm_IoctlGetFid;
!     smb_ioctlProcsp[VIOCGETOWNER] = cm_IoctlGetOwner;
!     smb_ioctlProcsp[VIOC_RXSTAT_PROC] = cm_IoctlRxStatProcess;
!     smb_ioctlProcsp[VIOC_RXSTAT_PEER] = cm_IoctlRxStatPeer;
! }	
  
  /* called to make a fid structure into an IOCTL fid structure */
  void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
***************
*** 159,287 ****
   */
  void smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
  {
! 	/* make sure the buffer(s) are allocated */
! 	if (!ioctlp->inAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA);
!         if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA);
! 
! 	/* Fixes fs la problem.  We do a StrToOEM later and if this data isn't initialized we get memory issues. */
!        (void) memset(ioctlp->inAllocp, 0, SMB_IOCTL_MAXDATA);
!        (void) memset(ioctlp->outAllocp, 0, SMB_IOCTL_MAXDATA);
! 
! 	/* and make sure that we've reset our state for the new incoming request */
! 	if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) {
! 	        ioctlp->inCopied = 0;
! 	        ioctlp->outCopied = 0;
! 		ioctlp->inDatap = ioctlp->inAllocp;
! 		ioctlp->outDatap = ioctlp->outAllocp;
! 	        ioctlp->flags |= SMB_IOCTLFLAG_DATAIN;
! 	}
! }
  
  /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
  long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
! 	smb_packet_t *outp)
  {
! 	smb_ioctl_t *iop;
!         long count;
!         long leftToCopy;
!         char *op;
!         long code;
!         cm_user_t *userp;
! 
!         iop = fidp->ioctlp;
!         count = smb_GetSMBParm(inp, 1);
!         userp = smb_GetUser(vcp, inp);
  
! 	/* Identify tree */
      code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
!     if(code) {
          cm_ReleaseUser(userp);
          return CM_ERROR_NOSUCHPATH;
      }
  
! 	/* turn the connection around, if required */
! 	code = smb_IoctlPrepareRead(fidp, iop, userp);
  
! 	if (code) {
! 		cm_ReleaseUser(userp);
! 		return code;
!         }
  
! 	leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
!         if (count > leftToCopy) count = leftToCopy;
!         
!         /* now set the parms for a read of count bytes */
!         smb_SetSMBParm(outp, 0, count);
!         smb_SetSMBParm(outp, 1, 0);
!         smb_SetSMBParm(outp, 2, 0);
!         smb_SetSMBParm(outp, 3, 0);
!         smb_SetSMBParm(outp, 4, 0);
! 
! 	smb_SetSMBDataLength(outp, count+3);
! 
!         op = smb_GetSMBData(outp, NULL);
!         *op++ = 1;
!         *op++ = (char)(count & 0xff);
!         *op++ = (char)((count >> 8) & 0xff);
!         
! 	/* now copy the data into the response packet */
!         memcpy(op, iop->outCopied + iop->outAllocp, count);
  
!         /* and adjust the counters */
!         iop->outCopied += count;
!         
!         cm_ReleaseUser(userp);
!         smb_ReleaseFID(fidp);
  
!         return 0;
! }
  
  /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
   * file descriptor.
   */
  long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
  {
! 	smb_ioctl_t *iop;
!         long count;
!         long code;
!         char *op;
!         int inDataBlockCount;
! 
! 	code = 0;
! 	count = smb_GetSMBParm(inp, 1);
!         iop = fidp->ioctlp;
!         
! 	smb_IoctlPrepareWrite(fidp, iop);
  
!         op = smb_GetSMBData(inp, NULL);
! 	op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
! 	
!         if (count + iop->inCopied > SMB_IOCTL_MAXDATA) {
! 		code = CM_ERROR_TOOBIG;
!                 goto done;
!         }
          
! 	/* copy data */
!         memcpy(iop->inDatap + iop->inCopied, op, count);
          
!         /* adjust counts */
!         iop->inCopied += count;
  
! done:
! 	/* return # of bytes written */
! 	if (code == 0) {
! 		smb_SetSMBParm(outp, 0, count);
!                 smb_SetSMBDataLength(outp, 0);
!         }
  
!         smb_ReleaseFID(fidp);
!         return code;
  }
  
  /* called from V3 read to handle IOCTL descriptor reads */
  long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
  {
! 	smb_ioctl_t *iop;
      long count;
      long code;
      long leftToCopy;
--- 159,287 ----
   */
  void smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
  {
!     /* make sure the buffer(s) are allocated */
!     if (!ioctlp->inAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA);
!     if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA);
! 
!     /* Fixes fs la problem.  We do a StrToOEM later and if this data isn't initialized we get memory issues. */
!     (void) memset(ioctlp->inAllocp, 0, SMB_IOCTL_MAXDATA);
!     (void) memset(ioctlp->outAllocp, 0, SMB_IOCTL_MAXDATA);
! 
!     /* and make sure that we've reset our state for the new incoming request */
!     if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) {
! 	ioctlp->inCopied = 0;
! 	ioctlp->outCopied = 0;
! 	ioctlp->inDatap = ioctlp->inAllocp;
! 	ioctlp->outDatap = ioctlp->outAllocp;
! 	ioctlp->flags |= SMB_IOCTLFLAG_DATAIN;
!     }
! }	
  
  /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
  long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
! 		   smb_packet_t *outp)
  {
!     smb_ioctl_t *iop;
!     long count;
!     long leftToCopy;
!     char *op;
!     long code;
!     cm_user_t *userp;
  
!     iop = fidp->ioctlp;
!     count = smb_GetSMBParm(inp, 1);
!     userp = smb_GetUser(vcp, inp);
! 
!     /* Identify tree */
      code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
!     if (code) {
          cm_ReleaseUser(userp);
          return CM_ERROR_NOSUCHPATH;
      }
  
!     /* turn the connection around, if required */
!     code = smb_IoctlPrepareRead(fidp, iop, userp);
  
!     if (code) {
! 	cm_ReleaseUser(userp);
! 	return code;
!     }
  
!     leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
!     if (count > leftToCopy) count = leftToCopy;
  
!     /* now set the parms for a read of count bytes */
!     smb_SetSMBParm(outp, 0, count);
!     smb_SetSMBParm(outp, 1, 0);
!     smb_SetSMBParm(outp, 2, 0);
!     smb_SetSMBParm(outp, 3, 0);
!     smb_SetSMBParm(outp, 4, 0);
! 
!     smb_SetSMBDataLength(outp, count+3);
! 
!     op = smb_GetSMBData(outp, NULL);
!     *op++ = 1;
!     *op++ = (char)(count & 0xff);
!     *op++ = (char)((count >> 8) & 0xff);
  
!     /* now copy the data into the response packet */
!     memcpy(op, iop->outCopied + iop->outAllocp, count);
! 
!     /* and adjust the counters */
!     iop->outCopied += count;
! 
!     cm_ReleaseUser(userp);
!     smb_ReleaseFID(fidp);
! 
!     return 0;
! }	
  
  /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
   * file descriptor.
   */
  long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
  {
!     smb_ioctl_t *iop;
!     long count;
!     long code;
!     char *op;
!     int inDataBlockCount;
  
!     code = 0;
!     count = smb_GetSMBParm(inp, 1);
!     iop = fidp->ioctlp;
          
!     smb_IoctlPrepareWrite(fidp, iop);
! 
!     op = smb_GetSMBData(inp, NULL);
!     op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
! 
!     if (count + iop->inCopied > SMB_IOCTL_MAXDATA) {
! 	code = CM_ERROR_TOOBIG;
! 	goto done;
!     }
          
!     /* copy data */
!     memcpy(iop->inDatap + iop->inCopied, op, count);
  
!     /* adjust counts */
!     iop->inCopied += count;
  
!   done:
!     /* return # of bytes written */
!     if (code == 0) {
! 	smb_SetSMBParm(outp, 0, count);
! 	smb_SetSMBDataLength(outp, 0);
!     }
! 
!     smb_ReleaseFID(fidp);
!     return code;
  }
  
  /* called from V3 read to handle IOCTL descriptor reads */
  long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
  {
!     smb_ioctl_t *iop;
      long count;
      long code;
      long leftToCopy;
***************
*** 292,373 ****
      iop = fidp->ioctlp;
      count = smb_GetSMBParm(inp, 5);
  	
! 	userp = smb_GetUser(vcp, inp);
! 	osi_assert(userp != 0);
  
      uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
      iop->uidp = uidp;
!     if (uidp && uidp->unp)
          osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
!                   uidp->userID, userp,
!                   osi_LogSaveString(afsd_logp, uidp->unp->name));
!     else {
          if (uidp)
! 		    osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
!                       uidp->userID, userp);
          else
! 		    osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
!                      userp);
      }
  
! 	code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
!     if(code) {
!         smb_ReleaseUID(uidp);
          cm_ReleaseUser(userp);
          smb_ReleaseFID(fidp);
          return CM_ERROR_NOSUCHPATH;
      }
  
! 	code = smb_IoctlPrepareRead(fidp, iop, userp);
      if (uidp) {
          iop->uidp = 0;
          smb_ReleaseUID(uidp);
      }
      if (code) {
! 		cm_ReleaseUser(userp);
          smb_ReleaseFID(fidp);
! 		return code;
      }
  
! 	leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
      if (count > leftToCopy) count = leftToCopy;
          
! 	/* 0 and 1 are reserved for request chaining, were setup by our caller,
!          * and will be further filled in after we return.
!          */
!         smb_SetSMBParm(outp, 2, 0);	/* remaining bytes, for pipes */
!         smb_SetSMBParm(outp, 3, 0);	/* resvd */
!         smb_SetSMBParm(outp, 4, 0);	/* resvd */
! 	smb_SetSMBParm(outp, 5, count);	/* # of bytes we're going to read */
!         /* fill in #6 when we have all the parameters' space reserved */
!         smb_SetSMBParm(outp, 7, 0);	/* resv'd */
!         smb_SetSMBParm(outp, 8, 0);	/* resv'd */
!         smb_SetSMBParm(outp, 9, 0);	/* resv'd */
!         smb_SetSMBParm(outp, 10, 0);	/* resv'd */
! 	smb_SetSMBParm(outp, 11, 0);	/* reserved */
  
! 	/* get op ptr after putting in the last parm, since otherwise we don't
!          * know where the data really is.
!          */
!         op = smb_GetSMBData(outp, NULL);
!         
!         /* now fill in offset from start of SMB header to first data byte (to op) */
!         smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
! 
! 	/* set the packet data length the count of the # of bytes */
!         smb_SetSMBDataLength(outp, count);
!         
! 	/* now copy the data into the response packet */
!         memcpy(op, iop->outCopied + iop->outAllocp, count);
! 
!         /* and adjust the counters */
!         iop->outCopied += count;
!         
!         /* and cleanup things */
!         cm_ReleaseUser(userp);
!         smb_ReleaseFID(fidp);
! 
!         return 0;
  }
  
  /* called from Read Raw to handle IOCTL descriptor reads */
--- 292,374 ----
      iop = fidp->ioctlp;
      count = smb_GetSMBParm(inp, 5);
  	
!     userp = smb_GetUser(vcp, inp);
!     osi_assert(userp != 0);
  
      uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
      iop->uidp = uidp;
!     if (uidp && uidp->unp) {
          osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
!                  uidp->userID, userp,
!                  osi_LogSaveString(afsd_logp, uidp->unp->name));
!     } else {
          if (uidp)
! 	    osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
!                      uidp->userID, userp);
          else
! 	    osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
! 		     userp);
      }
  
!     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
!     if (code) {
! 	if (uidp)
! 	    smb_ReleaseUID(uidp);
          cm_ReleaseUser(userp);
          smb_ReleaseFID(fidp);
          return CM_ERROR_NOSUCHPATH;
      }
  
!     code = smb_IoctlPrepareRead(fidp, iop, userp);
      if (uidp) {
          iop->uidp = 0;
          smb_ReleaseUID(uidp);
      }
      if (code) {
! 	cm_ReleaseUser(userp);
          smb_ReleaseFID(fidp);
! 	return code;
      }
  
!     leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
      if (count > leftToCopy) count = leftToCopy;
          
!     /* 0 and 1 are reserved for request chaining, were setup by our caller,
!      * and will be further filled in after we return.
!      */
!     smb_SetSMBParm(outp, 2, 0);	/* remaining bytes, for pipes */
!     smb_SetSMBParm(outp, 3, 0);	/* resvd */
!     smb_SetSMBParm(outp, 4, 0);	/* resvd */
!     smb_SetSMBParm(outp, 5, count);	/* # of bytes we're going to read */
!     /* fill in #6 when we have all the parameters' space reserved */
!     smb_SetSMBParm(outp, 7, 0);	/* resv'd */
!     smb_SetSMBParm(outp, 8, 0);	/* resv'd */
!     smb_SetSMBParm(outp, 9, 0);	/* resv'd */
!     smb_SetSMBParm(outp, 10, 0);	/* resv'd */
!     smb_SetSMBParm(outp, 11, 0);	/* reserved */
! 
!     /* get op ptr after putting in the last parm, since otherwise we don't
!      * know where the data really is.
!      */
!     op = smb_GetSMBData(outp, NULL);
! 
!     /* now fill in offset from start of SMB header to first data byte (to op) */
!     smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
! 
!     /* set the packet data length the count of the # of bytes */
!     smb_SetSMBDataLength(outp, count);
! 
!     /* now copy the data into the response packet */
!     memcpy(op, iop->outCopied + iop->outAllocp, count);
! 
!     /* and adjust the counters */
!     iop->outCopied += count;
! 
!     /* and cleanup things */
!     cm_ReleaseUser(userp);
!     smb_ReleaseFID(fidp);
  
!     return 0;
  }
  
  /* called from Read Raw to handle IOCTL descriptor reads */
***************
*** 378,418 ****
  #endif /* DJGPP */
  )
  {
! 	smb_ioctl_t *iop;
! 	long leftToCopy;
! 	NCB *ncbp;
! 	long code;
! 	cm_user_t *userp;
  #ifdef DJGPP
!         dos_ptr dos_ncb;
  
!         if (rawBuf == 0)
!         {
!                 osi_Log0(afsd_logp, "Failed to get raw buf for smb_IoctlReadRaw");
!                 return -1;
!         }
  #endif /* DJGPP */
  
! 	iop = fidp->ioctlp;
! 
! 	userp = smb_GetUser(vcp, inp);
  
! 	{
! 		smb_user_t *uidp;
  
! 		uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
! 		if (uidp && uidp->unp)
! 		    osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
! 			     uidp->userID, userp,
! 			     osi_LogSaveString(afsd_logp, uidp->unp->name));
! 		else if (uidp)
! 		    osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
! 			     uidp->userID, userp);
!         else 
! 		    osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
! 			     userp);
! 		if (uidp) smb_ReleaseUID(uidp);
  	}
  
      code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
      if(code) {
--- 379,422 ----
  #endif /* DJGPP */
  )
  {
!     smb_ioctl_t *iop;
!     long leftToCopy;
!     NCB *ncbp;
!     long code;
!     cm_user_t *userp;
  #ifdef DJGPP
!     dos_ptr dos_ncb;
  
!     if (rawBuf == 0)
!     {
! 	osi_Log0(afsd_logp, "Failed to get raw buf for smb_IoctlReadRaw");
! 	return -1;
!     }
  #endif /* DJGPP */
  
!     iop = fidp->ioctlp;
  
!     userp = smb_GetUser(vcp, inp);
  
!     /* Log the user */
!     {
! 	smb_user_t *uidp;
! 
! 	uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
! 	if (uidp && uidp->unp) {
! 	    osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
! 		     uidp->userID, userp,
! 		     osi_LogSaveString(afsd_logp, uidp->unp->name));
! 	} else if (uidp) {
! 	    osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
! 		     uidp->userID, userp);
! 	} else {
! 	    osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
! 		      userp);
  	}
+ 	if (uidp) 
+ 	    smb_ReleaseUID(uidp);
+     }
  
      code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
      if(code) {
***************
*** 421,459 ****
          return CM_ERROR_NOSUCHPATH;
      }
  
! 	code = smb_IoctlPrepareRead(fidp, iop, userp);
! 	if (code) {
! 		cm_ReleaseUser(userp);
! 		smb_ReleaseFID(fidp);
! 		return code;
! 	}
  
! 	leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
  
! 	ncbp = outp->ncbp;
! 	memset((char *)ncbp, 0, sizeof(NCB));
  
! 	ncbp->ncb_length = (unsigned short) leftToCopy;
! 	ncbp->ncb_lsn = (unsigned char) vcp->lsn;
! 	ncbp->ncb_command = NCBSEND;
      /*ncbp->ncb_lana_num = smb_LANadapter;*/
! 	ncbp->ncb_lana_num = vcp->lana;
  
  #ifndef DJGPP
! 	ncbp->ncb_buffer = iop->outCopied + iop->outAllocp;
! 	code = Netbios(ncbp);
  #else /* DJGPP */
!         dosmemput(iop->outCopied + iop->outAllocp, ncbp->ncb_length, rawBuf);
!         ncbp->ncb_buffer = rawBuf;
!         dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
! 	code = Netbios(ncbp, dos_ncb);
  #endif /* !DJGPP */
  
! 	if (code != 0)
! 		osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
  
! 	cm_ReleaseUser(userp);
! 	smb_ReleaseFID(fidp);
  
! 	return 0;
  }
--- 425,463 ----
          return CM_ERROR_NOSUCHPATH;
      }
  
!     code = smb_IoctlPrepareRead(fidp, iop, userp);
!     if (code) {
! 	cm_ReleaseUser(userp);
! 	smb_ReleaseFID(fidp);
! 	return code;
!     }
  
!     leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
  
!     ncbp = outp->ncbp;
!     memset((char *)ncbp, 0, sizeof(NCB));
  
!     ncbp->ncb_length = (unsigned short) leftToCopy;
!     ncbp->ncb_lsn = (unsigned char) vcp->lsn;
!     ncbp->ncb_command = NCBSEND;
      /*ncbp->ncb_lana_num = smb_LANadapter;*/
!     ncbp->ncb_lana_num = vcp->lana;
  
  #ifndef DJGPP
!     ncbp->ncb_buffer = iop->outCopied + iop->outAllocp;
!     code = Netbios(ncbp);
  #else /* DJGPP */
!     dosmemput(iop->outCopied + iop->outAllocp, ncbp->ncb_length, rawBuf);
!     ncbp->ncb_buffer = rawBuf;
!     dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
!     code = Netbios(ncbp, dos_ncb);
  #endif /* !DJGPP */
  
!     if (code != 0)
! 	osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
  
!     cm_ReleaseUser(userp);
!     smb_ReleaseFID(fidp);
  
!     return 0;
  }
Index: openafs/src/WINNT/client_config/afsmap.c
diff -c openafs/src/WINNT/client_config/afsmap.c:1.1.2.1 openafs/src/WINNT/client_config/afsmap.c:1.1.2.2
*** openafs/src/WINNT/client_config/afsmap.c:1.1.2.1	Fri Mar 11 02:23:09 2005
--- openafs/src/WINNT/client_config/afsmap.c	Mon Jan 16 22:58:05 2006
***************
*** 91,97 ****
  	if (code == ERROR_SUCCESS) {
  		cm_mountRootLen = strlen(cm_mountRoot);
  	} else {
! 		strcpy(mountRoot, sizeof(cm_mountRoot), "/afs");
  		cm_mountRootLen = 4;
  	}
  
--- 91,97 ----
  	if (code == ERROR_SUCCESS) {
  		cm_mountRootLen = strlen(cm_mountRoot);
  	} else {
! 		strncpy(mountRoot, sizeof(cm_mountRoot), "/afs");
  		cm_mountRootLen = 4;
  	}
  
Index: openafs/src/afs/afs.h
diff -c openafs/src/afs/afs.h:1.48.2.25 openafs/src/afs/afs.h:1.48.2.27
*** openafs/src/afs/afs.h:1.48.2.25	Fri Nov 18 23:35:39 2005
--- openafs/src/afs/afs.h	Tue Jan 24 12:41:20 2006
***************
*** 570,576 ****
  #define VREFCOUNT_GT(v, y)    (AFSTOV(v)->v_usecount > (y))
  #elif defined(AFS_LINUX24_ENV)
  #define VREFCOUNT(v)		atomic_read(&(AFSTOV(v)->v_count))
! #define VREFCOUNT_GT(v, y)    ((atomic_read(&((vnode_t *) v)->v_count)>y)?1:0)
  #define VREFCOUNT_SET(v, c)	atomic_set(&(AFSTOV(v)->v_count), c)
  #define VREFCOUNT_DEC(v)	atomic_dec(&(AFSTOV(v)->v_count))
  #define VREFCOUNT_INC(v)	atomic_inc(&(AFSTOV(v)->v_count))
--- 570,576 ----
  #define VREFCOUNT_GT(v, y)    (AFSTOV(v)->v_usecount > (y))
  #elif defined(AFS_LINUX24_ENV)
  #define VREFCOUNT(v)		atomic_read(&(AFSTOV(v)->v_count))
! #define VREFCOUNT_GT(v, y)      (VREFCOUNT(v)>y)
  #define VREFCOUNT_SET(v, c)	atomic_set(&(AFSTOV(v)->v_count), c)
  #define VREFCOUNT_DEC(v)	atomic_dec(&(AFSTOV(v)->v_count))
  #define VREFCOUNT_INC(v)	atomic_inc(&(AFSTOV(v)->v_count))
***************
*** 920,926 ****
    char lockers;
    char dirty;
    char hashIndex;
! #if AFS_USEBUFFERS
    struct buf *bufp;
  #endif
    afs_rwlock_t lock;          /* the lock for this structure */
--- 920,926 ----
    char lockers;
    char dirty;
    char hashIndex;
! #if defined(AFS_USEBUFFERS)
    struct buf *bufp;
  #endif
    afs_rwlock_t lock;          /* the lock for this structure */
Index: openafs/src/afs/afs_buffer.c
diff -c openafs/src/afs/afs_buffer.c:1.16.2.5 openafs/src/afs/afs_buffer.c:1.16.2.6
*** openafs/src/afs/afs_buffer.c:1.16.2.5	Thu Jul 28 17:33:57 2005
--- openafs/src/afs/afs_buffer.c	Tue Jan 24 12:41:20 2006
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_buffer.c,v 1.16.2.5 2005/07/28 21:33:57 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_buffer.c,v 1.16.2.6 2006/01/24 17:41:20 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
***************
*** 98,104 ****
      /* Initialize the venus buffer system. */
      register int i;
      register struct buffer *tb;
! #if AFS_USEBUFFERS
      struct buf *tub;		/* unix buffer for allocation */
  #endif
  
--- 98,104 ----
      /* Initialize the venus buffer system. */
      register int i;
      register struct buffer *tb;
! #if defined(AFS_USEBUFFERS)
      struct buf *tub;		/* unix buffer for allocation */
  #endif
  
***************
*** 106,119 ****
      if (dinit_flag)
  	return;
      dinit_flag = 1;
! #if AFS_USEBUFFERS
      /* round up to next multiple of NPB, since we allocate multiple pages per chunk */
      abuffers = ((abuffers - 1) | (NPB - 1)) + 1;
  #endif
      LOCK_INIT(&afs_bufferLock, "afs_bufferLock");
      Buffers =
  	(struct buffer *)afs_osi_Alloc(abuffers * sizeof(struct buffer));
! #if !AFS_USEBUFFERS
      BufferData = (char *)afs_osi_Alloc(abuffers * AFS_BUFFER_PAGESIZE);
  #endif
      timecounter = 1;
--- 106,119 ----
      if (dinit_flag)
  	return;
      dinit_flag = 1;
! #if defined(AFS_USEBUFFERS)
      /* round up to next multiple of NPB, since we allocate multiple pages per chunk */
      abuffers = ((abuffers - 1) | (NPB - 1)) + 1;
  #endif
      LOCK_INIT(&afs_bufferLock, "afs_bufferLock");
      Buffers =
  	(struct buffer *)afs_osi_Alloc(abuffers * sizeof(struct buffer));
! #if !defined(AFS_USEBUFFERS)
      BufferData = (char *)afs_osi_Alloc(abuffers * AFS_BUFFER_PAGESIZE);
  #endif
      timecounter = 1;
***************
*** 121,127 ****
      for (i = 0; i < PHSIZE; i++)
  	phTable[i] = 0;
      for (i = 0; i < abuffers; i++) {
! #if AFS_USEBUFFERS
  	if ((i & (NPB - 1)) == 0) {
  	    /* time to allocate a fresh buffer */
  	    tub = geteblk(AFS_BUFFER_PAGESIZE * NPB);
--- 121,127 ----
      for (i = 0; i < PHSIZE; i++)
  	phTable[i] = 0;
      for (i = 0; i < abuffers; i++) {
! #if defined(AFS_USEBUFFERS)
  	if ((i & (NPB - 1)) == 0) {
  	    /* time to allocate a fresh buffer */
  	    tub = geteblk(AFS_BUFFER_PAGESIZE * NPB);
***************
*** 134,140 ****
  	tb->inode = 0;
  	tb->accesstime = 0;
  	tb->lockers = 0;
! #if AFS_USEBUFFERS
  	if ((i & (NPB - 1)) == 0)
  	    tb->bufp = tub;
  	else
--- 134,140 ----
  	tb->inode = 0;
  	tb->accesstime = 0;
  	tb->lockers = 0;
! #if defined(AFS_USEBUFFERS)
  	if ((i & (NPB - 1)) == 0)
  	    tb->bufp = tub;
  	else
***************
*** 368,381 ****
      /* Release a buffer, specifying whether or not the buffer has been
       * modified by the locker. */
      register int index;
! #if AFS_USEBUFFERS
      register struct buffer *tp;
  #endif
  
      AFS_STATCNT(DRelease);
      if (!bp)
  	return;
! #if AFS_USEBUFFERS
      /* look for buffer by scanning Unix buffers for appropriate address */
      tp = Buffers;
      for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
--- 368,381 ----
      /* Release a buffer, specifying whether or not the buffer has been
       * modified by the locker. */
      register int index;
! #if defined(AFS_USEBUFFERS)
      register struct buffer *tp;
  #endif
  
      AFS_STATCNT(DRelease);
      if (!bp)
  	return;
! #if defined(AFS_USEBUFFERS)
      /* look for buffer by scanning Unix buffers for appropriate address */
      tp = Buffers;
      for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
***************
*** 404,415 ****
      /* Return the byte within a file represented by a buffer pointer. */
      register struct buffer *bp;
      register int index;
! #if AFS_USEBUFFERS
      register struct buffer *tp;
  #endif
      AFS_STATCNT(DVOffset);
      bp = ap;
! #if AFS_USEBUFFERS
      /* look for buffer by scanning Unix buffers for appropriate address */
      tp = Buffers;
      for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
--- 404,415 ----
      /* Return the byte within a file represented by a buffer pointer. */
      register struct buffer *bp;
      register int index;
! #if defined(AFS_USEBUFFERS)
      register struct buffer *tp;
  #endif
      AFS_STATCNT(DVOffset);
      bp = ap;
! #if defined(AFS_USEBUFFERS)
      /* look for buffer by scanning Unix buffers for appropriate address */
      tp = Buffers;
      for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
***************
*** 530,536 ****
  void
  shutdown_bufferpackage(void)
  {
! #if AFS_USEBUFFERS
      register struct buffer *tp;
  #endif
      int i;
--- 530,536 ----
  void
  shutdown_bufferpackage(void)
  {
! #if defined(AFS_USEBUFFERS)
      register struct buffer *tp;
  #endif
      int i;
***************
*** 541,547 ****
      DFlush();
      if (afs_cold_shutdown) {
  	dinit_flag = 0;
! #if !AFS_USEBUFFERS
  	afs_osi_Free(BufferData, nbuffers * AFS_BUFFER_PAGESIZE);
  #else
  	tp = Buffers;
--- 541,547 ----
      DFlush();
      if (afs_cold_shutdown) {
  	dinit_flag = 0;
! #if !defined(AFS_USEBUFFERS)
  	afs_osi_Free(BufferData, nbuffers * AFS_BUFFER_PAGESIZE);
  #else
  	tp = Buffers;
Index: openafs/src/afs/afs_call.c
diff -c openafs/src/afs/afs_call.c:1.74.2.11 openafs/src/afs/afs_call.c:1.74.2.12
*** openafs/src/afs/afs_call.c:1.74.2.11	Wed Oct  5 01:58:26 2005
--- openafs/src/afs/afs_call.c	Tue Jan 17 12:09:47 2006
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_call.c,v 1.74.2.11 2005/10/05 05:58:26 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_call.c,v 1.74.2.12 2006/01/17 17:09:47 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 150,155 ****
--- 150,282 ----
  
      return code;
  }
+ #if defined(AFS_DARWIN80_ENV)
+ struct afsd_thread_info {
+     unsigned long parm;
+ };
+ static int
+ afsd_thread(int *rock)
+ {
+     struct afsd_thread_info *arg = (struct afsd_thread_info *)rock;
+     unsigned long parm = arg->parm;
+ 
+     switch (parm) {
+     case AFSOP_START_RXCALLBACK:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	afs_CB_Running = 1;
+ 	while (afs_RX_Running != 2)
+ 	    afs_osi_Sleep(&afs_RX_Running);
+ 	afs_RXCallBackServer();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_START_AFS:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	AFS_Running = 1;
+ 	while (afs_initState < AFSOP_START_AFS)
+ 	    afs_osi_Sleep(&afs_initState);
+ 	afs_initState = AFSOP_START_BKG;
+ 	afs_osi_Wakeup(&afs_initState);
+ 	afs_Daemon();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_START_BKG:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	while (afs_initState < AFSOP_START_BKG)
+ 	    afs_osi_Sleep(&afs_initState);
+ 	if (afs_initState < AFSOP_GO) {
+ 	    afs_initState = AFSOP_GO;
+ 	    afs_osi_Wakeup(&afs_initState);
+ 	}
+ 	afs_BackgroundDaemon();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_START_TRUNCDAEMON:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	while (afs_initState < AFSOP_GO)
+ 	    afs_osi_Sleep(&afs_initState);
+ 	afs_CacheTruncateDaemon();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_START_CS:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	afs_CheckServerDaemon();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_RXEVENT_DAEMON:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	while (afs_initState < AFSOP_START_BKG)
+ 	    afs_osi_Sleep(&afs_initState);
+ 	afs_rxevent_daemon();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     case AFSOP_RXLISTENER_DAEMON:
+ 	AFS_GLOCK();
+ 	wakeup(arg);
+ 	afs_initState = AFSOP_START_AFS;
+ 	afs_osi_Wakeup(&afs_initState);
+ 	afs_RX_Running = 2;
+ 	afs_osi_Wakeup(&afs_RX_Running);
+ 	afs_osi_RxkRegister();
+ 	rxk_Listener();
+ 	AFS_GUNLOCK();
+ 	thread_terminate(current_thread());
+ 	break;
+     default:
+ 	printf("Unknown op %ld in StartDaemon()\n", (long)parm);
+ 	break;
+     }
+ }
+ 
+ void
+ afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
+ 	     long parm6)
+ {
+     int code;
+     struct afsd_thread_info info;
+     thread_t thread;
+ 
+     if (parm == AFSOP_START_RXCALLBACK) {
+ 	if (afs_CB_Running)
+ 	    return;
+     } else if (parm == AFSOP_RXLISTENER_DAEMON) {
+ 	if (afs_RX_Running)
+ 	    return;
+ 	afs_RX_Running = 1;
+ 	code = afs_InitSetup(parm2);
+ 	if (parm3) {
+ 	    rx_enablePeerRPCStats();
+ 	}
+ 	if (parm4) {
+ 	    rx_enableProcessRPCStats();
+ 	}
+ 	if (code)
+ 	    return;
+     } else if (parm == AFSOP_START_AFS) {
+ 	if (AFS_Running)
+ 	    return;
+     }				/* other functions don't need setup in the parent */
+     info.parm = parm;
+     kernel_thread_start((thread_continue_t)afsd_thread, &info, &thread);
+     AFS_GUNLOCK();
+     /* we need to wait cause we passed stack pointers around.... */
+     msleep(&info, NULL, PVFS, "afs_DaemonOp", NULL);
+     AFS_GLOCK();
+     thread_deallocate(thread);
+ }
+ #endif
+ 
  
  #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)
  struct afsd_thread_info {
***************
*** 381,387 ****
  #ifdef AFS_DARWIN80_ENV
      put_vfs_context();
  #endif
! #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS) && !defined(UKERNEL)
      if (parm < AFSOP_ADDCELL || parm == AFSOP_RXEVENT_DAEMON
  	|| parm == AFSOP_RXLISTENER_DAEMON) {
  	afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
--- 508,514 ----
  #ifdef AFS_DARWIN80_ENV
      put_vfs_context();
  #endif
! #if ((defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)) || defined(AFS_DARWIN80_ENV)) && !defined(UKERNEL)
      if (parm < AFSOP_ADDCELL || parm == AFSOP_RXEVENT_DAEMON
  	|| parm == AFSOP_RXLISTENER_DAEMON) {
  	afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
Index: openafs/src/afs/afs_callback.c
diff -c openafs/src/afs/afs_callback.c:1.27.2.4 openafs/src/afs/afs_callback.c:1.27.2.5
*** openafs/src/afs/afs_callback.c:1.27.2.4	Thu Oct 13 14:08:39 2005
--- openafs/src/afs/afs_callback.c	Tue Jan 24 12:34:15 2006
***************
*** 17,23 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_callback.c,v 1.27.2.4 2005/10/13 18:08:39 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
--- 17,23 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_callback.c,v 1.27.2.5 2006/01/24 17:34:15 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 59,65 ****
      "afs_xosi", (char *)&afs_xosi},
  #endif
      {
!     "afs_xsrvAddr", (char *)&afs_xsrvAddr}
  };
  unsigned long lastCallBack_vnode;
  unsigned int lastCallBack_dv;
--- 59,67 ----
      "afs_xosi", (char *)&afs_xosi},
  #endif
      {
!       "afs_xsrvAddr", (char *)&afs_xsrvAddr},
!     {
!     "afs_xvreclaim", (char *)&afs_xvreclaim}
  };
  unsigned long lastCallBack_vnode;
  unsigned int lastCallBack_dv;
Index: openafs/src/afs/afs_daemons.c
diff -c openafs/src/afs/afs_daemons.c:1.28.2.9 openafs/src/afs/afs_daemons.c:1.28.2.10
*** openafs/src/afs/afs_daemons.c:1.28.2.9	Sat Oct 15 10:24:24 2005
--- openafs/src/afs/afs_daemons.c	Tue Jan 24 12:34:15 2006
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.28.2.9 2005/10/15 14:24:24 shadow Exp $");
  
  #ifdef AFS_AIX51_ENV
  #define __FULL_PROTO
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.28.2.10 2006/01/24 17:34:15 shadow Exp $");
  
  #ifdef AFS_AIX51_ENV
  #define __FULL_PROTO
***************
*** 175,180 ****
--- 175,183 ----
  	    /* things to do every minute */
  	    DFlush();		/* write out dir buffers */
  	    afs_WriteThroughDSlots();	/* write through cacheinfo entries */
+ 	    ObtainWriteLock(&afs_xvcache, 736);
+ 	    afs_FlushReclaimedVcaches();
+ 	    ReleaseWriteLock(&afs_xvcache);
  	    afs_FlushActiveVcaches(1);	/* keep flocks held & flush nfs writes */
  #ifdef AFS_DISCON_ENV
  	    afs_StoreDirtyVcaches();
Index: openafs/src/afs/afs_prototypes.h
diff -c openafs/src/afs/afs_prototypes.h:1.53.2.12 openafs/src/afs/afs_prototypes.h:1.53.2.15
*** openafs/src/afs/afs_prototypes.h:1.53.2.12	Thu Oct 13 14:08:39 2005
--- openafs/src/afs/afs_prototypes.h	Tue Jan 24 23:47:11 2006
***************
*** 531,537 ****
  
  
  /* ARCH/osi_misc.c */
- extern void osi_iput(struct inode *ip);
  extern void afs_osi_SetTime(osi_timeval_t * atv);
  
  /* LINUX/osi_misc.c */
--- 531,536 ----
***************
*** 812,817 ****
--- 811,817 ----
  extern afs_int32 afs_maxvcount;
  extern afs_int32 afs_vcount;
  extern int afsvnumbers;
+ extern afs_rwlock_t afs_xvreclaim;
  extern afs_rwlock_t afs_xvcache;
  extern afs_lock_t afs_xvcb;
  extern struct afs_q VLRU;
***************
*** 820,825 ****
--- 820,826 ----
  extern struct afs_q afs_vhashTV[VCSIZE];
  extern afs_int32 afs_bulkStatsLost;
  extern int afs_norefpanic;
+ extern struct vcache *ReclaimedVCList;
  
  void afs_vcacheInit(int astatSize);
  extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 * retry,
Index: openafs/src/afs/afs_vcache.c
diff -c openafs/src/afs/afs_vcache.c:1.65.2.34 openafs/src/afs/afs_vcache.c:1.65.2.37
*** openafs/src/afs/afs_vcache.c:1.65.2.34	Thu Jan  5 00:57:56 2006
--- openafs/src/afs/afs_vcache.c	Tue Jan 24 23:47:11 2006
***************
*** 39,45 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.65.2.34 2006/01/05 05:57:56 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
--- 39,45 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.65.2.37 2006/01/25 04:47:11 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 62,70 ****
--- 62,72 ----
  
  /* Exported variables */
  afs_rwlock_t afs_xvcache;	/*Lock: alloc new stat cache entries */
+ afs_rwlock_t afs_xvreclaim;	/*Lock: entries reclaimed, not on free list */
  afs_lock_t afs_xvcb;		/*Lock: fids on which there are callbacks */
  #if !defined(AFS_LINUX22_ENV)
  static struct vcache *freeVCList;	/*Free list for stat cache entries */
+ struct vcache *ReclaimedVCList;	/*Reclaimed list for stat entries */
  static struct vcache *Initial_freeVCList;	/*Initial list for above */
  #endif
  struct afs_q VLRU;		/*vcache LRU */
***************
*** 572,577 ****
--- 574,611 ----
      MReleaseWriteLock(&afs_xvcb);
  }
  
+ void 
+ afs_FlushReclaimedVcaches(void)
+ {
+ #if !defined(AFS_LINUX22_ENV)
+     struct vcache *tvc;
+     int code, fv_slept;
+     struct vcache *tmpReclaimedVCList = NULL;	
+ 
+     ObtainWriteLock(&afs_xvreclaim, 76);
+     while (ReclaimedVCList) {
+ 	tvc = ReclaimedVCList;	/* take from free list */
+ 	ReclaimedVCList = tvc->nextfree;
+ 	tvc->nextfree = NULL;
+ 	code = afs_FlushVCache(tvc, &fv_slept);
+ 	if (code) {
+ 	    /* Ok, so, if we got code != 0, uh, wtf do we do? */
+ 	    /* Probably, build a temporary list and then put all back when we
+ 	       get to the end of the list */
+ 	    /* This is actually really crappy, but we need to not leak these.
+ 	       We probably need a way to be smarter about this. */
+ 	    tvc->nextfree = tmpReclaimedVCList;
+ 	    tmpReclaimedVCList = tvc;
+ 	    printf("Reclaim list flush %x failed: %d\n", tvc, code);
+ 	}
+     }
+     if (tmpReclaimedVCList) 
+ 	ReclaimedVCList = tmpReclaimedVCList;
+ 
+     ReleaseWriteLock(&afs_xvreclaim);
+ #endif
+ }
+ 
  /*
   * afs_NewVCache
   *
***************
*** 603,608 ****
--- 637,645 ----
      int code, fv_slept;
  
      AFS_STATCNT(afs_NewVCache);
+ 
+     afs_FlushReclaimedVcaches();
+ 
  #if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
  #if defined(AFS_OSF30_ENV) || defined(AFS_LINUX22_ENV)
      if (afs_vcount >= afs_maxvcount)
Index: openafs/src/afs/AIX/osi_machdep.h
diff -c openafs/src/afs/AIX/osi_machdep.h:1.3.2.2 openafs/src/afs/AIX/osi_machdep.h:1.3.2.3
*** openafs/src/afs/AIX/osi_machdep.h:1.3.2.2	Wed Apr 13 22:31:34 2005
--- openafs/src/afs/AIX/osi_machdep.h	Fri Jan 20 00:06:57 2006
***************
*** 69,74 ****
--- 69,76 ----
  			    simple_unlock((void *)&afs_global_lock);	\
  			} while(0)
  #define ISAFS_GLOCK()	lock_mine((void *)&afs_global_lock)
+ 
+ #define ifnet_flags(x) (x?(x)->if_flags:0)
  #endif
  
  #endif /* _OSI_MACHDEP_H_ */
Index: openafs/src/afs/AIX/osi_vnodeops.c
diff -c openafs/src/afs/AIX/osi_vnodeops.c:1.15.2.1 openafs/src/afs/AIX/osi_vnodeops.c:1.15.2.2
*** openafs/src/afs/AIX/osi_vnodeops.c:1.15.2.1	Sat Oct 15 10:24:25 2005
--- openafs/src/afs/AIX/osi_vnodeops.c	Fri Jan 20 00:06:57 2006
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/AIX/osi_vnodeops.c,v 1.15.2.1 2005/10/15 14:24:25 shadow Exp $");
  
  #include "h/systm.h"
  #include "h/types.h"
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/AIX/osi_vnodeops.c,v 1.15.2.2 2006/01/20 05:06:57 shadow Exp $");
  
  #include "h/systm.h"
  #include "h/types.h"
***************
*** 888,899 ****
--- 888,901 ----
      xfrOffset = uiop->afsio_offset;
      if (xfrOffset < 0 || xfrOffset + xfrSize < 0) {
  	code = EINVAL;
+ 	ReleaseReadLock(&vcp->lock);
  	goto fail;
      }
  #ifndef AFS_64BIT_CLIENT
      /* check for "file too big" error, which should really be done above us */
      if (rw == UIO_WRITE && xfrSize + fileSize > get_ulimit()) {
  	code = EFBIG;
+ 	ReleaseReadLock(&vcp->lock);
  	goto fail;
      }
  #endif /* AFS_64BIT_CLIENT */
***************
*** 903,911 ****
          if (rw == UIO_READ) {
              /* don't read past EOF */
              if (xfrSize+xfrOffset > fileSize) {
!             add2resid = xfrSize + xfrOffset - fileSize;
!             xfrSize = fileSize - xfrOffset;
!             if (xfrSize <= 0) goto fail;
                  txfrSize = xfrSize;
                  afsio_trim(uiop, txfrSize);
              }
--- 905,916 ----
          if (rw == UIO_READ) {
              /* don't read past EOF */
              if (xfrSize+xfrOffset > fileSize) {
! 		add2resid = xfrSize + xfrOffset - fileSize;
! 		xfrSize = fileSize - xfrOffset;
! 		if (xfrSize <= 0) {
! 		    ReleaseReadLock(&vcp->lock);
! 		    goto fail;
! 		}
                  txfrSize = xfrSize;
                  afsio_trim(uiop, txfrSize);
              }
***************
*** 932,940 ****
  	    ObtainWriteLock(&vcp->lock, 244);
  	    afs_FakeOpen(vcp);	/* XXXX For nfs trans and cores XXXX */
  	    ReleaseWriteLock(&vcp->lock);
- 	    ObtainReadLock(&vcp->lock);
  	    if (code)
  		goto fail;
  	    xfrSize = afs_vmMappingEnd - xfrOffset;
  	    txfrSize = xfrSize;
  	    afsio_trim(uiop, txfrSize);
--- 937,945 ----
  	    ObtainWriteLock(&vcp->lock, 244);
  	    afs_FakeOpen(vcp);	/* XXXX For nfs trans and cores XXXX */
  	    ReleaseWriteLock(&vcp->lock);
  	    if (code)
  		goto fail;
+ 	    ObtainReadLock(&vcp->lock);
  	    xfrSize = afs_vmMappingEnd - xfrOffset;
  	    txfrSize = xfrSize;
  	    afsio_trim(uiop, txfrSize);
***************
*** 956,961 ****
--- 961,967 ----
  	/* Consider  V_INTRSEG too for interrupts */
  	if (code =
  	    vms_create(&vcp->segid, V_CLIENT, (dev_t) vcp->v.v_gnode, tlen, 0, 0)) {
+ 	    ReleaseReadLock(&vcp->lock);
  	    goto fail;
  	}
  #ifdef AFS_64BIT_KERNEL
***************
*** 966,977 ****
      }
      vcp->v.v_gnode->gn_seg = vcp->segid;
      if (rw == UIO_READ) {
  	/* don't read past EOF */
  	if (xfrSize + xfrOffset > fileSize)
  	    xfrSize = fileSize - xfrOffset;
  	if (xfrSize <= 0)
  	    goto fail;
- 	ReleaseReadLock(&vcp->lock);
  #ifdef AFS_64BIT_CLIENT
  	toffset = xfrOffset;
  	uiop->afsio_offset = xfrOffset;
--- 972,983 ----
      }
      vcp->v.v_gnode->gn_seg = vcp->segid;
      if (rw == UIO_READ) {
+ 	ReleaseReadLock(&vcp->lock);
  	/* don't read past EOF */
  	if (xfrSize + xfrOffset > fileSize)
  	    xfrSize = fileSize - xfrOffset;
  	if (xfrSize <= 0)
  	    goto fail;
  #ifdef AFS_64BIT_CLIENT
  	toffset = xfrOffset;
  	uiop->afsio_offset = xfrOffset;
***************
*** 1072,1077 ****
--- 1078,1086 ----
  	    code = vm_move(vcp->segid, xfrOffset, xfrSize, rw, uiop);
  #endif /* AFS_64BIT_CLIENT */
  	    AFS_GLOCK();
+ 	    if (code) {
+ 		goto fail;
+ 	    }
  	    xfrOffset += len;
  	    xfrSize = 0;
  	} else {
***************
*** 1090,1095 ****
--- 1099,1107 ----
  		code = afs_DoPartialWrite(vcp, &treq);
  		vcp->states |= CDirty;
  		ReleaseWriteLock(&vcp->lock);
+ 		if (code) {
+ 		    goto fail;
+ 		}
  	    }
  	    counter++;
  
***************
*** 1107,1112 ****
--- 1119,1128 ----
  #endif /* AFS_64BIT_CLIENT */
  	    AFS_GLOCK();
  	    len -= tuio.afsio_resid;
+ 	    if (code || (len <= 0)) {
+ 		code = code ? code : EINVAL;
+ 		goto fail;
+ 	    }
  	    afsio_skip(uiop, len);
  	    xfrSize -= len;
  	    xfrOffset += len;
***************
*** 1120,1128 ****
  		   ICL_TYPE_INT32, first_page, ICL_TYPE_INT32, pages);
  	AFS_GUNLOCK();
  	code = vm_writep(vcp->segid, first_page, pages);
  	if (++count > AFS_MAX_VM_CHUNKS) {
  	    count = 0;
! 	    vms_iowait(vcp->segid);
  	}
  	AFS_GLOCK();
  
--- 1136,1153 ----
  		   ICL_TYPE_INT32, first_page, ICL_TYPE_INT32, pages);
  	AFS_GUNLOCK();
  	code = vm_writep(vcp->segid, first_page, pages);
+ 	if (code) {
+ 	    AFS_GLOCK();
+ 	    goto fail;
+ 	}
  	if (++count > AFS_MAX_VM_CHUNKS) {
  	    count = 0;
! 	    code = vms_iowait(vcp->segid);
! 	    if (code) {
! 		/* cache device failure? */
! 		AFS_GLOCK();
! 		goto fail;
! 	    }
  	}
  	AFS_GLOCK();
  
***************
*** 1130,1137 ****
  
      if (count) {
  	AFS_GUNLOCK();
! 	vms_iowait(vcp->segid);
  	AFS_GLOCK();
      }
  
      ObtainWriteLock(&vcp->lock, 242);
--- 1155,1166 ----
  
      if (count) {
  	AFS_GUNLOCK();
! 	code = vms_iowait(vcp->segid);
  	AFS_GLOCK();
+ 	if (code) {
+ 	    /* cache device failure? */
+ 	    goto fail;
+ 	}
      }
  
      ObtainWriteLock(&vcp->lock, 242);
***************
*** 1162,1170 ****
  	uiop->afsio_offset = finalOffset;
      }
  #endif /* AFS_64BIT_CLIENT */
  
    fail:
-     ReleaseReadLock(&vcp->lock);
      afs_Trace2(afs_iclSetp, CM_TRACE_VMWRITE3, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_INT32, code);
      return code;
--- 1191,1199 ----
  	uiop->afsio_offset = finalOffset;
      }
  #endif /* AFS_64BIT_CLIENT */
+     ReleaseReadLock(&vcp->lock);
  
    fail:
      afs_Trace2(afs_iclSetp, CM_TRACE_VMWRITE3, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_INT32, code);
      return code;
Index: openafs/src/afs/DARWIN/osi_vfsops.c
diff -c openafs/src/afs/DARWIN/osi_vfsops.c:1.11.2.3 openafs/src/afs/DARWIN/osi_vfsops.c:1.11.2.4
*** openafs/src/afs/DARWIN/osi_vfsops.c:1.11.2.3	Tue Nov 29 00:02:24 2005
--- openafs/src/afs/DARWIN/osi_vfsops.c	Tue Jan 17 11:08:20 2006
***************
*** 5,11 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v 1.11.2.3 2005/11/29 05:02:24 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
--- 5,11 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v 1.11.2.4 2006/01/17 16:08:20 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 503,510 ****
  	    switch (name[2]) {
  	    case AFS_SC_DARWIN_ALL_REALMODES:
  #ifdef AFS_DARWIN80_ENV
!                newlen;
!                /* XXX complicated */
  #else
  	        return sysctl_int(oldp, oldlenp, newp, newlen,
  				  &afs_darwin_realmodes);
--- 503,525 ----
  	    switch (name[2]) {
  	    case AFS_SC_DARWIN_ALL_REALMODES:
  #ifdef AFS_DARWIN80_ENV
! 		if (oldp != USER_ADDR_NULL && oldlenp == NULL)
! 		    return (EFAULT);
! 		if (oldp && *oldlenp < sizeof(u_int32_t))
! 		    return (ENOMEM);
! 		if (newp && newlen != sizeof(u_int32_t))
! 		    return (EINVAL);
! 		*oldlenp = sizeof(u_int32_t);
! 		if (oldp) {
! 		    if ((error = copyout(&afs_darwin_realmodes,
! 					 oldp, sizeof(u_int32_t)))) {
! 			return error;
! 		    }
! 		}
! 		if (newp)
! 		    return copyin(newp, &afs_darwin_realmodes,
! 				  sizeof(u_int32_t));
! 		return 0;
  #else
  	        return sysctl_int(oldp, oldlenp, newp, newlen,
  				  &afs_darwin_realmodes);
Index: openafs/src/afs/DARWIN/osi_vnodeops.c
diff -c openafs/src/afs/DARWIN/osi_vnodeops.c:1.18.2.11 openafs/src/afs/DARWIN/osi_vnodeops.c:1.18.2.15
*** openafs/src/afs/DARWIN/osi_vnodeops.c:1.18.2.11	Tue Jan 10 23:24:39 2006
--- openafs/src/afs/DARWIN/osi_vnodeops.c	Tue Jan 24 23:47:12 2006
***************
*** 5,11 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vnodeops.c,v 1.18.2.11 2006/01/11 04:24:39 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
--- 5,11 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vnodeops.c,v 1.18.2.15 2006/01/25 04:47:12 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 299,309 ****
      int wantparent;		/* 1 => wantparent or lockparent flag */
      struct proc *p;
  #ifdef AFS_DARWIN80_ENV
!     error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
!     if (error == -1) 
!        return 0;
!     if (error == ENOENT) 
!        return error;
  #endif
  
      GETNAME();
--- 299,312 ----
      int wantparent;		/* 1 => wantparent or lockparent flag */
      struct proc *p;
  #ifdef AFS_DARWIN80_ENV
!     vcp = VTOAFS(ap->a_dvp);
!     if (vcp->mvstat != 1) {
! 	error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
! 	if (error == -1) 
! 	    return 0;
! 	if (error == ENOENT) 
! 	    return error;
!     }
  #endif
  
      GETNAME();
***************
*** 1621,1627 ****
  				 * } */ *ap;
  {
      int error = 0;
!     int sl;
      register struct vnode *vp = ap->a_vp;
      struct vcache *tvc = VTOAFS(vp);
  
--- 1624,1630 ----
  				 * } */ *ap;
  {
      int error = 0;
!     int sl, writelocked;
      register struct vnode *vp = ap->a_vp;
      struct vcache *tvc = VTOAFS(vp);
  
***************
*** 1629,1653 ****
      cache_purge(vp);		/* just in case... */
      if (tvc) {
         AFS_GLOCK();
!        ObtainWriteLock(&afs_xvcache, 335);
!        error = afs_FlushVCache(tvc, &sl);	/* toss our stuff from vnode */
!        if (tvc->states & (CVInit
! #ifdef AFS_DARWIN80_ENV
! 			  | CDeadVnode
! #endif
! 			  )) {
!           tvc->states &= ~(CVInit
! #ifdef AFS_DARWIN80_ENV
! 			   | CDeadVnode
! #endif
! 			   );
!           afs_osi_Wakeup(&tvc->states);
         }
-        if (!error && vnode_fsnode(vp))
- 	   panic("afs_reclaim: vnode not cleaned");
-        if (!error && (tvc->v != NULL)) 
-            panic("afs_reclaim: vcache not cleaned");
-        ReleaseWriteLock(&afs_xvcache);
         AFS_GUNLOCK();
      }
      return error;
--- 1632,1671 ----
      cache_purge(vp);		/* just in case... */
      if (tvc) {
         AFS_GLOCK();
!        writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
!        if (!writelocked) {
! 	   ObtainWriteLock(&afs_xvreclaim, 176);
! #ifdef AFS_DARWIN80_ENV
! 	   vnode_clearfsnode(AFSTOV(tvc));
! 	   vnode_removefsref(AFSTOV(tvc));
! #else
! 	   tvc->v->v_data = NULL;  /* remove from vnode */
! #endif
! 	   AFSTOV(tvc) = NULL;             /* also drop the ptr to vnode */
! 	   tvc->states |= CVInit; /* also CDeadVnode? */
! 	   tvc->nextfree = ReclaimedVCList;
! 	   ReclaimedVCList = tvc;
! 	   ReleaseWriteLock(&afs_xvreclaim);
!        } else {
! 	   error = afs_FlushVCache(tvc, &sl);	/* toss our stuff from vnode */
! 	   if (tvc->states & (CVInit
! #ifdef AFS_DARWIN80_ENV
! 			      | CDeadVnode
! #endif
! 		   )) {
! 	       tvc->states &= ~(CVInit
! #ifdef AFS_DARWIN80_ENV
! 				| CDeadVnode
! #endif
! 		   );
! 	       afs_osi_Wakeup(&tvc->states);
! 	   }
! 	   if (!error && vnode_fsnode(vp))
! 	       panic("afs_reclaim: vnode not cleaned");
! 	   if (!error && (tvc->v != NULL)) 
! 	       panic("afs_reclaim: vcache not cleaned");
! 	   ReleaseWriteLock(&afs_xvcache);
         }
         AFS_GUNLOCK();
      }
      return error;
***************
*** 1727,1733 ****
  #endif
      AFS_GLOCK();
      error =
! 	afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, tcr, (int)ap->a_id);
      AFS_GUNLOCK();
      return error;
  }
--- 1745,1753 ----
  #endif
      AFS_GLOCK();
      error =
! 	afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl,
! 		    ap->a_op == F_UNLCK ? F_SETLK : ap->a_op, tcr, 
! 		    (int)ap->a_id);
      AFS_GUNLOCK();
      return error;
  }
Index: openafs/src/afs/LINUX/osi_vnodeops.c
diff -c openafs/src/afs/LINUX/osi_vnodeops.c:1.81.2.39 openafs/src/afs/LINUX/osi_vnodeops.c:1.81.2.40
*** openafs/src/afs/LINUX/osi_vnodeops.c:1.81.2.39	Sun Dec 18 22:29:58 2005
--- openafs/src/afs/LINUX/osi_vnodeops.c	Wed Jan 11 16:38:30 2006
***************
*** 22,28 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.81.2.39 2005/12/19 03:29:58 rra Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
--- 22,28 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.81.2.40 2006/01/11 21:38:30 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
***************
*** 1372,1380 ****
      ip->i_size = vcp->m.Length;
      ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1;
  
!     if (!code
! 	&& afs_stats_cmperf.cacheCurrDirtyChunks >
! 	afs_stats_cmperf.cacheMaxDirtyChunks) {
  	struct vrequest treq;
  
  	ObtainWriteLock(&vcp->lock, 533);
--- 1372,1378 ----
      ip->i_size = vcp->m.Length;
      ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1;
  
!     if (!code) {
  	struct vrequest treq;
  
  	ObtainWriteLock(&vcp->lock, 533);
***************
*** 1486,1500 ****
  	    code = afs_DoPartialWrite(vcp, &treq);
  	ReleaseWriteLock(&vcp->lock);
      }
-     if (!code) {
- 	struct vrequest treq;
- 
- 	ObtainWriteLock(&vcp->lock, 533);
- 	vcp->m.Date = osi_Time();   /* set modification time */
- 	if (!afs_InitReq(&treq, credp))
- 	    code = afs_DoPartialWrite(vcp, &treq);
- 	ReleaseWriteLock(&vcp->lock);
-     }
  
      code = code ? -code : count - tuio.uio_resid;
      afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
--- 1484,1489 ----
Index: openafs/src/afs/VNOPS/afs_vnop_lookup.c
diff -c openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.50.2.15 openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.50.2.16
*** openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.50.2.15	Fri Nov 18 23:35:41 2005
--- openafs/src/afs/VNOPS/afs_vnop_lookup.c	Tue Jan 17 00:00:21 2006
***************
*** 18,24 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_lookup.c,v 1.50.2.15 2005/11/19 04:35:41 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 18,24 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_lookup.c,v 1.50.2.16 2006/01/17 05:00:21 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 723,730 ****
--- 723,732 ----
  	    }
  	    if (!tvcp)
  	    {
+ 		DRelease((struct buffer *)dirEntryp, 0);
  		ReleaseReadLock(&dcp->lock);
  		ReleaseReadLock(&adp->lock);
+ 		afs_PutDCache(dcp);
  		goto done;	/* can happen if afs_NewVCache fails */
  	    }
  
Index: openafs/src/config/NTMakefile.amd64_w2k
diff -c openafs/src/config/NTMakefile.amd64_w2k:1.1.2.25 openafs/src/config/NTMakefile.amd64_w2k:1.1.2.26
*** openafs/src/config/NTMakefile.amd64_w2k:1.1.2.25	Mon Jan  9 00:36:52 2006
--- openafs/src/config/NTMakefile.amd64_w2k	Mon Jan 16 23:00:46 2006
***************
*** 80,86 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0094
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 80,86 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0095
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/config/NTMakefile.i386_nt40
diff -c openafs/src/config/NTMakefile.i386_nt40:1.46.2.40 openafs/src/config/NTMakefile.i386_nt40:1.46.2.41
*** openafs/src/config/NTMakefile.i386_nt40:1.46.2.40	Mon Jan  9 00:36:52 2006
--- openafs/src/config/NTMakefile.i386_nt40	Mon Jan 16 23:00:47 2006
***************
*** 80,86 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0094
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 80,86 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0095
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/config/NTMakefile.i386_w2k
diff -c openafs/src/config/NTMakefile.i386_w2k:1.1.2.27 openafs/src/config/NTMakefile.i386_w2k:1.1.2.28
*** openafs/src/config/NTMakefile.i386_w2k:1.1.2.27	Mon Jan  9 00:36:52 2006
--- openafs/src/config/NTMakefile.i386_w2k	Mon Jan 16 23:00:47 2006
***************
*** 80,86 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0094
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 80,86 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0095
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/packaging/MacOS/OpenAFS.info
diff -c openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.24 openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.25
*** openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.24	Tue Jan 10 23:36:10 2006
--- openafs/src/packaging/MacOS/OpenAFS.info	Fri Jan 20 01:32:23 2006
***************
*** 1,5 ****
  Title OpenAFS
! Version 1.4.1-rc4
  Description The OpenAFS distributed filesystem. This package installs an almost-ready-to-run client for OpenAFS. see http://www.openafs.org for more information.
  DefaultLocation /
  Diskname (null)
--- 1,5 ----
  Title OpenAFS
! Version 1.4.1-rc5
  Description The OpenAFS distributed filesystem. This package installs an almost-ready-to-run client for OpenAFS. see http://www.openafs.org for more information.
  DefaultLocation /
  Diskname (null)
Index: openafs/src/packaging/MacOS/ReadMe.rtf
diff -c openafs/src/packaging/MacOS/ReadMe.rtf:1.2.2.2 openafs/src/packaging/MacOS/ReadMe.rtf:1.2.2.3
*** openafs/src/packaging/MacOS/ReadMe.rtf:1.2.2.2	Wed Oct  5 01:58:40 2005
--- openafs/src/packaging/MacOS/ReadMe.rtf	Fri Jan 20 01:32:23 2006
***************
*** 4,10 ****
  \margl1440\margr1440\vieww9000\viewh9000\viewkind0
  \pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
  
! \f0\fs20 \cf0 This pre-release of OpenAFS is targeted at MacOS 10.4.1. It is *not* production ready. Use of this release with afs home directories or Library directories is not recommended. (keychain corruption may occur. keychain-using apps may hang). afssettings does not work either. unmount afs manually before rebooting/shutting down, or the shutdown will not complete. \
  \
  Select a client cell name by editing /var/db/openafs/etc/ThisCell\
  \
--- 4,10 ----
  \margl1440\margr1440\vieww9000\viewh9000\viewkind0
  \pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
  
! \f0\fs20 \cf0 This pre-release of OpenAFS is targeted at MacOS 10.4.x. 
  \
  Select a client cell name by editing /var/db/openafs/etc/ThisCell\
  \
Index: openafs/src/rx/rx_kcommon.c
diff -c openafs/src/rx/rx_kcommon.c:1.44.2.9 openafs/src/rx/rx_kcommon.c:1.44.2.10
*** openafs/src/rx/rx_kcommon.c:1.44.2.9	Sat Oct 15 10:24:29 2005
--- openafs/src/rx/rx_kcommon.c	Tue Jan 17 21:22:19 2006
***************
*** 15,21 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.44.2.9 2005/10/15 14:24:29 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
--- 15,21 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.44.2.10 2006/01/18 02:22:19 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
***************
*** 133,139 ****
  
      dpf((msg, a1, a2, a3));
  #ifdef AFS_LINUX24_ENV
!     BUG();
  #else
      panic(msg);
  #endif
--- 133,140 ----
  
      dpf((msg, a1, a2, a3));
  #ifdef AFS_LINUX24_ENV
!     printk("AFS BUG at %s\n", msg); 
!     * ((char *) 0) = 0; 
  #else
      panic(msg);
  #endif
Index: openafs/src/rx/rx_packet.c
diff -c openafs/src/rx/rx_packet.c:1.35.2.22 openafs/src/rx/rx_packet.c:1.35.2.23
*** openafs/src/rx/rx_packet.c:1.35.2.22	Sat Dec 17 12:28:31 2005
--- openafs/src/rx/rx_packet.c	Mon Jan 16 11:23:33 2006
***************
*** 15,21 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.35.2.22 2005/12/17 17:28:31 jaltman Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
--- 15,21 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.35.2.23 2006/01/16 16:23:33 jaltman Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
***************
*** 2383,2388 ****
--- 2383,2397 ----
  		clock_Addmsec(&(p->retryTime),
  			      10 + (((afs_uint32) p->backoff) << 8));
  	    }
+ #ifdef AFS_NT40_ENV
+ 	    /* Windows is nice -- it can tell us right away that we cannot
+ 	     * reach this recipient by returning an WSAEHOSTUNREACH error
+ 	     * code.  So, when this happens let's "down" the host NOW so
+ 	     * we don't sit around waiting for this host to timeout later.
+ 	     */
+ 	    if (call && code == -1 && errno == WSAEHOSTUNREACH)
+ 		call->lastReceiveTime = 0;
+ #endif
  #if defined(KERNEL) && defined(AFS_LINUX20_ENV)
  	    /* Linux is nice -- it can tell us right away that we cannot
  	     * reach this recipient by returning an ENETUNREACH error
Index: openafs/src/rx/DARWIN/rx_knet.c
diff -c openafs/src/rx/DARWIN/rx_knet.c:1.10.2.1 openafs/src/rx/DARWIN/rx_knet.c:1.10.2.2
*** openafs/src/rx/DARWIN/rx_knet.c:1.10.2.1	Wed Oct  5 01:58:43 2005
--- openafs/src/rx/DARWIN/rx_knet.c	Tue Jan 17 12:09:48 2006
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/DARWIN/rx_knet.c,v 1.10.2.1 2005/10/05 05:58:43 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/DARWIN/rx_knet.c,v 1.10.2.2 2006/01/17 17:09:48 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
***************
*** 145,153 ****
  #if defined(KERNEL_FUNNEL)
      thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  #endif
! #ifdef AFS_DARWIN80_ENV
!     proc_signal(rxk_ListenerPid, SIGUSR1);
! #else
      p = pfind(rxk_ListenerPid);
      if (p)
  	psignal(p, SIGUSR1);
--- 145,151 ----
  #if defined(KERNEL_FUNNEL)
      thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  #endif
! #ifndef AFS_DARWIN80_ENV
      p = pfind(rxk_ListenerPid);
      if (p)
  	psignal(p, SIGUSR1);
Index: openafs/src/venus/cmdebug.c
diff -c openafs/src/venus/cmdebug.c:1.15.2.1 openafs/src/venus/cmdebug.c:1.15.2.2
*** openafs/src/venus/cmdebug.c:1.15.2.1	Mon Oct 24 21:58:06 2005
--- openafs/src/venus/cmdebug.c	Thu Jan 19 19:03:10 2006
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/cmdebug.c,v 1.15.2.1 2005/10/25 01:58:06 jaltman Exp $");
  
  
  #include <sys/types.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/cmdebug.c,v 1.15.2.2 2006/01/20 00:03:10 shadow Exp $");
  
  
  #include <sys/types.h>
***************
*** 306,312 ****
  	    PrintLock(&centry.lock);
  	    printf("\n");
  	}
! 	printf("    %012d bytes  DV %012d  refcnt %05d\n", centry.Length,
  	       centry.DataVersion, centry.refCount);
  	printf("    callback %08x\texpires %u\n", centry.callback,
  	       centry.cbExpires);
--- 306,312 ----
  	    PrintLock(&centry.lock);
  	    printf("\n");
  	}
! 	printf("    %12d bytes  DV %12d  refcnt %5d\n", centry.Length,
  	       centry.DataVersion, centry.refCount);
  	printf("    callback %08x\texpires %u\n", centry.callback,
  	       centry.cbExpires);
Index: openafs/src/venus/fs.c
diff -c openafs/src/venus/fs.c:1.24.2.3 openafs/src/venus/fs.c:1.24.2.4
*** openafs/src/venus/fs.c:1.24.2.3	Mon Jul 11 15:03:42 2005
--- openafs/src/venus/fs.c	Mon Jan 23 16:07:42 2006
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/fs.c,v 1.24.2.3 2005/07/11 19:03:42 shadow Exp $");
  
  #include <afs/afs_args.h>
  #include <rx/xdr.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/fs.c,v 1.24.2.4 2006/01/23 21:07:42 shadow Exp $");
  
  #include <afs/afs_args.h>
  #include <rx/xdr.h>
***************
*** 69,75 ****
  static struct ubik_client *uclient;
  
  static int GetClientAddrsCmd(), SetClientAddrsCmd(), FlushMountCmd();
! static int RxStatProcCmd(), RxStatPeerCmd();
  
  extern char *hostutil_GetNameByINet();
  extern struct hostent *hostutil_GetHostByName();
--- 69,75 ----
  static struct ubik_client *uclient;
  
  static int GetClientAddrsCmd(), SetClientAddrsCmd(), FlushMountCmd();
! static int RxStatProcCmd(), RxStatPeerCmd(), GetFidCmd();
  
  extern char *hostutil_GetNameByINet();
  extern struct hostent *hostutil_GetHostByName();
***************
*** 3437,3442 ****
--- 3437,3447 ----
      ts = cmd_CreateSyntax("setcbaddr", CallBackRxConnCmd, 0, "configure callback connection address");
      cmd_AddParm(ts, "-addr", CMD_SINGLE, CMD_OPTIONAL, "host name or address");
  
+     /* try to find volume location information */
+     ts = cmd_CreateSyntax("getfid", GetFidCmd, 0,
+ 			  "get fid for file(s)");
+     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+ 
      code = cmd_Dispatch(argc, argv);
      if (rxInitDone)
  	rx_Finalize();
***************
*** 3794,3796 ****
--- 3799,3823 ----
      return 0;
  }
  
+ static int
+ GetFidCmd(struct cmd_syndesc *as, char *arock)
+ {
+     struct ViceIoctl blob;
+     struct cmd_item *ti;
+     for (ti = as->parms[0].items; ti; ti = ti->next) {
+       struct VenusFid vfid;
+       
+       blob.out_size = sizeof(struct VenusFid);
+       blob.out = (char *) &vfid;
+       blob.in_size = 0;
+       
+       if (0 == pioctl(ti->data, VIOCGETFID, &blob, 1)) {
+ 	printf("File %s (%u.%u.%u) contained in volume %u\n",
+ 	       ti->data, vfid.Fid.Volume, vfid.Fid.Vnode, vfid.Fid.Unique,
+ 	       vfid.Fid.Volume);
+       }
+     }
+ 
+     return 0;
+ }
+ 
Index: openafs/src/viced/host.c
diff -c openafs/src/viced/host.c:1.57.2.7 openafs/src/viced/host.c:1.57.2.10
*** openafs/src/viced/host.c:1.57.2.7	Fri Dec 16 08:29:38 2005
--- openafs/src/viced/host.c	Mon Jan 23 16:28:43 2006
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/host.c,v 1.57.2.7 2005/12/16 13:29:38 shadow Exp $");
  
  #include <stdio.h>
  #include <errno.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/host.c,v 1.57.2.10 2006/01/23 21:28:43 jaltman Exp $");
  
  #include <stdio.h>
  #include <errno.h>
***************
*** 902,909 ****
      if (hostCount == 0) {
  	return;
      }
!     if (!(held = h_Held_r(host)))
! 	h_Hold_r(host);
      for (host = enumstart; host; host = next, held = nheld) {
  	held = (*proc) (host, held, param);
  	next = host->next;
--- 902,909 ----
      if (hostCount == 0) {
  	return;
      }
!     if (enumstart && !(held = h_Held_r(enumstart)))
! 	h_Hold_r(enumstart); 
      for (host = enumstart; host; host = next, held = nheld) {
  	held = (*proc) (host, held, param);
  	next = host->next;
***************
*** 1025,1031 ****
      struct host *host;
      struct host *oldHost;
      int code;
!     int held;
      struct interfaceAddr interf;
      int interfValid = 0;
      struct Identity *identP = NULL;
--- 1025,1031 ----
      struct host *host;
      struct host *oldHost;
      int code;
!     int held, oheld;
      struct interfaceAddr interf;
      int interfValid = 0;
      struct Identity *identP = NULL;
***************
*** 1252,1258 ****
                  if (oldHost) {
                      int probefail = 0;
  
! 		    if (!(held = h_Held_r(oldHost)))
  			h_Hold_r(oldHost);
  		    h_Lock_r(oldHost);
  
--- 1252,1258 ----
                  if (oldHost) {
                      int probefail = 0;
  
! 		    if (!(oheld = h_Held_r(oldHost)))
  			h_Hold_r(oldHost);
  		    h_Lock_r(oldHost);
  
***************
*** 1279,1286 ****
                           * Delete it! */
                          oldHost->hostFlags |= HOSTDELETED;
                          h_Unlock_r(oldHost);
!                         h_Release_r(oldHost);
!                         oldHost = NULL;
                      }
                  }
  		if (oldHost) {
--- 1279,1289 ----
                           * Delete it! */
                          oldHost->hostFlags |= HOSTDELETED;
                          h_Unlock_r(oldHost);
! 			/* Let the holder be last release */
! 			if (!oheld) {
! 			    h_Release_r(oldHost);
! 			}
! 			oldHost = NULL;
                      }
                  }
  		if (oldHost) {
***************
*** 1296,1302 ****
  		    addInterfaceAddr_r(oldHost, haddr, hport);
  		    host->hostFlags |= HOSTDELETED;
  		    h_Unlock_r(host);
! 		    h_Release_r(host);
  		    host = oldHost;
  		} else {
  		    /* This really is a new host */
--- 1299,1306 ----
  		    addInterfaceAddr_r(oldHost, haddr, hport);
  		    host->hostFlags |= HOSTDELETED;
  		    h_Unlock_r(host);
! 		    if (!held)
! 			h_Release_r(host);
  		    host = oldHost;
  		} else {
  		    /* This really is a new host */
***************
*** 2201,2209 ****
      }
      if (host->LastCall < checktime) {
  	h_Lock_r(host);
- 	cb_conn = host->callback_rxcon;
- 	rx_GetConnection(cb_conn);
  	if (!(host->hostFlags & HOSTDELETED)) {
  	    if (host->LastCall < clientdeletetime) {
  		host->hostFlags |= HOSTDELETED;
  		if (!(host->hostFlags & VENUSDOWN)) {
--- 2205,2213 ----
      }
      if (host->LastCall < checktime) {
  	h_Lock_r(host);
  	if (!(host->hostFlags & HOSTDELETED)) {
+ 	    cb_conn = host->callback_rxcon;
+ 	    rx_GetConnection(cb_conn);
  	    if (host->LastCall < clientdeletetime) {
  		host->hostFlags |= HOSTDELETED;
  		if (!(host->hostFlags & VENUSDOWN)) {
***************
*** 2268,2278 ****
  		    }
  		}
  	    }
  	}
- 	H_UNLOCK;
- 	rx_PutConnection(cb_conn);
- 	cb_conn=NULL;
- 	H_LOCK;
  	h_Unlock_r(host);
      }
      H_UNLOCK;
--- 2272,2282 ----
  		    }
  		}
  	    }
+ 	    H_UNLOCK;
+ 	    rx_PutConnection(cb_conn);
+ 	    cb_conn=NULL;
+ 	    H_LOCK;
  	}
  	h_Unlock_r(host);
      }
      H_UNLOCK;
Index: openafs/src/viced/host.h
diff -c openafs/src/viced/host.h:1.9.2.2 openafs/src/viced/host.h:1.9.2.3
*** openafs/src/viced/host.h:1.9.2.2	Fri Dec 16 08:29:38 2005
--- openafs/src/viced/host.h	Mon Jan 23 16:30:18 2006
***************
*** 41,47 ****
  #define h_threadsMask		31	/* for remainder */
  
  /* size of the hold array for each host */
! #define h_maxSlots	((MAX_FILESERVER_THREAD+h_threadsPerSlot-1)>>h_threadsShift)
  
  struct Identity {
      char valid;			/* zero if UUID is unknown */
--- 41,47 ----
  #define h_threadsMask		31	/* for remainder */
  
  /* size of the hold array for each host */
! #define h_maxSlots	(((MAX_FILESERVER_THREAD+h_threadsPerSlot-1)>>h_threadsShift)+1)
  
  struct Identity {
      char valid;			/* zero if UUID is unknown */
Index: openafs/src/volser/volprocs.c
diff -c openafs/src/volser/volprocs.c:1.34.2.4 openafs/src/volser/volprocs.c:1.34.2.5
*** openafs/src/volser/volprocs.c:1.34.2.4	Wed Aug 31 18:14:59 2005
--- openafs/src/volser/volprocs.c	Tue Jan 24 22:25:49 2006
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volprocs.c,v 1.34.2.4 2005/08/31 22:14:59 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volprocs.c,v 1.34.2.5 2006/01/25 03:25:49 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 1790,1796 ****
  		pntr->volid = volid;
  		goto drop;
  	    }
! 	    tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
  	    if (error) {
  		pntr->status = 0;	/*things are messed up */
  		strcpy(pntr->name, volname);
--- 1790,1796 ----
  		pntr->volid = volid;
  		goto drop;
  	    }
! 	    tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
  	    if (error) {
  		pntr->status = 0;	/*things are messed up */
  		strcpy(pntr->name, volname);
***************
*** 2004,2010 ****
  	    /*
  	     * Attach the volume, give up on the volume if we can't.
  	     */
! 	    tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
  	    if (error) {
  		xInfoP->status = 0;	/*things are messed up */
  		strcpy(xInfoP->name, volname);
--- 2004,2010 ----
  	    /*
  	     * Attach the volume, give up on the volume if we can't.
  	     */
! 	    tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
  	    if (error) {
  		xInfoP->status = 0;	/*things are messed up */
  		strcpy(xInfoP->name, volname);
Index: openafs/src/volser/vsprocs.c
diff -c openafs/src/volser/vsprocs.c:1.33.2.5 openafs/src/volser/vsprocs.c:1.33.2.6
*** openafs/src/volser/vsprocs.c:1.33.2.5	Thu Dec 15 23:26:41 2005
--- openafs/src/volser/vsprocs.c	Tue Jan 24 22:49:53 2006
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/vsprocs.c,v 1.33.2.5 2005/12/16 04:26:41 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/vsprocs.c,v 1.33.2.6 2006/01/25 03:49:53 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 56,61 ****
--- 56,62 ----
  #include <errno.h>
  #define ERRCODE_RANGE 8		/* from error_table.h */
  #define	CLOCKSKEW   2		/* not really skew, but resolution */
+ #define CLOCKADJ(x) (((x) < CLOCKSKEW) ? 0 : (x) - CLOCKSKEW)
  
  /* for UV_MoveVolume() recovery */
  
***************
*** 1329,1335 ****
  	       newVol);
  	VDONE;
  
! 	fromDate = tstatus.creationDate - CLOCKSKEW;
      } else {
  	/* With RV_NOCLONE, just do a full copy from the source */
  	fromDate = 0;
--- 1330,1336 ----
  	       newVol);
  	VDONE;
  
! 	fromDate = CLOCKADJ(tstatus.creationDate);
      } else {
  	/* With RV_NOCLONE, just do a full copy from the source */
  	fromDate = 0;
***************
*** 2162,2168 ****
  	       cloneVol);
  	VDONE;
  
! 	fromDate = tstatus.creationDate - CLOCKSKEW;
      } else {
  	fromDate = 0;
      }
--- 2163,2169 ----
  	       cloneVol);
  	VDONE;
  
! 	fromDate = CLOCKADJ(tstatus.creationDate);
      } else {
  	fromDate = 0;
      }
***************
*** 2180,2186 ****
  	    VDONE;
  
  	    /* Using the update date should be OK here, but add some fudge */
! 	    cloneFromDate = tstatus.updateDate - CLOCKSKEW;
  	    if ((flags & RV_NOCLONE))
  		fromDate = cloneFromDate;
  
--- 2181,2187 ----
  	    VDONE;
  
  	    /* Using the update date should be OK here, but add some fudge */
! 	    cloneFromDate = CLOCKADJ(tstatus.updateDate);
  	    if ((flags & RV_NOCLONE))
  		fromDate = cloneFromDate;
  
***************
*** 3087,3094 ****
  		       code);
  	    goto fail;
  	}
! 	*crtimePtr = tstatus.creationDate - CLOCKSKEW;
! 	*uptimePtr = tstatus.updateDate - CLOCKSKEW;
      }
  
      return 0;
--- 3088,3095 ----
  		       code);
  	    goto fail;
  	}
! 	*crtimePtr = CLOCKADJ(tstatus.creationDate);
! 	*uptimePtr = CLOCKADJ(tstatus.updateDate);
      }
  
      return 0;
