Index: openafs/src/WINNT/afsd/afsd_eventmessages.mc
diff -c openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.4 openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.4.4.2
*** openafs/src/WINNT/afsd/afsd_eventmessages.mc:1.4	Sun Jan 15 21:05:27 2006
--- openafs/src/WINNT/afsd/afsd_eventmessages.mc	Thu Sep 11 13:26:21 2008
***************
*** 114,120 ****
  Facility=System
  SymbolicName=MSG_SERVER_REPORTS_VNOVOL
  Language=English
! Server %1 reported volume %2 as not attached.
  .
  
  MessageId=
--- 114,120 ----
  Facility=System
  SymbolicName=MSG_SERVER_REPORTS_VNOVOL
  Language=English
! Server %1 reported volume %2 as not attached (may have been moved or deleted).
  .
  
  MessageId=
***************
*** 326,331 ****
--- 326,340 ----
  MessageId=
  Severity=Informational
  Facility=System
+ SymbolicName=MSG_CRYPT_AUTH
+ Language=English
+ Security Level is Auth (Integrity Only).
+ .
+ 
+ 
+ MessageId=
+ Severity=Informational
+ Facility=System
  SymbolicName=MSG_CRYPT_ON
  Language=English
  Security Level is Crypt.
Index: openafs/src/WINNT/afsd/afsd_init.c
diff -c openafs/src/WINNT/afsd/afsd_init.c:1.79.2.46 openafs/src/WINNT/afsd/afsd_init.c:1.79.2.52
*** openafs/src/WINNT/afsd/afsd_init.c:1.79.2.46	Sat Aug 16 13:11:01 2008
--- openafs/src/WINNT/afsd/afsd_init.c	Fri Sep 12 10:41:30 2008
***************
*** 561,566 ****
--- 561,567 ----
      DWORD rx_enable_peer_stats;
      DWORD rx_enable_process_stats;
      DWORD rx_udpbufsize = -1;
+     DWORD lockOrderValidation;
      long traceBufSize;
      long maxcpus;
      long ltt, ltto;
***************
*** 625,630 ****
--- 626,644 ----
          osi_panic(buf, __FILE__, __LINE__);
      }
  
+     dummyLen = sizeof(lockOrderValidation);
+     code = RegQueryValueEx(parmKey, "LockOrderValidation", NULL, NULL,
+                             (BYTE *) &lockOrderValidation, &dummyLen);
+     if (code != ERROR_SUCCESS) {
+ #ifdef DEBUG
+         lockOrderValidation = 1;
+ #else
+         lockOrderValidation = 0;
+ #endif
+     }
+     osi_SetLockOrderValidation(lockOrderValidation);
+     afsi_log("Lock Order Validation %s", lockOrderValidation ? "On" : "Off");
+ 
      dummyLen = sizeof(maxcpus);
      code = RegQueryValueEx(parmKey, "MaxCPUs", NULL, NULL,
                              (BYTE *) &maxcpus, &dummyLen);
***************
*** 956,969 ****
      code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
                             (BYTE *) &cryptall, &dummyLen);
      if (code == ERROR_SUCCESS) {
!         afsi_log("SecurityLevel is %s", cryptall?"crypt":"clear");
      } else {
          cryptall = 0;
          afsi_log("Default SecurityLevel is clear");
      }
  
!     if (cryptall)
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
      else
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
  
--- 970,985 ----
      code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
                             (BYTE *) &cryptall, &dummyLen);
      if (code == ERROR_SUCCESS) {
!         afsi_log("SecurityLevel is %s", cryptall == 1?"crypt": cryptall == 2?"auth":"clear");
      } else {
          cryptall = 0;
          afsi_log("Default SecurityLevel is clear");
      }
  
!     if (cryptall == 1)
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+     else if (cryptall == 2)
+ 	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_AUTH);
      else
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
  
***************
*** 1049,1058 ****
      code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
                             (BYTE *) &rx_nojumbo, &dummyLen);
      if (code != ERROR_SUCCESS) {
!         rx_nojumbo = 0;
      }
      if (rx_nojumbo)
          afsi_log("RX Jumbograms are disabled");
  
      dummyLen = sizeof(rx_extraPackets);
      code = RegQueryValueEx(parmKey, "RxExtraPackets", NULL, NULL,
--- 1065,1084 ----
      code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
                             (BYTE *) &rx_nojumbo, &dummyLen);
      if (code != ERROR_SUCCESS) {
!         DWORD jumbo;
!         dummyLen = sizeof(jumbo);
!         code = RegQueryValueEx(parmKey, "RxJumbo", NULL, NULL,
!                                 (BYTE *) &jumbo, &dummyLen);
!         if (code != ERROR_SUCCESS) {
!             rx_nojumbo = 1;
!         } else {
!             rx_nojumbo = !jumbo;
!         }
      }
      if (rx_nojumbo)
          afsi_log("RX Jumbograms are disabled");
+     else
+         afsi_log("RX Jumbograms are enabled");
  
      dummyLen = sizeof(rx_extraPackets);
      code = RegQueryValueEx(parmKey, "RxExtraPackets", NULL, NULL,
***************
*** 1069,1075 ****
      if (code != ERROR_SUCCESS) {
          rx_udpbufsize = 256*1024;
      }
!     if (rx_udpbufsize)
          afsi_log("RX udpbufsize is %d", rx_udpbufsize);
  
      dummyLen = sizeof(rx_mtu);
--- 1095,1101 ----
      if (code != ERROR_SUCCESS) {
          rx_udpbufsize = 256*1024;
      }
!     if (rx_udpbufsize != -1)
          afsi_log("RX udpbufsize is %d", rx_udpbufsize);
  
      dummyLen = sizeof(rx_mtu);
***************
*** 1324,1329 ****
--- 1350,1358 ----
          *reasonP = "unknown error";
          return -1;
      }
+     rx_SetMinProcs(serverp, 2);
+     rx_SetMaxProcs(serverp, 4);
+     rx_SetCheckReach(serverp, 1);
  
      nullServerSecurityClassp = rxnull_NewServerSecurityObject();
      serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
***************
*** 1333,1338 ****
--- 1362,1369 ----
          *reasonP = "unknown error";
          return -1;
      }
+     rx_SetMinProcs(serverp, 2);
+     rx_SetMaxProcs(serverp, 4);
          
      /* start server threads, *not* donating this one to the pool */
      rx_StartServer(0);
***************
*** 1683,1690 ****
  void 
  GenerateMiniDump(PEXCEPTION_POINTERS ep)
  {
! 	if (IsDebuggerPresent())
! 		return;
  
      if (ep == NULL) 
      {
--- 1714,1721 ----
  void 
  GenerateMiniDump(PEXCEPTION_POINTERS ep)
  {
!     if (IsDebuggerPresent())
!         return;
  
      if (ep == NULL) 
      {
Index: openafs/src/WINNT/afsd/afsd_service.c
diff -c openafs/src/WINNT/afsd/afsd_service.c:1.52.4.27 openafs/src/WINNT/afsd/afsd_service.c:1.52.4.30
*** openafs/src/WINNT/afsd/afsd_service.c:1.52.4.27	Fri Aug  1 15:13:51 2008
--- openafs/src/WINNT/afsd/afsd_service.c	Fri Aug 29 22:06:28 2008
***************
*** 34,39 ****
--- 34,40 ----
  
  static SERVICE_STATUS		ServiceStatus;
  static SERVICE_STATUS_HANDLE	StatusHandle;
+ static BOOL bRunningAsService = TRUE;
  
  HANDLE hAFSDMainThread = NULL;
  
***************
*** 52,62 ****
--- 53,67 ----
  static int powerEventsRegistered = 0;
  extern int powerStateSuspended = 0;
  
+ static VOID (WINAPI* pRtlCaptureContext)(PCONTEXT ContextRecord) = NULL;
+ 
  /*
   * Notifier function for use by osi_panic
   */
  static void afsd_notifier(char *msgp, char *filep, long line)
  {
+     CONTEXT context;
+ 
      if (!msgp)
          msgp = "unspecified assert";
  
***************
*** 73,87 ****
      afsd_ForceTrace(TRUE);
      buf_ForceTrace(TRUE);
  
      afsi_log("--- begin dump ---");
      cm_MemDumpDirStats(afsi_file, "a", 0);
      cm_MemDumpBPlusStats(afsi_file, "a", 0);
      cm_DumpCells(afsi_file, "a", 0);
      cm_DumpVolumes(afsi_file, "a", 0);
      cm_DumpSCache(afsi_file, "a", 0);
- #ifdef keisa
-     cm_dnlcDump(afsi_file, "a");
- #endif
      cm_DumpBufHashTable(afsi_file, "a", 0);
      smb_DumpVCP(afsi_file, "a", 0);			
      afsi_log("--- end   dump ---");
--- 78,94 ----
      afsd_ForceTrace(TRUE);
      buf_ForceTrace(TRUE);
  
+     if (pRtlCaptureContext) {
+         pRtlCaptureContext(&context);
+         afsd_printStack(GetCurrentThread(), &context);
+     }
+ 
      afsi_log("--- begin dump ---");
      cm_MemDumpDirStats(afsi_file, "a", 0);
      cm_MemDumpBPlusStats(afsi_file, "a", 0);
      cm_DumpCells(afsi_file, "a", 0);
      cm_DumpVolumes(afsi_file, "a", 0);
      cm_DumpSCache(afsi_file, "a", 0);
      cm_DumpBufHashTable(afsi_file, "a", 0);
      smb_DumpVCP(afsi_file, "a", 0);			
      afsi_log("--- end   dump ---");
***************
*** 91,96 ****
--- 98,105 ----
          DebugBreak();	
  #endif
  
+     GenerateMiniDump(NULL);
+ 
      SetEvent(WaitToTerminate);
  
  #ifdef JUMP
***************
*** 98,110 ****
          longjmp(notifier_jmp, 1);
  #endif /* JUMP */
  
!     ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!     ServiceStatus.dwWin32ExitCode = NO_ERROR;
!     ServiceStatus.dwCheckPoint = 0;
!     ServiceStatus.dwWaitHint = 0;
!     ServiceStatus.dwControlsAccepted = 0;
!     SetServiceStatus(StatusHandle, &ServiceStatus);
! 
      exit(1);
  }
  
--- 107,120 ----
          longjmp(notifier_jmp, 1);
  #endif /* JUMP */
  
!     if (bRunningAsService) {
!         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!         ServiceStatus.dwWin32ExitCode = NO_ERROR;
!         ServiceStatus.dwCheckPoint = 0;
!         ServiceStatus.dwWaitHint = 0;
!         ServiceStatus.dwControlsAccepted = 0;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
!     }
      exit(1);
  }
  
***************
*** 1095,1100 ****
--- 1105,1111 ----
  #endif /* JUMP */
      HMODULE hHookDll;
      HMODULE hAdvApi32;
+     HMODULE hKernel32;
  
  #ifdef _DEBUG
      void afsd_DbgBreakAllocInit();
***************
*** 1109,1114 ****
--- 1120,1133 ----
      osi_InitPanic(afsd_notifier);
      osi_InitTraceOption();
  
+     hKernel32 = LoadLibrary("kernel32.dll");
+     if (hKernel32 == NULL)
+     {
+         afsi_log("Fatal: cannot load kernel32.dll");
+         return;
+     }
+     pRtlCaptureContext = GetProcAddress(hKernel32, "RtlCaptureContext");
+ 
      GlobalStatus = 0;
  
      afsi_start();
***************
*** 1125,1150 ****
          return;
      }
  
!     pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
!     if (pRegisterServiceCtrlHandlerEx)
!     {
!         afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
!         StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
!     }
!     else
!     {
!         StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
!     }
  
!     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
!     ServiceStatus.dwServiceSpecificExitCode = 0;
!     ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
!     ServiceStatus.dwWin32ExitCode = NO_ERROR;
!     ServiceStatus.dwCheckPoint = 1;
!     ServiceStatus.dwWaitHint = 120000;
!     /* accept Power Events */
!     ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!     SetServiceStatus(StatusHandle, &ServiceStatus);
  #endif
  
      LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
--- 1144,1171 ----
          return;
      }
  
!     if (bRunningAsService) {
!         pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
!         if (pRegisterServiceCtrlHandlerEx)
!         {
!             afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
!             StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
!         }
!         else
!         {
!             StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
!         }
  
!         ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
!         ServiceStatus.dwServiceSpecificExitCode = 0;
!         ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
!         ServiceStatus.dwWin32ExitCode = NO_ERROR;
!         ServiceStatus.dwCheckPoint = 1;
!         ServiceStatus.dwWaitHint = 120000;
!         /* accept Power Events */
!         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
!     }
  #endif
  
      LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
***************
*** 1179,1191 ****
  
      /* Verify the versions of the DLLs which were loaded */
      if (!AFSModulesVerify()) {
!         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!         ServiceStatus.dwWin32ExitCode = NO_ERROR;
!         ServiceStatus.dwCheckPoint = 0;
!         ServiceStatus.dwWaitHint = 0;
!         ServiceStatus.dwControlsAccepted = 0;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
! 
  	LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
  
          /* exit if initialization failed */
--- 1200,1213 ----
  
      /* Verify the versions of the DLLs which were loaded */
      if (!AFSModulesVerify()) {
!         if (bRunningAsService) {
!             ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!             ServiceStatus.dwWin32ExitCode = NO_ERROR;
!             ServiceStatus.dwCheckPoint = 0;
!             ServiceStatus.dwWaitHint = 0;
!             ServiceStatus.dwControlsAccepted = 0;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!         }
  	LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
  
          /* exit if initialization failed */
***************
*** 1207,1234 ****
  
          if (hookRc == FALSE)
          {
!             ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!             ServiceStatus.dwWin32ExitCode = NO_ERROR;
!             ServiceStatus.dwCheckPoint = 0;
!             ServiceStatus.dwWaitHint = 0;
!             ServiceStatus.dwControlsAccepted = 0;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!                        
              /* exit if initialization failed */
              return;
          }
          else
          {
              /* allow another 120 seconds to start */
!             ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
!             ServiceStatus.dwServiceSpecificExitCode = 0;
!             ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
!             ServiceStatus.dwWin32ExitCode = NO_ERROR;
!             ServiceStatus.dwCheckPoint = 2;
!             ServiceStatus.dwWaitHint = 120000;
!             /* accept Power Events */
!             ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
          }
      }
  
--- 1229,1259 ----
  
          if (hookRc == FALSE)
          {
!             if (bRunningAsService) {
!                 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                 ServiceStatus.dwCheckPoint = 0;
!                 ServiceStatus.dwWaitHint = 0;
!                 ServiceStatus.dwControlsAccepted = 0;
!                 SetServiceStatus(StatusHandle, &ServiceStatus);
!             }       
              /* exit if initialization failed */
              return;
          }
          else
          {
              /* allow another 120 seconds to start */
!             if (bRunningAsService) {
!                 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
!                 ServiceStatus.dwServiceSpecificExitCode = 0;
!                 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
!                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                 ServiceStatus.dwCheckPoint = 2;
!                 ServiceStatus.dwWaitHint = 120000;
!                 /* accept Power Events */
!                 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!                 SetServiceStatus(StatusHandle, &ServiceStatus);
!             }
          }
      }
  
***************
*** 1249,1257 ****
          }
  
  #ifndef NOTSERVICE
!         ServiceStatus.dwCheckPoint = 3;
!         ServiceStatus.dwWaitHint = 30000;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
  #endif
          code = afsd_InitDaemons(&reason);
          if (code != 0) {
--- 1274,1284 ----
          }
  
  #ifndef NOTSERVICE
!         if (bRunningAsService) {
!             ServiceStatus.dwCheckPoint = 3;
!             ServiceStatus.dwWaitHint = 30000;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!         }
  #endif
          code = afsd_InitDaemons(&reason);
          if (code != 0) {
***************
*** 1274,1295 ****
  
              if (hookRc == FALSE)
              {
!                 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                 ServiceStatus.dwCheckPoint = 0;
!                 ServiceStatus.dwWaitHint = 0;
!                 ServiceStatus.dwControlsAccepted = 0;
!                 SetServiceStatus(StatusHandle, &ServiceStatus);
!                        
                  /* exit if initialization failed */
                  return;
              }
          }
  
  #ifndef NOTSERVICE
!         ServiceStatus.dwCheckPoint = 4;
!         ServiceStatus.dwWaitHint = 15000;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
  #endif
  
          /* Notify any volume status handlers that the cache manager has started */
--- 1301,1325 ----
  
              if (hookRc == FALSE)
              {
!                 if (bRunningAsService) {
!                     ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                     ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                     ServiceStatus.dwCheckPoint = 0;
!                     ServiceStatus.dwWaitHint = 0;
!                     ServiceStatus.dwControlsAccepted = 0;
!                     SetServiceStatus(StatusHandle, &ServiceStatus);
!                 }   
                  /* exit if initialization failed */
                  return;
              }
          }
  
  #ifndef NOTSERVICE
!         if (bRunningAsService) {
!             ServiceStatus.dwCheckPoint = 4;
!             ServiceStatus.dwWaitHint = 15000;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!         }
  #endif
  
          /* Notify any volume status handlers that the cache manager has started */
***************
*** 1319,1331 ****
  
              if (hookRc == FALSE)
              {
!                 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                 ServiceStatus.dwCheckPoint = 0;
!                 ServiceStatus.dwWaitHint = 0;
!                 ServiceStatus.dwControlsAccepted = 0;
!                 SetServiceStatus(StatusHandle, &ServiceStatus);
!                        
                  /* exit if initialization failed */
                  return;
              }
--- 1349,1362 ----
  
              if (hookRc == FALSE)
              {
!                 if (bRunningAsService) {
!                     ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                     ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                     ServiceStatus.dwCheckPoint = 0;
!                     ServiceStatus.dwWaitHint = 0;
!                     ServiceStatus.dwControlsAccepted = 0;
!                     SetServiceStatus(StatusHandle, &ServiceStatus);
!                 }   
                  /* exit if initialization failed */
                  return;
              }
***************
*** 1334,1347 ****
          MountGlobalDrives();
  
  #ifndef NOTSERVICE
!         ServiceStatus.dwCurrentState = SERVICE_RUNNING;
!         ServiceStatus.dwWin32ExitCode = NO_ERROR;
!         ServiceStatus.dwCheckPoint = 5;
!         ServiceStatus.dwWaitHint = 0;
  
!         /* accept Power events */
!         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
  #endif  
  
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
--- 1365,1380 ----
          MountGlobalDrives();
  
  #ifndef NOTSERVICE
!         if (bRunningAsService) {
!             ServiceStatus.dwCurrentState = SERVICE_RUNNING;
!             ServiceStatus.dwWin32ExitCode = NO_ERROR;
!             ServiceStatus.dwCheckPoint = 5;
!             ServiceStatus.dwWaitHint = 0;
  
!             /* accept Power events */
!             ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!         }
  #endif  
  
  	LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
***************
*** 1362,1374 ****
  
          if (hookRc == FALSE)
          {
!             ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!             ServiceStatus.dwWin32ExitCode = NO_ERROR;
!             ServiceStatus.dwCheckPoint = 0;
!             ServiceStatus.dwWaitHint = 0;
!             ServiceStatus.dwControlsAccepted = 0;
!             SetServiceStatus(StatusHandle, &ServiceStatus);
!                        
              /* exit if initialization failed */
              return;
          }
--- 1395,1408 ----
  
          if (hookRc == FALSE)
          {
!             if (bRunningAsService) {
!                 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
!                 ServiceStatus.dwCheckPoint = 0;
!                 ServiceStatus.dwWaitHint = 0;
!                 ServiceStatus.dwControlsAccepted = 0;
!                 SetServiceStatus(StatusHandle, &ServiceStatus);
!             }                       
              /* exit if initialization failed */
              return;
          }
***************
*** 1376,1388 ****
  
      WaitForSingleObject(WaitToTerminate, INFINITE);
  
!     ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
!     ServiceStatus.dwWin32ExitCode = NO_ERROR;
!     ServiceStatus.dwCheckPoint = 6;
!     ServiceStatus.dwWaitHint = 120000;
!     ServiceStatus.dwControlsAccepted = 0;
!     SetServiceStatus(StatusHandle, &ServiceStatus);
! 
      afsi_log("Received Termination Signal, Stopping Service");
  
      if ( GlobalStatus )
--- 1410,1423 ----
  
      WaitForSingleObject(WaitToTerminate, INFINITE);
  
!     if (bRunningAsService) {
!         ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
!         ServiceStatus.dwWin32ExitCode = NO_ERROR;
!         ServiceStatus.dwCheckPoint = 6;
!         ServiceStatus.dwWaitHint = 120000;
!         ServiceStatus.dwControlsAccepted = 0;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
!     }
      afsi_log("Received Termination Signal, Stopping Service");
  
      if ( GlobalStatus )
***************
*** 1413,1426 ****
      DismountGlobalDrives();
      afsi_log("Global Drives dismounted");
                                           
-     cm_DaemonShutdown();                 
-     afsi_log("Daemon shutdown complete");
-     
-     afsd_ShutdownCM();
- 
-     buf_Shutdown();                      
-     afsi_log("Buffer shutdown complete");
-                                          
      smb_Shutdown();                      
      afsi_log("smb shutdown complete");   
                                           
--- 1448,1453 ----
***************
*** 1428,1433 ****
--- 1455,1468 ----
  
      cm_ReleaseAllLocks();
  
+     cm_DaemonShutdown();                 
+     afsi_log("Daemon shutdown complete");
+     
+     buf_Shutdown();                      
+     afsi_log("Buffer shutdown complete");
+                                          
+     afsd_ShutdownCM();
+ 
      cm_ShutdownMappedMemory();           
  
      rx_Finalize();
***************
*** 1467,1478 ****
      /* Remove the ExceptionFilter */
      SetUnhandledExceptionFilter(NULL);
  
!     ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!     ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
!     ServiceStatus.dwCheckPoint = 7;
!     ServiceStatus.dwWaitHint = 0;
!     ServiceStatus.dwControlsAccepted = 0;
!     SetServiceStatus(StatusHandle, &ServiceStatus);
  }       
  
  DWORD __stdcall afsdMain_thread(void* notUsed)
--- 1502,1515 ----
      /* Remove the ExceptionFilter */
      SetUnhandledExceptionFilter(NULL);
  
!     if (bRunningAsService) {
!         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
!         ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
!         ServiceStatus.dwCheckPoint = 7;
!         ServiceStatus.dwWaitHint = 0;
!         ServiceStatus.dwControlsAccepted = 0;
!         SetServiceStatus(StatusHandle, &ServiceStatus);
!     }
  }       
  
  DWORD __stdcall afsdMain_thread(void* notUsed)
***************
*** 1516,1521 ****
--- 1553,1561 ----
          if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
          {
              DWORD tid;
+ 
+             bRunningAsService = FALSE;
+ 
              hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
  		
              printf("Hit <Enter> to terminate OpenAFS Client Service\n");
Index: openafs/src/WINNT/afsd/cm.h
diff -c openafs/src/WINNT/afsd/cm.h:1.17.2.15 openafs/src/WINNT/afsd/cm.h:1.17.2.17
*** openafs/src/WINNT/afsd/cm.h:1.17.2.15	Mon Jul 28 19:05:32 2008
--- openafs/src/WINNT/afsd/cm.h	Tue Sep 16 07:47:47 2008
***************
*** 99,108 ****
--- 99,154 ----
  #define CM_ERROR_RANGE_NOT_LOCKED       (CM_ERROR_BASE+57)
  #define CM_ERROR_NOSUCHDEVICE           (CM_ERROR_BASE+58)
  #define CM_ERROR_LOCK_NOT_GRANTED       (CM_ERROR_BASE+59)
+ #define CM_ERROR_NOTINCACHE             (CM_ERROR_BASE+60)
  
  /* Used by cm_FollowMountPoint and cm_FindVolumeByName */
  /* And as an index in cm_volume_t */
  #define RWVOL	0
  #define ROVOL	1
  #define BACKVOL	2
+ 
+ #define LOCK_HIERARCHY_IGNORE                    0
+ 
+ #define LOCK_HIERARCHY_SMB_STARTED              30
+ #define LOCK_HIERARCHY_SMB_LISTENER             35
+ #define LOCK_HIERARCHY_SMB_GLOBAL               40
+ #define LOCK_HIERARCHY_SMB_DIRSEARCH            50
+ #define LOCK_HIERARCHY_SMB_FID                  60
+ #define LOCK_HIERARCHY_SMB_TID                  70
+ #define LOCK_HIERARCHY_SMB_UID                  80
+ #define LOCK_HIERARCHY_SMB_RAWBUF              100
+ #define LOCK_HIERARCHY_SMB_DIRWATCH            105
+ #define LOCK_HIERARCHY_SMB_RCT_GLOBAL          110
+ #define LOCK_HIERARCHY_SMB_USERNAME            115
+ #define LOCK_HIERARCHY_SMB_VC                  120
+ 
+ 
+ #define LOCK_HIERARCHY_DAEMON_GLOBAL           400
+ 
+ #define LOCK_HIERARCHY_SCACHE_DIRLOCK          500
+ #define LOCK_HIERARCHY_SCACHE_BUFCREATE        510
+ #define LOCK_HIERARCHY_BUFFER                  530
+ #define LOCK_HIERARCHY_SCACHE                  540
+ #define LOCK_HIERARCHY_BUF_GLOBAL              550
+ #define LOCK_HIERARCHY_VOLUME                  560
+ #define LOCK_HIERARCHY_USER                    570
+ #define LOCK_HIERARCHY_SCACHE_GLOBAL           580
+ #define LOCK_HIERARCHY_CONN_GLOBAL             600
+ #define LOCK_HIERARCHY_CELL                    620
+ #define LOCK_HIERARCHY_CELL_GLOBAL             630
+ #define LOCK_HIERARCHY_SERVER                  640
+ #define LOCK_HIERARCHY_CALLBACK_GLOBAL         645
+ #define LOCK_HIERARCHY_SERVER_GLOBAL           650
+ #define LOCK_HIERARCHY_CONN                    660 
+ #define LOCK_HIERARCHY_VOLUME_GLOBAL           670
+ #define LOCK_HIERARCHY_DNLC_GLOBAL             690
+ #define LOCK_HIERARCHY_FREELANCE_GLOBAL        700
+ #define LOCK_HIERARCHY_UTILS_GLOBAL            710
+ #define LOCK_HIERARCHY_OTHER_GLOBAL            720
+ #define LOCK_HIERARCHY_ACL_GLOBAL              730
+ #define LOCK_HIERARCHY_USER_GLOBAL             740
+ #define LOCK_HIERARCHY_AFSDBSBMT_GLOBAL       1000
+ #define LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL     2000
+ #define LOCK_HIERARCHY_SYSCFG_GLOBAL          3000
  #endif /*  __CM_H_ENV__ */
+ 
Index: openafs/src/WINNT/afsd/cm_access.c
diff -c openafs/src/WINNT/afsd/cm_access.c:1.7.2.21 openafs/src/WINNT/afsd/cm_access.c:1.7.2.22
*** openafs/src/WINNT/afsd/cm_access.c:1.7.2.21	Tue Aug  5 11:46:37 2008
--- openafs/src/WINNT/afsd/cm_access.c	Fri Aug 22 14:10:00 2008
***************
*** 39,50 ****
      long trights;
      int release = 0;    /* Used to avoid a call to cm_HoldSCache in the directory case */
  
- #if 0
-     if (scp->flags & CM_SCACHEFLAG_EACCESS) {
-     	*outRightsp = 0;
- 	return 1;
-     }
- #endif
      didLock = 0;
      if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
          aclScp = scp;   /* not held, not released */
--- 39,44 ----
***************
*** 54,65 ****
          if (!aclScp) 
              return 0;
          if (aclScp != scp) {
!             code = lock_TryRead(&aclScp->rw);
!             if (code == 0) {
!                 /* can't get lock safely and easily */
!                 cm_ReleaseSCache(aclScp);
!                 return 0;
!             }
  
  	    /* check that we have a callback, too */
              if (!cm_HaveCallback(aclScp)) {
--- 48,58 ----
          if (!aclScp) 
              return 0;
          if (aclScp != scp) {
!             if (aclScp->fid.vnode < scp->fid.vnode)
!                 lock_ReleaseWrite(&scp->rw);
!             lock_ObtainRead(&aclScp->rw);
!             if (aclScp->fid.vnode < scp->fid.vnode)
!                 lock_ObtainWrite(&scp->rw);
  
  	    /* check that we have a callback, too */
              if (!cm_HaveCallback(aclScp)) {
***************
*** 167,172 ****
--- 160,167 ----
  			 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
  	if (!code) 
  	    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+     else
+         osi_Log3(afsd_logp, "GetAccessRights syncop failure scp %x user %x code %x", scp, userp, code);
      } else {
          /* not a dir, use parent dir's acl */
          cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique);
***************
*** 184,189 ****
--- 179,186 ----
  	if (!code)
  	    cm_SyncOpDone(aclScp, NULL, 
  			  CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+     else 
+         osi_Log3(afsd_logp, "GetAccessRights parent syncop failure scp %x user %x code %x", aclScp, userp, code);
  	lock_ReleaseWrite(&aclScp->rw);
          cm_ReleaseSCache(aclScp);
          lock_ObtainWrite(&scp->rw);
Index: openafs/src/WINNT/afsd/cm_aclent.c
diff -c openafs/src/WINNT/afsd/cm_aclent.c:1.14.2.6 openafs/src/WINNT/afsd/cm_aclent.c:1.14.2.7
*** openafs/src/WINNT/afsd/cm_aclent.c:1.14.2.6	Thu Jul 31 00:34:16 2008
--- openafs/src/WINNT/afsd/cm_aclent.c	Fri Aug 22 14:10:00 2008
***************
*** 257,263 ****
      static osi_once_t once;
  
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_aclLock, "cm_aclLock");
          osi_EndOnce(&once);
      }
  
--- 257,263 ----
      static osi_once_t once;
  
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_aclLock, "cm_aclLock", LOCK_HIERARCHY_ACL_GLOBAL);
          osi_EndOnce(&once);
      }
  
Index: openafs/src/WINNT/afsd/cm_buf.c
diff -c openafs/src/WINNT/afsd/cm_buf.c:1.31.2.44 openafs/src/WINNT/afsd/cm_buf.c:1.31.2.46
*** openafs/src/WINNT/afsd/cm_buf.c:1.31.2.44	Thu Jul 31 00:41:20 2008
--- openafs/src/WINNT/afsd/cm_buf.c	Fri Aug 29 22:15:07 2008
***************
*** 213,285 ****
      }
  }
  
! /* incremental sync daemon.  Writes all dirty buffers every 5000 ms */
! void buf_IncrSyncer(long parm)
  {
      cm_buf_t **bpp, *bp, *prevbp;
-     long i;				/* counter */
      long wasDirty = 0;
      cm_req_t req;
  
!     while (buf_ShutdownFlag == 0) {
! 	if (!wasDirty) {
! 	    i = SleepEx(5000, 1);
! 	    if (i != 0) continue;
! 	}
! 
! 	wasDirty = 0;
! 
!         /* go through all of the dirty buffers */
!         lock_ObtainRead(&buf_globalLock);
!         for (bpp = &cm_data.buf_dirtyListp, prevbp = NULL; bp = *bpp; ) {
!             lock_ReleaseRead(&buf_globalLock);
! 	    /* all dirty buffers are held when they are added to the
! 	     * dirty list.  No need for an additional hold.
! 	     */
!             lock_ObtainMutex(&bp->mx);
  
! 	    if (bp->flags & CM_BUF_DIRTY) {
! 		/* start cleaning the buffer; don't touch log pages since
!  		 * the log code counts on knowing exactly who is writing
! 		 * a log page at any given instant.
! 		 */
! 		cm_InitReq(&req);
! 		req.flags |= CM_REQ_NORETRY;
! 		wasDirty |= buf_CleanAsyncLocked(bp, &req);
! 	    }
  
! 	    /* the buffer may or may not have been dirty
! 	     * and if dirty may or may not have been cleaned
! 	     * successfully.  check the dirty flag again.  
! 	     */
!             if (!(bp->flags & CM_BUF_DIRTY)) {
!                 /* remove the buffer from the dirty list */
!                 lock_ObtainWrite(&buf_globalLock);
  #ifdef DEBUG_REFCOUNT
!                 if (bp->dirtyp == NULL && bp != cm_data.buf_dirtyListEndp) {
!                     osi_Log1(afsd_logp,"buf_IncrSyncer bp 0x%p list corruption",bp);
!                     afsi_log("buf_IncrSyncer bp 0x%p list corruption", bp);
!                 }
! #endif
!                 *bpp = bp->dirtyp;
!                 bp->dirtyp = NULL;
!                 bp->flags &= ~CM_BUF_INDL;
!                 if (cm_data.buf_dirtyListp == NULL)
!                     cm_data.buf_dirtyListEndp = NULL;
!                 else if (cm_data.buf_dirtyListEndp == bp)
!                     cm_data.buf_dirtyListEndp = prevbp;
!                 buf_ReleaseLocked(bp, TRUE);
!                 lock_ConvertWToR(&buf_globalLock);
!             } else {
!                 /* advance the pointer so we don't loop forever */
!                 lock_ObtainRead(&buf_globalLock);
!                 bpp = &bp->dirtyp;
!                 prevbp = bp;
              }
!             lock_ReleaseMutex(&bp->mx);
!         }	/* for loop over a bunch of buffers */
!         lock_ReleaseRead(&buf_globalLock);
!     }		/* whole daemon's while loop */
  }
  
  long
--- 213,298 ----
      }
  }
  
! long 
! buf_Sync(int quitOnShutdown) 
  {
      cm_buf_t **bpp, *bp, *prevbp;
      long wasDirty = 0;
      cm_req_t req;
  
!     /* go through all of the dirty buffers */
!     lock_ObtainRead(&buf_globalLock);
!     for (bpp = &cm_data.buf_dirtyListp, prevbp = NULL; bp = *bpp; ) {
!         if (quitOnShutdown && buf_ShutdownFlag)
!             break;
  
!         lock_ReleaseRead(&buf_globalLock);
!         /* all dirty buffers are held when they are added to the
!         * dirty list.  No need for an additional hold.
!         */
!         lock_ObtainMutex(&bp->mx);
  
!         if (bp->flags & CM_BUF_DIRTY) {
!             /* start cleaning the buffer; don't touch log pages since
!             * the log code counts on knowing exactly who is writing
!             * a log page at any given instant.
!             */
!             cm_InitReq(&req);
!             req.flags |= CM_REQ_NORETRY;
!             wasDirty |= buf_CleanAsyncLocked(bp, &req);
!         }
! 
!         /* the buffer may or may not have been dirty
!         * and if dirty may or may not have been cleaned
!         * successfully.  check the dirty flag again.  
!         */
!         if (!(bp->flags & CM_BUF_DIRTY)) {
!             /* remove the buffer from the dirty list */
!             lock_ObtainWrite(&buf_globalLock);
  #ifdef DEBUG_REFCOUNT
!             if (bp->dirtyp == NULL && bp != cm_data.buf_dirtyListEndp) {
!                 osi_Log1(afsd_logp,"buf_IncrSyncer bp 0x%p list corruption",bp);
!                 afsi_log("buf_IncrSyncer bp 0x%p list corruption", bp);
              }
! #endif
!             *bpp = bp->dirtyp;
!             bp->dirtyp = NULL;
!             bp->flags &= ~CM_BUF_INDL;
!             if (cm_data.buf_dirtyListp == NULL)
!                 cm_data.buf_dirtyListEndp = NULL;
!             else if (cm_data.buf_dirtyListEndp == bp)
!                 cm_data.buf_dirtyListEndp = prevbp;
!             buf_ReleaseLocked(bp, TRUE);
!             lock_ConvertWToR(&buf_globalLock);
!         } else {
!             /* advance the pointer so we don't loop forever */
!             lock_ObtainRead(&buf_globalLock);
!             bpp = &bp->dirtyp;
!             prevbp = bp;
!         }
!         lock_ReleaseMutex(&bp->mx);
!     }	/* for loop over a bunch of buffers */
!     lock_ReleaseRead(&buf_globalLock);
! 
!     return wasDirty;
! }
! 
! /* incremental sync daemon.  Writes all dirty buffers every 5000 ms */
! void buf_IncrSyncer(long parm)
! {
!     long wasDirty = 0;
!     long i;
! 
!     while (buf_ShutdownFlag == 0) {
! 
!         if (!wasDirty) {
! 	    i = SleepEx(5000, 1);
! 	    if (i != 0) 
!                 continue;
! 	}
! 
!         wasDirty = buf_Sync(1);
!     } /* whole daemon's while loop */
  }
  
  long
***************
*** 359,366 ****
  }
  
  void buf_Shutdown(void)  
! {                        
      buf_ShutdownFlag = 1;
  }                        
  
  /* initialize the buffer package; called with no locks
--- 372,383 ----
  }
  
  void buf_Shutdown(void)  
! {  
!     /* disable the buf_IncrSyncer() threads */
      buf_ShutdownFlag = 1;
+ 
+     /* then force all dirty buffers to the file servers */
+     buf_Sync(0);
  }                        
  
  /* initialize the buffer package; called with no locks
***************
*** 389,395 ****
  
      if (osi_Once(&once)) {
          /* initialize global locks */
!         lock_InitializeRWLock(&buf_globalLock, "Global buffer lock");
  
          if ( newFile ) {
              /* remember this for those who want to reset it */
--- 406,412 ----
  
      if (osi_Once(&once)) {
          /* initialize global locks */
!         lock_InitializeRWLock(&buf_globalLock, "Global buffer lock", LOCK_HIERARCHY_BUF_GLOBAL);
  
          if ( newFile ) {
              /* remember this for those who want to reset it */
***************
*** 424,430 ****
                  
                  osi_QAdd((osi_queue_t **)&cm_data.buf_freeListp, &bp->q);
                  bp->flags |= CM_BUF_INLRU;
!                 lock_InitializeMutex(&bp->mx, "Buffer mutex");
                  
                  /* grab appropriate number of bytes from aligned zone */
                  bp->datap = data;
--- 441,447 ----
                  
                  osi_QAdd((osi_queue_t **)&cm_data.buf_freeListp, &bp->q);
                  bp->flags |= CM_BUF_INLRU;
!                 lock_InitializeMutex(&bp->mx, "Buffer mutex", LOCK_HIERARCHY_BUFFER);
                  
                  /* grab appropriate number of bytes from aligned zone */
                  bp->datap = data;
***************
*** 448,454 ****
              data = cm_data.bufDataBaseAddress;
              
              for (i=0; i<cm_data.buf_nbuffers; i++) {
!                 lock_InitializeMutex(&bp->mx, "Buffer mutex");
                  bp->userp = NULL;
                  bp->waitCount = 0;
                  bp->waitRequests = 0;
--- 465,471 ----
              data = cm_data.bufDataBaseAddress;
              
              for (i=0; i<cm_data.buf_nbuffers; i++) {
!                 lock_InitializeMutex(&bp->mx, "Buffer mutex", LOCK_HIERARCHY_BUFFER);
                  bp->userp = NULL;
                  bp->waitCount = 0;
                  bp->waitRequests = 0;
***************
*** 516,522 ****
      for (i=0; i<nbuffers; i++) {
          memset(bp, 0, sizeof(*bp));
          
!         lock_InitializeMutex(&bp->mx, "cm_buf_t");
  
          /* grab appropriate number of bytes from aligned zone */
          bp->datap = data;
--- 533,539 ----
      for (i=0; i<nbuffers; i++) {
          memset(bp, 0, sizeof(*bp));
          
!         lock_InitializeMutex(&bp->mx, "cm_buf_t", LOCK_HIERARCHY_BUFFER);
  
          /* grab appropriate number of bytes from aligned zone */
          bp->datap = data;
***************
*** 998,1021 ****
              osi_QRemove((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
              bp->flags &= ~CM_BUF_INLRU;
  
              /* grab the mutex so that people don't use it
               * before the caller fills it with data.  Again, no one	
               * should have been able to get to this dude to lock it.
               */
  	    if (!lock_TryMutex(&bp->mx)) {
  	    	osi_Log2(afsd_logp, "buf_GetNewLocked bp 0x%p cannot be mutex locked.  refCount %d should be 0",
! 			 bp, bp->refCount);
  		osi_panic("buf_GetNewLocked: TryMutex failed",__FILE__,__LINE__);
  	    }
  
- 	    /* prepare to return it.  Give it a refcount */
-             bp->refCount = 1;
- #ifdef DEBUG_REFCOUNT
-             osi_Log2(afsd_logp,"buf_GetNewLocked bp 0x%p ref %d", bp, 1);
-             afsi_log("%s:%d buf_GetNewLocked bp 0x%p, ref %d", __FILE__, __LINE__, bp, 1);
- #endif
              lock_ReleaseWrite(&buf_globalLock);
              lock_ReleaseRead(&scp->bufCreateLock);
              *bufpp = bp;
  
  #ifdef TESTING
--- 1015,1039 ----
              osi_QRemove((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
              bp->flags &= ~CM_BUF_INLRU;
  
+             /* prepare to return it.  Give it a refcount */
+             bp->refCount = 1;
+ #ifdef DEBUG_REFCOUNT
+             osi_Log2(afsd_logp,"buf_GetNewLocked bp 0x%p ref %d", bp, 1);
+             afsi_log("%s:%d buf_GetNewLocked bp 0x%p, ref %d", __FILE__, __LINE__, bp, 1);
+ #endif
              /* grab the mutex so that people don't use it
               * before the caller fills it with data.  Again, no one	
               * should have been able to get to this dude to lock it.
               */
  	    if (!lock_TryMutex(&bp->mx)) {
  	    	osi_Log2(afsd_logp, "buf_GetNewLocked bp 0x%p cannot be mutex locked.  refCount %d should be 0",
!                          bp, bp->refCount);
  		osi_panic("buf_GetNewLocked: TryMutex failed",__FILE__,__LINE__);
  	    }
  
              lock_ReleaseWrite(&buf_globalLock);
              lock_ReleaseRead(&scp->bufCreateLock);
+ 
              *bufpp = bp;
  
  #ifdef TESTING
Index: openafs/src/WINNT/afsd/cm_callback.c
diff -c openafs/src/WINNT/afsd/cm_callback.c:1.41.4.47 openafs/src/WINNT/afsd/cm_callback.c:1.41.4.51
*** openafs/src/WINNT/afsd/cm_callback.c:1.41.4.47	Fri Aug  1 15:13:51 2008
--- openafs/src/WINNT/afsd/cm_callback.c	Sat Sep 13 00:20:48 2008
***************
*** 599,605 ****
  extern osi_rwlock_t smb_rctLock;
  
  extern osi_mutex_t cm_Freelance_Lock;
- extern osi_mutex_t cm_bufGetMutex;
  extern osi_mutex_t cm_Afsdsbmt_Lock;
  extern osi_mutex_t tokenEventLock;
  extern osi_mutex_t  smb_ListenerLock;
--- 599,604 ----
***************
*** 629,635 ****
      {"smb_globalLock",   (char*)&smb_globalLock,        LOCKTYPE_RW},
      {"smb_rctLock",      (char*)&smb_rctLock,           LOCKTYPE_RW},
      {"cm_Freelance_Lock",(char*)&cm_Freelance_Lock,     LOCKTYPE_MUTEX},
-     {"cm_bufGetMutex",   (char*)&cm_bufGetMutex,        LOCKTYPE_MUTEX},
      {"cm_Afsdsbmt_Lock", (char*)&cm_Afsdsbmt_Lock,      LOCKTYPE_MUTEX},
      {"tokenEventLock",   (char*)&tokenEventLock,        LOCKTYPE_MUTEX},
      {"smb_ListenerLock", (char*)&smb_ListenerLock,      LOCKTYPE_MUTEX},
--- 628,633 ----
***************
*** 1493,1499 ****
  /* called by afsd without any locks to initialize this module */
  void cm_InitCallback(void)
  {
!     lock_InitializeRWLock(&cm_callbackLock, "cm_callbackLock");
      cm_activeCallbackGrantingCalls = 0;
  }
  
--- 1491,1497 ----
  /* called by afsd without any locks to initialize this module */
  void cm_InitCallback(void)
  {
!     lock_InitializeRWLock(&cm_callbackLock, "cm_callbackLock", LOCK_HIERARCHY_CALLBACK_GLOBAL);
      cm_activeCallbackGrantingCalls = 0;
  }
  
***************
*** 1869,1874 ****
--- 1867,1874 ----
          return 1;
  
      for (found = 0,tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
          if (tsrp->server == scp->cbServerp)
              found = 1;
          if (tsrp->server->downTime > *downTime)
***************
*** 1951,1963 ****
              cm_volume_t * volp;
              int i;
  
              lock_ObtainMutex(&tsp->mx);
              if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                  tsp->flags |= CM_SERVERFLAG_DOWN;
                  tsp->downTime = time(NULL);
              }
-             cm_ForceNewConnections(tsp);
- 
              /* Now update the volume status */
              for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
                  for (i=0; i<NUM_SERVER_VOLS; i++) {
--- 1951,1963 ----
              cm_volume_t * volp;
              int i;
  
+             cm_ForceNewConnections(tsp);
+ 
              lock_ObtainMutex(&tsp->mx);
              if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                  tsp->flags |= CM_SERVERFLAG_DOWN;
                  tsp->downTime = time(NULL);
              }
              /* Now update the volume status */
              for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
                  for (i=0; i<NUM_SERVER_VOLS; i++) {
***************
*** 1965,1977 ****
                          cm_req_t req;
  
                          cm_InitReq(&req);
! 
                          code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
                                                   &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
                          if (code == 0) {    
                              cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
                              cm_PutVolume(volp);
!                         }
                      }
                  }
              }
--- 1965,1978 ----
                          cm_req_t req;
  
                          cm_InitReq(&req);
!                         lock_ReleaseMutex(&tsp->mx);
                          code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
                                                   &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
+                         lock_ObtainMutex(&tsp->mx);
                          if (code == 0) {    
                              cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
                              cm_PutVolume(volp);
!                         }       
                      }
                  }
              }
Index: openafs/src/WINNT/afsd/cm_cell.c
diff -c openafs/src/WINNT/afsd/cm_cell.c:1.23.2.18 openafs/src/WINNT/afsd/cm_cell.c:1.23.2.25
*** openafs/src/WINNT/afsd/cm_cell.c:1.23.2.18	Thu Aug 14 13:25:04 2008
--- openafs/src/WINNT/afsd/cm_cell.c	Thu Sep 11 13:05:32 2008
***************
*** 87,93 ****
          || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) &&
           ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))
  #endif
!             ) {
          /* must empty cp->vlServersp */
          if (cp->vlServersp) {
              cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
--- 87,96 ----
          || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) &&
           ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))
  #endif
!             ) 
!     {
!         lock_ReleaseMutex(&cp->mx);
! 
          /* must empty cp->vlServersp */
          if (cp->vlServersp) {
              cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
***************
*** 97,112 ****
          rock.cellp = cp;
          rock.flags = flags;
          code = cm_SearchCellFile(cp->name, NULL, cm_AddCellProc, &rock);
  #ifdef AFS_AFSDB_ENV
!         if (code) {
              if (cm_dnsEnabled) {
                  int ttl;
  
                  code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock);
                  if (code == 0) {   /* got cell from DNS */
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
  		    cp->timeout = time(0) + ttl;
  #ifdef DEBUG
                      fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl);
  #endif
--- 100,122 ----
          rock.cellp = cp;
          rock.flags = flags;
          code = cm_SearchCellFile(cp->name, NULL, cm_AddCellProc, &rock);
+         if (code == 0) {
+             lock_ObtainMutex(&cp->mx);
+ 	    cp->timeout = time(0) + 7200;
+             lock_ReleaseMutex(&cp->mx);
+         }
  #ifdef AFS_AFSDB_ENV
!         else {
              if (cm_dnsEnabled) {
                  int ttl;
  
                  code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock);
                  if (code == 0) {   /* got cell from DNS */
+                     lock_ObtainMutex(&cp->mx);
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
  		    cp->timeout = time(0) + ttl;
+                     lock_ReleaseMutex(&cp->mx);
  #ifdef DEBUG
                      fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl);
  #endif
***************
*** 114,129 ****
                      /* if we fail to find it this time, we'll just do nothing and leave the
                       * current entry alone 
  		     */
                      cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
                  }
  	    }
! 	} else 
  #endif /* AFS_AFSDB_ENV */
! 	{
! 	    cp->timeout = time(0) + 7200;
! 	}	
      }
-     lock_ReleaseMutex(&cp->mx);
      return code ? NULL : cp;
  }
  
--- 124,139 ----
                      /* if we fail to find it this time, we'll just do nothing and leave the
                       * current entry alone 
  		     */
+                     lock_ObtainMutex(&cp->mx);
                      cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+                     lock_ReleaseMutex(&cp->mx);
                  }
  	    }
! 	}
  #endif /* AFS_AFSDB_ENV */
!     } else {
!         lock_ReleaseMutex(&cp->mx);
      }
      return code ? NULL : cp;
  }
  
***************
*** 133,144 ****
--- 143,165 ----
      return cm_GetCell_Gen(namep, NULL, flags);
  }
  
+ void cm_FreeCell(cm_cell_t *cellp)
+ {
+     if (cellp->vlServersp)
+         cm_FreeServerList(&cellp->vlServersp, CM_FREESERVERLIST_DELETE);
+     cellp->name[0] = '\0';    
+ 
+     cellp->freeNextp = cm_data.freeCellsp;
+     cm_data.freeCellsp = cellp;
+ }
+ 
  cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
  {
      cm_cell_t *cp, *cp2;
      long code;
      char fullname[CELL_MAXNAMELEN]="";
      int  hasWriteLock = 0;
+     int  hasMutex = 0;
      afs_uint32 hash;
      cm_cell_rock_t rock;
  
***************
*** 166,177 ****
          }   
      }
  
-     lock_ReleaseRead(&cm_cellLock);
- 
      if (cp) {
          cm_UpdateCell(cp, flags);
      } else if (flags & CM_FLAG_CREATE) {
!         lock_ObtainWrite(&cm_cellLock);
          hasWriteLock = 1;
  
          /* when we dropped the lock the cell could have been added
--- 187,197 ----
          }   
      }
  
      if (cp) {
+         lock_ReleaseRead(&cm_cellLock);
          cm_UpdateCell(cp, flags);
      } else if (flags & CM_FLAG_CREATE) {
!         lock_ConvertRToW(&cm_cellLock);
          hasWriteLock = 1;
  
          /* when we dropped the lock the cell could have been added
***************
*** 196,214 ****
              }
          }   
  
!         if (cp)
              goto done;
  
!         if ( cm_data.currentCells >= cm_data.maxCells )
!             osi_panic("Exceeded Max Cells", __FILE__, __LINE__);
  
-         /* don't increment currentCells until we know that we 
-          * are going to keep this entry 
-          */
-         cp = &cm_data.cellBaseAddress[cm_data.currentCells];
-         memset(cp, 0, sizeof(cm_cell_t));
-         cp->magic = CM_CELL_MAGIC;
-         
          rock.cellp = cp;
          rock.flags = flags;
          code = cm_SearchCellFile(namep, fullname, cm_AddCellProc, &rock);
--- 216,257 ----
              }
          }   
  
!         if (cp) {
!             lock_ObtainMutex(&cp->mx);
!             cm_AddCellToNameHashTable(cp);
!             cm_AddCellToIDHashTable(cp);           
!             lock_ReleaseMutex(&cp->mx);
              goto done;
+         }
  
!         if ( cm_data.freeCellsp != NULL ) {
!             cp = cm_data.freeCellsp;
!             cm_data.freeCellsp = cp->freeNextp;
! 
!             /* 
!              * The magic, cellID, and mx fields are already set.
!              */
!         } else {
!             if ( cm_data.currentCells >= cm_data.maxCells )
!                 osi_panic("Exceeded Max Cells", __FILE__, __LINE__);
! 
!             /* don't increment currentCells until we know that we 
!              * are going to keep this entry 
!              */
!             cp = &cm_data.cellBaseAddress[cm_data.currentCells];
!             memset(cp, 0, sizeof(cm_cell_t));
!             cp->magic = CM_CELL_MAGIC;
! 
!             /* the cellID cannot be 0 */
!             cp->cellID = ++cm_data.currentCells;
! 
!             /* otherwise we found the cell, and so we're nearly done */
!             lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
!         }
! 
!         lock_ReleaseWrite(&cm_cellLock);
!         hasWriteLock = 0;
  
          rock.cellp = cp;
          rock.flags = flags;
          code = cm_SearchCellFile(namep, fullname, cm_AddCellProc, &rock);
***************
*** 224,244 ****
                  if ( code ) {
                      osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", 
                               osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname));
                      cp = NULL;
                      goto done;
                  } else {   /* got cell from DNS */
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                      cp->timeout = time(0) + ttl;
                  }
!             } else {
  #endif
                  cp = NULL;
                  goto done;
- #ifdef AFS_AFSDB_ENV
  	    }
- #endif
          } else {
  	    cp->timeout = time(0) + 7200;	/* two hour timeout */
  	}
  
--- 267,293 ----
                  if ( code ) {
                      osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", 
                               osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname));
+                     cm_FreeCell(cp);
                      cp = NULL;
                      goto done;
                  } else {   /* got cell from DNS */
+                     lock_ObtainMutex(&cp->mx);
+                     hasMutex = 1;
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                      cp->timeout = time(0) + ttl;
                  }
!             } 
!             else 
  #endif
+             {
+                 cm_FreeCell(cp);
                  cp = NULL;
                  goto done;
  	    }
          } else {
+             lock_ObtainMutex(&cp->mx);
+             hasMutex = 1;
  	    cp->timeout = time(0) + 7200;	/* two hour timeout */
  	}
  
***************
*** 255,280 ****
          }   
  
          if (cp2) {
!             cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
              cp = cp2;
              goto done;
          }
  
- 
          /* randomise among those vlservers having the same rank*/ 
          cm_RandomizeServer(&cp->vlServersp);
  
!         /* otherwise we found the cell, and so we're nearly done */
!         lock_InitializeMutex(&cp->mx, "cm_cell_t mutex");
! 
          /* copy in name */
          strncpy(cp->name, fullname, CELL_MAXNAMELEN);
          cp->name[CELL_MAXNAMELEN-1] = '\0';
  
!         /* the cellID cannot be 0 */
!         cp->cellID = ++cm_data.currentCells;
  
! 		/* append cell to global list */
          if (cm_data.allCellsp == NULL) {
              cm_data.allCellsp = cp;
          } else {
--- 304,333 ----
          }   
  
          if (cp2) {
!             if (hasMutex) {
!                 lock_ReleaseMutex(&cp->mx);
!                 hasMutex = 0;
!             }
!             cm_FreeCell(cp);
              cp = cp2;
              goto done;
          }
  
          /* randomise among those vlservers having the same rank*/ 
          cm_RandomizeServer(&cp->vlServersp);
  
!         if (!hasMutex)
!             lock_ObtainMutex(&cp->mx);
          /* copy in name */
          strncpy(cp->name, fullname, CELL_MAXNAMELEN);
          cp->name[CELL_MAXNAMELEN-1] = '\0';
  
!         cm_AddCellToNameHashTable(cp);
!         cm_AddCellToIDHashTable(cp);           
!         lock_ReleaseMutex(&cp->mx);
!         hasMutex = 0;
  
!         /* append cell to global list */
          if (cm_data.allCellsp == NULL) {
              cm_data.allCellsp = cp;
          } else {
***************
*** 284,301 ****
          }
          cp->allNextp = NULL;
  
!         cm_AddCellToNameHashTable(cp);
!         cm_AddCellToIDHashTable(cp);           
      }
- 
    done:
      if (hasWriteLock)
          lock_ReleaseWrite(&cm_cellLock);
      
      /* fullname is not valid if cp == NULL */
!     if (cp && newnamep) {
!         strncpy(newnamep, fullname, CELL_MAXNAMELEN);
!         newnamep[CELL_MAXNAMELEN-1]='\0';
      }
      return cp;
  }
--- 337,359 ----
          }
          cp->allNextp = NULL;
  
!     } else {
!         lock_ReleaseRead(&cm_cellLock);
      }
    done:
+     if (hasMutex && cp)
+         lock_ReleaseMutex(&cp->mx);
      if (hasWriteLock)
          lock_ReleaseWrite(&cm_cellLock);
      
      /* fullname is not valid if cp == NULL */
!     if (newnamep) {
!         if (cp) {
!             strncpy(newnamep, fullname, CELL_MAXNAMELEN);
!             newnamep[CELL_MAXNAMELEN-1]='\0';
!         } else {
!             newnamep[0] = '\0';
!         }
      }
      return cp;
  }
***************
*** 341,350 ****
          }
      }
  
      if ( count != cm_data.currentCells ) {
          afsi_log("cm_ValidateCell failure: count != cm_data.currentCells");
          fprintf(stderr, "cm_ValidateCell failure: count != cm_data.currentCells\n");
!         return -3;
      }
      
      return 0;
--- 399,417 ----
          }
      }
  
+     for (cellp = cm_data.freeCellsp; cellp; cellp=cellp->freeNextp, count++) {
+         if ( count != 0 && cellp == cm_data.freeCellsp ||
+              count > cm_data.maxCells ) {
+             afsi_log("cm_ValidateCell failure: cm_data.freeCellsp infinite loop");
+             fprintf(stderr, "cm_ValidateCell failure: cm_data.freeCellsp infinite loop\n");
+             return -3;
+         }
+     }
+ 
      if ( count != cm_data.currentCells ) {
          afsi_log("cm_ValidateCell failure: count != cm_data.currentCells");
          fprintf(stderr, "cm_ValidateCell failure: count != cm_data.currentCells\n");
!         return -4;
      }
      
      return 0;
***************
*** 370,376 ****
      if (osi_Once(&once)) {
          cm_cell_t * cellp;
  
!         lock_InitializeRWLock(&cm_cellLock, "cell global lock");
  
          if ( newFile ) {
              cm_data.allCellsp = NULL;
--- 437,443 ----
      if (osi_Once(&once)) {
          cm_cell_t * cellp;
  
!         lock_InitializeRWLock(&cm_cellLock, "cell global lock", LOCK_HIERARCHY_CELL_GLOBAL);
  
          if ( newFile ) {
              cm_data.allCellsp = NULL;
***************
*** 388,394 ****
              memset(cellp, 0, sizeof(cm_cell_t));
              cellp->magic = CM_CELL_MAGIC;
  
!             lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex");
  
              /* copy in name */
              strncpy(cellp->name, "Freelance.Local.Cell", CELL_MAXNAMELEN); /*safe*/
--- 455,461 ----
              memset(cellp, 0, sizeof(cm_cell_t));
              cellp->magic = CM_CELL_MAGIC;
  
!             lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
  
              /* copy in name */
              strncpy(cellp->name, "Freelance.Local.Cell", CELL_MAXNAMELEN); /*safe*/
***************
*** 402,413 ****
              cellp->vlServersp = NULL;
              cellp->flags = CM_CELLFLAG_FREELANCE;
  
! 	    cm_AddCellToNameHashTable(cellp);
! 	    cm_AddCellToIDHashTable(cellp);           
  #endif  
          } else {
              for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) {
!                 lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex");
                  cellp->vlServersp = NULL;
                  cellp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
              }
--- 469,482 ----
              cellp->vlServersp = NULL;
              cellp->flags = CM_CELLFLAG_FREELANCE;
  
!             lock_ObtainMutex(&cellp->mx);
!             cm_AddCellToNameHashTable(cellp);
!             cm_AddCellToIDHashTable(cellp);           
!             lock_ReleaseMutex(&cellp->mx);
  #endif  
          } else {
              for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) {
!                 lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
                  cellp->vlServersp = NULL;
                  cellp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
              }
Index: openafs/src/WINNT/afsd/cm_cell.h
diff -c openafs/src/WINNT/afsd/cm_cell.h:1.7.6.8 openafs/src/WINNT/afsd/cm_cell.h:1.7.6.10
*** openafs/src/WINNT/afsd/cm_cell.h:1.7.6.8	Thu Feb 14 22:31:36 2008
--- openafs/src/WINNT/afsd/cm_cell.h	Tue Sep  2 16:18:33 2008
***************
*** 21,35 ****
      struct cm_cell *allNextp;	        /* locked by cm_cellLock */
      struct cm_cell *nameNextp;	        /* locked by cm_cellLock */
      struct cm_cell *idNextp;	        /* locked by cm_cellLock */
      char name[CELL_MAXNAMELEN];         /* cell name; never changes */
      cm_serverRef_t *vlServersp;         /* locked by cm_serverLock */
      osi_mutex_t mx;			/* mutex locking fields (flags) */
      long flags;			        /* locked by mx */
!     time_t timeout;                     /* if dns, time at which the server addrs expire */
  } cm_cell_t;
  
  /* These are bit flag values */
! #define CM_CELLFLAG_SUID	       1	/* setuid flag; not yet used */
  #define CM_CELLFLAG_DNS                2  /* cell servers are from DNS */
  #define CM_CELLFLAG_VLSERVER_INVALID   4  /* cell servers are invalid */
  #define CM_CELLFLAG_FREELANCE          8  /* local freelance fake cell */
--- 21,36 ----
      struct cm_cell *allNextp;	        /* locked by cm_cellLock */
      struct cm_cell *nameNextp;	        /* locked by cm_cellLock */
      struct cm_cell *idNextp;	        /* locked by cm_cellLock */
+     struct cm_cell *freeNextp;
      char name[CELL_MAXNAMELEN];         /* cell name; never changes */
      cm_serverRef_t *vlServersp;         /* locked by cm_serverLock */
      osi_mutex_t mx;			/* mutex locking fields (flags) */
      long flags;			        /* locked by mx */
!     time_t timeout;                     /* if dns, time at which the server addrs expire (mx) */
  } cm_cell_t;
  
  /* These are bit flag values */
! #define CM_CELLFLAG_SUID	       1  /* setuid flag; not yet used */
  #define CM_CELLFLAG_DNS                2  /* cell servers are from DNS */
  #define CM_CELLFLAG_VLSERVER_INVALID   4  /* cell servers are invalid */
  #define CM_CELLFLAG_FREELANCE          8  /* local freelance fake cell */
Index: openafs/src/WINNT/afsd/cm_conn.c
diff -c openafs/src/WINNT/afsd/cm_conn.c:1.49.2.47 openafs/src/WINNT/afsd/cm_conn.c:1.49.2.54
*** openafs/src/WINNT/afsd/cm_conn.c:1.49.2.47	Thu Aug 14 16:24:03 2008
--- openafs/src/WINNT/afsd/cm_conn.c	Wed Sep 24 18:42:53 2008
***************
*** 49,55 ****
      HKEY parmKey;
          
      if (osi_Once(&once)) {
! 	lock_InitializeRWLock(&cm_connLock, "connection global lock");
  
          /* keisa - read timeout value for lanmanworkstation  service.
           * jaltman - as per 
--- 49,56 ----
      HKEY parmKey;
          
      if (osi_Once(&once)) {
! 	lock_InitializeRWLock(&cm_connLock, "connection global lock",
!                                LOCK_HIERARCHY_CONN_GLOBAL);
  
          /* keisa - read timeout value for lanmanworkstation  service.
           * jaltman - as per 
***************
*** 140,151 ****
      if (code) 
          return code;
      
!     *serversppp = cm_GetVolServers(volp, fidp->volume);
  
      lock_ObtainRead(&cm_volumeLock);
      cm_PutVolume(volp);
      lock_ReleaseRead(&cm_volumeLock);
!     return 0;
  }
  
  /*
--- 141,152 ----
      if (code) 
          return code;
      
!     *serversppp = cm_GetVolServers(volp, fidp->volume, userp, reqp);
  
      lock_ObtainRead(&cm_volumeLock);
      cm_PutVolume(volp);
      lock_ReleaseRead(&cm_volumeLock);
!     return (*serversppp ? 0 : CM_ERROR_NOSUCHVOLUME);
  }
  
  /*
***************
*** 231,236 ****
--- 232,239 ----
          if (cellp == NULL && serversp) {
              struct cm_serverRef * refp;
              for ( refp=serversp ; cellp == NULL && refp != NULL; refp=refp->next) {
+                 if (refp->status == srv_deleted)
+                     continue;
                  if ( refp->server )
                      cellp = refp->server->cellp;
              }
***************
*** 265,278 ****
       */
      else if (errorCode == CM_ERROR_NOSUCHVOLUME) {
  	osi_Log0(afsd_logp, "cm_Analyze passed CM_ERROR_NOSUCHVOLUME.");
!         if (timeLeft > 7) {
!             thrd_Sleep(5000);
!             
!             retry = 1;
! 
!             if (fidp != NULL)   /* Not a VLDB call */
!                 cm_ForceUpdateVolume(fidp, userp, reqp);
!         }
      }
  
      else if (errorCode == CM_ERROR_ALLDOWN) {
--- 268,277 ----
       */
      else if (errorCode == CM_ERROR_NOSUCHVOLUME) {
  	osi_Log0(afsd_logp, "cm_Analyze passed CM_ERROR_NOSUCHVOLUME.");
!         /* 
!          * The VNOVOL or VL_NOENT error has already been translated
!          * to CM_ERROR_NOSUCHVOLUME.  There is nothing for us to do.
!          */
      }
  
      else if (errorCode == CM_ERROR_ALLDOWN) {
***************
*** 338,343 ****
--- 337,344 ----
                          }
                          lock_ObtainWrite(&cm_serverLock);
                          for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+                             if (tsrp->status == srv_deleted)
+                                 continue;
                              if (tsrp->status == srv_busy) {
                                  tsrp->status = srv_not_busy;
                              }       
***************
*** 345,351 ****
                          lock_ReleaseWrite(&cm_serverLock);
                          if (free_svr_list) {
                              cm_FreeServerList(&serversp, 0);
!                             *serverspp = serversp;
                          }
  
                          cm_UpdateVolumeStatus(volp, fidp->volume);
--- 346,353 ----
                          lock_ReleaseWrite(&cm_serverLock);
                          if (free_svr_list) {
                              cm_FreeServerList(&serversp, 0);
!                             *serverspp = serversp = NULL;
!                             free_svr_list = 0;
                          }
  
                          cm_UpdateVolumeStatus(volp, fidp->volume);
***************
*** 367,372 ****
--- 369,376 ----
                  if (serversp) {
                      lock_ObtainWrite(&cm_serverLock);
                      for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+                         if (tsrp->status == srv_deleted)
+                             continue;
                          if (tsrp->status == srv_busy) {
                              tsrp->status = srv_not_busy;
                          }
***************
*** 389,402 ****
--- 393,410 ----
          }
          lock_ObtainWrite(&cm_serverLock);
          for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+             if (tsrp->status == srv_deleted)
+                 continue;
              if (tsrp->server == serverp && tsrp->status == srv_not_busy) {
                  tsrp->status = srv_busy;
                  if (fidp) { /* File Server query */
+                     lock_ReleaseWrite(&cm_serverLock);
                      code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp, 
                                               CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                               &volp);
                      if (code == 0)
                          statep = cm_VolumeStateByID(volp, fidp->volume);
+                     lock_ObtainWrite(&cm_serverLock);
                  }
                  break;
              }
***************
*** 413,419 ****
  
          if (free_svr_list) {
              cm_FreeServerList(&serversp, 0);
!             *serverspp = serversp;
          }
          retry = 1;
      }
--- 421,428 ----
  
          if (free_svr_list) {
              cm_FreeServerList(&serversp, 0);
!             *serverspp = serversp = NULL;
!             free_svr_list = 0;
          }
          retry = 1;
      }
***************
*** 428,434 ****
          switch ( errorCode ) {
          case VNOVOL:
  	    msgID = MSG_SERVER_REPORTS_VNOVOL;
!             format = "Server %s reported volume %d as not attached.";
              break;
          case VMOVED:
  	    msgID = MSG_SERVER_REPORTS_VMOVED;
--- 437,443 ----
          switch ( errorCode ) {
          case VNOVOL:
  	    msgID = MSG_SERVER_REPORTS_VNOVOL;
!             format = "Server %s reported volume %d as not attached (does not exist).";
              break;
          case VMOVED:
  	    msgID = MSG_SERVER_REPORTS_VMOVED;
***************
*** 468,514 ****
          if (!serversp && fidp) {
              code = cm_GetServerList(fidp, userp, reqp, &serverspp);
              if (code == 0) {
!                 serversp = *serverspp;
                  free_svr_list = 1;
              }
          }
  
          lock_ObtainWrite(&cm_serverLock);
          for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
              if (tsrp->server == serverp) {
                  /* REDIRECT */
!                 if (errorCode == VMOVED) {
                      tsrp->status = srv_deleted;
                  } else {
                      tsrp->status = srv_offline;
                  }
- 
-                 if (fidp) { /* File Server query */
-                     code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp, 
-                                              CM_GETVOL_FLAG_NO_LRU_UPDATE, 
-                                              &volp);
-                     if (code == 0)
-                         cm_VolumeStateByID(volp, fidp->volume);
-                 }   
              }
          }   
          lock_ReleaseWrite(&cm_serverLock);
  
!         if (fidp && errorCode == VMOVED)
!             cm_ForceUpdateVolume(fidp, userp, reqp);
! 
!         if (statep) {
!             cm_UpdateVolumeStatus(volp, statep->ID);
!             lock_ObtainRead(&cm_volumeLock);
!             cm_PutVolume(volp);
!             lock_ReleaseRead(&cm_volumeLock);
!             volp = NULL;
!         }
! 
          if (free_svr_list) {
              cm_FreeServerList(&serversp, 0);
!             *serverspp = serversp;
          }
          if ( timeLeft > 2 )
              retry = 1;
      } else if ( errorCode == VNOVNODE ) {
--- 477,540 ----
          if (!serversp && fidp) {
              code = cm_GetServerList(fidp, userp, reqp, &serverspp);
              if (code == 0) {
!                 serversp = *serverspp = NULL;
                  free_svr_list = 1;
              }
          }
  
          lock_ObtainWrite(&cm_serverLock);
          for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+             if (tsrp->status == srv_deleted)
+                 continue;
              if (tsrp->server == serverp) {
                  /* REDIRECT */
!                 if (errorCode == VMOVED || errorCode == VNOVOL) {
                      tsrp->status = srv_deleted;
+                     if (fidp)
+                         cm_RemoveVolumeFromServer(serverp, fidp->volume);
                  } else {
                      tsrp->status = srv_offline;
                  }
              }
          }   
          lock_ReleaseWrite(&cm_serverLock);
  
!         /* Free the server list before cm_ForceUpdateVolume is called */
          if (free_svr_list) {
              cm_FreeServerList(&serversp, 0);
!             *serverspp = serversp = NULL;
!             free_svr_list = 0;
!         }
! 
!         if (fidp) { /* File Server query */
!             code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp, 
!                                       CM_GETVOL_FLAG_NO_LRU_UPDATE, 
!                                       &volp);
!             if (code == 0)
!                 statep = cm_VolumeStateByID(volp, fidp->volume);
! 
!             if (errorCode == VMOVED || errorCode == VNOVOL) {
!                 code = cm_ForceUpdateVolume(fidp, userp, reqp);
!                 if (code) 
!                     timeLeft = 0;   /* prevent a retry on failure */
!                 osi_Log3(afsd_logp, "cm_Analyze called cm_ForceUpdateVolume cell %u vol %u code 0x%x",
!                         fidp->cell, fidp->volume, code);
!             }
! 
!             if (statep) {
!                 cm_UpdateVolumeStatus(volp, statep->ID);
!                 osi_Log3(afsd_logp, "cm_Analyze NewVolState cell %u vol %u state %u", 
!                          fidp->cell, fidp->volume, statep->state);
!             }
! 
!             if (volp) {
!                 lock_ObtainRead(&cm_volumeLock);
!                 cm_PutVolume(volp);
!                 lock_ReleaseRead(&cm_volumeLock);
!                 volp = NULL;
!             }
          }
+ 
          if ( timeLeft > 2 )
              retry = 1;
      } else if ( errorCode == VNOVNODE ) {
***************
*** 609,614 ****
--- 635,653 ----
              reqp->tokenError = errorCode;
              retry = 1;
          }
+     } else if (errorCode >= ERROR_TABLE_BASE_U && errorCode < ERROR_TABLE_BASE_U + 256) {
+       /*
+        * We received a ubik error.  its possible that the server we are
+        * communicating with has a corrupted database or is partitioned
+        * from the rest of the servers and another server might be able
+        * to answer our query.  Therefore, we will retry the request
+        * and force the use of another server.
+        */
+       if (serverp) {
+ 	reqp->tokenIdleErrorServp = serverp;
+ 	reqp->tokenError = errorCode;
+ 	retry = 1;
+       }
      } else if (errorCode == VICECONNBAD || errorCode == VICETOKENDEAD) {
  	cm_ForceNewConnections(serverp);
          if ( timeLeft > 2 )
***************
*** 653,658 ****
--- 692,699 ----
  	    case UAEACCES 	   : s = "UAEACCES";           break;
  	    case ENOENT            : s = "ENOENT"; 	       break;
  	    case UAENOENT          : s = "UAENOENT";           break;
+             case EEXIST            : s = "EEXIST";             break;
+             case UAEEXIST          : s = "UAEEXIST";           break;
  	    case VICECONNBAD	   : s = "VICECONNBAD";	       break;
  	    case VICETOKENDEAD     : s = "VICETOKENDEAD";      break;
              case WSAEWOULDBLOCK    : s = "WSAEWOULDBLOCK";     break;
***************
*** 790,795 ****
--- 831,839 ----
  
      lock_ObtainRead(&cm_serverLock);
      for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
+ 
          tsp = tsrp->server;
          if (reqp->tokenIdleErrorServp) {
              /* 
***************
*** 807,815 ****
              lock_ReleaseRead(&cm_serverLock);
              if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                  allDown = 0;
!                 if (tsrp->status == srv_deleted) {
!                     /* skip this entry.  no longer valid. */;
!                 } else if (tsrp->status == srv_busy) {
                      allOffline = 0;
                      someBusy = 1;
                  } else if (tsrp->status == srv_offline) {
--- 851,857 ----
              lock_ReleaseRead(&cm_serverLock);
              if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                  allDown = 0;
!                 if (tsrp->status == srv_busy) {
                      allOffline = 0;
                      someBusy = 1;
                  } else if (tsrp->status == srv_offline) {
***************
*** 913,922 ****
      }
      if (ucellp->flags & CM_UCELLFLAG_RXKAD) {
          secIndex = 2;
!         if (cryptall) {
!             tcp->cryptlevel = rxkad_crypt;
!         } else {
              tcp->cryptlevel = rxkad_clear;
          }
          secObjp = rxkad_NewClientSecurityObject(tcp->cryptlevel,
                                                  &ucellp->sessionKey, ucellp->kvno,
--- 955,969 ----
      }
      if (ucellp->flags & CM_UCELLFLAG_RXKAD) {
          secIndex = 2;
!         switch (cryptall) {
!         case 0:
              tcp->cryptlevel = rxkad_clear;
+             break;
+         case 2:
+             tcp->cryptlevel = rxkad_auth;
+             break;
+         default:
+             tcp->cryptlevel = rxkad_crypt;
          }
          secObjp = rxkad_NewClientSecurityObject(tcp->cryptlevel,
                                                  &ucellp->sessionKey, ucellp->kvno,
***************
*** 977,983 ****
          serverp->connsp = tcp;
          cm_HoldUser(userp);
          tcp->userp = userp;
!         lock_InitializeMutex(&tcp->mx, "cm_conn_t mutex");
          lock_ObtainMutex(&tcp->mx);
          tcp->serverp = serverp;
          tcp->cryptlevel = rxkad_clear;
--- 1024,1030 ----
          serverp->connsp = tcp;
          cm_HoldUser(userp);
          tcp->userp = userp;
!         lock_InitializeMutex(&tcp->mx, "cm_conn_t mutex", LOCK_HIERARCHY_CONN);
          lock_ObtainMutex(&tcp->mx);
          tcp->serverp = serverp;
          tcp->cryptlevel = rxkad_clear;
***************
*** 993,999 ****
          lock_ObtainMutex(&tcp->mx);
          if ((tcp->flags & CM_CONN_FLAG_FORCE_NEW) ||
              (tcp->ucgen < ucellp->gen) ||
!             (tcp->cryptlevel != (cryptall ? (ucellp->flags & CM_UCELLFLAG_RXKAD ? rxkad_crypt : rxkad_clear) : rxkad_clear)))
          {
              if (tcp->ucgen < ucellp->gen)
                  osi_Log0(afsd_logp, "cm_ConnByServer replace connection due to token update");
--- 1040,1046 ----
          lock_ObtainMutex(&tcp->mx);
          if ((tcp->flags & CM_CONN_FLAG_FORCE_NEW) ||
              (tcp->ucgen < ucellp->gen) ||
!             (tcp->cryptlevel != (ucellp->flags & CM_UCELLFLAG_RXKAD ? (cryptall == 1 ? rxkad_crypt : (cryptall == 2 ? rxkad_auth : rxkad_clear)) : rxkad_clear)))
          {
              if (tcp->ucgen < ucellp->gen)
                  osi_Log0(afsd_logp, "cm_ConnByServer replace connection due to token update");
***************
*** 1031,1036 ****
--- 1078,1085 ----
  
      lock_ObtainRead(&cm_serverLock);
      for (tsrp = *serverspp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
          tsp = tsrp->server;
          if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
  	    allDown = 0;
***************
*** 1090,1096 ****
  
      *connpp = NULL;
  
!     serverspp = cm_GetVolServers(volp, volid);
  
      code = cm_ConnByMServers(*serverspp, userp, reqp, connpp);
      cm_FreeServerList(serverspp, 0);
--- 1139,1145 ----
  
      *connpp = NULL;
  
!     serverspp = cm_GetVolServers(volp, volid, userp, reqp);
  
      code = cm_ConnByMServers(*serverspp, userp, reqp, connpp);
      cm_FreeServerList(serverspp, 0);
Index: openafs/src/WINNT/afsd/cm_daemon.c
diff -c openafs/src/WINNT/afsd/cm_daemon.c:1.16.4.30 openafs/src/WINNT/afsd/cm_daemon.c:1.16.4.31
*** openafs/src/WINNT/afsd/cm_daemon.c:1.16.4.30	Fri Aug  8 12:46:35 2008
--- openafs/src/WINNT/afsd/cm_daemon.c	Fri Aug 22 14:10:01 2008
***************
*** 601,607 ****
      cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
      
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_daemonLock, "cm_daemonLock");
          osi_EndOnce(&once);
  
  	/* creating IP Address Change monitor daemon */
--- 601,608 ----
      cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
      
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_daemonLock, "cm_daemonLock", 
!                                LOCK_HIERARCHY_DAEMON_GLOBAL);
          osi_EndOnce(&once);
  
  	/* creating IP Address Change monitor daemon */
Index: openafs/src/WINNT/afsd/cm_dcache.c
diff -c openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.33 openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.34
*** openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.33	Tue Aug  5 11:46:38 2008
--- openafs/src/WINNT/afsd/cm_dcache.c	Fri Aug 22 14:10:01 2008
***************
*** 26,32 ****
  extern void afsi_log(char *pattern, ...);
  #endif
  
- osi_mutex_t cm_bufGetMutex;
  #ifdef AFS_FREELANCE_CLIENT
  extern osi_mutex_t cm_Freelance_Lock;
  #endif
--- 26,31 ----
***************
*** 483,489 ****
  
  int cm_InitDCache(int newFile, long chunkSize, afs_uint64 nbuffers)
  {
-     lock_InitializeMutex(&cm_bufGetMutex, "buf_Get mutex");
      return buf_Init(newFile, &cm_bufOps, nbuffers);
  }
  
--- 482,487 ----
***************
*** 1092,1098 ****
       * sequence at a time.
       */
  
-     // lock_ObtainMutex(&cm_bufGetMutex);
      /* first hold all buffers, since we can't hold any locks in buf_Get */
      while (1) {
          /* stop at chunk boundary */
--- 1090,1095 ----
***************
*** 1105,1111 ****
  
          code = buf_Get(scp, &pageBase, &tbp);
          if (code) {
-             //lock_ReleaseMutex(&cm_bufGetMutex);
              lock_ObtainWrite(&scp->rw);
              cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
              return code;
--- 1102,1107 ----
***************
*** 1121,1128 ****
      /* reserve a chunk's worth of buffers if possible */
      reserving = buf_TryReserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
  
-     // lock_ReleaseMutex(&cm_bufGetMutex);
- 
      pageBase = *offsetp;
      collected = pageBase.LowPart & (cm_chunkSize - 1);
  
--- 1117,1122 ----
Index: openafs/src/WINNT/afsd/cm_dir.c
diff -c openafs/src/WINNT/afsd/cm_dir.c:1.4.4.18 openafs/src/WINNT/afsd/cm_dir.c:1.4.4.20
*** openafs/src/WINNT/afsd/cm_dir.c:1.4.4.18	Fri Jul 11 18:27:01 2008
--- openafs/src/WINNT/afsd/cm_dir.c	Tue Sep 16 07:47:47 2008
***************
*** 98,104 ****
  cm_DirOpDelBuffer(cm_dirOp_t * op, cm_buf_t * buffer, int flags);
  
  static long
! cm_DirCheckStatus(cm_dirOp_t * op, afs_uint32 locked);
  
  static long
  cm_DirReleasePage(cm_dirOp_t * op, cm_buf_t ** bufferpp, int modified);
--- 98,104 ----
  cm_DirOpDelBuffer(cm_dirOp_t * op, cm_buf_t * buffer, int flags);
  
  static long
! cm_DirCheckStatus(cm_dirOp_t * op, int locked);
  
  static long
  cm_DirReleasePage(cm_dirOp_t * op, cm_buf_t ** bufferpp, int modified);
***************
*** 116,121 ****
--- 116,123 ----
  static long
  cm_DirFreeBlobs(cm_dirOp_t * op, int firstblob, int nblobs);
  
+ static long
+ cm_DirPrefetchBuffers(cm_dirOp_t * op);
  
  /* compute how many 32 byte entries an AFS 3 dir requires for storing
   * the specified name.
***************
*** 393,398 ****
--- 395,403 ----
                  dhpModified = TRUE;
  	    }
  
+             /* the create flag is not set for the GetPage call below
+                since the page should have been added if necessary
+                above. */
              code = cm_DirGetPage(op, i, &pagebuf, &pp);
              if (code) {
                  cm_DirReleasePage(op, &dhpbuf, dhpModified);
***************
*** 603,608 ****
--- 608,621 ----
      code = cm_DirFindItem(op, entry,
                            &itembuf, &firstitem,
                            &pibuf, &previtem);
+ 
+     if (code == CM_ERROR_NOTINCACHE) {
+         code = cm_DirPrefetchBuffers(op);
+         if (code == 0)
+             code = cm_DirFindItem(op, entry, &itembuf, &firstitem,
+                                   &pibuf, &previtem);
+     }
+ 
      if (code != 0) {
          dir_lookup_misses++;
          code = ENOENT;
***************
*** 1121,1127 ****
  }
  
  /* Check if it is safe for us to perform local directory updates.
!    Called with scp->rw unlocked. */
  int
  cm_CheckDirOpForSingleChange(cm_dirOp_t * op)
  {
--- 1134,1140 ----
  }
  
  /* Check if it is safe for us to perform local directory updates.
!    Called with op->scp->rw unlocked. */
  int
  cm_CheckDirOpForSingleChange(cm_dirOp_t * op)
  {
***************
*** 1194,1199 ****
--- 1207,1213 ----
           * and update the dataVersion for each. */
          lock_ObtainWrite(&op->scp->rw);
          code = buf_ForceDataVersion(op->scp, op->dataVersion, op->newDataVersion);
+         op->scp->flags |= CM_SCACHEFLAG_LOCAL;
          lock_ReleaseWrite(&op->scp->rw);
      }
  
***************
*** 1271,1285 ****
                           CM_SCACHESYNC_BUFLOCKED);
  
          if (code == 0 && bufferp->dataVersion != op->dataVersion) {
!             osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %d. needs %d", 
!                      bufferp->dataVersion, op->dataVersion);
  
!             cm_SyncOpDone(op->scp, bufferp,
!                           CM_SCACHESYNC_NEEDCALLBACK |
!                          (op->lockType == CM_DIRLOCK_WRITE ? CM_SCACHESYNC_WRITE : CM_SCACHESYNC_READ) |
!                           CM_SCACHESYNC_BUFLOCKED);
! 
!             code = CM_ERROR_INVAL;
          }
  
          lock_ReleaseWrite(&op->scp->rw);
--- 1285,1300 ----
                           CM_SCACHESYNC_BUFLOCKED);
  
          if (code == 0 && bufferp->dataVersion != op->dataVersion) {
!                 osi_Log2(afsd_logp,
!                          "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %d. needs %d", 
!                          bufferp->dataVersion, op->dataVersion);
! 
!                 cm_SyncOpDone(op->scp, bufferp,
!                               CM_SCACHESYNC_NEEDCALLBACK |
!                               (op->lockType == CM_DIRLOCK_WRITE ? CM_SCACHESYNC_WRITE : CM_SCACHESYNC_READ) |
!                               CM_SCACHESYNC_BUFLOCKED);
  
!             code = CM_ERROR_NOTINCACHE;
          }
  
          lock_ReleaseWrite(&op->scp->rw);
***************
*** 1441,1455 ****
       scp->rw may be released
   */
  static long
! cm_DirCheckStatus(cm_dirOp_t * op, afs_uint32 locked)
  {
      long code;
  
!     if (!locked)
          lock_ObtainWrite(&op->scp->rw);
      code = cm_SyncOp(op->scp, NULL, op->userp, &op->req, PRSFS_LOOKUP,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
!     if (!locked)
          lock_ReleaseWrite(&op->scp->rw);
  
      osi_Log2(afsd_logp, "cm_DirCheckStatus for op 0x%p returning code 0x%x",
--- 1456,1470 ----
       scp->rw may be released
   */
  static long
! cm_DirCheckStatus(cm_dirOp_t * op, int scp_locked)
  {
      long code;
  
!     if (!scp_locked)
          lock_ObtainWrite(&op->scp->rw);
      code = cm_SyncOp(op->scp, NULL, op->userp, &op->req, PRSFS_LOOKUP,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
!     if (!scp_locked)
          lock_ReleaseWrite(&op->scp->rw);
  
      osi_Log2(afsd_logp, "cm_DirCheckStatus for op 0x%p returning code 0x%x",
***************
*** 1458,1463 ****
--- 1473,1564 ----
      return code;
  }
  
+ /* Attempt to prefetch all the buffers for this operation.
+ 
+    Called with scp->rw unlocked
+  */
+ static long
+ cm_DirPrefetchBuffers(cm_dirOp_t * op)
+ {
+     long code = 0;
+     osi_hyper_t offset;
+     cm_buf_t *bufferp = NULL;
+ 
+     osi_Log1(afsd_logp, "cm_DirPrefetchBuffers for op 0x%p", op);
+ 
+     /* prefetching is only done on read operations where we don't
+        expect the data version to change. */
+     if (op->dataVersion != op->newDataVersion) {
+         osi_Log0(afsd_logp, "Skipping prefetch for write operation.");
+         return CM_ERROR_INVAL;
+     }
+ 
+     lock_ObtainWrite(&op->scp->rw);
+ 
+     /* When we are prefetching a file, we first flush out any of its
+        contents just to make sure that we don't end up with buffers
+        that was locally modified. */
+ 
+     if (op->scp->flags & CM_SCACHEFLAG_LOCAL) {
+         lock_ReleaseWrite(&op->scp->rw);
+         code = cm_FlushFile(op->scp, op->userp, &op->req);
+         if (code != 0)
+             return code;
+         lock_ObtainWrite(&op->scp->rw);
+     }
+ 
+     offset = ConvertLongToLargeInteger(0);
+     while (LargeIntegerLessThan(offset, op->scp->length)) {
+         osi_Log2(afsd_logp, "Trying prefetch for offset %08x:%08x",
+                  offset.HighPart, offset.LowPart);
+         lock_ReleaseWrite(&op->scp->rw);
+ 
+         code = buf_Get(op->scp, &offset, &bufferp);
+ 
+         lock_ObtainWrite(&op->scp->rw);
+ 
+         if (code)
+             break;
+ 
+         while (1) {
+ 
+             code = cm_SyncOp(op->scp, bufferp, op->userp, &op->req, PRSFS_LOOKUP,
+                              CM_SCACHESYNC_NEEDCALLBACK |
+                              (op->lockType == CM_DIRLOCK_WRITE ? CM_SCACHESYNC_WRITE : CM_SCACHESYNC_READ));
+ 
+             if (code)
+                 break;
+ 
+             cm_SyncOpDone(op->scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK |
+                           (op->lockType == CM_DIRLOCK_WRITE ? CM_SCACHESYNC_WRITE : CM_SCACHESYNC_READ));
+ 
+             if (cm_HaveBuffer(op->scp, bufferp, 0))
+                 break;
+ 
+             code = cm_GetBuffer(op->scp, bufferp, NULL, op->userp, &op->req);
+             if (code)
+                 break;
+         }
+ 
+         if (code)
+             break;
+ 
+         if (bufferp) {
+             buf_Release(bufferp);
+             bufferp = NULL;
+         }
+ 
+         offset = LargeIntegerAdd(offset, ConvertLongToLargeInteger(cm_data.buf_blockSize));
+     }
+ 
+  done:
+     lock_ReleaseWrite(&op->scp->rw);
+ 
+     osi_Log1(afsd_logp, "cm_DirPrefetchBuffers returning code 0x%x", code);
+ 
+     return code;
+ }
+ 
  /* Release a directory buffer that was obtained via a call to
     cm_DirGetPage() or any other function that returns a locked, held,
     directory page buffer.
***************
*** 1497,1502 ****
--- 1598,1606 ----
     released and a new buffer returned that contains the requested
     page.
  
+    If the specified page exists beyond the EOF for the scp, a new
+    buffer will be allocated only if create is set to TRUE.
+ 
     Note: If a buffer is specified on entry via bufferpp, it is assumed
     that the buffer is unmodified.  If the buffer is modified, it
     should be released via cm_DirReleasePage().
***************
*** 1577,1626 ****
              bufferp = NULL;
              goto _exit;
          }
- 
- #if 0
-         /* The code below is for making sure the buffer contains
-            current data.  This is a bad idea, since the whole point of
-            doing directory updates locally is to avoid fetching all
-            the data from the server. */
-         while (1) {
-             lock_ObtainWrite(&op->scp->rw);
-             code = cm_SyncOp(op->scp, bufferp, op->userp, &op->req, PRSFS_LOOKUP,
-                              CM_SCACHESYNC_NEEDCALLBACK |
-                              CM_SCACHESYNC_READ |
-                              CM_SCACHESYNC_BUFLOCKED);
- 
-             if (code) {
-                 lock_ReleaseWrite(&op->scp->rw);
-                 break;
-             }
- 
-             cm_SyncOpDone(op->scp, bufferp,
-                           CM_SCACHESYNC_NEEDCALLBACK |
-                           CM_SCACHESYNC_READ |
-                           CM_SCACHESYNC_BUFLOCKED);
- 
-             if (cm_HaveBuffer(op->scp, bufferp, 1)) {
-                 lock_ReleaseWrite(&op->scp->rw);
-                 break;
-             }
- 
-             lock_ReleaseMutex(&bufferp->mx);
-             code = cm_GetBuffer(op->scp, bufferp, NULL, op->userp, &op->req);
-             lock_ReleaseWrite(&op->scp->rw);
-             lock_ObtainMutex(&bufferp->mx);
- 
-             if (code)
-                 break;
-         }
- 
-         if (code) {
-             cm_DirOpDelBuffer(op, bufferp, 0);
-             buf_Release(bufferp);
-             bufferp = NULL;
-             goto _exit;
-         }
- #endif
      }
  
   _has_buffer:
--- 1681,1686 ----
Index: openafs/src/WINNT/afsd/cm_dnlc.c
diff -c openafs/src/WINNT/afsd/cm_dnlc.c:1.10.4.9 openafs/src/WINNT/afsd/cm_dnlc.c:1.10.4.10
*** openafs/src/WINNT/afsd/cm_dnlc.c:1.10.4.9	Thu Jun 26 12:38:29 2008
--- openafs/src/WINNT/afsd/cm_dnlc.c	Fri Aug 22 14:10:01 2008
***************
*** 672,678 ****
  
      memset (&dnlcstats, 0, sizeof(dnlcstats));
  
!     lock_InitializeRWLock(&cm_dnlcLock, "cm_dnlcLock");
      if ( newFile ) {
          lock_ObtainWrite(&cm_dnlcLock);
          cm_data.ncfreelist = (cm_nc_t *) 0;
--- 672,678 ----
  
      memset (&dnlcstats, 0, sizeof(dnlcstats));
  
!     lock_InitializeRWLock(&cm_dnlcLock, "cm_dnlcLock", LOCK_HIERARCHY_DNLC_GLOBAL);
      if ( newFile ) {
          lock_ObtainWrite(&cm_dnlcLock);
          cm_data.ncfreelist = (cm_nc_t *) 0;
Index: openafs/src/WINNT/afsd/cm_freelance.c
diff -c openafs/src/WINNT/afsd/cm_freelance.c:1.33.2.16 openafs/src/WINNT/afsd/cm_freelance.c:1.33.2.17
*** openafs/src/WINNT/afsd/cm_freelance.c:1.33.2.16	Fri Aug 15 16:19:06 2008
--- openafs/src/WINNT/afsd/cm_freelance.c	Fri Aug 22 14:10:01 2008
***************
*** 139,145 ****
      thread_t phandle;
      int lpid;
  
!     lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
  
      // yj: first we make a call to cm_initLocalMountPoints
      // to read all the local mount points from the registry
--- 139,145 ----
      thread_t phandle;
      int lpid;
  
!     lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
  
      // yj: first we make a call to cm_initLocalMountPoints
      // to read all the local mount points from the registry
***************
*** 391,397 ****
              if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
                  // mark the scp to be reused
                  cm_HoldSCacheNoLock(scp);
!                 lock_ReleaseWrite(&cm_Freelance_Lock);
                  lock_ReleaseWrite(&cm_scacheLock);
                  lock_ObtainWrite(&scp->rw);
                  cm_DiscardSCache(scp);
--- 391,397 ----
              if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
                  // mark the scp to be reused
                  cm_HoldSCacheNoLock(scp);
!                 lock_ReleaseMutex(&cm_Freelance_Lock);
                  lock_ReleaseWrite(&cm_scacheLock);
                  lock_ObtainWrite(&scp->rw);
                  cm_DiscardSCache(scp);
Index: openafs/src/WINNT/afsd/cm_ioctl.c
diff -c openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.55 openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.62
*** openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.55	Mon Aug 11 19:56:14 2008
--- openafs/src/WINNT/afsd/cm_ioctl.c	Wed Sep 24 18:58:32 2008
***************
*** 60,66 ****
  
  void cm_InitIoctl(void)
  {
!     lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
  }
  
  /* 
--- 60,67 ----
  
  void cm_InitIoctl(void)
  {
!     lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock",
!                           LOCK_HIERARCHY_AFSDBSBMT_GLOBAL);
  }
  
  /* 
***************
*** 103,108 ****
--- 104,111 ----
          
      lock_ObtainWrite(&scp->rw);
      cm_DiscardSCache(scp);
+     if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
+         cm_ResetSCacheDirectory(scp);
      lock_ReleaseWrite(&scp->rw);
  
      osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
***************
*** 905,911 ****
  afs_int32 
  cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
  {
!     afs_int32 code;
      cm_cell_t *cellp;
      cm_volume_t *tvp;
      cm_serverRef_t **tsrpp, *current;
--- 908,914 ----
  afs_int32 
  cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
  {
!     afs_int32 code = 0;
      cm_cell_t *cellp;
      cm_volume_t *tvp;
      cm_serverRef_t **tsrpp, *current;
***************
*** 949,964 ****
  	
          cp = ioctlp->outDatap;
          
!         tsrpp = cm_GetVolServers(tvp, volume);
!         lock_ObtainRead(&cm_serverLock);
!         for (current = *tsrpp; current; current = current->next) {
!             tsp = current->server;
!             memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
!             cp += sizeof(long);
          }
-         lock_ReleaseRead(&cm_serverLock);
-         cm_FreeServerList(tsrpp, 0);
- 
          /* still room for terminating NULL, add it on */
          volume = 0;	/* reuse vbl */
          memcpy(cp, (char *)&volume, sizeof(long));
--- 952,970 ----
  	
          cp = ioctlp->outDatap;
          
!         tsrpp = cm_GetVolServers(tvp, volume, userp, reqp);
!         if (tsrpp == NULL) {
!             code = CM_ERROR_NOSUCHVOLUME;
!         } else {
!             lock_ObtainRead(&cm_serverLock);
!             for (current = *tsrpp; current; current = current->next) {
!                 tsp = current->server;
!                 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
!                 cp += sizeof(long);
!             }
!             lock_ReleaseRead(&cm_serverLock);
!             cm_FreeServerList(tsrpp, 0);
          }
          /* still room for terminating NULL, add it on */
          volume = 0;	/* reuse vbl */
          memcpy(cp, (char *)&volume, sizeof(long));
***************
*** 967,973 ****
          ioctlp->outDatap = cp;
          cm_PutVolume(tvp);
      }
!     return 0;
  }       
  
  /* 
--- 973,979 ----
          ioctlp->outDatap = cp;
          cm_PutVolume(tvp);
      }
!     return code;
  }       
  
  /* 
***************
*** 984,990 ****
      clientchar_t *cp;
  
      cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
!     code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      if (code) 
          goto done_2;
  
--- 990,997 ----
      clientchar_t *cp;
  
      cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
! 
!     code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      if (code) 
          goto done_2;
  
***************
*** 1039,1045 ****
  
      cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
  
!     code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
          
      /* if something went wrong, bail out now */
      if (code)
--- 1046,1052 ----
  
      cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
  
!     code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
          
      /* if something went wrong, bail out now */
      if (code)
***************
*** 1406,1415 ****
      for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) 
      {
          afs_int32 code;
! 	lock_ObtainMutex(&cp->mx);
          /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
          cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
          cp->vlServersp = NULL;
          rock.cellp = cp;
          rock.flags = 0;
          code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
--- 1413,1424 ----
      for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) 
      {
          afs_int32 code;
! 
          /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
          cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
          cp->vlServersp = NULL;
+         lock_ReleaseWrite(&cm_cellLock);
+ 
          rock.cellp = cp;
          rock.flags = 0;
          code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
***************
*** 1419,1444 ****
                  int ttl;
                  code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
                  if ( code == 0 ) { /* got cell from DNS */
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                      cp->timeout = time(0) + ttl;
                  }
              }
          } 
          else {
              cp->flags &= ~CM_CELLFLAG_DNS;
          }
  #endif /* AFS_AFSDB_ENV */
          if (code) {
              cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
          }
          else {
              cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
              cm_RandomizeServer(&cp->vlServersp);
          }
- 	lock_ReleaseMutex(&cp->mx);
      }
-     
      lock_ReleaseWrite(&cm_cellLock);
      return 0;       
  }
--- 1428,1461 ----
                  int ttl;
                  code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
                  if ( code == 0 ) { /* got cell from DNS */
+                     lock_ObtainMutex(&cp->mx);
                      cp->flags |= CM_CELLFLAG_DNS;
                      cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                      cp->timeout = time(0) + ttl;
+                     lock_ReleaseMutex(&cp->mx);
                  }
              }
          } 
          else {
+             lock_ObtainMutex(&cp->mx);
              cp->flags &= ~CM_CELLFLAG_DNS;
+             lock_ReleaseMutex(&cp->mx);
          }
  #endif /* AFS_AFSDB_ENV */
          if (code) {
+             lock_ObtainMutex(&cp->mx);
              cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+             lock_ReleaseMutex(&cp->mx);
+             lock_ObtainWrite(&cm_cellLock);
          }
          else {
+             lock_ObtainMutex(&cp->mx);
              cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
+             lock_ReleaseMutex(&cp->mx);
+             lock_ObtainWrite(&cm_cellLock);
              cm_RandomizeServer(&cp->vlServersp);
          }
      }
      lock_ReleaseWrite(&cm_cellLock);
      return 0;       
  }
***************
*** 1943,1949 ****
      cp = ioctlp->inDatap;
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      free(clientp);
      if (code) 
          return code;
--- 1960,1966 ----
      cp = ioctlp->inDatap;
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      free(clientp);
      if (code) 
          return code;
***************
*** 1959,1974 ****
      code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, reqp);
      cm_ReleaseSCache(scp);
      if (code == 0) {
          cp = ioctlp->outDatap;
          if (newRootScp != NULL) {
              StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
              StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
              cp += strlen(cp);
          }
!         StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
          cp += strlen(cp) + 1;
          ioctlp->outDatap = cp;
          cm_FreeSpace(spacep);
          if (newRootScp != NULL)
              cm_ReleaseSCache(newRootScp);
          code = 0;
--- 1976,1995 ----
      code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, reqp);
      cm_ReleaseSCache(scp);
      if (code == 0) {
+         char * linkstr;
          cp = ioctlp->outDatap;
          if (newRootScp != NULL) {
              StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
              StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
              cp += strlen(cp);
          }
! 
!         linkstr = cm_ClientStringToFsStringAlloc(spacep->wdata, -1, NULL);
!         StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), linkstr);
          cp += strlen(cp) + 1;
          ioctlp->outDatap = cp;
          cm_FreeSpace(spacep);
+         free(linkstr);
          if (newRootScp != NULL)
              cm_ReleaseSCache(newRootScp);
          code = 0;
***************
*** 2009,2015 ****
      osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      free(clientp);
      if (code)
          return code;
--- 2030,2036 ----
      osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
      free(clientp);
      if (code)
          return code;
***************
*** 2046,2052 ****
      cp = ioctlp->inDatap;
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
  
      /* if something went wrong, bail out now */
      if (code)
--- 2067,2073 ----
      cp = ioctlp->inDatap;
  
      clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
!     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
  
      /* if something went wrong, bail out now */
      if (code)
***************
*** 2807,2814 ****
      memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
  
      if (c != cryptall) {
! 	if (cryptall)
              LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
  	else
              LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
      }
--- 2828,2837 ----
      memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
  
      if (c != cryptall) {
! 	if (cryptall == 1)
              LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+ 	else if (cryptall == 2)
+             LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_AUTH);
  	else
              LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
      }
***************
*** 3029,3034 ****
--- 3052,3059 ----
  
      lock_ObtainRead(&cm_serverLock);
      for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
          if (tsp = tsrp->server) {
              cm_GetServerNoLock(tsp);
              lock_ReleaseRead(&cm_serverLock);
Index: openafs/src/WINNT/afsd/cm_memmap.h
diff -c openafs/src/WINNT/afsd/cm_memmap.h:1.3.4.11 openafs/src/WINNT/afsd/cm_memmap.h:1.3.4.13
*** openafs/src/WINNT/afsd/cm_memmap.h:1.3.4.11	Mon Apr 21 11:36:49 2008
--- openafs/src/WINNT/afsd/cm_memmap.h	Tue Sep 16 07:47:47 2008
***************
*** 10,16 ****
  #ifndef CM_MEMMAP_H
  #define CM_MEMMAP_H 1
  
! #define CM_CONFIG_DATA_VERSION  3
  #define CM_CONFIG_DATA_MAGIC            ('A' | 'F'<<8 | 'S'<<16 | CM_CONFIG_DATA_VERSION<<24)
  
  typedef struct cm_config_data {
--- 10,16 ----
  #ifndef CM_MEMMAP_H
  #define CM_MEMMAP_H 1
  
! #define CM_CONFIG_DATA_VERSION  5
  #define CM_CONFIG_DATA_MAGIC            ('A' | 'F'<<8 | 'S'<<16 | CM_CONFIG_DATA_VERSION<<24)
  
  typedef struct cm_config_data {
***************
*** 39,44 ****
--- 39,45 ----
      afs_uint32          maxVolumes;
  
      cm_cell_t	*       allCellsp;
+     cm_cell_t   *       freeCellsp;
      afs_uint32          currentCells;
      afs_uint32          maxCells;
  
Index: openafs/src/WINNT/afsd/cm_rpc.c
diff -c openafs/src/WINNT/afsd/cm_rpc.c:1.7.8.1 openafs/src/WINNT/afsd/cm_rpc.c:1.7.8.2
*** openafs/src/WINNT/afsd/cm_rpc.c:1.7.8.1	Thu Jun 26 10:38:24 2008
--- openafs/src/WINNT/afsd/cm_rpc.c	Fri Aug 22 14:10:01 2008
***************
*** 209,215 ****
      ULONG listenThreadID = 0;
      char * name = "afsd_rpc_ShutdownEvent";
  
!     lock_InitializeMutex(&tokenEventLock, "token event lock");
  
      rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
      if ( GetLastError() == ERROR_ALREADY_EXISTS )
--- 209,216 ----
      ULONG listenThreadID = 0;
      char * name = "afsd_rpc_ShutdownEvent";
  
!     lock_InitializeMutex(&tokenEventLock, "token event lock",
!                           LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL);
  
      rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
      if ( GetLastError() == ERROR_ALREADY_EXISTS )
Index: openafs/src/WINNT/afsd/cm_scache.c
diff -c openafs/src/WINNT/afsd/cm_scache.c:1.35.2.84 openafs/src/WINNT/afsd/cm_scache.c:1.35.2.89
*** openafs/src/WINNT/afsd/cm_scache.c:1.35.2.84	Thu Aug 14 16:21:27 2008
--- openafs/src/WINNT/afsd/cm_scache.c	Tue Sep 16 07:47:47 2008
***************
*** 75,84 ****
      }
  }
  
! /* called with cm_scacheLock write-locked; recycles an existing scp. 
!  *
!  * this function ignores all of the locking hierarchy.  
!  */
  long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
  {
      if (scp->refCount != 0) {
--- 75,99 ----
      }
  }
  
! /* called with cm_scacheLock and scp write-locked */
! void cm_ResetSCacheDirectory(cm_scache_t *scp)
! {
! #ifdef USE_BPLUS
!     /* destroy directory Bplus Tree */
!     if (scp->dirBplus) {
!         LARGE_INTEGER start, end;
!         QueryPerformanceCounter(&start);
!         bplus_free_tree++;
!         freeBtree(scp->dirBplus);
!         scp->dirBplus = NULL;
!         QueryPerformanceCounter(&end);
! 
!         bplus_free_time += (end.QuadPart - start.QuadPart);
!     }
! #endif
! }
! 
! /* called with cm_scacheLock and scp write-locked; recycles an existing scp. */
  long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
  {
      if (scp->refCount != 0) {
***************
*** 93,101 ****
  	return -1;
      }
  
-     lock_ObtainWrite(&scp->rw);
      cm_RemoveSCacheFromHashTable(scp);
-     lock_ReleaseWrite(&scp->rw);
  
  #if 0
      if (flags & CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS) {
--- 108,114 ----
***************
*** 209,233 ****
       */
      cm_FreeAllACLEnts(scp);
  
! #ifdef USE_BPLUS
!     /* destroy directory Bplus Tree */
!     if (scp->dirBplus) {
!         LARGE_INTEGER start, end;
!         QueryPerformanceCounter(&start);
!         bplus_free_tree++;
!         freeBtree(scp->dirBplus);
!         scp->dirBplus = NULL;
!         QueryPerformanceCounter(&end);
! 
!         bplus_free_time += (end.QuadPart - start.QuadPart);
!     }
! #endif
      return 0;
  }
  
  
! /* called with cm_scacheLock write-locked; find a vnode to recycle.
   * Can allocate a new one if desperate, or if below quota (cm_data.maxSCaches).
   */
  cm_scache_t *cm_GetNewSCache(void)
  {
--- 222,236 ----
       */
      cm_FreeAllACLEnts(scp);
  
!     cm_ResetSCacheDirectory(scp);
      return 0;
  }
  
  
! /* 
!  * called with cm_scacheLock write-locked; find a vnode to recycle.
   * Can allocate a new one if desperate, or if below quota (cm_data.maxSCaches).
+  * returns scp->mx held.
   */
  cm_scache_t *cm_GetNewSCache(void)
  {
***************
*** 246,251 ****
--- 249,257 ----
  
  	if (scp->refCount == 0) {
  	    if (scp->flags & CM_SCACHEFLAG_DELETED) {
+                 if (!lock_TryWrite(&scp->rw))
+                     continue;
+ 
  		osi_Log1(afsd_logp, "GetNewSCache attempting to recycle deleted scp 0x%x", scp);
  		if (!cm_RecycleSCache(scp, CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS)) {
  
***************
*** 258,265 ****
--- 264,275 ----
  		    /* and we're done */
  		    return scp;
  		} 
+                 lock_ReleaseWrite(&scp->rw);
  		osi_Log1(afsd_logp, "GetNewSCache recycled failed scp 0x%x", scp);
  	    } else if (!(scp->flags & CM_SCACHEFLAG_INHASH)) {
+                 if (!lock_TryWrite(&scp->rw))
+                     continue;
+ 
  		/* we found an entry, so return it */
  		/* now remove from the LRU queue and put it back at the
  		* head of the LRU queue.
***************
*** 287,292 ****
--- 297,305 ----
               * we must not recycle the scp. */
              if (scp->refCount == 0 && scp->bufReadsp == NULL && scp->bufWritesp == NULL) {
                  if (!buf_DirtyBuffersExist(&scp->fid)) {
+                     if (!lock_TryWrite(&scp->rw))
+                         continue;
+ 
                      if (!cm_RecycleSCache(scp, 0)) {
                          /* we found an entry, so return it */
                          /* now remove from the LRU queue and put it back at the
***************
*** 297,302 ****
--- 310,316 ----
                          /* and we're done */
                          return scp;
                      }
+                     lock_ReleaseWrite(&scp->rw);
                  } else {
                      osi_Log1(afsd_logp,"GetNewSCache dirty buffers exist scp 0x%x", scp);
                  }
***************
*** 315,324 ****
                  "invalid cm_scache_t address");
      memset(scp, 0, sizeof(cm_scache_t));
      scp->magic = CM_SCACHE_MAGIC;
!     lock_InitializeRWLock(&scp->rw, "cm_scache_t rw");
!     lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock");
  #ifdef USE_BPLUS
!     lock_InitializeRWLock(&scp->dirlock, "cm_scache_t dirlock");
  #endif
      scp->serverLock = -1;
  
--- 329,339 ----
                  "invalid cm_scache_t address");
      memset(scp, 0, sizeof(cm_scache_t));
      scp->magic = CM_SCACHE_MAGIC;
!     lock_InitializeRWLock(&scp->rw, "cm_scache_t rw", LOCK_HIERARCHY_SCACHE);
!     osi_assertx(lock_TryWrite(&scp->rw), "cm_scache_t rw held after allocation");
!     lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock", LOCK_HIERARCHY_SCACHE_BUFCREATE);
  #ifdef USE_BPLUS
!     lock_InitializeRWLock(&scp->dirlock, "cm_scache_t dirlock", LOCK_HIERARCHY_SCACHE_DIRLOCK);
  #endif
      scp->serverLock = -1;
  
***************
*** 371,377 ****
          cm_data.fakeSCache.linkCount = 1;
          cm_data.fakeSCache.refCount = 1;
      }
!     lock_InitializeRWLock(&cm_data.fakeSCache.rw, "cm_scache_t rw");
  }
  
  long
--- 386,392 ----
          cm_data.fakeSCache.linkCount = 1;
          cm_data.fakeSCache.refCount = 1;
      }
!     lock_InitializeRWLock(&cm_data.fakeSCache.rw, "cm_scache_t rw", LOCK_HIERARCHY_SCACHE);
  }
  
  long
***************
*** 523,529 ****
--- 538,546 ----
      for ( scp = cm_data.allSCachesp; scp;
            scp = scp->allNextp ) {
          if (scp->randomACLp) {
+             lock_ReleaseWrite(&cm_scacheLock);
              lock_ObtainWrite(&scp->rw);
+             lock_ObtainWrite(&cm_scacheLock);
              cm_FreeAllACLEnts(scp);
              lock_ReleaseWrite(&scp->rw);
          }
***************
*** 557,563 ****
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock");
          if ( newFile ) {
              memset(cm_data.scacheHashTablep, 0, sizeof(cm_scache_t *) * cm_data.scacheHashTableSize);
              cm_data.allSCachesp = NULL;
--- 574,580 ----
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock", LOCK_HIERARCHY_SCACHE_GLOBAL);
          if ( newFile ) {
              memset(cm_data.scacheHashTablep, 0, sizeof(cm_scache_t *) * cm_data.scacheHashTableSize);
              cm_data.allSCachesp = NULL;
***************
*** 569,578 ****
  
              for ( scp = cm_data.allSCachesp; scp;
                    scp = scp->allNextp ) {
!                 lock_InitializeRWLock(&scp->rw, "cm_scache_t rw");
!                 lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock");
  #ifdef USE_BPLUS
!                 lock_InitializeRWLock(&scp->dirlock, "cm_scache_t dirlock");
  #endif
                  scp->cbServerp = NULL;
                  scp->cbExpires = 0;
--- 586,595 ----
  
              for ( scp = cm_data.allSCachesp; scp;
                    scp = scp->allNextp ) {
!                 lock_InitializeRWLock(&scp->rw, "cm_scache_t rw", LOCK_HIERARCHY_SCACHE);
!                 lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock", LOCK_HIERARCHY_SCACHE_BUFCREATE);
  #ifdef USE_BPLUS
!                 lock_InitializeRWLock(&scp->dirlock, "cm_scache_t dirlock", LOCK_HIERARCHY_SCACHE_DIRLOCK);
  #endif
                  scp->cbServerp = NULL;
                  scp->cbExpires = 0;
***************
*** 667,674 ****
      for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
          if (cm_FidCmp(fidp, &scp->fid) == 0) {
  #ifdef DEBUG_REFCOUNT
! 	    afsi_log("%s:%d cm_GetSCache (1) outScpp 0x%p ref %d", file, line, scp, scp->refCount);
! 	    osi_Log1(afsd_logp,"cm_GetSCache (1) outScpp 0x%p", scp);
  #endif
  #ifdef AFS_FREELANCE_CLIENT
              if (cm_freelanceEnabled && special && 
--- 684,691 ----
      for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
          if (cm_FidCmp(fidp, &scp->fid) == 0) {
  #ifdef DEBUG_REFCOUNT
! 	    afsi_log("%s:%d cm_GetSCache (1) scp 0x%p ref %d", file, line, scp, scp->refCount);
! 	    osi_Log1(afsd_logp,"cm_GetSCache (1) scp 0x%p", scp);
  #endif
  #ifdef AFS_FREELANCE_CLIENT
              if (cm_freelanceEnabled && special && 
***************
*** 726,749 ****
          }
          lock_ReleaseMutex(&cm_Freelance_Lock);
          lock_ObtainWrite(&cm_scacheLock);
!         if (scp == NULL)
!             scp = cm_GetNewSCache();
! 	if (scp == NULL) {
! 	    osi_Log0(afsd_logp,"cm_GetSCache unable to obtain *new* scache entry");
              lock_ReleaseWrite(&cm_scacheLock);
! 	    return CM_ERROR_WOULDBLOCK;
! 	}
! 
! #if not_too_dangerous
! 	/* dropping the cm_scacheLock allows more than one thread
! 	 * to obtain the same cm_scache_t from the LRU list.  Since
! 	 * the refCount is known to be zero at this point we have to
! 	 * assume that no one else is using the one this is returned.
! 	 */
! 	lock_ReleaseWrite(&cm_scacheLock);
! 	lock_ObtainWrite(&scp->rw);
! 	lock_ObtainWrite(&cm_scacheLock);
! #endif
          scp->fid = *fidp;
          scp->dotdotFid.cell=AFS_FAKE_ROOT_CELL_ID;
          scp->dotdotFid.volume=AFS_FAKE_ROOT_VOL_ID;
--- 743,760 ----
          }
          lock_ReleaseMutex(&cm_Freelance_Lock);
          lock_ObtainWrite(&cm_scacheLock);
!         if (scp == NULL) {
!             scp = cm_GetNewSCache();    /* returns scp->rw held */
!             if (scp == NULL) {
!                 osi_Log0(afsd_logp,"cm_GetSCache unable to obtain *new* scache entry");
!                 lock_ReleaseWrite(&cm_scacheLock);
!                 return CM_ERROR_WOULDBLOCK;
!             }
!         } else {
              lock_ReleaseWrite(&cm_scacheLock);
!             lock_ObtainWrite(&scp->rw);
!             lock_ObtainWrite(&cm_scacheLock);
!         }
          scp->fid = *fidp;
          scp->dotdotFid.cell=AFS_FAKE_ROOT_CELL_ID;
          scp->dotdotFid.volume=AFS_FAKE_ROOT_VOL_ID;
***************
*** 771,784 ****
          scp->dataVersion=cm_data.fakeDirVersion;
          scp->bufDataVersionLow=cm_data.fakeDirVersion;
          scp->lockDataVersion=-1; /* no lock yet */
! #if not_too_dangerous
! 	lock_ReleaseWrite(&scp->rw);
! #endif
! 	*outScpp = scp;
          lock_ReleaseWrite(&cm_scacheLock);
  #ifdef DEBUG_REFCOUNT
! 	afsi_log("%s:%d cm_GetSCache (2) outScpp 0x%p ref %d", file, line, scp, scp->refCount);
! 	osi_Log1(afsd_logp,"cm_GetSCache (2) outScpp 0x%p", scp);
  #endif
          return 0;
      }
--- 782,793 ----
          scp->dataVersion=cm_data.fakeDirVersion;
          scp->bufDataVersionLow=cm_data.fakeDirVersion;
          scp->lockDataVersion=-1; /* no lock yet */
!         lock_ReleaseWrite(&scp->rw);
          lock_ReleaseWrite(&cm_scacheLock);
+ 	*outScpp = scp;
  #ifdef DEBUG_REFCOUNT
! 	afsi_log("%s:%d cm_GetSCache (2) scp 0x%p ref %d", file, line, scp, scp->refCount);
! 	osi_Log1(afsd_logp,"cm_GetSCache (2) scp 0x%p", scp);
  #endif
          return 0;
      }
***************
*** 804,811 ****
      for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
          if (cm_FidCmp(fidp, &scp->fid) == 0) {
  #ifdef DEBUG_REFCOUNT
! 	    afsi_log("%s:%d cm_GetSCache (3) outScpp 0x%p ref %d", file, line, scp, scp->refCount);
! 	    osi_Log1(afsd_logp,"cm_GetSCache (3) outScpp 0x%p", scp);
  #endif
              cm_HoldSCacheNoLock(scp);
              cm_AdjustScacheLRU(scp);
--- 813,820 ----
      for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
          if (cm_FidCmp(fidp, &scp->fid) == 0) {
  #ifdef DEBUG_REFCOUNT
! 	    afsi_log("%s:%d cm_GetSCache (3) scp 0x%p ref %d", file, line, scp, scp->refCount);
! 	    osi_Log1(afsd_logp,"cm_GetSCache (3) scp 0x%p", scp);
  #endif
              cm_HoldSCacheNoLock(scp);
              cm_AdjustScacheLRU(scp);
***************
*** 818,824 ****
      }
          
      /* now, if we don't have the fid, recycle something */
!     scp = cm_GetNewSCache();
      if (scp == NULL) {
  	osi_Log0(afsd_logp,"cm_GetNewSCache unable to obtain *new* scache entry");
  	lock_ReleaseWrite(&cm_scacheLock);
--- 827,833 ----
      }
          
      /* now, if we don't have the fid, recycle something */
!     scp = cm_GetNewSCache();    /* returns scp->rw held */
      if (scp == NULL) {
  	osi_Log0(afsd_logp,"cm_GetNewSCache unable to obtain *new* scache entry");
  	lock_ReleaseWrite(&cm_scacheLock);
***************
*** 826,845 ****
  	    cm_PutVolume(volp);
  	return CM_ERROR_WOULDBLOCK;
      }
!     osi_Log2(afsd_logp,"cm_GetNewSCache returns scp 0x%x flags 0x%x", scp, scp->flags);
  
      osi_assertx(!(scp->flags & CM_SCACHEFLAG_INHASH), "CM_SCACHEFLAG_INHASH set");
  
- #if not_too_dangerous
-     /* dropping the cm_scacheLock allows more than one thread
-      * to obtain the same cm_scache_t from the LRU list.  Since
-      * the refCount is known to be zero at this point we have to
-      * assume that no one else is using the one this is returned.
-      */
-     lock_ReleaseWrite(&cm_scacheLock);
-     lock_ObtainWrite(&scp->rw);
-     lock_ObtainWrite(&cm_scacheLock);
- #endif
      scp->fid = *fidp;
      if (!cm_freelanceEnabled || !isRoot) {
          /* if this scache entry represents a volume root then we need 
--- 835,847 ----
  	    cm_PutVolume(volp);
  	return CM_ERROR_WOULDBLOCK;
      }
! #ifdef DEBUG_REFCOUNT
!     afsi_log("%s:%d cm_GetNewSCache returns scp 0x%p flags 0x%x", file, line, scp, scp->flags);
! #endif
!     osi_Log2(afsd_logp,"cm_GetNewSCache returns scp 0x%p flags 0x%x", scp, scp->flags);
  
      osi_assertx(!(scp->flags & CM_SCACHEFLAG_INHASH), "CM_SCACHEFLAG_INHASH set");
  
      scp->fid = *fidp;
      if (!cm_freelanceEnabled || !isRoot) {
          /* if this scache entry represents a volume root then we need 
***************
*** 864,874 ****
      scp->nextp = cm_data.scacheHashTablep[hash];
      cm_data.scacheHashTablep[hash] = scp;
      scp->flags |= CM_SCACHEFLAG_INHASH;
-     scp->refCount = 1;
-     osi_Log1(afsd_logp,"cm_GetSCache sets refCount to 1 scp 0x%x", scp);
- #if not_too_dangerous
      lock_ReleaseWrite(&scp->rw);
  #endif
  
      /* XXX - The following fields in the cm_scache are 
       * uninitialized:
--- 866,877 ----
      scp->nextp = cm_data.scacheHashTablep[hash];
      cm_data.scacheHashTablep[hash] = scp;
      scp->flags |= CM_SCACHEFLAG_INHASH;
      lock_ReleaseWrite(&scp->rw);
+     scp->refCount = 1;
+ #ifdef DEBUG_REFCOUNT
+     afsi_log("%s:%d cm_GetSCache sets refCount to 1 scp 0x%x", file, line, scp);
  #endif
+     osi_Log1(afsd_logp,"cm_GetSCache sets refCount to 1 scp 0x%x", scp);
  
      /* XXX - The following fields in the cm_scache are 
       * uninitialized:
***************
*** 876,889 ****
       *   parentVnode
       *   parentUnique
       */
-     lock_ReleaseWrite(&cm_scacheLock);
          
      /* now we have a held scache entry; just return it */
      *outScpp = scp;
  #ifdef DEBUG_REFCOUNT
!     afsi_log("%s:%d cm_GetSCache (4) outScpp 0x%p ref %d", file, line, scp, scp->refCount);
!     osi_Log1(afsd_logp,"cm_GetSCache (4) outScpp 0x%p", scp);
  #endif
      return 0;
  }
  
--- 879,892 ----
       *   parentVnode
       *   parentUnique
       */
          
      /* now we have a held scache entry; just return it */
      *outScpp = scp;
  #ifdef DEBUG_REFCOUNT
!     afsi_log("%s:%d cm_GetSCache (4) scp 0x%p ref %d", file, line, scp, scp->refCount);
!     osi_Log1(afsd_logp,"cm_GetSCache (4) scp 0x%p", scp);
  #endif
+     lock_ReleaseWrite(&cm_scacheLock);
      return 0;
  }
  
***************
*** 1044,1050 ****
      afs_uint32 sleep_buf_cmflags = 0;
      afs_uint32 sleep_scp_bufs = 0;
      int wakeupCycle;
-     int getAccessRights = 1;
  
      lock_AssertWrite(&scp->rw);
  
--- 1047,1052 ----
***************
*** 1249,1255 ****
              if ((rights & (PRSFS_WRITE|PRSFS_DELETE)) && (scp->flags & CM_SCACHEFLAG_RO))
                  return CM_ERROR_READONLY;
  
!             if (cm_HaveAccessRights(scp, userp, rights, &outRights) || !getAccessRights) {
                  if (~outRights & rights) 
  		    return CM_ERROR_NOACCESS;
              }
--- 1251,1257 ----
              if ((rights & (PRSFS_WRITE|PRSFS_DELETE)) && (scp->flags & CM_SCACHEFLAG_RO))
                  return CM_ERROR_READONLY;
  
!             if (cm_HaveAccessRights(scp, userp, rights, &outRights)) {
                  if (~outRights & rights) 
  		    return CM_ERROR_NOACCESS;
              }
***************
*** 1264,1270 ****
                  }
                  if (code) 
                      return code;
-                 getAccessRights = 0;    /* do not repeat */
                  continue;
              }
          }
--- 1266,1271 ----
***************
*** 1753,1759 ****
  	scp->cbServerp = NULL;
      }
      scp->cbExpires = 0;
!     scp->flags &= ~CM_SCACHEFLAG_CALLBACK;
      cm_dnlcPurgedp(scp);
      cm_dnlcPurgevp(scp);
      cm_FreeAllACLEnts(scp);
--- 1754,1760 ----
  	scp->cbServerp = NULL;
      }
      scp->cbExpires = 0;
!     scp->flags &= ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_LOCAL);
      cm_dnlcPurgedp(scp);
      cm_dnlcPurgevp(scp);
      cm_FreeAllACLEnts(scp);
***************
*** 1814,1825 ****
  #endif
  {
      afs_int32 refCount;
-     long      lockstate;
  
      osi_assertx(scp != NULL, "null cm_scache_t");
      lock_AssertAny(&cm_scacheLock);
  
-     lockstate = lock_GetRWLockState(&cm_scacheLock);
      refCount = InterlockedDecrement(&scp->refCount);
  #ifdef DEBUG_REFCOUNT
      if (refCount < 0)
--- 1815,1824 ----
***************
*** 1833,1848 ****
  
      if (refCount == 0 && (scp->flags & CM_SCACHEFLAG_DELETED)) {
          int deleted = 0;
          if (lockstate != OSI_RWLOCK_WRITEHELD) 
!             lock_ConvertRToW(&cm_scacheLock);
          lock_ObtainWrite(&scp->rw);
          if (scp->flags & CM_SCACHEFLAG_DELETED)
              deleted = 1;
!         lock_ReleaseWrite(&scp->rw);
!         if (refCount == 0 && deleted)
              cm_RecycleSCache(scp, 0);
!         if (lockstate != OSI_RWLOCK_WRITEHELD) 
!             lock_ConvertWToR(&cm_scacheLock);
      }
  }
  
--- 1832,1861 ----
  
      if (refCount == 0 && (scp->flags & CM_SCACHEFLAG_DELETED)) {
          int deleted = 0;
+         long      lockstate;
+ 
+         lockstate = lock_GetRWLockState(&cm_scacheLock);
          if (lockstate != OSI_RWLOCK_WRITEHELD) 
!             lock_ReleaseRead(&cm_scacheLock);
!         else
!             lock_ReleaseWrite(&cm_scacheLock);
! 
          lock_ObtainWrite(&scp->rw);
          if (scp->flags & CM_SCACHEFLAG_DELETED)
              deleted = 1;
! 
!         if (refCount == 0 && deleted) {
!             lock_ObtainWrite(&cm_scacheLock);
              cm_RecycleSCache(scp, 0);
!             if (lockstate != OSI_RWLOCK_WRITEHELD) 
!                 lock_ConvertWToR(&cm_scacheLock);
!         } else {
!             if (lockstate != OSI_RWLOCK_WRITEHELD) 
!                 lock_ObtainRead(&cm_scacheLock);
!             else
!                 lock_ObtainWrite(&cm_scacheLock);
!         }
!         lock_ReleaseWrite(&scp->rw);
      }
  }
  
***************
*** 1866,1886 ****
      osi_Log2(afsd_logp,"cm_ReleaseSCache scp 0x%p ref %d",scp, refCount);
      afsi_log("%s:%d cm_ReleaseSCache scp 0x%p ref %d", file, line, scp, refCount);
  #endif
  
      if (scp->flags & CM_SCACHEFLAG_DELETED) {
          int deleted = 0;
          lock_ObtainWrite(&scp->rw);
          if (scp->flags & CM_SCACHEFLAG_DELETED)
              deleted = 1;
-         lock_ReleaseWrite(&scp->rw);
          if (deleted) {
!             lock_ConvertRToW(&cm_scacheLock);
              cm_RecycleSCache(scp, 0);
!             lock_ConvertWToR(&cm_scacheLock);
          }
      }
- 
-     lock_ReleaseRead(&cm_scacheLock);
  }
  
  /* just look for the scp entry to get filetype */
--- 1879,1898 ----
      osi_Log2(afsd_logp,"cm_ReleaseSCache scp 0x%p ref %d",scp, refCount);
      afsi_log("%s:%d cm_ReleaseSCache scp 0x%p ref %d", file, line, scp, refCount);
  #endif
+     lock_ReleaseRead(&cm_scacheLock);
  
      if (scp->flags & CM_SCACHEFLAG_DELETED) {
          int deleted = 0;
          lock_ObtainWrite(&scp->rw);
          if (scp->flags & CM_SCACHEFLAG_DELETED)
              deleted = 1;
          if (deleted) {
!             lock_ObtainWrite(&cm_scacheLock);
              cm_RecycleSCache(scp, 0);
!             lock_ReleaseWrite(&cm_scacheLock);
          }
+         lock_ReleaseWrite(&scp->rw);
      }
  }
  
  /* just look for the scp entry to get filetype */
Index: openafs/src/WINNT/afsd/cm_scache.h
diff -c openafs/src/WINNT/afsd/cm_scache.h:1.21.2.27 openafs/src/WINNT/afsd/cm_scache.h:1.21.2.30
*** openafs/src/WINNT/afsd/cm_scache.h:1.21.2.27	Thu Jun 26 12:38:30 2008
--- openafs/src/WINNT/afsd/cm_scache.h	Tue Sep 16 07:47:47 2008
***************
*** 23,29 ****
  
  /* Key used for byte range locking.  Each unique key identifies a
     unique client per cm_scache_t for the purpose of locking. */
! typedef afs_uint64 cm_key_t;
  
  typedef struct cm_range {
      afs_int64 offset;
--- 23,33 ----
  
  /* Key used for byte range locking.  Each unique key identifies a
     unique client per cm_scache_t for the purpose of locking. */
! typedef struct cm_key {
!     afs_offs_t process_id;      /* process IDs can be 64bit on 64bit environments */
!     afs_uint16 session_id;
!     afs_uint16 file_id;
! } cm_key_t;
  
  typedef struct cm_range {
      afs_int64 offset;
***************
*** 257,262 ****
--- 261,267 ----
  
  #define CM_SCACHEFLAG_EACCESS           0x200000 /* Bulk Stat returned EACCES */
  #define CM_SCACHEFLAG_SMB_FID	        0x400000
+ #define CM_SCACHEFLAG_LOCAL             0x800000 /* Locally modified */
  
  /* sync flags for calls to the server.  The CM_SCACHEFLAG_FETCHING,
   * CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
***************
*** 409,412 ****
--- 414,419 ----
  extern void cm_AdjustScacheLRU(cm_scache_t *scp);
  
  extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
+ 
+ extern void cm_ResetSCacheDirectory(cm_scache_t *scp);
  #endif /*  __CM_SCACHE_H_ENV__ */
Index: openafs/src/WINNT/afsd/cm_server.c
diff -c openafs/src/WINNT/afsd/cm_server.c:1.25.2.31 openafs/src/WINNT/afsd/cm_server.c:1.25.2.37
*** openafs/src/WINNT/afsd/cm_server.c:1.25.2.31	Wed Aug 13 22:37:59 2008
--- openafs/src/WINNT/afsd/cm_server.c	Sat Sep 13 00:20:48 2008
***************
*** 19,24 ****
--- 19,25 ----
  
  #include "afsd.h"
  #include <WINNT\syscfg.h>
+ #include <WINNT/afsreg.h>
  #include <osi.h>
  #include <rx/rx.h>
  
***************
*** 37,43 ****
--- 38,46 ----
      lock_ObtainRead(&cm_serverLock);
      for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
          cm_GetServerNoLock(tsp);
+         lock_ReleaseRead(&cm_serverLock);
  	cm_ForceNewConnections(tsp);
+         lock_ObtainRead(&cm_serverLock);
          cm_PutServerNoLock(tsp);
      }
      lock_ReleaseRead(&cm_serverLock);
***************
*** 155,163 ****
              tsp->flags |= CM_SERVERFLAG_DOWN;
              tsp->downTime = time(NULL);
          }
! 	if (code != VRESTARTING)
  	    cm_ForceNewConnections(tsp);
! 
  	osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x",
  		  osi_LogSaveString(afsd_logp, hoststr), 
  		  tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
--- 158,168 ----
              tsp->flags |= CM_SERVERFLAG_DOWN;
              tsp->downTime = time(NULL);
          }
! 	if (code != VRESTARTING) {
!             lock_ReleaseMutex(&tsp->mx);
  	    cm_ForceNewConnections(tsp);
!             lock_ObtainMutex(&tsp->mx);
!         }
  	osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x",
  		  osi_LogSaveString(afsd_logp, hoststr), 
  		  tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
***************
*** 195,203 ****
      lock_ReleaseMutex(&tsp->mx);
  }
  
! #define MULTI_CHECKSERVERS 1
! #ifndef MULTI_CHECKSERVERS
! void cm_CheckServers(afs_uint32 flags, cm_cell_t *cellp)
  {
      /* ping all file servers, up or down, with unauthenticated connection,
       * to find out whether we have all our callbacks from the server still.
--- 200,206 ----
      lock_ReleaseMutex(&tsp->mx);
  }
  
! static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
  {
      /* ping all file servers, up or down, with unauthenticated connection,
       * to find out whether we have all our callbacks from the server still.
***************
*** 251,258 ****
      }
      lock_ReleaseRead(&cm_serverLock);
  }       
! #else /* MULTI_CHECKSERVERS */
! void cm_CheckServers(afs_uint32 flags, cm_cell_t *cellp)
  {
      /* 
       * The goal of this function is to probe simultaneously 
--- 254,261 ----
      }
      lock_ReleaseRead(&cm_serverLock);
  }       
! 
! static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
  {
      /* 
       * The goal of this function is to probe simultaneously 
***************
*** 272,278 ****
      cm_conn_t **conns = NULL;
      struct rx_connection **rxconns = NULL;
      cm_req_t req;
!     afs_int32 i, j, nconns = 0;
      afs_int32 *conntimer, *results;
      Capabilities *caps = NULL;
      cm_server_t ** serversp, *tsp;
--- 275,281 ----
      cm_conn_t **conns = NULL;
      struct rx_connection **rxconns = NULL;
      cm_req_t req;
!     afs_int32 i, j, nconns = 0, maxconns;
      afs_int32 *conntimer, *results;
      Capabilities *caps = NULL;
      cm_server_t ** serversp, *tsp;
***************
*** 284,307 ****
      char hoststr[16];
  
      cm_InitReq(&req);
  
!     j = max(cm_numFileServers,cm_numVldbServers);
!     conns = (cm_conn_t **)malloc(j * sizeof(cm_conn_t *));
!     rxconns = (struct rx_connection **)malloc(j * sizeof(struct rx_connection *));
!     conntimer = (afs_int32 *)malloc(j * sizeof (afs_int32));
!     deltas = (time_t *)malloc(j * sizeof (time_t));
!     results = (afs_int32 *)malloc(j * sizeof (afs_int32));
!     serversp = (cm_server_t **)malloc(j * sizeof(cm_server_t *));
!     caps = (Capabilities *)malloc(j * sizeof(Capabilities));
  
!     memset(caps, 0, j * sizeof(Capabilities));
  
      if ((flags & CM_FLAG_CHECKFILESERVERS) || 
          !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
      {
          lock_ObtainRead(&cm_serverLock);
!         nconns = 0;
!         for (nconns=0, tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
              if (tsp->type != CM_SERVER_FILE || 
                  tsp->cellp == NULL ||           /* SetPref only */
                  cellp && cellp != tsp->cellp)
--- 287,311 ----
      char hoststr[16];
  
      cm_InitReq(&req);
+     maxconns = max(cm_numFileServers,cm_numVldbServers);
+     if (maxconns == 0)
+         return;
  
!     conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *));
!     rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *));
!     conntimer = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
!     deltas = (time_t *)malloc(maxconns * sizeof (time_t));
!     results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
!     serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *));
!     caps = (Capabilities *)malloc(maxconns * sizeof(Capabilities));
  
!     memset(caps, 0, maxconns * sizeof(Capabilities));
  
      if ((flags & CM_FLAG_CHECKFILESERVERS) || 
          !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
      {
          lock_ObtainRead(&cm_serverLock);
!         for (nconns=0, tsp = cm_allServersp; tsp && nconns < maxconns; tsp = tsp->allNextp) {
              if (tsp->type != CM_SERVER_FILE || 
                  tsp->cellp == NULL ||           /* SetPref only */
                  cellp && cellp != tsp->cellp)
***************
*** 418,426 ****
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING)
                      cm_ForceNewConnections(tsp);
! 
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
--- 422,432 ----
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING) {
!                     lock_ReleaseMutex(&tsp->mx);
                      cm_ForceNewConnections(tsp);
!                     lock_ObtainMutex(&tsp->mx);
!                 }
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
***************
*** 547,555 ****
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING)
                      cm_ForceNewConnections(tsp);
! 
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
--- 553,563 ----
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING) {
!                     lock_ReleaseMutex(&tsp->mx);
                      cm_ForceNewConnections(tsp);
!                     lock_ObtainMutex(&tsp->mx);
!                 }
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
***************
*** 596,603 ****
          !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
      {
          lock_ObtainRead(&cm_serverLock);
!         nconns = 0;
!         for (nconns=0, tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
              if (tsp->type != CM_SERVER_VLDB ||
                  tsp->cellp == NULL ||           /* SetPref only */
                  cellp && cellp != tsp->cellp)
--- 604,610 ----
          !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
      {
          lock_ObtainRead(&cm_serverLock);
!         for (nconns=0, tsp = cm_allServersp; tsp && nconns < maxconns; tsp = tsp->allNextp) {
              if (tsp->type != CM_SERVER_VLDB ||
                  tsp->cellp == NULL ||           /* SetPref only */
                  cellp && cellp != tsp->cellp)
***************
*** 648,654 ****
              } multi_End;
          }
  
!         /* Process results of servers that support RXAFS_GetCapabilities */
          for (i=0; i<nconns; i++) {
              if (conntimer[i])
                  rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
--- 655,661 ----
              } multi_End;
          }
  
!         /* Process results of servers that support VL_ProbeServer */
          for (i=0; i<nconns; i++) {
              if (conntimer[i])
                  rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
***************
*** 672,739 ****
                            osi_LogSaveString(afsd_logp, hoststr), 
                            tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
                            tsp->capabilities);
- 
-                 /* Now update the volume status if necessary */
-                 if (wasDown) {
-                     cm_server_vols_t * tsrvp;
-                     cm_volume_t * volp;
-                     int i;
- 
-                     for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
-                         for (i=0; i<NUM_SERVER_VOLS; i++) {
-                             if (tsrvp->ids[i] != 0) {
-                                 cm_InitReq(&req);
- 
-                                 lock_ReleaseMutex(&tsp->mx);
-                                 code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
-                                                          &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
-                                 lock_ObtainMutex(&tsp->mx);
-                                 if (code == 0) {
-                                     cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
-                                     cm_PutVolume(volp);
-                                 }
-                             }
-                         }
-                     }
-                 }
              } else {
                  /* mark server as down */
                  if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING)
                      cm_ForceNewConnections(tsp);
! 
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
                            tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
                            tsp->capabilities);
- 
-                 /* Now update the volume status if necessary */
-                 if (!wasDown) {
-                     cm_server_vols_t * tsrvp;
-                     cm_volume_t * volp;
-                     int i;
- 
-                     for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
-                         for (i=0; i<NUM_SERVER_VOLS; i++) {
-                             if (tsrvp->ids[i] != 0) {
-                                 cm_InitReq(&req);
- 
-                                 lock_ReleaseMutex(&tsp->mx);
-                                 code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
-                                                          &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
-                                 lock_ObtainMutex(&tsp->mx);
-                                 if (code == 0) {
-                                     cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
-                                     cm_PutVolume(volp);
-                                 }
-                             }
-                         }
-                     }
-                 }
              }
  
              if (tsp->waitCount == 0)
--- 679,700 ----
                            osi_LogSaveString(afsd_logp, hoststr), 
                            tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
                            tsp->capabilities);
              } else {
                  /* mark server as down */
                  if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                      tsp->flags |= CM_SERVERFLAG_DOWN;
                      tsp->downTime = time(NULL);
                  }
!                 if (code != VRESTARTING) {
!                     lock_ReleaseMutex(&tsp->mx);
                      cm_ForceNewConnections(tsp);
!                     lock_ObtainMutex(&tsp->mx);
!                 }
                  afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
                  osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
                            osi_LogSaveString(afsd_logp, hoststr), 
                            tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
                            tsp->capabilities);
              }
  
              if (tsp->waitCount == 0)
***************
*** 755,769 ****
      free(serversp);
      free(caps);
  }
! #endif /* MULTI_CHECKSERVERS */
  
  void cm_InitServer(void)
  {
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_serverLock, "cm_serverLock");
!         lock_InitializeRWLock(&cm_syscfgLock, "cm_syscfgLock");
          osi_EndOnce(&once);
      }
  }
--- 716,751 ----
      free(serversp);
      free(caps);
  }
! 
! void cm_CheckServers(afs_uint32 flags, cm_cell_t *cellp)
! {
!     DWORD code;
!     HKEY parmKey;
!     DWORD dummyLen;
!     DWORD multi = 1;
! 
!     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
!                          0, KEY_QUERY_VALUE, &parmKey);
!     if (code == ERROR_SUCCESS) {
!         dummyLen = sizeof(multi);
!         code = RegQueryValueEx(parmKey, "MultiCheckServers", NULL, NULL,
!                                 (BYTE *) &multi, &dummyLen);
!         RegCloseKey (parmKey);
!     }
! 
!     if (multi)
!         cm_CheckServersMulti(flags, cellp);
!     else
!         cm_CheckServersSingular(flags, cellp);
! }
  
  void cm_InitServer(void)
  {
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_serverLock, "cm_serverLock", LOCK_HIERARCHY_SERVER_GLOBAL);
!         lock_InitializeRWLock(&cm_syscfgLock, "cm_syscfgLock", LOCK_HIERARCHY_SYSCFG_GLOBAL);
          osi_EndOnce(&once);
      }
  }
***************
*** 905,911 ****
          tsp->type = type;
          tsp->cellp = cellp;
          tsp->refCount = 1;
!         lock_InitializeMutex(&tsp->mx, "cm_server_t mutex");
          tsp->addr = *socketp;
  
          cm_SetServerPrefs(tsp); 
--- 887,893 ----
          tsp->type = type;
          tsp->cellp = cellp;
          tsp->refCount = 1;
!         lock_InitializeMutex(&tsp->mx, "cm_server_t mutex", LOCK_HIERARCHY_SERVER);
          tsp->addr = *socketp;
  
          cm_SetServerPrefs(tsp); 
***************
*** 1052,1057 ****
--- 1034,1041 ----
  
      lock_ObtainRead(&cm_serverLock);
      for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
          if (first)
              first = 0;
          else
***************
*** 1252,1257 ****
--- 1236,1242 ----
      }
  }
  
+ /* Called with cm_serverLock write locked */
  void cm_RemoveVolumeFromServer(cm_server_t * serverp, afs_uint32 volID)
  {
      cm_server_vols_t * tsrvp;
***************
*** 1276,1281 ****
--- 1261,1269 ----
      cm_serverRef_t  **nextp = 0;
      cm_serverRef_t  * next = 0;
  
+ 	if (*list == NULL)
+ 		return;
+ 
      lock_ObtainWrite(&cm_serverLock);
  
      while (*current)
Index: openafs/src/WINNT/afsd/cm_user.c
diff -c openafs/src/WINNT/afsd/cm_user.c:1.8.4.6 openafs/src/WINNT/afsd/cm_user.c:1.8.4.7
*** openafs/src/WINNT/afsd/cm_user.c:1.8.4.6	Thu Jun 26 10:58:05 2008
--- openafs/src/WINNT/afsd/cm_user.c	Fri Aug 22 14:10:01 2008
***************
*** 29,35 ****
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_userLock, "cm_userLock");
          osi_EndOnce(&once);
      }
          
--- 29,35 ----
      static osi_once_t once;
          
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_userLock, "cm_userLock", LOCK_HIERARCHY_USER_GLOBAL);
          osi_EndOnce(&once);
      }
          
***************
*** 43,49 ****
      userp = malloc(sizeof(*userp));
      memset(userp, 0, sizeof(*userp));
      userp->refCount = 1;
!     lock_InitializeMutex(&userp->mx, "cm_user_t");
      return userp;
  }
  
--- 43,49 ----
      userp = malloc(sizeof(*userp));
      memset(userp, 0, sizeof(*userp));
      userp->refCount = 1;
!     lock_InitializeMutex(&userp->mx, "cm_user_t", LOCK_HIERARCHY_USER);
      return userp;
  }
  
Index: openafs/src/WINNT/afsd/cm_utils.c
diff -c openafs/src/WINNT/afsd/cm_utils.c:1.11.4.13 openafs/src/WINNT/afsd/cm_utils.c:1.11.4.16
*** openafs/src/WINNT/afsd/cm_utils.c:1.11.4.13	Thu Jul 31 08:39:24 2008
--- openafs/src/WINNT/afsd/cm_utils.c	Tue Sep 16 07:34:31 2008
***************
*** 340,346 ****
  	cm_space_t *tsp;
  
  	if (osi_Once(&cm_utilsOnce)) {
! 		lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock");
  		osi_EndOnce(&cm_utilsOnce);
          }
          
--- 340,346 ----
  	cm_space_t *tsp;
  
  	if (osi_Once(&cm_utilsOnce)) {
! 		lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock", LOCK_HIERARCHY_UTILS_GLOBAL);
  		osi_EndOnce(&cm_utilsOnce);
          }
          
***************
*** 440,446 ****
  {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 
   'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 
!  'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '+', '='
  };
  int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
  
--- 440,446 ----
  {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 
   'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 
!  'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
  };
  int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
  
***************
*** 657,662 ****
--- 657,670 ----
                                              cm_ClientCharNext(p), FALSE))
                      return TRUE;
              } /* endfor */
+             if (*pattern == '.' && *pattern_next == '\0') {
+                 for (p = name; p && *p; p = cm_ClientCharNext(p))
+                     if (*p == '.')
+                         break;
+                 if (p && *p)
+                     return FALSE;
+                 return TRUE;
+             }
              return FALSE;
  
          default:
***************
*** 681,688 ****
   */
  int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags) 
  {
!     clientchar_t * newmask;
!     int    i, j, star, qmark, casefold, retval;
  
      /* make sure we only match 8.3 names, if requested */
      if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) 
--- 689,697 ----
   */
  int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags) 
  {
!     clientchar_t *newmask, lastchar = _C('\0');
!     int    i, j, casefold, retval;
!     int  star = 0, qmark = 0, dot = 0;
  
      /* make sure we only match 8.3 names, if requested */
      if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) 
***************
*** 695,702 ****
       * for example  the sequence "*?*?*?*"
       * must be turned into the form "*"
       */
!     newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+1)*sizeof(clientchar_t));
      for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
          switch ( maskp[i] ) {
          case '?':
          case '>':
--- 704,712 ----
       * for example  the sequence "*?*?*?*"
       * must be turned into the form "*"
       */
!     newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
      for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
+         lastchar = maskp[i];
          switch ( maskp[i] ) {
          case '?':
          case '>':
***************
*** 706,711 ****
--- 716,724 ----
          case '*':
              star++;
              break;
+         case '.':
+             dot++;
+             /* fallthrough */
          default:
              if ( star ) {
                  newmask[j++] = '*';
***************
*** 724,729 ****
--- 737,744 ----
          while ( qmark-- )
              newmask[j++] = '?';
      }
+     if (dot == 0 && lastchar == '<')
+         newmask[j++] = '.';
      newmask[j++] = '\0';
  
      retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
Index: openafs/src/WINNT/afsd/cm_vnodeops.c
diff -c openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.88 openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.91
*** openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.88	Tue Aug 12 00:31:31 2008
--- openafs/src/WINNT/afsd/cm_vnodeops.c	Sat Sep 13 09:51:50 2008
***************
*** 254,260 ****
  	    (*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
  	    if (!*ldpp) {
  		code = ENOMEM;
! 		goto _syncopdone;
  	    }
  
  	    (*ldpp)->key = key;
--- 254,260 ----
  	    (*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
  	    if (!*ldpp) {
  		code = ENOMEM;
! 		goto _done;
  	    }
  
  	    (*ldpp)->key = key;
***************
*** 288,296 ****
          goto _done;
      }
  
-   _syncopdone:
-     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
- 
   _done:
      lock_ReleaseWrite(&scp->rw);
  
--- 288,293 ----
***************
*** 302,315 ****
  			       cm_lock_data_t ** ldpp)
  {
      osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
      if (*ldpp) {
- 	lock_ObtainWrite(&scp->rw);
  	cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength, 
  		  (*ldpp)->key, userp, reqp);
- 	lock_ReleaseWrite(&scp->rw);
  	free(*ldpp);
  	*ldpp = NULL;
      }
      return 0;
  }
  /*
--- 299,313 ----
  			       cm_lock_data_t ** ldpp)
  {
      osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
+     lock_ObtainWrite(&scp->rw);
      if (*ldpp) {
  	cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength, 
  		  (*ldpp)->key, userp, reqp);
  	free(*ldpp);
  	*ldpp = NULL;
      }
+     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+     lock_ReleaseWrite(&scp->rw);
      return 0;
  }
  /*
***************
*** 891,896 ****
--- 889,896 ----
      size_t vnLength;
      int targetType;
  
+     *outScpp = NULL;
+ 
      if (scp->mountRootFid.cell != 0 && scp->mountRootGen >= cm_data.mountRootGen) {
          tfid = scp->mountRootFid;
          lock_ReleaseWrite(&scp->rw);
***************
*** 1013,1019 ****
  }       
  
  long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_user_t *userp,
!                        cm_req_t *reqp, cm_scache_t **outpScpp)
  {
      long code;
      int dnlcHit = 1;	/* did we hit in the dnlc? yes, we did */
--- 1013,1019 ----
  }       
  
  long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_user_t *userp,
!                        cm_req_t *reqp, cm_scache_t **outScpp)
  {
      long code;
      int dnlcHit = 1;	/* did we hit in the dnlc? yes, we did */
***************
*** 1024,1029 ****
--- 1024,1031 ----
      normchar_t *nnamep = NULL;
      fschar_t *fnamep = NULL;
  
+     *outScpp = NULL;
+ 
      memset(&rock, 0, sizeof(rock));
  
      if (dscp->fid.vnode == 1 && dscp->fid.unique == 1
***************
*** 1222,1228 ****
      }
  
      /* copy back pointer */
!     *outpScpp = tscp;
  
      /* insert scache in dnlc */
      if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
--- 1224,1230 ----
      }
  
      /* copy back pointer */
!     *outScpp = tscp;
  
      /* insert scache in dnlc */
      if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
***************
*** 1281,1287 ****
  }   
  
  long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * userp,
!                                 cm_req_t *reqp, cm_scache_t ** outpScpp)
  {
      afs_uint32    code = 0;
      fschar_t      cellName[CELL_MAXNAMELEN];
--- 1283,1289 ----
  }   
  
  long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * userp,
!                                 cm_req_t *reqp, cm_scache_t ** outScpp)
  {
      afs_uint32    code = 0;
      fschar_t      cellName[CELL_MAXNAMELEN];
***************
*** 1370,1376 ****
  
      cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
  
!     code = cm_GetSCache(&fid, outpScpp, userp, reqp);
  
    _exit_cleanup:
      if (fnamep)
--- 1372,1378 ----
  
      cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
  
!     code = cm_GetSCache(&fid, outScpp, userp, reqp);
  
    _exit_cleanup:
      if (fnamep)
***************
*** 1391,1400 ****
  
  #ifdef DEBUG_REFCOUNT
  long cm_LookupDbg(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
!                cm_req_t *reqp, cm_scache_t **outpScpp, char * file, long line)
  #else
  long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
!                cm_req_t *reqp, cm_scache_t **outpScpp)
  #endif
  {
      long code;
--- 1393,1402 ----
  
  #ifdef DEBUG_REFCOUNT
  long cm_LookupDbg(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
!                cm_req_t *reqp, cm_scache_t **outScpp, char * file, long line)
  #else
  long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
!                cm_req_t *reqp, cm_scache_t **outScpp)
  #endif
  {
      long code;
***************
*** 1416,1422 ****
  
      if (dscp == cm_data.rootSCachep &&
          cm_ClientStrCmpNI(namep, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH) == 0) {
!         return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outpScpp);
      }
  
      if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
--- 1418,1424 ----
  
      if (dscp == cm_data.rootSCachep &&
          cm_ClientStrCmpNI(namep, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH) == 0) {
!         return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outScpp);
      }
  
      if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
***************
*** 1430,1436 ****
  #endif
  
                  if (code == 0) {
!                     *outpScpp = scp;
                      return 0;
                  }
                  if (scp) {
--- 1432,1438 ----
  #endif
  
                  if (code == 0) {
!                     *outScpp = scp;
                      return 0;
                  }
                  if (scp) {
***************
*** 1443,1449 ****
                  afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
                  osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
  #endif
!                 *outpScpp = scp;
                  return code;
              }
          }
--- 1445,1451 ----
                  afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
                  osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
  #endif
!                 *outScpp = scp;
                  return code;
              }
          }
***************
*** 1453,1459 ****
          afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
          osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
  #endif
!         *outpScpp = scp;
          return code;
      }
  
--- 1455,1461 ----
          afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
          osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
  #endif
!         *outScpp = scp;
          return code;
      }
  
***************
*** 1804,1813 ****
      int fid_count = 0;          /* number of fids processed in this path walk */
      int i;
  
  #ifdef DEBUG_REFCOUNT
      afsi_log("%s:%d cm_NameI rootscp 0x%p ref %d", file, line, rootSCachep, rootSCachep->refCount);
      osi_Log4(afsd_logp,"cm_NameI rootscp 0x%p path %S tidpath %S flags 0x%x",
!              rootSCachep, pathp ? pathp : "<NULL>", tidPathp ? tidPathp : "<NULL>", 
               flags);
  #endif
  
--- 1806,1817 ----
      int fid_count = 0;          /* number of fids processed in this path walk */
      int i;
  
+     *outScpp = NULL;
+ 
  #ifdef DEBUG_REFCOUNT
      afsi_log("%s:%d cm_NameI rootscp 0x%p ref %d", file, line, rootSCachep, rootSCachep->refCount);
      osi_Log4(afsd_logp,"cm_NameI rootscp 0x%p path %S tidpath %S flags 0x%x",
!              rootSCachep, pathp ? pathp : L"<NULL>", tidPathp ? tidPathp : L"<NULL>", 
               flags);
  #endif
  
***************
*** 2073,2079 ****
          cm_ReleaseSCache(tscp);
  
  #ifdef DEBUG_REFCOUNT
!     afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp)->refCount);
  #endif
      osi_Log2(afsd_logp,"cm_NameI code 0x%x outScpp 0x%p", code, *outScpp);
      return code;
--- 2077,2083 ----
          cm_ReleaseSCache(tscp);
  
  #ifdef DEBUG_REFCOUNT
!     afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp) ? (*outScpp)->refCount : 0);
  #endif
      osi_Log2(afsd_logp,"cm_NameI code 0x%x outScpp 0x%p", code, *outScpp);
      return code;
***************
*** 2101,2106 ****
--- 2105,2112 ----
      cm_space_t *spacep;
      cm_scache_t *newRootScp;
  
+     *outScpp = NULL;
+ 
      osi_Log1(afsd_logp, "Evaluating symlink scp 0x%p", linkScp);
  
      code = cm_AssembleLink(linkScp, "", &newRootScp, &spacep, userp, reqp);
***************
*** 3902,3908 ****
  
          if (INTERSECT_RANGE(range, fileLock->range)) {
              if (IS_LOCK_ACTIVE(fileLock)) {
!                 if (fileLock->key == key) {
  
                      /* If there is an active lock for this client, it
                         is safe to substract ranges.*/
--- 3908,3914 ----
  
          if (INTERSECT_RANGE(range, fileLock->range)) {
              if (IS_LOCK_ACTIVE(fileLock)) {
!                 if (cm_KeyEquals(&fileLock->key, &key, 0)) {
  
                      /* If there is an active lock for this client, it
                         is safe to substract ranges.*/
***************
*** 3924,3930 ****
                          cm_LockRangeSubtract(&range, &fileLock->range);
                  }
              } else if (IS_LOCK_LOST(fileLock) &&
!                       (fileLock->key == key || fileLock->lockType == LockWrite)) {
                  code = CM_ERROR_BADFD;
                  break;
              }
--- 3930,3936 ----
                          cm_LockRangeSubtract(&range, &fileLock->range);
                  }
              } else if (IS_LOCK_LOST(fileLock) &&
!                        (cm_KeyEquals(&fileLock->key, &key, 0) || fileLock->lockType == LockWrite)) {
                  code = CM_ERROR_BADFD;
                  break;
              }
***************
*** 3983,3989 ****
  
          if (INTERSECT_RANGE(range, fileLock->range)) {
              if (IS_LOCK_ACTIVE(fileLock)) {
!                 if (fileLock->key == key) {
                      if (fileLock->lockType == LockWrite) {
  
                          /* if there is an active lock for this client, it
--- 3989,3995 ----
  
          if (INTERSECT_RANGE(range, fileLock->range)) {
              if (IS_LOCK_ACTIVE(fileLock)) {
!                 if (cm_KeyEquals(&fileLock->key, &key, 0)) {
                      if (fileLock->lockType == LockWrite) {
  
                          /* if there is an active lock for this client, it
***************
*** 4233,4240 ****
  
      osi_Log4(afsd_logp, "cm_Lock scp 0x%x type 0x%x offset %d length %d",
               scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
!     osi_Log3(afsd_logp, "... allowWait %d key 0x%x:%x", allowWait, 
!              (unsigned long)(key >> 32), (unsigned long)(key & 0xffffffff));
  
      /*
     A client C can OBTAIN a lock L on cm_scache_t S iff (both 3 and 4):
--- 4239,4246 ----
  
      osi_Log4(afsd_logp, "cm_Lock scp 0x%x type 0x%x offset %d length %d",
               scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
!     osi_Log4(afsd_logp, "... allowWait %d key <0x%x, 0x%x, 0x%x>", allowWait, 
!              key.process_id, key.session_id, key.file_id);
  
      /*
     A client C can OBTAIN a lock L on cm_scache_t S iff (both 3 and 4):
***************
*** 4268,4274 ****
              (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
  
          if (IS_LOCK_LOST(fileLock)) {
!             if (fileLock->key == key) {
                  code = CM_ERROR_BADFD;
                  break;
              } else if (fileLock->lockType == LockWrite && INTERSECT_RANGE(range, fileLock->range)) {
--- 4274,4280 ----
              (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
  
          if (IS_LOCK_LOST(fileLock)) {
!             if (cm_KeyEquals(&fileLock->key, &key, 0)) {
                  code = CM_ERROR_BADFD;
                  break;
              } else if (fileLock->lockType == LockWrite && INTERSECT_RANGE(range, fileLock->range)) {
***************
*** 4581,4588 ****
      return code;
  }
  
- static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags);
- 
  /* Called with scp->rw held */
  long cm_UnlockByKey(cm_scache_t * scp,
  		    cm_key_t key,
--- 4587,4592 ----
***************
*** 4595,4605 ****
      osi_queue_t *q, *qn;
      int n_unlocks = 0;
  
!     osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key 0x%x:%x flags=0x%x",
!              scp,
!              (unsigned long)(key >> 32),
!              (unsigned long)(key & 0xffffffff),
!              flags);
  
      lock_ObtainWrite(&cm_scacheLock);
  
--- 4599,4607 ----
      osi_queue_t *q, *qn;
      int n_unlocks = 0;
  
!     osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key <0x%x,0x%x,0x%x",
!              scp, key.process_id, key.session_id, key.file_id);
!     osi_Log1(afsd_logp, "    flags=0x%x", flags);
  
      lock_ObtainWrite(&cm_scacheLock);
  
***************
*** 4615,4623 ****
                   (unsigned long) fileLock->range.offset,
                   (unsigned long) fileLock->range.length,
                  fileLock->lockType);
!         osi_Log3(afsd_logp, "     key[0x%x:%x] flags[0x%x]",
!                  (unsigned long)(fileLock->key >> 32),
!                  (unsigned long)(fileLock->key & 0xffffffff),
                   fileLock->flags);
  
          if (cm_FidCmp(&fileLock->fid, &fileLock->scp->fid)) {
--- 4617,4624 ----
                   (unsigned long) fileLock->range.offset,
                   (unsigned long) fileLock->range.length,
                  fileLock->lockType);
!         osi_Log4(afsd_logp, "     key<0x%x, 0x%x, 0x%x> flags[0x%x]",
!                  fileLock->key.process_id, fileLock->key.session_id, fileLock->key.file_id,
                   fileLock->flags);
  
          if (cm_FidCmp(&fileLock->fid, &fileLock->scp->fid)) {
***************
*** 4637,4643 ****
  #endif
  
          if (!IS_LOCK_DELETED(fileLock) &&
!             cm_KeyEquals(fileLock->key, key, flags)) {
              osi_Log3(afsd_logp, "...Unlock range [%d,+%d] type %d",
                      fileLock->range.offset,
                      fileLock->range.length,
--- 4638,4644 ----
  #endif
  
          if (!IS_LOCK_DELETED(fileLock) &&
!             cm_KeyEquals(&fileLock->key, &key, flags)) {
              osi_Log3(afsd_logp, "...Unlock range [%d,+%d] type %d",
                      fileLock->range.offset,
                      fileLock->range.length,
***************
*** 4785,4792 ****
  
      osi_Log4(afsd_logp, "cm_Unlock scp 0x%p type 0x%x offset %d length %d",
               scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
!     osi_Log2(afsd_logp, "... key 0x%x:%x",
!              (unsigned long) (key >> 32), (unsigned long) (key & 0xffffffff));
  
      lock_ObtainRead(&cm_scacheLock);
  
--- 4786,4793 ----
  
      osi_Log4(afsd_logp, "cm_Unlock scp 0x%p type 0x%x offset %d length %d",
               scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
!     osi_Log3(afsd_logp, "... key <0x%x,0x%x,0x%x>",
!              key.process_id, key.session_id, key.file_id);
  
      lock_ObtainRead(&cm_scacheLock);
  
***************
*** 4811,4817 ****
          }
  #endif
          if (!IS_LOCK_DELETED(fileLock) &&
!             fileLock->key == key &&
              fileLock->range.offset == LOffset.QuadPart &&
              fileLock->range.length == LLength.QuadPart) {
              break;
--- 4812,4818 ----
          }
  #endif
          if (!IS_LOCK_DELETED(fileLock) &&
!             cm_KeyEquals(&fileLock->key, &key, 0) &&
              fileLock->range.offset == LOffset.QuadPart &&
              fileLock->range.length == LLength.QuadPart) {
              break;
***************
*** 5233,5241 ****
               (unsigned)(oldFileLock->range.offset & 0xffffffff),
               (unsigned)(oldFileLock->range.length >> 32),
               (unsigned)(oldFileLock->range.length & 0xffffffff));
!     osi_Log3(afsd_logp, "    key(%x:%x) flags=%x",
!              (unsigned)(oldFileLock->key >> 32),
!              (unsigned)(oldFileLock->key & 0xffffffff),
               (unsigned)(oldFileLock->flags));
  
      /* if the lock has already been granted, then we have nothing to do */
--- 5234,5241 ----
               (unsigned)(oldFileLock->range.offset & 0xffffffff),
               (unsigned)(oldFileLock->range.length >> 32),
               (unsigned)(oldFileLock->range.length & 0xffffffff));
!     osi_Log4(afsd_logp, "    key<0x%x,0x%x,0x%x> flags=%x",
!              oldFileLock->key.process_id, oldFileLock->key.session_id, oldFileLock->key.file_id,
               (unsigned)(oldFileLock->flags));
  
      /* if the lock has already been granted, then we have nothing to do */
***************
*** 5307,5313 ****
                  ((char *) q - offsetof(cm_file_lock_t, fileq));
  
              if (IS_LOCK_LOST(fileLock)) {
!                 if (fileLock->key == oldFileLock->key) {
                      code = CM_ERROR_BADFD;
                      oldFileLock->flags |= CM_FILELOCK_FLAG_LOST;
                      osi_Log1(afsd_logp, "    found lost lock %p for same key.  Marking lock as lost",
--- 5307,5313 ----
                  ((char *) q - offsetof(cm_file_lock_t, fileq));
  
              if (IS_LOCK_LOST(fileLock)) {
!                 if (cm_KeyEquals(&fileLock->key, &oldFileLock->key, 0)) {
                      code = CM_ERROR_BADFD;
                      oldFileLock->flags |= CM_FILELOCK_FLAG_LOST;
                      osi_Log1(afsd_logp, "    found lost lock %p for same key.  Marking lock as lost",
***************
*** 5509,5535 ****
      return code;
  }
  
! cm_key_t cm_GenerateKey(unsigned int session_id, unsigned long process_id, unsigned int file_id)
  {
! #ifdef DEBUG
!     osi_assertx((process_id & 0xffffffff) == process_id, "unexpected process_id");
!     osi_assertx((session_id & 0xffff) == session_id, "unexpected session_id");
!     osi_assertx((file_id & 0xffff) == file_id, "unexpected file_id");
! #endif
  
!     return 
!         (((cm_key_t) (process_id & 0xffffffff)) << 32) |
!         (((cm_key_t) (session_id & 0xffff)) << 16) |
!         (((cm_key_t) (file_id & 0xffff)));
  }
  
! static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags)
  {
!     if (flags & CM_UNLOCK_BY_FID) {
!         return ((k1 & 0xffffffff) == (k2 & 0xffffffff));
!     } else {
!         return (k1 == k2);
!     }
  }
  
  void cm_ReleaseAllLocks(void)
--- 5509,5529 ----
      return code;
  }
  
! cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16 file_id)
  {
!     cm_key_t key;
! 
!     key.process_id = process_id;
!     key.session_id = session_id;
!     key.file_id = file_id;
  
!     return key;
  }
  
! int cm_KeyEquals(cm_key_t *k1, cm_key_t *k2, int flags)
  {
!     return (k1->session_id == k2->session_id) && (k1->file_id == k2->file_id) &&
!         ((flags & CM_UNLOCK_BY_FID) || (k1->process_id == k2->process_id));
  }
  
  void cm_ReleaseAllLocks(void)
Index: openafs/src/WINNT/afsd/cm_vnodeops.h
diff -c openafs/src/WINNT/afsd/cm_vnodeops.h:1.14.4.13 openafs/src/WINNT/afsd/cm_vnodeops.h:1.14.4.14
*** openafs/src/WINNT/afsd/cm_vnodeops.h:1.14.4.13	Thu Jul 24 13:56:54 2008
--- openafs/src/WINNT/afsd/cm_vnodeops.h	Sat Sep 13 09:51:50 2008
***************
*** 231,237 ****
  #define CM_SESSION_CMINT    0xfffd
  #define CM_SESSION_RESERVED 0xfff0
  
! extern cm_key_t cm_GenerateKey(unsigned int session, unsigned long process_id, unsigned int file_id);
  
  #define MAX_SYMLINK_COUNT 16
  
--- 231,239 ----
  #define CM_SESSION_CMINT    0xfffd
  #define CM_SESSION_RESERVED 0xfff0
  
! extern cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16 file_id);
! 
! extern int cm_KeyEquals(cm_key_t * k1, cm_key_t * k2, int flags);
  
  #define MAX_SYMLINK_COUNT 16
  
Index: openafs/src/WINNT/afsd/cm_volume.c
diff -c openafs/src/WINNT/afsd/cm_volume.c:1.14.4.50 openafs/src/WINNT/afsd/cm_volume.c:1.14.4.55
*** openafs/src/WINNT/afsd/cm_volume.c:1.14.4.50	Thu Aug 14 16:21:27 2008
--- openafs/src/WINNT/afsd/cm_volume.c	Wed Sep 24 18:42:55 2008
***************
*** 83,89 ****
      static osi_once_t once;
  
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_volumeLock, "cm global volume lock");
  
          if ( newFile ) {
              cm_data.allVolumesp = NULL;
--- 83,89 ----
      static osi_once_t once;
  
      if (osi_Once(&once)) {
!         lock_InitializeRWLock(&cm_volumeLock, "cm global volume lock", LOCK_HIERARCHY_VOLUME_GLOBAL);
  
          if ( newFile ) {
              cm_data.allVolumesp = NULL;
***************
*** 100,113 ****
              for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
                  afs_uint32 volType;
  
!                 lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock");
                  volp->flags |= CM_VOLUMEFLAG_RESET;
                  volp->flags &= ~CM_VOLUMEFLAG_UPDATING_VL;
                  for (volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
                      volp->vol[volType].state = vl_unknown;
                      volp->vol[volType].serversp = NULL;
                      if (volp->vol[volType].ID)
!                         cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_alldown, volp->vol[volType].state);
                  }
                  volp->cbExpiresRO = 0;
              }
--- 100,113 ----
              for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
                  afs_uint32 volType;
  
!                 lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock", LOCK_HIERARCHY_VOLUME);
                  volp->flags |= CM_VOLUMEFLAG_RESET;
                  volp->flags &= ~CM_VOLUMEFLAG_UPDATING_VL;
                  for (volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
                      volp->vol[volType].state = vl_unknown;
                      volp->vol[volType].serversp = NULL;
                      if (volp->vol[volType].ID)
!                         cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_unknown, volp->vol[volType].state);
                  }
                  volp->cbExpiresRO = 0;
              }
***************
*** 227,233 ****
              cm_UpdateCell(cellp, 0);
  
          /* now we have volume structure locked and held; make RPC to fill it */
! 	osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s", volp->cellp->name, volp->namep);
          do {
              struct rx_connection * rxconnp;
  
--- 227,235 ----
              cm_UpdateCell(cellp, 0);
  
          /* now we have volume structure locked and held; make RPC to fill it */
! 	osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s", 
!                   osi_LogSaveString(afsd_logp,volp->cellp->name), 
!                   osi_LogSaveString(afsd_logp,volp->namep));
          do {
              struct rx_connection * rxconnp;
  
***************
*** 254,263 ****
          code = cm_MapVLRPCError(code, reqp);
  	if ( code )
  	    osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x", 
! 		      volp->cellp->name, volp->namep, code);
  	else
  	    osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS", 
! 		      volp->cellp->name, volp->namep);
      }
  
      /* We can end up here with code == CM_ERROR_NOSUCHVOLUME if the base volume name
--- 256,267 ----
          code = cm_MapVLRPCError(code, reqp);
  	if ( code )
  	    osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x", 
! 		      osi_LogSaveString(afsd_logp,volp->cellp->name), 
!                       osi_LogSaveString(afsd_logp,volp->namep), code);
  	else
  	    osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS", 
! 		      osi_LogSaveString(afsd_logp,volp->cellp->name), 
!                       osi_LogSaveString(afsd_logp,volp->namep));
      }
  
      /* We can end up here with code == CM_ERROR_NOSUCHVOLUME if the base volume name
***************
*** 271,277 ****
          snprintf(name, VL_MAXNAMELEN, "%s.readonly", volp->namep);
                  
          /* now we have volume structure locked and held; make RPC to fill it */
! 	osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s", volp->cellp->name, 
                   osi_LogSaveString(afsd_logp,name));
          do {
              struct rx_connection * rxconnp;
--- 275,282 ----
          snprintf(name, VL_MAXNAMELEN, "%s.readonly", volp->namep);
                  
          /* now we have volume structure locked and held; make RPC to fill it */
! 	osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s", 
!                  osi_LogSaveString(afsd_logp,volp->cellp->name),
                   osi_LogSaveString(afsd_logp,name));
          do {
              struct rx_connection * rxconnp;
***************
*** 299,308 ****
          code = cm_MapVLRPCError(code, reqp);
  	if ( code )
  	    osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x", 
! 		      volp->cellp->name, osi_LogSaveString(afsd_logp,name), code);
  	else
  	    osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS", 
! 		      volp->cellp->name, osi_LogSaveString(afsd_logp,name));
      }
      
      lock_ObtainWrite(&volp->rw);
--- 304,315 ----
          code = cm_MapVLRPCError(code, reqp);
  	if ( code )
  	    osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x", 
! 		     osi_LogSaveString(afsd_logp,volp->cellp->name), 
!                      osi_LogSaveString(afsd_logp,name), code);
  	else
  	    osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS", 
! 		     osi_LogSaveString(afsd_logp,volp->cellp->name), 
!                      osi_LogSaveString(afsd_logp,name));
      }
      
      lock_ObtainWrite(&volp->rw);
***************
*** 427,433 ****
                  name[len - 9] = '\0';
              }
              
!             osi_Log2(afsd_logp, "cm_UpdateVolume name %s -> %s", volp->namep, name);
  
              if (volp->flags & CM_VOLUMEFLAG_IN_HASH)
                  cm_RemoveVolumeFromNameHashTable(volp);
--- 434,441 ----
                  name[len - 9] = '\0';
              }
              
!             osi_Log2(afsd_logp, "cm_UpdateVolume name %s -> %s", 
!                      osi_LogSaveString(afsd_logp,volp->namep), osi_LogSaveString(afsd_logp,name));
  
              if (volp->flags & CM_VOLUMEFLAG_IN_HASH)
                  cm_RemoveVolumeFromNameHashTable(volp);
***************
*** 558,563 ****
--- 566,572 ----
              cm_RandomizeServer(&volp->vol[ROVOL].serversp);
          }
  
+ 
          rwNewstate = rwServers_alldown ? vl_alldown : vl_online;
          roNewstate = roServers_alldown ? vl_alldown : vl_online;
          bkNewstate = bkServers_alldown ? vl_alldown : vl_online;
***************
*** 604,610 ****
  
      volp->flags &= ~CM_VOLUMEFLAG_UPDATING_VL;
      osi_Log4(afsd_logp, "cm_UpdateVolumeLocation done, waking others name %s:%s flags 0x%x code 0x%x", 
!              volp->cellp->name, volp->namep, volp->flags, code);
      osi_Wakeup((LONG_PTR) &volp->flags);
  
      return code;
--- 613,620 ----
  
      volp->flags &= ~CM_VOLUMEFLAG_UPDATING_VL;
      osi_Log4(afsd_logp, "cm_UpdateVolumeLocation done, waking others name %s:%s flags 0x%x code 0x%x", 
!              osi_LogSaveString(afsd_logp,volp->cellp->name), 
!              osi_LogSaveString(afsd_logp,volp->namep), volp->flags, code);
      osi_Wakeup((LONG_PTR) &volp->flags);
  
      return code;
***************
*** 846,851 ****
--- 856,864 ----
                      cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_unknown);
                  volp->vol[volType].ID = 0;
                  cm_SetFid(&volp->vol[volType].dotdotFid, 0, 0, 0, 0);
+                 lock_ReleaseWrite(&cm_volumeLock);
+                 cm_FreeServerList(&volp->vol[volType].serversp, CM_FREESERVERLIST_DELETE);
+                 lock_ObtainWrite(&cm_volumeLock);
              }
  	} else {
  	    volp = &cm_data.volumeBaseAddress[cm_data.currentVolumes++];
***************
*** 853,859 ****
  	    volp->magic = CM_VOLUME_MAGIC;
  	    volp->allNextp = cm_data.allVolumesp;
  	    cm_data.allVolumesp = volp;
! 	    lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock");
              lock_ReleaseWrite(&cm_volumeLock);
              lock_ObtainWrite(&volp->rw);
              lock_ObtainWrite(&cm_volumeLock);
--- 866,872 ----
  	    volp->magic = CM_VOLUME_MAGIC;
  	    volp->allNextp = cm_data.allVolumesp;
  	    cm_data.allVolumesp = volp;
! 	    lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock", LOCK_HIERARCHY_VOLUME);
              lock_ReleaseWrite(&cm_volumeLock);
              lock_ObtainWrite(&volp->rw);
              lock_ObtainWrite(&cm_volumeLock);
***************
*** 910,916 ****
      return code;
  }	
  
! void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
  {
      cm_cell_t *cellp;
      cm_volume_t *volp;
--- 923,934 ----
      return code;
  }	
  
! /* 
!  * Only call this function in response to a VNOVOL or VMOVED error
!  * from a file server.  Do not call it in response to CM_ERROR_NOSUCHVOLUME
!  * as that can lead to recursive calls.
!  */
! long cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
  {
      cm_cell_t *cellp;
      cm_volume_t *volp;
***************
*** 918,928 ****
      cm_volume_t *volp2;
  #endif
      afs_uint32  hash;
  
!     if (!fidp) return;
  
      cellp = cm_FindCellByID(fidp->cell, 0);
!     if (!cellp) return;
  
      /* search for the volume */
      lock_ObtainRead(&cm_volumeLock);
--- 936,949 ----
      cm_volume_t *volp2;
  #endif
      afs_uint32  hash;
+     long code;
  
!     if (!fidp) 
!         return CM_ERROR_INVAL;
  
      cellp = cm_FindCellByID(fidp->cell, 0);
!     if (!cellp) 
!         return CM_ERROR_NOSUCHCELL;
  
      /* search for the volume */
      lock_ObtainRead(&cm_volumeLock);
***************
*** 970,1007 ****
      lock_ReleaseRead(&cm_volumeLock);
  
      if (!volp)
!         return;
  
      /* update it */
      cm_data.mountRootGen = time(NULL);
      lock_ObtainWrite(&volp->rw);
      volp->flags |= CM_VOLUMEFLAG_RESET;
! #ifdef COMMENT
!     /* Mark the volume to be updated but don't update it now.
!      * This function is called only from within cm_Analyze
!      * when cm_ConnByMServers has failed with all servers down
!      * The problem is that cm_UpdateVolume is going to call
!      * cm_ConnByMServers which may cause a recursive chain
!      * of calls each returning a retry on failure.
!      * Instead, set the flag so the next time the volume is
!      * accessed by Name or ID the UpdateVolume call will
!      * occur.
!      */
      code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
- #endif
      lock_ReleaseWrite(&volp->rw);
  
      lock_ObtainRead(&cm_volumeLock);
      cm_PutVolume(volp);
      lock_ReleaseRead(&cm_volumeLock);
  }
  
  /* find the appropriate servers from a volume */
! cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume)
  {
      cm_serverRef_t **serverspp;
!     cm_serverRef_t *current;;
  
      lock_ObtainWrite(&cm_serverLock);
  
      if (volume == volp->vol[RWVOL].ID)
--- 991,1021 ----
      lock_ReleaseRead(&cm_volumeLock);
  
      if (!volp)
!         return CM_ERROR_NOSUCHVOLUME;
  
      /* update it */
      cm_data.mountRootGen = time(NULL);
      lock_ObtainWrite(&volp->rw);
      volp->flags |= CM_VOLUMEFLAG_RESET;
! 
      code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
      lock_ReleaseWrite(&volp->rw);
  
      lock_ObtainRead(&cm_volumeLock);
      cm_PutVolume(volp);
      lock_ReleaseRead(&cm_volumeLock);
+ 
+     return code;
  }
  
  /* find the appropriate servers from a volume */
! cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume, cm_user_t *userp, cm_req_t *reqp)
  {
      cm_serverRef_t **serverspp;
!     cm_serverRef_t *current;
!     int firstTry = 1;
  
+   start:
      lock_ObtainWrite(&cm_serverLock);
  
      if (volume == volp->vol[RWVOL].ID)
***************
*** 1010,1019 ****
          serverspp = &volp->vol[ROVOL].serversp;
      else if (volume == volp->vol[BACKVOL].ID)
          serverspp = &volp->vol[BACKVOL].serversp;
!     else 
!         osi_panic("bad volume ID in cm_GetVolServers", __FILE__, __LINE__);
!         
!     for (current = *serverspp; current; current = current->next)
          current->refCount++;
  
      lock_ReleaseWrite(&cm_serverLock);
--- 1024,1049 ----
          serverspp = &volp->vol[ROVOL].serversp;
      else if (volume == volp->vol[BACKVOL].ID)
          serverspp = &volp->vol[BACKVOL].serversp;
!     else {
!         lock_ReleaseWrite(&cm_serverLock);
!         if (firstTry) {
!             afs_int32 code;
!             firstTry = 0;
!             lock_ObtainWrite(&volp->rw);
!             volp->flags |= CM_VOLUMEFLAG_RESET;
!             code = cm_UpdateVolumeLocation(volp->cellp, userp, reqp, volp);
!             lock_ReleaseWrite(&volp->rw);
!             if (code == 0)
!                 goto start;
!         }
!         return NULL;
!     }
! 
!     /* 
!      * Increment the refCount on deleted items as well.
!      * They will be freed by cm_FreeServerList when they get to zero 
!      */
!     for (current = *serverspp; current; current = current->next) 
          current->refCount++;
  
      lock_ReleaseWrite(&cm_serverLock);
***************
*** 1088,1099 ****
  
  }
  
! 
! /* The return code is 0 if the volume is not online and 
!  * 1 if the volume is online
!  */
! long
! cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID)
  {
      cm_conn_t *connp;
      long code;
--- 1118,1126 ----
  
  }
  
! void
! cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32 volID,
!                            afs_uint32 *onlinep, afs_uint32 *volumeUpdatedp)
  {
      cm_conn_t *connp;
      long code;
***************
*** 1106,1245 ****
      char volName[32];
      char offLineMsg[256];
      char motd[256];
!     long online = 0;
      cm_serverRef_t *serversp;
  
      Name = volName;
      OfflineMsg = offLineMsg;
      MOTD = motd;
  
!     lock_ObtainWrite(&volp->rw);
! 
!     if (volp->flags & CM_VOLUMEFLAG_RESET) {
!         cm_InitReq(&req);
!         code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
!     }
! 
!     if (volp->vol[RWVOL].ID != 0 && (!volID || volID == volp->vol[RWVOL].ID) &&
!          volp->vol[RWVOL].serversp) {
!        
!         for (serversp = volp->vol[RWVOL].serversp; serversp; serversp = serversp->next) {
!             if (serversp->status == srv_busy || serversp->status == srv_offline) {
!                 serversp->status = srv_not_busy;
!                 online = 1;
!             }
!         }
! 
!         if (volp->vol[RWVOL].state == vl_busy || volp->vol[RWVOL].state == vl_offline || volp->vol[RWVOL].state == vl_unknown) {
              cm_InitReq(&req);
  
!             lock_ReleaseWrite(&volp->rw);
!             do {
!                 code = cm_ConnFromVolume(volp, volp->vol[RWVOL].ID, cm_rootUserp, &req, &connp);
!                 if (code) 
                      continue;
  
!                 rxconnp = cm_GetRxConn(connp);
!                 code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[RWVOL].ID,
!                                              &volStat, &Name, &OfflineMsg, &MOTD);
!                 rx_PutConnection(rxconnp);            
! 
!             } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
!             code = cm_MapRPCError(code, &req);
! 
!             lock_ObtainWrite(&volp->rw);
!             if (code == 0 && volStat.Online) {
!                 cm_VolumeStatusNotification(volp, volp->vol[RWVOL].ID, volp->vol[RWVOL].state, vl_online);
!                 volp->vol[RWVOL].state = vl_online;
!                 online = 1;
!             } else if (code == CM_ERROR_NOACCESS) {
!                 cm_VolumeStatusNotification(volp, volp->vol[RWVOL].ID, volp->vol[RWVOL].state, vl_unknown);
!                 volp->vol[RWVOL].state = vl_unknown;
!                 online = 1;
              }
-         }
-     }
- 
-     if (volp->vol[ROVOL].ID != 0 && (!volID || volID == volp->vol[ROVOL].ID) &&
-          volp->vol[ROVOL].serversp) {
  
!         for (serversp = volp->vol[ROVOL].serversp; serversp; serversp = serversp->next) {
!             if (serversp->status == srv_busy || serversp->status == srv_offline) {
!                 serversp->status = srv_not_busy;
!                 online = 1;
              }
-         }
  
!         if (volp->vol[ROVOL].state == vl_busy || volp->vol[ROVOL].state == vl_offline || volp->vol[ROVOL].state == vl_unknown) {
!             cm_InitReq(&req);
  
!             lock_ReleaseWrite(&volp->rw);
!             do {
!                 code = cm_ConnFromVolume(volp, volp->vol[ROVOL].ID, cm_rootUserp, &req, &connp);
!                 if (code) 
!                     continue;
  
!                 rxconnp = cm_GetRxConn(connp);
!                 code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[ROVOL].ID,
!                                               &volStat, &Name, &OfflineMsg, &MOTD);
!                 rx_PutConnection(rxconnp);        
  
!             } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
!             code = cm_MapRPCError(code, &req);
  
!             lock_ObtainWrite(&volp->rw);
!             if (code == 0 && volStat.Online) {
!                 cm_VolumeStatusNotification(volp, volp->vol[ROVOL].ID, volp->vol[ROVOL].state, vl_online);
!                 volp->vol[ROVOL].state = vl_online;
!                 online = 1;
!             } else if (code == CM_ERROR_NOACCESS) {
!                 cm_VolumeStatusNotification(volp, volp->vol[ROVOL].ID, volp->vol[ROVOL].state, vl_unknown);
!                 volp->vol[ROVOL].state = vl_unknown;
!                 online = 1;
!             }
          }
      }
  
!     if (volp->vol[BACKVOL].ID != 0 && (!volID || volID == volp->vol[BACKVOL].ID) &&
!          volp->vol[BACKVOL].serversp) {
!         
!         for (serversp = volp->vol[BACKVOL].serversp; serversp; serversp = serversp->next) {
!             if (serversp->status == srv_busy || serversp->status == srv_offline) {
!                 serversp->status = srv_not_busy;
!                 online = 1;
!             }
!         }
! 
!         if (volp->vol[BACKVOL].state == vl_busy || volp->vol[BACKVOL].state == vl_offline || volp->vol[BACKVOL].state == vl_unknown) {
!             cm_InitReq(&req);
! 
!             lock_ReleaseWrite(&volp->rw);
!             do {
!                 code = cm_ConnFromVolume(volp, volp->vol[BACKVOL].ID, cm_rootUserp, &req, &connp);
!                 if (code) 
!                     continue;
! 
!                 rxconnp = cm_GetRxConn(connp);
!                 code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[BACKVOL].ID,
!                                               &volStat, &Name, &OfflineMsg, &MOTD);
!                 rx_PutConnection(rxconnp);        
  
!             } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
!             code = cm_MapRPCError(code, &req);
  
!             lock_ObtainWrite(&volp->rw);
!             if (code == 0 && volStat.Online) {
!                 cm_VolumeStatusNotification(volp, volp->vol[BACKVOL].ID, volp->vol[BACKVOL].state, vl_online);
!                 volp->vol[BACKVOL].state = vl_online;
!                 online = 1;
!             } else if (code == CM_ERROR_NOACCESS) {
!                 cm_VolumeStatusNotification(volp, volp->vol[BACKVOL].ID, volp->vol[BACKVOL].state, vl_unknown);
!                 volp->vol[BACKVOL].state = vl_unknown;
!                 online = 1;
!             }
!         }
      }
  
      lock_ReleaseWrite(&volp->rw);
      return online;
  }
--- 1133,1235 ----
      char volName[32];
      char offLineMsg[256];
      char motd[256];
!     long alldown, alldeleted;
      cm_serverRef_t *serversp;
  
      Name = volName;
      OfflineMsg = offLineMsg;
      MOTD = motd;
  
!     if (statep->ID != 0 && (!volID || volID == statep->ID)) {
!         if (!statep->serversp && !(*volumeUpdatedp)) {
              cm_InitReq(&req);
+             code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
+             *volumeUpdatedp = 1;
+         }
  
!         if (statep->serversp) {
!             alldown = 1;
!             alldeleted = 1;
!             for (serversp = statep->serversp; serversp; serversp = serversp->next) {
!                 if (serversp->status == srv_deleted)
                      continue;
  
!                 alldeleted = 0;
!                 *onlinep = 1;
!                 alldown = 0;
!                 
!                 if (serversp->status == srv_busy || serversp->status == srv_offline)
!                     serversp->status = srv_not_busy;
              }
  
!             if (alldeleted && !(*volumeUpdatedp)) {
!                 cm_InitReq(&req);
!                 code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
!                 *volumeUpdatedp = 1;
              }
  
!             if (statep->state == vl_busy || statep->state == vl_offline || statep->state == vl_unknown ||
!                 (!alldown && statep->state == vl_alldown)) {
!                 cm_InitReq(&req);
  
!                 lock_ReleaseWrite(&volp->rw);
!                 do {
!                     code = cm_ConnFromVolume(volp, statep->ID, cm_rootUserp, &req, &connp);
!                     if (code) 
!                         continue;
  
!                     rxconnp = cm_GetRxConn(connp);
!                     code = RXAFS_GetVolumeStatus(rxconnp, statep->ID,
!                                                  &volStat, &Name, &OfflineMsg, &MOTD);
!                     rx_PutConnection(rxconnp);            
  
!                 } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
!                 code = cm_MapRPCError(code, &req);
  
!                 lock_ObtainWrite(&volp->rw);
!                 if (code == 0 && volStat.Online) {
!                     cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_online);
!                     statep->state = vl_online;
!                     *onlinep = 1;
!                 } else if (code == CM_ERROR_NOACCESS) {
!                     cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_unknown);
!                     statep->state = vl_unknown;
!                     *onlinep = 1;
!                 }
!             } else if (alldown && statep->state != vl_alldown) {
!                 cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown);
!                 statep->state = vl_alldown;
!             }
!         } else if (statep->state != vl_alldown) {
!             cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown);
!             statep->state = vl_alldown;
          }
      }
+ }
  
! /* The return code is 0 if the volume is not online and 
!  * 1 if the volume is online
!  */
! long
! cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID)
! {
!     long code;
!     cm_req_t req;
!     afs_uint32 online = 0;
!     afs_uint32 volumeUpdated = 0;
  
!     lock_ObtainWrite(&volp->rw);
  
!     if (volp->flags & CM_VOLUMEFLAG_RESET) {
!         cm_InitReq(&req);
!         code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
!         volumeUpdated = 1;
      }
  
+     cm_CheckOfflineVolumeState(volp, &volp->vol[RWVOL], volID, &online, &volumeUpdated);
+     cm_CheckOfflineVolumeState(volp, &volp->vol[ROVOL], volID, &online, &volumeUpdated);
+     cm_CheckOfflineVolumeState(volp, &volp->vol[BACKVOL], volID, &online, &volumeUpdated);
+ 
      lock_ReleaseWrite(&volp->rw);
      return online;
  }
***************
*** 1283,1288 ****
--- 1273,1280 ----
  
      lock_ObtainWrite(&cm_serverLock);
      for (tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
+         if (tsrp->status == srv_deleted)
+             continue;
          tsp = tsrp->server;
          if (tsp) {
              cm_GetServerNoLock(tsp);
Index: openafs/src/WINNT/afsd/cm_volume.h
diff -c openafs/src/WINNT/afsd/cm_volume.h:1.5.6.14 openafs/src/WINNT/afsd/cm_volume.h:1.5.6.16
*** openafs/src/WINNT/afsd/cm_volume.h:1.5.6.14	Wed May 28 13:34:52 2008
--- openafs/src/WINNT/afsd/cm_volume.h	Wed Sep 24 18:42:55 2008
***************
*** 89,98 ****
  
  extern long cm_GetROVolumeID(cm_volume_t *volp);
  
! extern void cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp,
  	cm_req_t *reqp);
  
! extern cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume);
  
  extern void cm_ChangeRankVolume(cm_server_t *tsp);
  
--- 89,99 ----
  
  extern long cm_GetROVolumeID(cm_volume_t *volp);
  
! extern long cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp,
  	cm_req_t *reqp);
  
! extern cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume, 
!                                          cm_user_t *userp, cm_req_t *reqp);
  
  extern void cm_ChangeRankVolume(cm_server_t *tsp);
  
***************
*** 124,129 ****
--- 125,134 ----
  
  extern long cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID);
  
+ extern void cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, 
+                                        afs_uint32 volID,  afs_uint32 *onlinep, 
+                                        afs_uint32 *volumeUpdatedp);
+ 
  extern void cm_UpdateVolumeStatus(cm_volume_t *volp, afs_uint32 volID);
  
  extern void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum volstatus oldState, enum volstatus newState);
Index: openafs/src/WINNT/afsd/fs.c
diff -c openafs/src/WINNT/afsd/fs.c:1.32.4.23 openafs/src/WINNT/afsd/fs.c:1.32.4.25
*** openafs/src/WINNT/afsd/fs.c:1.32.4.23	Wed Aug  6 01:11:31 2008
--- openafs/src/WINNT/afsd/fs.c	Tue Sep  2 17:25:55 2008
***************
*** 3998,4005 ****
        flag = 1;
      else if (strcmp(tp, "off") == 0)
        flag = 0;
      else {
!       fprintf (stderr, "%s: %s must be \"on\" or \"off\".\n", pn, tp);
        return EINVAL;
      }
  
--- 3998,4007 ----
        flag = 1;
      else if (strcmp(tp, "off") == 0)
        flag = 0;
+     else if (strcmp(tp, "auth") == 0)
+       flag = 2;
      else {
!       fprintf (stderr, "%s: %s must be \"on\", \"auth\", or \"off\".\n", pn, tp);
        return EINVAL;
      }
  
***************
*** 4032,4038 ****
        tp = space;
        memcpy(&flag, tp, sizeof(afs_int32));
        printf("Security level is currently ");
!       if (flag == 1)
          printf("crypt (data security).\n");
        else
          printf("clear.\n");
--- 4034,4042 ----
        tp = space;
        memcpy(&flag, tp, sizeof(afs_int32));
        printf("Security level is currently ");
!       if (flag == 2)
!           printf("auth (data integrity).\n");
!       else if (flag == 1)
          printf("crypt (data security).\n");
        else
          printf("clear.\n");
Index: openafs/src/WINNT/afsd/smb.c
diff -c openafs/src/WINNT/afsd/smb.c:1.118.2.93 openafs/src/WINNT/afsd/smb.c:1.118.2.98
*** openafs/src/WINNT/afsd/smb.c:1.118.2.93	Thu Aug 14 13:25:06 2008
--- openafs/src/WINNT/afsd/smb.c	Wed Sep  3 16:41:04 2008
***************
*** 851,857 ****
          vcp->uidCounter = 1;  	/* UID 0 is reserved for blank user */
          vcp->nextp = smb_allVCsp;
          smb_allVCsp = vcp;
!         lock_InitializeMutex(&vcp->mx, "vc_t mutex");
          vcp->lsn = lsn;
          vcp->lana = lana;
          vcp->secCtx = NULL;
--- 851,857 ----
          vcp->uidCounter = 1;  	/* UID 0 is reserved for blank user */
          vcp->nextp = smb_allVCsp;
          smb_allVCsp = vcp;
!         lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
          vcp->lsn = lsn;
          vcp->lana = lana;
          vcp->secCtx = NULL;
***************
*** 884,890 ****
  
              if (ntsEx == STATUS_SUCCESS) {
                  memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
-                 LsaFreeReturnBuffer(lsaResp);
              } else {
                  /* 
                   * This will cause the subsequent authentication to fail but
--- 884,889 ----
***************
*** 893,898 ****
--- 892,899 ----
                   */
                  memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
              }
+             if (lsaResp)
+                 LsaFreeReturnBuffer(lsaResp);
          }
          else
              memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
***************
*** 1199,1205 ****
          tidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->tidsp = tidp;
!         lock_InitializeMutex(&tidp->mx, "tid_t mutex");
          tidp->tid = tid;
      }
  #ifdef DEBUG_SMB_REFCOUNT
--- 1200,1206 ----
          tidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->tidsp = tidp;
!         lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
          tidp->tid = tid;
      }
  #ifdef DEBUG_SMB_REFCOUNT
***************
*** 1294,1300 ****
          uidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->usersp = uidp;
!         lock_InitializeMutex(&uidp->mx, "user_t mutex");
          uidp->userID = uid;
          osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
  		 vcp, uidp->userID,
--- 1295,1301 ----
          uidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
          vcp->usersp = uidp;
!         lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
          uidp->userID = uid;
          osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
  		 vcp, uidp->userID,
***************
*** 1325,1331 ****
          unp->name = cm_ClientStrDup(usern);
          unp->machine = cm_ClientStrDup(machine);
          usernamesp = unp;
!         lock_InitializeMutex(&unp->mx, "username_t mutex");
  	if (flags & SMB_FLAG_AFSLOGON)
  	    unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
      }
--- 1326,1332 ----
          unp->name = cm_ClientStrDup(usern);
          unp->machine = cm_ClientStrDup(machine);
          usernamesp = unp;
!         lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
  	if (flags & SMB_FLAG_AFSLOGON)
  	    unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
      }
***************
*** 1571,1577 ****
          fidp->refCount = 1;
          fidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
!         lock_InitializeMutex(&fidp->mx, "fid_t mutex");
          fidp->fid = fid;
          fidp->curr_chunk = fidp->prev_chunk = -2;
          fidp->raw_write_event = event;
--- 1572,1578 ----
          fidp->refCount = 1;
          fidp->vcp = vcp;
          smb_HoldVCNoLock(vcp);
!         lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
          fidp->fid = fid;
          fidp->curr_chunk = fidp->prev_chunk = -2;
          fidp->raw_write_event = event;
***************
*** 1995,2001 ****
          if (code == 0) {
              clientchar_t temp[1024];
  
!             cm_FsStringToClientString(ftemp, (int)cm_FsStrLen(ftemp), temp, 1024);
              cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
                                  rw ? _C("/.%S/") : _C("/%S/"), temp);
              *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
--- 1996,2002 ----
          if (code == 0) {
              clientchar_t temp[1024];
  
!             cm_FsStringToClientString(ftemp, -1, temp, 1024);
              cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
                                  rw ? _C("/.%S/") : _C("/%S/"), temp);
              *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
***************
*** 2071,2079 ****
                  if (!smb_lastDirSearchp)
                      smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
              }
-             lock_ObtainMutex(&dsp->mx);
              dsp->refCount++;
-             lock_ReleaseMutex(&dsp->mx);
              break;
          }
      }
--- 2072,2078 ----
***************
*** 2089,2095 ****
  
  void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
  {
-     lock_ObtainWrite(&smb_globalLock);
      lock_ObtainMutex(&dsp->mx);
      osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p", 
  	      dsp->cookie, dsp, dsp->scp);
--- 2088,2093 ----
***************
*** 2104,2110 ****
          lock_ReleaseWrite(&dsp->scp->rw);
      }	
      lock_ReleaseMutex(&dsp->mx);
-     lock_ReleaseWrite(&smb_globalLock);
  }               
  
  /* Must be called with the smb_globalLock held */
--- 2102,2107 ----
***************
*** 2112,2131 ****
  {
      cm_scache_t *scp = NULL;
  
-     lock_ObtainMutex(&dsp->mx);
      osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
!     if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
!         if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
!             smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
!         osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
!         lock_ReleaseMutex(&dsp->mx);
!         lock_FinalizeMutex(&dsp->mx);
!         scp = dsp->scp;
! 	osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p", 
! 		 dsp->cookie, dsp, scp);
!         free(dsp);
!     } else {
!         lock_ReleaseMutex(&dsp->mx);
      }
      /* do this now to avoid spurious locking hierarchy creation */
      if (scp) 
--- 2109,2130 ----
  {
      cm_scache_t *scp = NULL;
  
      osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
!     if (dsp->refCount == 0) {
!         lock_ObtainMutex(&dsp->mx);
!         if (dsp->flags & SMB_DIRSEARCH_DELETE) {
!             if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
!                 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
!             osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
!             lock_ReleaseMutex(&dsp->mx);
!             lock_FinalizeMutex(&dsp->mx);
!             scp = dsp->scp;
!             osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p", 
!                      dsp->cookie, dsp, scp);
!             free(dsp);
!         } else {
!             lock_ReleaseMutex(&dsp->mx);
!         }
      }
      /* do this now to avoid spurious locking hierarchy creation */
      if (scp) 
***************
*** 2157,2184 ****
  void smb_GCDirSearches(int isV3)
  {
      smb_dirSearch_t *prevp;
!     smb_dirSearch_t *tp;
      smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
      int victimCount;
      int i;
          
      victimCount = 0;	/* how many have we got so far */
!     for (tp = smb_lastDirSearchp; tp; tp=prevp) {
          /* we'll move tp from queue, so
           * do this early.
           */
!         prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);	
          /* if no one is using this guy, and we're either in the new protocol,
           * or we're in the old one and this is a small enough ID to be useful
           * to the old protocol, GC this guy.
           */
!         if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
              /* hold and delete */
! 	    lock_ObtainMutex(&tp->mx);
!             tp->flags |= SMB_DIRSEARCH_DELETE;
! 	    lock_ReleaseMutex(&tp->mx);
!             victimsp[victimCount++] = tp;
!             tp->refCount++;
          }
  
          /* don't do more than this */
--- 2156,2183 ----
  void smb_GCDirSearches(int isV3)
  {
      smb_dirSearch_t *prevp;
!     smb_dirSearch_t *dsp;
      smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
      int victimCount;
      int i;
          
      victimCount = 0;	/* how many have we got so far */
!     for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
          /* we'll move tp from queue, so
           * do this early.
           */
!         prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);	
          /* if no one is using this guy, and we're either in the new protocol,
           * or we're in the old one and this is a small enough ID to be useful
           * to the old protocol, GC this guy.
           */
!         if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
              /* hold and delete */
! 	    lock_ObtainMutex(&dsp->mx);
!             dsp->flags |= SMB_DIRSEARCH_DELETE;
! 	    lock_ReleaseMutex(&dsp->mx);
!             victimsp[victimCount++] = dsp;
!             dsp->refCount++;
          }
  
          /* don't do more than this */
***************
*** 2238,2246 ****
              /* don't need to watch for refcount zero and deleted, since
              * we haven't dropped the global lock.
              */
-             lock_ObtainMutex(&dsp->mx);
              dsp->refCount--;
-             lock_ReleaseMutex(&dsp->mx);
              ++smb_dirSearchCounter;
              continue;
          }	
--- 2237,2243 ----
***************
*** 2250,2256 ****
          dsp->cookie = smb_dirSearchCounter;
          ++smb_dirSearchCounter;
          dsp->refCount = 1;
!         lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
          dsp->lastTime = osi_Time();
          osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
          if (!smb_lastDirSearchp) 
--- 2247,2253 ----
          dsp->cookie = smb_dirSearchCounter;
          ++smb_dirSearchCounter;
          dsp->refCount = 1;
!         lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
          dsp->lastTime = osi_Time();
          osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
          if (!smb_lastDirSearchp) 
***************
*** 2631,2637 ****
  #endif
          cb = sizeof(pktp->data);
      }
!     return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
  }
  
  clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
--- 2628,2635 ----
  #endif
          cb = sizeof(pktp->data);
      }
!     return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
!                               flags | SMB_STRF_SRCNULTERM);
  }
  
  clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
***************
*** 2727,2733 ****
          *stringspp = spacep;
  
          cchdest = lengthof(spacep->wdata);
!         cm_Utf8ToUtf16(inp, (int)*pcb_max, spacep->wdata, cchdest);
  
          return spacep->wdata;
  #ifdef SMB_UNICODE
--- 2725,2732 ----
          *stringspp = spacep;
  
          cchdest = lengthof(spacep->wdata);
!         cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
!                        spacep->wdata, cchdest);
  
          return spacep->wdata;
  #ifdef SMB_UNICODE
***************
*** 5917,5922 ****
--- 5916,5923 ----
          /* if the call worked, stop doing the search now, since we
           * really only want to rename one file.
           */
+     if (code)
+         osi_Log0(smb_logp, "cm_Rename failure");
  	osi_Log1(smb_logp, "cm_Rename returns %ld", code);
      } else if (code == 0) {
          code = CM_ERROR_NOSUCHFILE;
***************
*** 7026,7037 ****
  
      lock_ObtainMutex(&fidp->mx);
      if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
!          && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
          smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
                            fidp->NTopen_dscp, fidp->NTopen_pathp,
                            NULL, TRUE);
!     }       
!     lock_ReleaseMutex(&fidp->mx);
  
      if (code == 0) {
          if (smb_AsyncStore > 0) {
--- 7027,7041 ----
  
      lock_ObtainMutex(&fidp->mx);
      if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
!          && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) 
!     {
!         lock_ReleaseMutex(&fidp->mx);
          smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
                            fidp->NTopen_dscp, fidp->NTopen_pathp,
                            NULL, TRUE);
!     } else {
!         lock_ReleaseMutex(&fidp->mx);
!     }
  
      if (code == 0) {
          if (smb_AsyncStore > 0) {
***************
*** 9449,9462 ****
      smb_logp = logp;
          
      /* and the global lock */
!     lock_InitializeRWLock(&smb_globalLock, "smb global lock");
!     lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
  
      /* Raw I/O data structures */
!     lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
  
!     lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
!     lock_InitializeMutex(&smb_StartedLock, "smb started lock");
  	
      /* 4 Raw I/O buffers */
      smb_RawBufs = calloc(65536,1);
--- 9453,9466 ----
      smb_logp = logp;
          
      /* and the global lock */
!     lock_InitializeRWLock(&smb_globalLock, "smb global lock", LOCK_HIERARCHY_SMB_GLOBAL);
!     lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock", LOCK_HIERARCHY_SMB_RCT_GLOBAL);
  
      /* Raw I/O data structures */
!     lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock", LOCK_HIERARCHY_SMB_RAWBUF);
  
!     lock_InitializeMutex(&smb_ListenerLock, "smb listener lock", LOCK_HIERARCHY_SMB_LISTENER);
!     lock_InitializeMutex(&smb_StartedLock, "smb started lock", LOCK_HIERARCHY_SMB_STARTED);
  	
      /* 4 Raw I/O buffers */
      smb_RawBufs = calloc(65536,1);
***************
*** 9859,9864 ****
--- 9863,9869 ----
              if (fidp->scp != NULL) {
                  cm_scache_t * scp;
  
+                 lock_ReleaseWrite(&smb_rctLock);
                  lock_ObtainMutex(&fidp->mx);
                  if (fidp->scp != NULL) {
                      scp = fidp->scp;
***************
*** 9870,9875 ****
--- 9875,9881 ----
                      cm_ReleaseSCache(scp);
                  }
                  lock_ReleaseMutex(&fidp->mx);
+                 lock_ObtainWrite(&smb_rctLock);
              }
          }
  
Index: openafs/src/WINNT/afsd/smb.h
diff -c openafs/src/WINNT/afsd/smb.h:1.41.2.36 openafs/src/WINNT/afsd/smb.h:1.41.2.37
*** openafs/src/WINNT/afsd/smb.h:1.41.2.36	Sat Aug  9 00:49:50 2008
--- openafs/src/WINNT/afsd/smb.h	Fri Aug 22 14:10:03 2008
***************
*** 649,654 ****
--- 649,655 ----
  #define SMB_STRF_FORCEASCII (1<<0)
  #define SMB_STRF_ANSIPATH   (1<<1)
  #define SMB_STRF_IGNORENUL  (1<<2)
+ #define SMB_STRF_SRCNULTERM (1<<3)
  
  extern clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
                                           char **chainpp, int flags);
Index: openafs/src/WINNT/afsd/smb3.c
diff -c openafs/src/WINNT/afsd/smb3.c:1.95.2.74 openafs/src/WINNT/afsd/smb3.c:1.95.2.79
*** openafs/src/WINNT/afsd/smb3.c:1.95.2.74	Sat Aug  9 00:49:50 2008
--- openafs/src/WINNT/afsd/smb3.c	Sat Sep 13 09:51:50 2008
***************
*** 2644,2650 ****
      case SMB_INFO_VOLUME: 
          /* volume info */
          qi.u.volumeInfo.vsn = 1234;  /* Volume serial number */
!         qi.u.volumeInfo.vnCount = 4; /* Number of characters in label (AFS\0)*/
  
          /* we're supposed to pad it out with zeroes to the end */
          memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
--- 2644,2650 ----
      case SMB_INFO_VOLUME: 
          /* volume info */
          qi.u.volumeInfo.vsn = 1234;  /* Volume serial number */
!         qi.u.volumeInfo.vnCount = 3; /* Number of characters in label (AFS\0)*/
  
          /* we're supposed to pad it out with zeroes to the end */
          memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
***************
*** 2663,2669 ****
          }
  
          qi.u.FSvolumeInfo.vsn = 1234;
!         qi.u.FSvolumeInfo.vnCount = 8; /* This is always in Unicode */
          memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
          break;
  
--- 2663,2670 ----
          }
  
          qi.u.FSvolumeInfo.vsn = 1234;
!         qi.u.FSvolumeInfo.vnCount = 6; /* This is always in Unicode */
!         memset(&qi.u.FSvolumeInfo.label, 0, sizeof(qi.u.FSvolumeInfo.label));
          memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
          break;
  
***************
*** 3070,3076 ****
  	qpi.u.QPfileBasicInfo.reserved = 0;
      }
      else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
! 	smb_fid_t *fidp = smb_FindFIDByScache(vcp, scp);
  
          qpi.u.QPfileStandardInfo.allocationSize = scp->length;
          qpi.u.QPfileStandardInfo.endOfFile = scp->length;
--- 3071,3081 ----
  	qpi.u.QPfileBasicInfo.reserved = 0;
      }
      else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
! 	smb_fid_t * fidp;
!             
!         lock_ReleaseRead(&scp->rw);
!         scp_rw_held = 0;
!         fidp = smb_FindFIDByScache(vcp, scp);
  
          qpi.u.QPfileStandardInfo.allocationSize = scp->length;
          qpi.u.QPfileStandardInfo.endOfFile = scp->length;
***************
*** 3082,3089 ****
          qpi.u.QPfileStandardInfo.reserved = 0;
  
      	if (fidp) {
- 	    lock_ReleaseRead(&scp->rw);
- 	    scp_rw_held = 0;
  	    lock_ObtainMutex(&fidp->mx);
  	    delonclose = fidp->flags & SMB_FID_DELONCLOSE;
  	    lock_ReleaseMutex(&fidp->mx);
--- 3087,3092 ----
***************
*** 6002,6008 ****
              for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
              {
                  for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
!                     if (wl->key == key && LargeIntegerEqualTo(wl->LOffset, LOffset) && 
                          LargeIntegerEqualTo(wl->LLength, LLength)) {
                          wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
                          goto found_lock_request;
--- 6005,6011 ----
              for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
              {
                  for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
!                     if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) && 
                          LargeIntegerEqualTo(wl->LLength, LLength)) {
                          wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
                          goto found_lock_request;
***************
*** 6645,6650 ****
--- 6648,6659 ----
  #define FILE_RANDOM_ACCESS        0x0800
  #define FILE_DELETE_ON_CLOSE      0x1000
  #define FILE_OPEN_BY_FILE_ID      0x2000
+ #define FILE_OPEN_FOR_BACKUP_INTENT             0x00004000
+ #define FILE_NO_COMPRESSION                     0x00008000
+ #define FILE_RESERVE_OPFILTER                   0x00100000
+ #define FILE_OPEN_REPARSE_POINT                 0x00200000
+ #define FILE_OPEN_NO_RECALL                     0x00400000
+ #define FILE_OPEN_FOR_FREE_SPACE_QUERY          0x00800000
  
  /* SMB_COM_NT_CREATE_ANDX */
  long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
***************
*** 6686,6691 ****
--- 6695,6702 ----
      BOOL foundscp;
      cm_req_t req;
      int created = 0;
+     int prefetch = 0;
+     int checkDoneRequired = 0;
      cm_lock_data_t *ldp = NULL;
  
      smb_InitReq(&req);
***************
*** 6870,6875 ****
--- 6881,6888 ----
  	fidflags |= SMB_FID_SEQUENTIAL;
      if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
  	fidflags |= SMB_FID_RANDOM;
+     if (createOptions & FILE_OPEN_REPARSE_POINT)
+         osi_Log0(smb_logp, "NTCreateX Open Reparse Point");
      if (smb_IsExecutableFileName(lastNamep))
          fidflags |= SMB_FID_EXECUTABLE;
  
***************
*** 7078,7083 ****
--- 7091,7097 ----
      if (code == 0 && !treeCreate) {
          code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
          if (code) {
+             cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              if (dscp)
                  cm_ReleaseSCache(dscp);
              if (scp)
***************
*** 7086,7091 ****
--- 7100,7106 ----
              free(realPathp);
              return code;
          }
+         checkDoneRequired = 1;
  
  	if (createDisp == FILE_CREATE) {
              /* oops, file shouldn't be there */
***************
*** 7123,7128 ****
--- 7138,7144 ----
                      scp = targetScp;
  		    code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
  		    if (code) {
+                         cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  			if (dscp)
  			    cm_ReleaseSCache(dscp);
  			if (scp)
***************
*** 7287,7293 ****
  
      if (code) {
          /* something went wrong creating or truncating the file */
! 	if (ldp)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          if (scp) 
              cm_ReleaseSCache(scp);
--- 7303,7309 ----
  
      if (code) {
          /* something went wrong creating or truncating the file */
! 	if (checkDoneRequired)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          if (scp) 
              cm_ReleaseSCache(scp);
***************
*** 7311,7325 ****
                  * we'll just use the symlink anyway.
                  */
                  osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
! 		if (ldp)
  		    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
                  cm_ReleaseSCache(scp);
                  scp = targetScp;
              }
          }
  
          if (scp->fileType != CM_SCACHETYPE_FILE) {
! 	    if (ldp)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              if (dscp)
                  cm_ReleaseSCache(dscp);
--- 7327,7343 ----
                  * we'll just use the symlink anyway.
                  */
                  osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
! 		if (checkDoneRequired) {
  		    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+                     checkDoneRequired = 0;
+                 }
                  cm_ReleaseSCache(scp);
                  scp = targetScp;
              }
          }
  
          if (scp->fileType != CM_SCACHETYPE_FILE) {
! 	    if (checkDoneRequired)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              if (dscp)
                  cm_ReleaseSCache(dscp);
***************
*** 7332,7338 ****
  
      /* (only applies to single component case) */
      if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
! 	if (ldp)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          cm_ReleaseSCache(scp);
          if (dscp)
--- 7350,7356 ----
  
      /* (only applies to single component case) */
      if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
! 	if (checkDoneRequired)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          cm_ReleaseSCache(scp);
          if (dscp)
***************
*** 7381,7387 ****
          lock_ReleaseWrite(&scp->rw);
  
          if (code) {
! 	    if (ldp)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              if (dscp)
--- 7399,7405 ----
          lock_ReleaseWrite(&scp->rw);
  
          if (code) {
! 	    if (checkDoneRequired)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              if (dscp)
***************
*** 7396,7403 ****
      }
  
      /* Now its safe to release the file server lock obtained by cm_CheckNTOpen() */
!     if (ldp)
  	cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  
      lock_ObtainMutex(&fidp->mx);
      /* save a pointer to the vnode */
--- 7414,7423 ----
      }
  
      /* Now its safe to release the file server lock obtained by cm_CheckNTOpen() */
!     if (checkDoneRequired) {
  	cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+         checkDoneRequired = 0;
+     }
  
      lock_ObtainMutex(&fidp->mx);
      /* save a pointer to the vnode */
***************
*** 7461,7471 ****
      if ((fidp->flags & SMB_FID_EXECUTABLE) && 
          LargeIntegerGreaterThanZero(fidp->scp->length) && 
          !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
          cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
                             fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                             userp);
!     }
!     lock_ReleaseRead(&scp->rw);
  
      osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %S", fidp->fid,
                osi_LogSaveClientString(smb_logp, realPathp));
--- 7481,7495 ----
      if ((fidp->flags & SMB_FID_EXECUTABLE) && 
          LargeIntegerGreaterThanZero(fidp->scp->length) && 
          !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+         prefetch = 1;
+     }
+     lock_ReleaseRead(&scp->rw);
+ 
+     if (prefetch)
          cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
                             fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                             userp);
! 
  
      osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %S", fidp->fid,
                osi_LogSaveClientString(smb_logp, realPathp));
***************
*** 7505,7519 ****
      unsigned int extendedRespRequired;
      int realDirFlag;
      unsigned int desiredAccess;
- #ifdef DEBUG_VERBOSE    
      unsigned int allocSize;
- #endif
      unsigned int shareAccess;
      unsigned int extAttributes;
      unsigned int createDisp;
- #ifdef DEBUG_VERBOSE
      unsigned int sdLen;
! #endif
      unsigned int createOptions;
      int initialModeBits;
      unsigned short baseFid;
--- 7529,7542 ----
      unsigned int extendedRespRequired;
      int realDirFlag;
      unsigned int desiredAccess;
      unsigned int allocSize;
      unsigned int shareAccess;
      unsigned int extAttributes;
      unsigned int createDisp;
      unsigned int sdLen;
!     unsigned int eaLen;
!     unsigned int impLevel;
!     unsigned int secFlags;
      unsigned int createOptions;
      int initialModeBits;
      unsigned short baseFid;
***************
*** 7532,7538 ****
--- 7555,7563 ----
      char *outData;
      cm_req_t req;
      int created = 0;
+     int prefetch = 0;
      cm_lock_data_t *ldp = NULL;
+     int checkDoneRequired = 0;
  
      smb_InitReq(&req);
  
***************
*** 7558,7580 ****
          return CM_ERROR_INVAL;
      baseFid = (unsigned short)lparmp[1];
      desiredAccess = lparmp[2];
- #ifdef DEBUG_VERBOSE
      allocSize = lparmp[3];
- #endif /* DEBUG_VERSOSE */
      extAttributes = lparmp[5];
      shareAccess = lparmp[6];
      createDisp = lparmp[7];
      createOptions = lparmp[8];
- #ifdef DEBUG_VERBOSE
      sdLen = lparmp[9];
! #endif
!     nameLength = lparmp[11];
! 
! #ifdef DEBUG_VERBOSE
!     osi_Log4(smb_logp,"NTTranCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
!     osi_Log3(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
!     osi_Log1(smb_logp,"... flags[%x]",flags);
! #endif
  
      /* mustBeDir is never set; createOptions directory bit seems to be
       * more important
--- 7583,7598 ----
          return CM_ERROR_INVAL;
      baseFid = (unsigned short)lparmp[1];
      desiredAccess = lparmp[2];
      allocSize = lparmp[3];
      extAttributes = lparmp[5];
      shareAccess = lparmp[6];
      createDisp = lparmp[7];
      createOptions = lparmp[8];
      sdLen = lparmp[9];
!     eaLen = lparmp[10];
!     nameLength = lparmp[11];    /* spec says chars but appears to be bytes */
!     impLevel = lparmp[12];
!     secFlags = lparmp[13];
  
      /* mustBeDir is never set; createOptions directory bit seems to be
       * more important
***************
*** 7594,7608 ****
      if (extAttributes & SMB_ATTR_READONLY) 
          initialModeBits &= ~0222;
  
!     pathp = smb_ParseStringCch(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
                                 nameLength, NULL, SMB_STRF_ANSIPATH);
!     /* Sometimes path is not null-terminated, so we make a copy. */
!     realPathp = malloc((nameLength+1) * sizeof(clientchar_t));
!     memcpy(realPathp, pathp, nameLength * sizeof(clientchar_t));
!     realPathp[nameLength] = 0;
      spacep = cm_GetSpace();
      smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
  
      /*
       * Nothing here to handle SMB_IOCTL_FILENAME.
       * Will add it if necessary.
--- 7612,7631 ----
      if (extAttributes & SMB_ATTR_READONLY) 
          initialModeBits &= ~0222;
  
!     pathp = smb_ParseStringCb(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
                                 nameLength, NULL, SMB_STRF_ANSIPATH);
!     /* Sometimes path is not nul-terminated, so we make a copy. */
!     realPathp = malloc(nameLength+sizeof(clientchar_t));
!     memcpy(realPathp, pathp, nameLength);
!     realPathp[nameLength/sizeof(clientchar_t)] = 0;
      spacep = cm_GetSpace();
      smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
  
+     osi_Log1(smb_logp,"NTTranCreate %S",osi_LogSaveStringW(smb_logp,realPathp));
+     osi_Log4(smb_logp,"... da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+     osi_Log4(smb_logp,"... co[%x],sdl[%x],eal[%x],as[%x],flags[%x]",createOptions,sdLen,eaLen,allocSize);
+     osi_Log3(smb_logp,"... imp[%x],sec[%x],flags[%x]", impLevel, secFlags, flags);
+ 
      /*
       * Nothing here to handle SMB_IOCTL_FILENAME.
       * Will add it if necessary.
***************
*** 7677,7682 ****
--- 7700,7707 ----
  	fidflags |= SMB_FID_SEQUENTIAL;
      if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
  	fidflags |= SMB_FID_RANDOM;
+     if (createOptions & FILE_OPEN_REPARSE_POINT)
+         osi_Log0(smb_logp, "NTTranCreate Open Reparse Point");
      if (smb_IsExecutableFileName(lastNamep))
          fidflags |= SMB_FID_EXECUTABLE;
  
***************
*** 7819,7824 ****
--- 7844,7850 ----
      if (code == 0) {
          code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
          if (code) {     
+             cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              if (dscp) 
                  cm_ReleaseSCache(dscp);
              cm_ReleaseSCache(scp);
***************
*** 7826,7831 ****
--- 7852,7858 ----
              free(realPathp);
              return code;
          }
+         checkDoneRequired = 1;
  
          if (createDisp == FILE_CREATE) {
              /* oops, file shouldn't be there */
***************
*** 7861,7866 ****
--- 7888,7894 ----
                      scp = targetScp;
  		    code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
  		    if (code) {
+                         cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  			if (dscp)
  			    cm_ReleaseSCache(dscp);
  			if (scp)
***************
*** 7963,7969 ****
  
      if (code) {
          /* something went wrong creating or truncating the file */
! 	if (ldp)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  	if (scp) 
              cm_ReleaseSCache(scp);
--- 7991,7997 ----
  
      if (code) {
          /* something went wrong creating or truncating the file */
! 	if (checkDoneRequired)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  	if (scp) 
              cm_ReleaseSCache(scp);
***************
*** 7986,8000 ****
                  */
                  osi_Log2(smb_logp, "symlink vp %x to vp %x",
                            scp, targetScp);
! 		if (ldp)
  		    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
                  cm_ReleaseSCache(scp);
                  scp = targetScp;
              }
          }
  
          if (scp->fileType != CM_SCACHETYPE_FILE) {
! 	    if (ldp)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              cm_ReleaseUser(userp);
--- 8014,8030 ----
                  */
                  osi_Log2(smb_logp, "symlink vp %x to vp %x",
                            scp, targetScp);
! 		if (checkDoneRequired) {
  		    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+                     checkDoneRequired = 0;
+                 }
                  cm_ReleaseSCache(scp);
                  scp = targetScp;
              }
          }
  
          if (scp->fileType != CM_SCACHETYPE_FILE) {
! 	    if (checkDoneRequired)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              cm_ReleaseUser(userp);
***************
*** 8004,8010 ****
      }
  
      if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
! 	if (ldp)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          cm_ReleaseSCache(scp);
          cm_ReleaseUser(userp);
--- 8034,8040 ----
      }
  
      if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
! 	if (checkDoneRequired)
  	    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
          cm_ReleaseSCache(scp);
          cm_ReleaseUser(userp);
***************
*** 8049,8055 ****
          lock_ReleaseWrite(&scp->rw);
  
          if (code) {
! 	    if (ldp)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              cm_ReleaseUser(userp);
--- 8079,8085 ----
          lock_ReleaseWrite(&scp->rw);
  
          if (code) {
! 	    if (checkDoneRequired)
  		cm_CheckNTOpenDone(scp, userp, &req, &ldp);
              cm_ReleaseSCache(scp);
              cm_ReleaseUser(userp);
***************
*** 8062,8069 ****
      }
  
      /* Now its safe to drop the file server lock obtained by cm_CheckNTOpen() */
!     if (ldp)
  	cm_CheckNTOpenDone(scp, userp, &req, &ldp);
  
      lock_ObtainMutex(&fidp->mx);
      /* save a pointer to the vnode */
--- 8092,8101 ----
      }
  
      /* Now its safe to drop the file server lock obtained by cm_CheckNTOpen() */
!     if (checkDoneRequired) {
  	cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+         checkDoneRequired = 0;
+     }
  
      lock_ObtainMutex(&fidp->mx);
      /* save a pointer to the vnode */
***************
*** 8206,8216 ****
      if ((fidp->flags & SMB_FID_EXECUTABLE) && 
           LargeIntegerGreaterThanZero(fidp->scp->length) && 
           !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
          cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
                             fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                             userp);
-     }
-     lock_ReleaseRead(&scp->rw);
  
      osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
  
--- 8238,8251 ----
      if ((fidp->flags & SMB_FID_EXECUTABLE) && 
           LargeIntegerGreaterThanZero(fidp->scp->length) && 
           !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+         prefetch = 1;
+     }
+     lock_ReleaseRead(&scp->rw);
+ 
+     if (prefetch)
          cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
                             fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
                             userp);
  
      osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
  
***************
*** 8511,8522 ****
              (!isDirectParent && !wtree)) 
          {
              osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
-             smb_ReleaseFID(fidp);
              lastWatch = watch;
              watch = watch->nextp;
              continue;
          }
-         smb_ReleaseFID(fidp);
  
          osi_Log4(smb_logp,
                    "Sending Change Notification for fid %d filter 0x%x wtree %d file %S",
--- 8546,8558 ----
              (!isDirectParent && !wtree)) 
          {
              osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
              lastWatch = watch;
              watch = watch->nextp;
+             lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+             smb_ReleaseFID(fidp);
+             lock_ObtainMutex(&smb_Dir_Watch_Lock);
              continue;
          }
  
          osi_Log4(smb_logp,
                    "Sending Change Notification for fid %d filter 0x%x wtree %d file %S",
***************
*** 8553,8558 ****
--- 8589,8597 ----
          else
              lastWatch->nextp = nextWatch;
  
+         /* The watch is off the list, its ours now, safe to drop the lock */
+         lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+ 
          /* Turn off WATCHED flag in dscp */
          lock_ObtainWrite(&dscp->rw);
          if (wtree)
***************
*** 8653,8658 ****
--- 8692,8700 ----
  
          smb_SendPacket(watch->vcp, watch);
          smb_FreePacket(watch);
+ 
+         smb_ReleaseFID(fidp);
+         lock_ObtainMutex(&smb_Dir_Watch_Lock);
          watch = nextWatch;
      }
      lock_ReleaseMutex(&smb_Dir_Watch_Lock);
***************
*** 8763,8781 ****
      osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
               osi_LogSaveClientString(smb_logp, oldPathp),
               osi_LogSaveClientString(smb_logp, newPathp),
!              ((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink"));
  
      if (rename_type == RENAME_FLAG_RENAME) {
          code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
!     } else { /* RENAME_FLAG_HARD_LINK */
          code = smb_Link(vcp,inp,oldPathp,newPathp);
!     }
      return code;
  }
  
  void smb3_Init()
  {
!     lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
  }
  
  cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)
--- 8805,8824 ----
      osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
               osi_LogSaveClientString(smb_logp, oldPathp),
               osi_LogSaveClientString(smb_logp, newPathp),
!              ((rename_type==RENAME_FLAG_RENAME)?"rename":(rename_type==RENAME_FLAG_HARD_LINK)?"hardlink":"other"));
  
      if (rename_type == RENAME_FLAG_RENAME) {
          code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
!     } else if (rename_type == RENAME_FLAG_HARD_LINK) { /* RENAME_FLAG_HARD_LINK */
          code = smb_Link(vcp,inp,oldPathp,newPathp);
!     } else 
!         code = CM_ERROR_BADOP;
      return code;
  }
  
  void smb3_Init()
  {
!     lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock", LOCK_HIERARCHY_SMB_DIRWATCH);
  }
  
  cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)
Index: openafs/src/WINNT/afsd/smb_ioctl.c
diff -c openafs/src/WINNT/afsd/smb_ioctl.c:1.25.2.16 openafs/src/WINNT/afsd/smb_ioctl.c:1.25.2.17
*** openafs/src/WINNT/afsd/smb_ioctl.c:1.25.2.16	Sat Jul 26 22:48:11 2008
--- openafs/src/WINNT/afsd/smb_ioctl.c	Tue Sep  2 17:21:35 2008
***************
*** 1064,1071 ****
          int cch;
  
          cch = cm_ClientStringToUtf8(uidp->unp->name,
!                                     cm_ClientStrLen(uidp->unp->name),
! 
                                      ioctlp->ioctl.outDatap,
                                      (SMB_IOCTL_MAXDATA -
                                       (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
--- 1064,1070 ----
          int cch;
  
          cch = cm_ClientStringToUtf8(uidp->unp->name,
!                                     -1,
                                      ioctlp->ioctl.outDatap,
                                      (SMB_IOCTL_MAXDATA -
                                       (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
Index: openafs/src/WINNT/client_creds/main.cpp
diff -c openafs/src/WINNT/client_creds/main.cpp:1.16.4.2 openafs/src/WINNT/client_creds/main.cpp:1.16.4.3
*** openafs/src/WINNT/client_creds/main.cpp:1.16.4.2	Mon Feb 11 11:44:27 2008
--- openafs/src/WINNT/client_creds/main.cpp	Fri Aug 22 14:10:08 2008
***************
*** 254,261 ****
     InitCommonControls();
     RegisterCheckListClass();
     osi_Init();
!    lock_InitializeMutex(&g.expirationCheckLock, "expiration check lock");
!    lock_InitializeMutex(&g.credsLock, "global creds lock");
  
     KFW_AFS_wait_for_service_start();
  
--- 254,261 ----
     InitCommonControls();
     RegisterCheckListClass();
     osi_Init();
!    lock_InitializeMutex(&g.expirationCheckLock, "expiration check lock", 0);
!    lock_InitializeMutex(&g.credsLock, "global creds lock", 0);
  
     KFW_AFS_wait_for_service_start();
  
Index: openafs/src/WINNT/client_osi/libosi.def
diff -c openafs/src/WINNT/client_osi/libosi.def:1.3.14.3 openafs/src/WINNT/client_osi/libosi.def:1.3.14.4
*** openafs/src/WINNT/client_osi/libosi.def:1.3.14.3	Thu Jun 26 12:00:53 2008
--- openafs/src/WINNT/client_osi/libosi.def	Sat Aug 30 10:05:14 2008
***************
*** 72,74 ****
--- 72,75 ----
          osi_QRemoveHT           @65
  	lock_ConvertRToW	@66
          osi_LogSaveStringW      @67
+         osi_SetLockOrderValidation @68
Index: openafs/src/WINNT/client_osi/osi.h
diff -c openafs/src/WINNT/client_osi/osi.h:1.5.14.1 openafs/src/WINNT/client_osi/osi.h:1.5.14.2
*** openafs/src/WINNT/client_osi/osi.h:1.5.14.1	Mon Sep 10 15:02:39 2007
--- openafs/src/WINNT/client_osi/osi.h	Fri Aug 22 14:10:08 2008
***************
*** 17,31 ****
  /* misc definitions */
  
  /* large int */
- #ifndef DJGPP
  #include <rpc.h>
  #if !defined(_MSC_VER) || (_MSC_VER < 1300)
  #include "largeint.h"
  #endif
  #include "osithrdnt.h"
- #else /* DJGPP */
- #include "largeint95.h"
- #endif /* !DJGPP */
  
  typedef LARGE_INTEGER osi_hyper_t;
  #if _MSC_VER >= 1300
--- 17,27 ----
***************
*** 62,76 ****
  
  #define LargeIntegerNotEqualToZero(a) ((a).HighPart || (a).LowPart)
  #endif
- #ifndef DJGPP
  typedef GUID osi_uid_t;
- #else /* DJGPP */
- typedef int osi_uid_t;
- #endif /* !DJGPP */
- 
  typedef int int32;
  
- #ifndef DJGPP
  /* basic util functions */
  #include "osiutils.h"
  
--- 58,66 ----
***************
*** 79,90 ****
  
  /* lock type definitions */
  #include "osiltype.h"
- #endif /* !DJGPP */
  
  /* basic sleep operations */
  #include "osisleep.h"
  
- #ifndef DJGPP
  /* base lock definitions */
  #include "osibasel.h"
  
--- 69,78 ----
***************
*** 93,101 ****
  
  /* RPC debug stuff */
  #include "osidb.h"
- #else /* DJGPP */
- #include "osithrd95.h"
- #endif /* !DJGPP */
  
  /* log stuff */
  #include "osilog.h"
--- 81,86 ----
Index: openafs/src/WINNT/client_osi/osibasel.c
diff -c openafs/src/WINNT/client_osi/osibasel.c:1.4.4.3 openafs/src/WINNT/client_osi/osibasel.c:1.4.4.6
*** openafs/src/WINNT/client_osi/osibasel.c:1.4.4.3	Wed Feb 27 12:06:44 2008
--- openafs/src/WINNT/client_osi/osibasel.c	Sat Aug 30 10:05:14 2008
***************
*** 16,549 ****
  #include <windows.h>
  #include "osi.h"
  #include <assert.h>
  
  /* atomicity-providing critical sections */
  CRITICAL_SECTION osi_baseAtomicCS[OSI_MUTEXHASHSIZE];
  static long     atomicIndexCounter = 0;
  
  void osi_BaseInit(void)
  {
! 	int i;
! 
!         for(i=0; i<OSI_MUTEXHASHSIZE; i++)
! 		InitializeCriticalSection(&osi_baseAtomicCS[i]);
! }
  
! void lock_ObtainWrite(osi_rwlock_t *lockp)
! {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ObtainWriteProc)(lockp);
! 	    return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)
! 		|| (lockp->readers > 0)) {
!                 lockp->waiters++;
! 		osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!                 lockp->waiters--;
! 		osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
! 	}
!         else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->flags |= OSI_LOCKFLAG_EXCL;
! 	}
  
!         lockp->tid = thrd_Current();
  
! 	LeaveCriticalSection(csp);
  }
  
! void lock_ObtainRead(osi_rwlock_t *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ObtainReadProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
! 		lockp->waiters++;
! 		osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
! 		lockp->waiters--;
! 		osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
! 	}
!         else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->readers++;
! 	}
  
!         LeaveCriticalSection(csp);
  }
  
! void lock_ReleaseRead(osi_rwlock_t *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ReleaseReadProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(lockp->readers > 0, "read lock not held");
! 	
! 	/* releasing a read lock can allow readers or writers */
! 	if (--lockp->readers == 0 && !osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, csp);
! 	}
!         else {
! 		/* and finally release the big lock */
! 		LeaveCriticalSection(csp);
! 	}
  }
  
! void lock_ReleaseWrite(osi_rwlock_t *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ReleaseWriteProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
  
! 	osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
! 	
!         lockp->tid = 0;
  
! 	lockp->flags &= ~OSI_LOCKFLAG_EXCL;
! 	if (!osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, csp);
! 	}
! 	else {
! 		/* and finally release the big lock */
! 		LeaveCriticalSection(csp);
! 	}
  }
  
! void lock_ConvertWToR(osi_rwlock_t *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ConvertWToRProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
  
! 	osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
! 	
! 	/* convert write lock to read lock */
! 	lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!         lockp->readers++;
  
!         lockp->tid = 0;
  
! 	if (!osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, /* still have readers */ 1, csp);
! 	}
!         else {
! 		/* and finally release the big lock */
! 		LeaveCriticalSection(csp);
! 	}
  }
  
  void lock_ConvertRToW(osi_rwlock_t *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ConvertRToWProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(!(lockp->flags & OSI_LOCKFLAG_EXCL), "write lock held");
!         osi_assertx(lockp->readers > 0, "read lock not held");
! 	
!         if (--lockp->readers == 0) {
!             /* convert read lock to write lock */
!             lockp->flags |= OSI_LOCKFLAG_EXCL;
!         } else {
!             lockp->waiters++;
!             osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!             lockp->waiters--;
!             osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
! 	}
  
!         lockp->tid = thrd_Current();
!         LeaveCriticalSection(csp);
! }
  
  void lock_ObtainMutex(struct osi_mutex *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i=lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ObtainMutexProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
!         	lockp->waiters++;
! 		osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!                 lockp->waiters--;
! 		osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
! 	}
!         else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->flags |= OSI_LOCKFLAG_EXCL;
! 	}
!         lockp->tid = thrd_Current();
! 	LeaveCriticalSection(csp);
  }
  
  void lock_ReleaseMutex(struct osi_mutex *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->ReleaseMutexProc)(lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "mutex not held");
! 	
! 	lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!         lockp->tid = 0;
! 	if (!osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, csp);
! 	}
! 	else {
! 		/* and finally release the big lock */
! 		LeaveCriticalSection(csp);
! 	}
! }
  
  int lock_TryRead(struct osi_rwlock *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=lockp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		return (osi_lockOps[i]->TryReadProc)(lockp);
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
! 		i = 0;
! 	}
! 	else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->readers++;
! 		i = 1;
! 	}
  
! 	LeaveCriticalSection(csp);
  
! 	return i;
! }
  
  
  int lock_TryWrite(struct osi_rwlock *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=lockp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		return (osi_lockOps[i]->TryWriteProc)(lockp);
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)
! 		|| (lockp->readers > 0)) {
! 		i = 0;
! 	}
! 	else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->flags |= OSI_LOCKFLAG_EXCL;
! 		i = 1;
! 	}
  
! 	if (i)
! 	    lockp->tid = thrd_Current();
  
!         LeaveCriticalSection(csp);
  
! 	return i;
  }
  
  
  int lock_TryMutex(struct osi_mutex *lockp) {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i=lockp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		return (osi_lockOps[i]->TryMutexProc)(lockp);
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
! 		i = 0;
! 	}
! 	else {
! 		/* if we're here, all clear to set the lock */
! 		lockp->flags |= OSI_LOCKFLAG_EXCL;
! 		i = 1;
! 	}
  
!         if (i)
! 	    lockp->tid = thrd_Current();
  
! 	LeaveCriticalSection(csp);
  
! 	return i;
  }
  
  void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->SleepRProc)(sleepVal, lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(lockp->readers > 0, "osi_SleepR: not held");
! 	
! 	/* XXX better to get the list of things to wakeup from TSignalForMLs, and
!          * then do the wakeup after SleepSpin releases the low-level mutex.
!          */
! 	if (--lockp->readers == 0 && !osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
! 	}
! 
! 	/* now call into scheduler to sleep atomically with releasing spin lock */
! 	osi_SleepSpin(sleepVal, csp);
! }
  
  void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
! 
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->SleepWProc)(sleepVal, lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepW: not held");
! 	
! 	lockp->flags &= ~OSI_LOCKFLAG_EXCL;
! 	if (!osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
! 	}
  
! 	/* and finally release the big lock */
! 	osi_SleepSpin(sleepVal, csp);
  }
  
  void osi_SleepM(LONG_PTR sleepVal, struct osi_mutex *lockp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i = lockp->type) != 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->SleepMProc)(sleepVal, lockp);
! 		return;
! 	}
! 
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lockp->atomicIndex];
!         EnterCriticalSection(csp);
! 
! 	osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepM not held");
  	
! 	lockp->flags &= ~OSI_LOCKFLAG_EXCL;
! 	if (!osi_TEmpty(&lockp->d.turn)) {
! 		osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
! 	}
  
! 	/* and finally release the big lock */
! 	osi_SleepSpin(sleepVal, csp);
  }
  
  void lock_FinalizeRWLock(osi_rwlock_t *lockp)
  {
! 	long i;
  
! 	if ((i=lockp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->FinalizeRWLockProc)(lockp);
! }
  
  void lock_FinalizeMutex(osi_mutex_t *lockp)
! {
! 	long i;
! 
! 	if ((i=lockp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->FinalizeMutexProc)(lockp);
! }
! 
! void lock_InitializeMutex(osi_mutex_t *mp, char *namep)
! {
! 	int i;
  
! 	if ((i = osi_lockTypeDefault) > 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->InitializeMutexProc)(mp, namep);
! 		return;
! 	}
! 
! 	/* otherwise we have the base case, which requires no special
! 	 * initialization.
! 	 */
! 	mp->type = 0;
! 	mp->flags = 0;
!         mp->tid = 0;
! 	mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
!         osi_TInit(&mp->d.turn);
! 	return;
! }
! 
! void lock_InitializeRWLock(osi_rwlock_t *mp, char *namep)
! {
! 	int i;
! 
! 	if ((i = osi_lockTypeDefault) > 0) {
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		(osi_lockOps[i]->InitializeRWLockProc)(mp, namep);
! 		return;
! 	}
  	
! 	/* otherwise we have the base case, which requires no special
! 	 * initialization.
! 	 */
! 	mp->type = 0;
! 	mp->flags = 0;
!         mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
! 	mp->readers = 0;
!         mp->tid = 0;
!         osi_TInit(&mp->d.turn);
! 	return;
  }
  
  int lock_GetRWLockState(osi_rwlock_t *lp)
  {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=lp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		return (osi_lockOps[i]->GetRWLockState)(lp);
  
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[lp->atomicIndex];
!         EnterCriticalSection(csp);
  
! 	/* here we have the fast lock, so see if we can obtain the real lock */
! 	if (lp->flags & OSI_LOCKFLAG_EXCL) i = OSI_RWLOCK_WRITEHELD;
!         else i = 0;
! 	if (lp->readers > 0) i |= OSI_RWLOCK_READHELD;
  
! 	LeaveCriticalSection(csp);
  
! 	return i;
  }
  
! int lock_GetMutexState(struct osi_mutex *mp) {
! 	long i;
!         CRITICAL_SECTION *csp;
  
! 	if ((i=mp->type) != 0)
! 	    if (i >= 0 && i < OSI_NLOCKTYPES)
! 		return (osi_lockOps[i]->GetMutexState)(mp);
  
! 	/* otherwise we're the fast base type */
! 	csp = &osi_baseAtomicCS[mp->atomicIndex];
!         EnterCriticalSection(csp);
  
! 	if (mp->flags & OSI_LOCKFLAG_EXCL)
!         	i = OSI_MUTEX_HELD;
! 	else
!         	i = 0;
  
! 	LeaveCriticalSection(csp);
  
! 	return i;
  }
--- 16,881 ----
  #include <windows.h>
  #include "osi.h"
  #include <assert.h>
+ #include <stdio.h>
  
  /* atomicity-providing critical sections */
  CRITICAL_SECTION osi_baseAtomicCS[OSI_MUTEXHASHSIZE];
  static long     atomicIndexCounter = 0;
  
+ /* Thread local storage index for lock tracking */
+ static DWORD tls_LockRefH = 0;
+ static DWORD tls_LockRefT = 0;
+ static BOOLEAN lockOrderValidation = 0;
+ 
  void osi_BaseInit(void)
  {
!     int i;
  
!     for(i=0; i<OSI_MUTEXHASHSIZE; i++)
!         InitializeCriticalSection(&osi_baseAtomicCS[i]);
  
!     if ((tls_LockRefH = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
!         osi_panic("TlsAlloc(tls_LockRefH) failure", __FILE__, __LINE__); 
  
!     if ((tls_LockRefT = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
!         osi_panic("TlsAlloc(tls_LockRefT) failure", __FILE__, __LINE__); 
! }       
  
! void osi_SetLockOrderValidation(int on)
! {
!     lockOrderValidation = (BOOLEAN)on;
  }
  
! osi_lock_ref_t *lock_GetLockRef(void * lockp, char type)
  {
!     osi_lock_ref_t * lockRefp = (osi_lock_ref_t *)malloc(sizeof(osi_lock_ref_t));
  
!     memset(lockRefp, 0, sizeof(osi_lock_ref_t));
!     lockRefp->type = type;
!     switch (type) {
!     case OSI_LOCK_MUTEX:
!         lockRefp->mx = lockp;
!         break;
!     case OSI_LOCK_RW:
!         lockRefp->rw = lockp;
!         break;
!     default:
!         osi_panic("Invalid Lock Type", __FILE__, __LINE__);
!     }
  
!     return lockRefp;
  }
  
! void lock_VerifyOrderRW(osi_queue_t *lockRefH, osi_queue_t *lockRefT, osi_rwlock_t *lockp)
  {
!     char msg[512];
!     osi_lock_ref_t * lockRefp;
  
!     for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!         if (lockRefp->type == OSI_LOCK_RW) {
!             if (lockRefp->rw == lockp) {
!                 sprintf(msg, "RW Lock 0x%p level %d already held", lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!             if (lockRefp->rw->level > lockp->level) {
!                 sprintf(msg, "Lock hierarchy violation Held lock 0x%p level %d > Requested lock 0x%p level %d",
!                          lockRefp->rw, lockRefp->rw->level, lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!         } else {
!             if (lockRefp->mx->level > lockp->level) {
!                 sprintf(msg, "Lock hierarchy violation Held lock 0x%p level %d > Requested lock 0x%p level %d",
!                          lockRefp->mx, lockRefp->mx->level, lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!             osi_assertx(lockRefp->mx->level <= lockp->level, "Lock hierarchy violation");
!         }
!     }
! }
! 
! void lock_VerifyOrderMX(osi_queue_t *lockRefH, osi_queue_t *lockRefT, osi_mutex_t *lockp)
! {
!     char msg[512];
!     osi_lock_ref_t * lockRefp;
! 
!     for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!         if (lockRefp->type == OSI_LOCK_MUTEX) {
!             if (lockRefp->mx == lockp) {
!                 sprintf(msg, "MX Lock 0x%p level %d already held", lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!             if (lockRefp->mx->level > lockp->level) {
!                 sprintf(msg, "Lock hierarchy violation Held lock 0x%p level %d > Requested lock 0x%p level %d",
!                          lockRefp->mx, lockRefp->mx->level, lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!         } else {
!             if (lockRefp->rw->level > lockp->level) {
!                 sprintf(msg, "Lock hierarchy violation Held lock 0x%p level %d > Requested lock 0x%p level %d",
!                          lockRefp->rw, lockRefp->rw->level, lockp, lockp->level);
!                 osi_panic(msg, __FILE__, __LINE__);
!             }
!         }
!     }
  }
  
! void lock_ObtainWrite(osi_rwlock_t *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
!         
!     if ((i=lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ObtainWriteProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) 
!             lock_VerifyOrderRW(lockRefH, lockRefT, lockp);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL) || 
!         (lockp->readers > 0)) {
!         lockp->waiters++;
!         osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!         lockp->waiters--;
!         osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->flags |= OSI_LOCKFLAG_EXCL;
!     }
! 
!     lockp->tid = thrd_Current();
! 
!     LeaveCriticalSection(csp);
! 
!     if (lockOrderValidation) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! }       
  
! void lock_ObtainRead(osi_rwlock_t *lockp)
! {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
!         
!     if ((i=lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ObtainReadProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) 
!             lock_VerifyOrderRW(lockRefH, lockRefT, lockp);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
!         lockp->waiters++;
!         osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
!         lockp->waiters--;
!         osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->readers++;
!     }
  
!     LeaveCriticalSection(csp);
  
!     if (lockOrderValidation) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
  }
  
! void lock_ReleaseRead(osi_rwlock_t *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
!         
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ReleaseReadProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         int found = 0;
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 found = 1;
!                 break;
!             }
!         }
!         osi_assertx(found, "read lock not found in TLS queue");
! 
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->readers > 0, "read lock not held");
! 
!     /* releasing a read lock can allow readers or writers */
!     if (--lockp->readers == 0 && !osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, csp);
!     }
!     else {
!         /* and finally release the big lock */
!         LeaveCriticalSection(csp);
!     }
! }
  
! void lock_ReleaseWrite(osi_rwlock_t *lockp)
! {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ReleaseWriteProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         int found = 0;
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 found = 1;
!                 break;
!             }
!         }
!         osi_assertx(found, "write lock not found in TLS queue");
! 
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
!     osi_assertx(lockp->tid == thrd_Current(), "write lock not held by current thread");
! 
!     lockp->tid = 0;
! 
!     lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!     if (!osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, csp);
!     }
!     else {
!         /* and finally release the big lock */
!         LeaveCriticalSection(csp);
!     }
! }       
  
! void lock_ConvertWToR(osi_rwlock_t *lockp)
! {
!     long i;
!     CRITICAL_SECTION *csp;
  
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ConvertWToRProc)(lockp);
!         return;
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
!     osi_assertx(lockp->tid == thrd_Current(), "write lock not held by current thread");
! 
!     /* convert write lock to read lock */
!     lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!     lockp->readers++;
! 
!     lockp->tid = 0;
! 
!     if (!osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, /* still have readers */ 1, csp);
!     }
!     else {
!         /* and finally release the big lock */
!         LeaveCriticalSection(csp);
!     }
  }
  
  void lock_ConvertRToW(osi_rwlock_t *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
  
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ConvertRToWProc)(lockp);
!         return;
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(!(lockp->flags & OSI_LOCKFLAG_EXCL), "write lock held");
!     osi_assertx(lockp->readers > 0, "read lock not held");
! 
!     if (--lockp->readers == 0) {
!         /* convert read lock to write lock */
!         lockp->flags |= OSI_LOCKFLAG_EXCL;
!     } else {
!         lockp->waiters++;
!         osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!         lockp->waiters--;
!         osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
!     }
! 
!     lockp->tid = thrd_Current();
!     LeaveCriticalSection(csp);
! }       
  
  void lock_ObtainMutex(struct osi_mutex *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
!         
!     if ((i=lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ObtainMutexProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) 
!             lock_VerifyOrderMX(lockRefH, lockRefT, lockp);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
!         lockp->waiters++;
!         osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
!         lockp->waiters--;
!         osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->flags |= OSI_LOCKFLAG_EXCL;
!     }
!     lockp->tid = thrd_Current();
!     LeaveCriticalSection(csp);
! 
!     if (lockOrderValidation) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_MUTEX);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
  }
  
  void lock_ReleaseMutex(struct osi_mutex *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->ReleaseMutexProc)(lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         int found = 0;
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_MUTEX && lockRefp->mx == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 found = 1;
!                 break;
!             }
!         }
!     
!         osi_assertx(found, "mutex lock not found in TLS queue");
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "mutex not held");
!     osi_assertx(lockp->tid == thrd_Current(), "mutex not held by current thread");
! 
!     lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!     lockp->tid = 0;
!     if (!osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, csp);
!     }
!     else {
!         /* and finally release the big lock */
!         LeaveCriticalSection(csp);
!     }
! }       
  
  int lock_TryRead(struct osi_rwlock *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i=lockp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             return (osi_lockOps[i]->TryReadProc)(lockp);
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) {
!             for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!                 if (lockRefp->type == OSI_LOCK_RW) {
!                     osi_assertx(lockRefp->rw != lockp, "RW Lock already held");
!                 }
!             }
!         }
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
!         i = 0;
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->readers++;
!         i = 1;
!     }
  
!     LeaveCriticalSection(csp);
  
!     if (lockOrderValidation && i) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
  
!     return i;
! }       
  
  
  int lock_TryWrite(struct osi_rwlock *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i=lockp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             return (osi_lockOps[i]->TryWriteProc)(lockp);
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) {
!             for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!                 if (lockRefp->type == OSI_LOCK_RW) {
!                     osi_assertx(lockRefp->rw != lockp, "RW Lock already held");
!                 }
!             }
!         }
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)
!          || (lockp->readers > 0)) {
!         i = 0;
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->flags |= OSI_LOCKFLAG_EXCL;
!         i = 1;
!     }
  
!     if (i)
!         lockp->tid = thrd_Current();
  
!     LeaveCriticalSection(csp);
  
!     if (lockOrderValidation && i) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
  
!     return i;
  }
  
  
  int lock_TryMutex(struct osi_mutex *lockp) {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i=lockp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             return (osi_lockOps[i]->TryMutexProc)(lockp);
! 
!     if (lockOrderValidation) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         if (lockp->level != 0) {
!             for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!                 if (lockRefp->type == OSI_LOCK_MUTEX) {
!                     osi_assertx(lockRefp->mx != lockp, "Mutex already held");
!                 }
!             }
!         }
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
!         i = 0;
!     }
!     else {
!         /* if we're here, all clear to set the lock */
!         lockp->flags |= OSI_LOCKFLAG_EXCL;
!         i = 1;
!     }
  
!     if (i)
!         lockp->tid = thrd_Current();
  
!     LeaveCriticalSection(csp);
  
!     if (lockOrderValidation && i) {
!         lockRefp = lock_GetLockRef(lockp, OSI_LOCK_MUTEX);
!         osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q);
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
!     return i;
  }
  
  void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->SleepRProc)(sleepVal, lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 break;
!             }
!         }
! 
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->readers > 0, "osi_SleepR: not held");
! 
!     /* XXX better to get the list of things to wakeup from TSignalForMLs, and
!      * then do the wakeup after SleepSpin releases the low-level mutex.
!      */
!     if (--lockp->readers == 0 && !osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
!     }
! 
!     /* now call into scheduler to sleep atomically with releasing spin lock */
!     osi_SleepSpin(sleepVal, csp);
! }       
  
  void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->SleepWProc)(sleepVal, lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 break;
!             }
!         }
! 
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
! 
!     osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepW: not held");
! 
!     lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!     if (!osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
!     }
  
!     /* and finally release the big lock */
!     osi_SleepSpin(sleepVal, csp);
  }
  
  void osi_SleepM(LONG_PTR sleepVal, struct osi_mutex *lockp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
!     osi_queue_t * lockRefH, *lockRefT;
!     osi_lock_ref_t *lockRefp;
! 
!     if ((i = lockp->type) != 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->SleepMProc)(sleepVal, lockp);
!         return;
!     }
! 
!     if (lockOrderValidation && lockp->level != 0) {
!         lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
!         lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);
! 
!         for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
!             if (lockRefp->type == OSI_LOCK_MUTEX && lockRefp->mx == lockp) {
!                 osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
!                 free(lockRefp);
!                 break;
!             }
!         }
!     
!         TlsSetValue(tls_LockRefH, lockRefH);
!         TlsSetValue(tls_LockRefT, lockRefT);
!     }
! 
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lockp->atomicIndex];
!     EnterCriticalSection(csp);
  
!     osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepM not held");
  	
!     lockp->flags &= ~OSI_LOCKFLAG_EXCL;
!     if (!osi_TEmpty(&lockp->d.turn)) {
!         osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
!     }
  
!     /* and finally release the big lock */
!     osi_SleepSpin(sleepVal, csp);
  }
  
  void lock_FinalizeRWLock(osi_rwlock_t *lockp)
  {
!     long i;
  
!     if ((i=lockp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->FinalizeRWLockProc)(lockp);
! }       
  
  void lock_FinalizeMutex(osi_mutex_t *lockp)
! {       
!     long i;
  
!     if ((i=lockp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->FinalizeMutexProc)(lockp);
! }       
! 
! void lock_InitializeMutex(osi_mutex_t *mp, char *namep, unsigned short level)
! {
!     int i;
! 
!     if ((i = osi_lockTypeDefault) > 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->InitializeMutexProc)(mp, namep, level);
!         return;
!     }
! 
!     /* otherwise we have the base case, which requires no special
!      * initialization.
!      */
!     mp->type = 0;
!     mp->flags = 0;
!     mp->tid = 0;
!     mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
!     mp->level = level;
!     osi_TInit(&mp->d.turn);
!     return;
! }
! 
! void lock_InitializeRWLock(osi_rwlock_t *mp, char *namep, unsigned short level)
! {
!     int i;
! 
!     if ((i = osi_lockTypeDefault) > 0) {
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             (osi_lockOps[i]->InitializeRWLockProc)(mp, namep, level);
!         return;
!     }
  	
!     /* otherwise we have the base case, which requires no special
!      * initialization.
!      */
!     mp->type = 0;
!     mp->flags = 0;
!     mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
!     mp->readers = 0;
!     mp->tid = 0;
!     mp->level = level;
!     osi_TInit(&mp->d.turn);
!     return;
  }
  
  int lock_GetRWLockState(osi_rwlock_t *lp)
  {
!     long i;
!     CRITICAL_SECTION *csp;
  
!     if ((i=lp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             return (osi_lockOps[i]->GetRWLockState)(lp);
  
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[lp->atomicIndex];
!     EnterCriticalSection(csp);
  
!     /* here we have the fast lock, so see if we can obtain the real lock */
!     if (lp->flags & OSI_LOCKFLAG_EXCL) 
!         i = OSI_RWLOCK_WRITEHELD;
!     else 
!         i = 0;
!     if (lp->readers > 0) 
!         i |= OSI_RWLOCK_READHELD;
  
!     LeaveCriticalSection(csp);
  
!     return i;
  }
  
! int lock_GetMutexState(struct osi_mutex *mp) 
! {
!     long i;
!     CRITICAL_SECTION *csp;
  
!     if ((i=mp->type) != 0)
!         if (i >= 0 && i < OSI_NLOCKTYPES)
!             return (osi_lockOps[i]->GetMutexState)(mp);
  
!     /* otherwise we're the fast base type */
!     csp = &osi_baseAtomicCS[mp->atomicIndex];
!     EnterCriticalSection(csp);
  
!     if (mp->flags & OSI_LOCKFLAG_EXCL)
!         i = OSI_MUTEX_HELD;
!     else
!         i = 0;
  
!     LeaveCriticalSection(csp);
  
!     return i;
  }
Index: openafs/src/WINNT/client_osi/osibasel.h
diff -c openafs/src/WINNT/client_osi/osibasel.h:1.5.4.3 openafs/src/WINNT/client_osi/osibasel.h:1.5.4.4
*** openafs/src/WINNT/client_osi/osibasel.h:1.5.4.3	Wed Feb 27 12:06:44 2008
--- openafs/src/WINNT/client_osi/osibasel.h	Fri Aug 22 14:10:08 2008
***************
*** 28,43 ****
   * lock using an atomic increment operation.
   */
  typedef struct osi_mutex {
! 	char type;			/* for all types; type 0 uses atomic count */
! 	char flags;			/* flags for base type */
! 	unsigned short atomicIndex;	/* index of lock for low-level sync */
!         DWORD tid;			/* tid of thread that owns the lock */
! 	unsigned short waiters;		/* waiters */
!         unsigned short pad;
! 	union {
! 		void *privateDatap;	/* data pointer for non-zero types */
!                 osi_turnstile_t turn;	/* turnstile */
! 	} d;
  } osi_mutex_t;
  
  /* a read/write lock.  This structure has two forms.  In the
--- 28,44 ----
   * lock using an atomic increment operation.
   */
  typedef struct osi_mutex {
!     char type;			/* for all types; type 0 uses atomic count */
!     char flags;			/* flags for base type */
!     unsigned short atomicIndex;	/* index of lock for low-level sync */
!     DWORD tid;			/* tid of thread that owns the lock */
!     unsigned short waiters;	/* waiters */
!     unsigned short pad;
!     union {
!         void *privateDatap;	/* data pointer for non-zero types */
!         osi_turnstile_t turn;	/* turnstile */
!     } d;
!     unsigned short level;       /* locking hierarchy level */
  } osi_mutex_t;
  
  /* a read/write lock.  This structure has two forms.  In the
***************
*** 53,70 ****
   * This type of lock has N readers or one writer.
   */
  typedef struct osi_rwlock {
! 	char type;			/* for all types; type 0 uses atomic count */
! 	char flags;			/* flags for base type */
!         unsigned short atomicIndex;	/* index into hash table for low-level sync */
!         DWORD tid;			/* writer's tid */
!         unsigned short waiters;		/* waiters */
! 	unsigned short readers;		/* readers */
! 	union {
! 		void *privateDatap;	/* data pointer for non-zero types */
!                 osi_turnstile_t turn;	/* turnstile */
! 	} d;
  } osi_rwlock_t;
  
  extern void lock_ObtainRead (struct osi_rwlock *);
  
  extern void lock_ObtainWrite (struct osi_rwlock *);
--- 54,90 ----
   * This type of lock has N readers or one writer.
   */
  typedef struct osi_rwlock {
!     char type;			/* for all types; type 0 uses atomic count */
!     char flags;			/* flags for base type */
!     unsigned short atomicIndex;	/* index into hash table for low-level sync */
!     DWORD tid;			/* writer's tid */
!     unsigned short waiters;	/* waiters */
!     unsigned short readers;	/* readers */
!     union {
!         void *privateDatap;	/* data pointer for non-zero types */
!         osi_turnstile_t turn;	/* turnstile */
!     } d;
!     unsigned short level;       /* locking hierarchy level */
  } osi_rwlock_t;
  
+ 
+ /* 
+  * a lock reference is a queue object that maintains a reference to a 
+  * mutex or read/write lock object.  Its intended purpose is for 
+  * maintaining lists of lock objects on a per thread basis.
+  */
+ typedef struct osi_lock_ref {
+     osi_queue_t q;
+     char type;
+     union {
+         osi_rwlock_t *rw;
+         osi_mutex_t  *mx;
+     };
+ } osi_lock_ref_t;
+ 
+ #define OSI_LOCK_MUTEX  1
+ #define OSI_LOCK_RW     2
+ 
  extern void lock_ObtainRead (struct osi_rwlock *);
  
  extern void lock_ObtainWrite (struct osi_rwlock *);
***************
*** 101,109 ****
  
  /* and define the functions that create basic locks and mutexes */
  
! extern void lock_InitializeRWLock(struct osi_rwlock *, char *);
  
! extern void lock_InitializeMutex(struct osi_mutex *, char *);
  
  extern void osi_Init (void);
  
--- 121,129 ----
  
  /* and define the functions that create basic locks and mutexes */
  
! extern void lock_InitializeRWLock(struct osi_rwlock *, char *, unsigned short level);
  
! extern void lock_InitializeMutex(struct osi_mutex *, char *, unsigned short level);
  
  extern void osi_Init (void);
  
***************
*** 123,128 ****
--- 143,150 ----
  
  /* and friendly macros */
  
+ #define lock_AssertNone(x) osi_assertx(lock_GetRWLockState(x) == 0, "(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
+ 
  #define lock_AssertRead(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_READHELD, "!OSI_RWLOCK_READHELD")
  
  #define lock_AssertWrite(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD, "!OSI_RWLOCK_WRITEHELD")
Index: openafs/src/WINNT/client_osi/osifd.c
diff -c openafs/src/WINNT/client_osi/osifd.c:1.3 openafs/src/WINNT/client_osi/osifd.c:1.3.14.1
*** openafs/src/WINNT/client_osi/osifd.c:1.3	Sun Mar  9 20:59:15 2003
--- openafs/src/WINNT/client_osi/osifd.c	Fri Aug 22 14:10:08 2008
***************
*** 13,23 ****
  #include <afs/param.h>
  #include <afs/stds.h>
  
- #ifndef DJGPP
  #include <windows.h>
  #include <rpc.h>
  #include "dbrpc.h"
- #endif /* !DJGPP */
  #include <malloc.h>
  #include "osi.h"
  #include <assert.h>
--- 13,21 ----
***************
*** 29,37 ****
  
  osi_fdOps_t osi_TypeFDOps = {
  	osi_FDTypeCreate,
- #ifndef DJGPP
  	osi_FDTypeGetInfo,
- #endif
  	osi_FDTypeClose
  };
  
--- 27,33 ----
***************
*** 216,222 ****
  }
  
  
- #ifndef DJGPP
  long osi_FDTypeGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *outp)
  {
  	osi_typeFD_t *fdp;
--- 212,217 ----
***************
*** 239,245 ****
  		return OSI_DBRPC_EOF;
  	}
  }
- #endif /* !DJGPP */
  
  long osi_FDTypeClose(osi_fd_t *ifdp)
  {
--- 234,239 ----
Index: openafs/src/WINNT/client_osi/osilog.c
diff -c openafs/src/WINNT/client_osi/osilog.c:1.12.4.5 openafs/src/WINNT/client_osi/osilog.c:1.12.4.6
*** openafs/src/WINNT/client_osi/osilog.c:1.12.4.5	Fri Aug  1 00:23:56 2008
--- openafs/src/WINNT/client_osi/osilog.c	Fri Aug 22 14:10:08 2008
***************
*** 12,26 ****
  #include <afs/param.h>
  #include <afs/stds.h>
  
- #ifndef DJGPP
  #include <windows.h>
  #include <rpc.h>
- #endif /* !DJGPP */
  #include <malloc.h>
  #include "osi.h"
- #ifndef DJGPP
  #include "dbrpc.h"
- #endif /* !DJGPP */
  #include <stdio.h>
  #include <assert.h>
  #include <WINNT\afsreg.h>
--- 12,22 ----
***************
*** 48,56 ****
  
  osi_fdOps_t osi_logFDOps = {
  	osi_LogFDCreate,
- #ifndef DJGPP
          osi_LogFDGetInfo,
- #endif
          osi_LogFDClose
  };
  
--- 44,50 ----
***************
*** 64,70 ****
          LARGE_INTEGER bigTemp;
          LARGE_INTEGER bigJunk;
  	
- #ifndef DJGPP
  	if (osi_Once(&osi_logOnce)) {
  		QueryPerformanceFrequency(&bigFreq);
                  if (bigFreq.LowPart == 0 && bigFreq.HighPart == 0)
--- 58,63 ----
***************
*** 86,92 ****
  		/* done with init */
  		osi_EndOnce(&osi_logOnce);
          }
- #endif /* !DJGPP */
  
          logp = malloc(sizeof(osi_log_t));
          memset(logp, 0, sizeof(osi_log_t));
--- 79,84 ----
***************
*** 116,122 ****
  	StringCbCopyA(tbuffer, sizeof(tbuffer), "log:");
          StringCbCatA(tbuffer, sizeof(tbuffer), namep);
  	typep = osi_RegisterFDType(tbuffer, &osi_logFDOps, logp);
- #ifndef DJGPP
  	if (typep) {
  		/* add formatting info */
  		osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
--- 108,113 ----
***************
*** 124,138 ****
  		osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 1,
  			"Time (mics)", 0);
  	}
- #endif
  	
          return logp;
  }
  
! /* we just panic'd.  Turn off all logging adding special log record
!  * to all enabled logs.  Be careful not to wait for a lock.
   */
! void osi_LogPanic(char *filep, size_t lineNumber)
  {
  	osi_log_t *tlp;
  
--- 115,128 ----
  		osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 1,
  			"Time (mics)", 0);
  	}
  	
          return logp;
  }
  
! /* we just panic'd.  Log the error to all enabled log files.
!  * Be careful not to wait for a lock.
   */
! void osi_LogPanic(char *msgp, char *filep, size_t lineNumber)
  {
  	osi_log_t *tlp;
  
***************
*** 141,149 ****
  
  		/* otherwise, proceed */
  		if (filep)
! 	                osi_LogAdd(tlp, "**PANIC** (file %s:%d)", (size_t) filep, lineNumber, 0, 0, 0);
  		else
! 			osi_LogAdd(tlp, "**PANIC**", 0, 0, 0, 0, 0);
  		
                  /* should grab lock for this, but we're in panic, and better safe than
                   * sorry.
--- 131,139 ----
  
  		/* otherwise, proceed */
  		if (filep)
! 	                osi_LogAdd(tlp, "**PANIC** \"%s\" (file %s:%d)", (size_t) msgp, (size_t) filep, lineNumber, 0, 0);
  		else
! 			osi_LogAdd(tlp, "**PANIC** \"%s\"", (size_t)msgp, 0, 0, 0, 0);
  		
                  /* should grab lock for this, but we're in panic, and better safe than
                   * sorry.
***************
*** 203,217 ****
          lep->tid = thrd_Current();
  
  	/* get the time, using the high res timer if available */
- #ifndef DJGPP
          if (osi_logFreq) {
  		QueryPerformanceCounter(&bigTime);
  		lep->micros = (bigTime.LowPart / osi_logFreq) * osi_logTixToMicros;
          }
          else lep->micros = GetCurrentTime() * 1000;
- #else
-         lep->micros = gettime_us();
- #endif /* !DJGPP */                
  
          lep->formatp = formatp;
          lep->parms[0] = p0;
--- 193,203 ----
Index: openafs/src/WINNT/client_osi/osilog.h
diff -c openafs/src/WINNT/client_osi/osilog.h:1.7.4.3 openafs/src/WINNT/client_osi/osilog.h:1.7.4.4
*** openafs/src/WINNT/client_osi/osilog.h:1.7.4.3	Fri Aug  1 00:23:56 2008
--- openafs/src/WINNT/client_osi/osilog.h	Fri Aug 22 14:10:08 2008
***************
*** 75,81 ****
  
  extern void osi_LogDisable(osi_log_t *);
  
! extern void osi_LogPanic(char *filep, size_t line);
  
  extern void osi_LogPrint(osi_log_t *logp, FILE_HANDLE handle);
  
--- 75,81 ----
  
  extern void osi_LogDisable(osi_log_t *);
  
! extern void osi_LogPanic(char *msgp, char *filep, size_t line);
  
  extern void osi_LogPrint(osi_log_t *logp, FILE_HANDLE handle);
  
Index: openafs/src/WINNT/client_osi/osiltype.h
diff -c openafs/src/WINNT/client_osi/osiltype.h:1.2.4.1 openafs/src/WINNT/client_osi/osiltype.h:1.2.4.2
*** openafs/src/WINNT/client_osi/osiltype.h:1.2.4.1	Wed Feb 27 12:06:44 2008
--- openafs/src/WINNT/client_osi/osiltype.h	Fri Aug 22 14:10:08 2008
***************
*** 30,37 ****
  	void (*SleepRProc)(LONG_PTR, struct osi_rwlock *);
  	void (*SleepWProc)(LONG_PTR, struct osi_rwlock *);
  	void (*SleepMProc)(LONG_PTR, struct osi_mutex *);
! 	void (*InitializeMutexProc)(struct osi_mutex *, char *);
! 	void (*InitializeRWLockProc)(struct osi_rwlock *, char *);
  	void (*FinalizeMutexProc)(struct osi_mutex *);
  	void (*FinalizeRWLockProc)(struct osi_rwlock *);
          void (*ConvertWToRProc)(struct osi_rwlock *);
--- 30,37 ----
  	void (*SleepRProc)(LONG_PTR, struct osi_rwlock *);
  	void (*SleepWProc)(LONG_PTR, struct osi_rwlock *);
  	void (*SleepMProc)(LONG_PTR, struct osi_mutex *);
! 	void (*InitializeMutexProc)(struct osi_mutex *, char *, unsigned short);
! 	void (*InitializeRWLockProc)(struct osi_rwlock *, char *, unsigned short);
  	void (*FinalizeMutexProc)(struct osi_mutex *);
  	void (*FinalizeRWLockProc)(struct osi_rwlock *);
          void (*ConvertWToRProc)(struct osi_rwlock *);
Index: openafs/src/WINNT/client_osi/osiqueue.c
diff -c openafs/src/WINNT/client_osi/osiqueue.c:1.3.14.1 openafs/src/WINNT/client_osi/osiqueue.c:1.3.14.2
*** openafs/src/WINNT/client_osi/osiqueue.c:1.3.14.1	Thu Jun  1 11:39:55 2006
--- openafs/src/WINNT/client_osi/osiqueue.c	Fri Aug 22 14:10:08 2008
***************
*** 12,20 ****
  #include <afs/param.h>
  #include <afs/stds.h>
  
- #ifndef DJGPP
  #include <windows.h>
- #endif /* !DJGPP */
  #include "osi.h"
  #include <stdlib.h>
  
--- 12,18 ----
Index: openafs/src/WINNT/client_osi/osisleep.c
diff -c openafs/src/WINNT/client_osi/osisleep.c:1.5.4.1 openafs/src/WINNT/client_osi/osisleep.c:1.5.4.2
*** openafs/src/WINNT/client_osi/osisleep.c:1.5.4.1	Thu Jun  1 11:39:55 2006
--- openafs/src/WINNT/client_osi/osisleep.c	Fri Aug 22 14:10:08 2008
***************
*** 674,683 ****
  
  void osi_panic(char *msgp, char *filep, long line)
  {
! 	osi_LogPanic(filep, line);
  
! 	if (notifFunc)
!        		(*notifFunc)(msgp, filep, line);
  }
  
  /* get time in seconds since some relatively recent time */
--- 674,683 ----
  
  void osi_panic(char *msgp, char *filep, long line)
  {
!     if (notifFunc)
!         (*notifFunc)(msgp, filep, line);
  
!     osi_LogPanic(msgp, filep, line);
  }
  
  /* get time in seconds since some relatively recent time */
Index: openafs/src/afs/afs.h
diff -c openafs/src/afs/afs.h:1.85.2.8 openafs/src/afs/afs.h:1.85.2.10
*** openafs/src/afs/afs.h:1.85.2.8	Wed Apr 30 15:08:04 2008
--- openafs/src/afs/afs.h	Mon Sep 22 15:35:26 2008
***************
*** 121,126 ****
--- 121,130 ----
  #define	BOP_STORE	2	/* parm1 is chunk to store */
  #define	BOP_PATH	3	/* parm1 is path, parm2 is chunk to fetch */
  
+ #if defined(AFS_CACHE_BYPASS)
+ #define	BOP_FETCH_NOCACHE	4   /* parms are: vnode ptr, offset, segment ptr, addr, cred ptr */
+ #endif
+ 
  #define	B_DONTWAIT	1	/* On failure return; don't wait */
  
  /* protocol is: refCount is incremented by user to take block out of free pool.
***************
*** 570,575 ****
--- 574,616 ----
  #define VRevokeWait   0x1
  #define VPageCleaning 0x2	/* Solaris - Cache Trunc Daemon sez keep out */
  
+ #if defined(AFS_DISCON_ENV)
+ 
+ /* Dirty disconnected vcache flags. */
+ #define VDisconSetTime		0x00000001  	/* set time. */
+ #define VDisconSetMode		0x00000002	/* set mode. */
+ /* XXX: to be continued ? */
+ #define VDisconTrunc		0x00000020	/* truncate file. */
+ #define VDisconSetAttrMask	0x0000003F	/* Masks for setattr ops. */
+ #define VDisconWriteClose	0x00000400	/* Write op on file close. */
+ #define VDisconWriteFlush	0x00000800	/* Write op on normal fsync/flush. */
+ #define VDisconWriteOsiFlush	0x00001000	/* Write op on osi flush. */
+ 
+ #define VDisconShadowed		0x00002000	/* Shadowed dir. */
+ #define VDisconRemove		0x00004000	/* Remove vnop. */
+ #define VDisconCreate		0x00008000	/* Create vnop. */
+ #define VDisconRename		0x00010000	/* Rename vnop. */
+ #define VDisconRenameSameDir	0x00020000	/* Rename in same dir. */
+ 
+ /*... to be continued ...  */
+ #endif
+ 
+ #if defined(AFS_CACHE_BYPASS)
+ /* vcache (file) cachingStates bits */
+ #define FCSDesireBypass   0x1	/* This file should bypass the cache */
+ #define FCSBypass         0x2	/* This file is currently NOT being cached */
+ #define FCSManuallySet    0x4	/* The bypass flags were set, or reset, manually (via pioctl)
+  				 				   and should not be overridden by the file's name */
+ 
+ /* Flag values used by the Transition routines */
+ #define TRANSChangeDesiredBit		0x1	/* The Transition routine should set or 
+ 										 * reset the FCSDesireBypass bit */
+ #define TRANSVcacheIsLocked			0x2	/* The Transition routine does not need to
+ 										 * lock vcache (it's already locked) */
+ #define TRANSSetManualBit		0x4	/* The Transition routine should set FCSManuallySet so that
+ 									 * filename checking does not override pioctl requests */	
+ #endif /* AFS_CACHE_BYPASS */
+ 
  #define	CPSIZE	    2
  #if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV)
  #define vrefCount   v->v_usecount
***************
*** 634,639 ****
--- 675,694 ----
  #endif
      struct vcache *hnext;	/* Hash next */
      struct afs_q vhashq;	/* Hashed per-volume list */
+ 
+ #if defined(AFS_DISCON_ENV)
+     /*! Next element in afs_DDirtyVCList. Lock it with afs_DDirtyVCListLock. */
+     struct vcache *ddirty_next;
+     /*! Disconnected flags for this vcache element. */
+     uint32_t ddirty_flags;
+     /*! Shadow vnode + unique keep the shadow dir location. */
+     afs_uint32 shVnode;
+     afs_uint32 shUnique;
+     /*! The old parent FID for renamed vnodes. */
+     afs_uint32 oldVnode;
+     afs_uint32 oldUnique;
+ #endif
+ 
      struct VenusFid fid;
      struct mstat {
  	afs_size_t Length;
***************
*** 705,710 ****
--- 760,776 ----
  				 * this file. */
      short flockCount;		/* count of flock readers, or -1 if writer */
      char mvstat;		/* 0->normal, 1->mt pt, 2->root. */
+ 
+ #if defined(AFS_CACHE_BYPASS)
+ 	char cachingStates;			/* Caching policies for this file */
+ 	afs_uint32 cachingTransitions;		/* # of times file has flopped between caching and not */
+ #if defined(AFS_LINUX24_ENV)
+ 	off_t next_seq_offset;	/* Next sequential offset (used by prefetch/readahead) */
+ #else
+ 	off_t next_seq_blk_offset; /* accounted in blocks for Solaris & IRIX */
+ #endif
+ #endif		
+ 	
      afs_uint32 states;		/* state bits */
  #if	defined(AFS_SUN5_ENV)
      afs_uint32 vstates;		/* vstate bits */
Index: openafs/src/afs/afs_analyze.c
diff -c openafs/src/afs/afs_analyze.c:1.22.14.8 openafs/src/afs/afs_analyze.c:1.22.14.9
*** openafs/src/afs/afs_analyze.c:1.22.14.8	Sat Jun 28 23:39:12 2008
--- openafs/src/afs/afs_analyze.c	Fri Aug 22 14:52:57 2008
***************
*** 14,20 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_analyze.c,v 1.22.14.8 2008/06/29 03:39:12 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
--- 14,20 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_analyze.c,v 1.22.14.9 2008/08/22 18:52:57 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
***************
*** 382,388 ****
  	return shouldRetry;	/* should retry */
      }
  
!     if (!aconn) {
  	if (!areq->volumeError) {
  	    if (aerrP)
  		(aerrP->err_Network)++;
--- 382,388 ----
  	return shouldRetry;	/* should retry */
      }
  
!     if (!aconn || !aconn->srvr) {
  	if (!areq->volumeError) {
  	    if (aerrP)
  		(aerrP->err_Network)++;
Index: openafs/src/afs/afs_bypasscache.c
diff -c /dev/null openafs/src/afs/afs_bypasscache.c:1.1.2.2
*** /dev/null	Fri Sep 26 04:30:52 2008
--- openafs/src/afs/afs_bypasscache.c	Mon Sep 22 15:35:26 2008
***************
*** 0 ****
--- 1,649 ----
+ /*
+  * COPYRIGHT  ©  2000
+  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+  * ALL RIGHTS RESERVED
+  * 
+  * Permission is granted to use, copy, create derivative works
+  * and redistribute this software and such derivative works
+  * for any purpose, so long as the name of The University of
+  * Michigan is not used in any advertising or publicity
+  * pertaining to the use of distribution of this software
+  * without specific, written prior authorization.  If the
+  * above copyright notice or any other identification of the
+  * University of Michigan is included in any copy of any
+  * portion of this software, then the disclaimer below must
+  * also be included.
+  * 
+  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY O 
+  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGES.
+  */
+  
+  /*
+  * Portions Copyright (c) 2008
+  * The Linux Box Corporation
+  * ALL RIGHTS RESERVED
+  *
+  * Permission is granted to use, copy, create derivative works
+  * and redistribute this software and such derivative works
+  * for any purpose, so long as the name of the Linux Box
+  * Corporation is not used in any advertising or publicity
+  * pertaining to the use or distribution of this software
+  * without specific, written prior authorization.  If the
+  * above copyright notice or any other identification of the
+  * Linux Box Corporation is included in any copy of any
+  * portion of this software, then the disclaimer below must
+  * also be included.
+  *
+  * This software is provided as is, without representation
+  * from the Linux Box Corporation as to its fitness for any
+  * purpose, and without warranty by the Linux Box Corporation
+  * of any kind, either express or implied, including
+  * without limitation the implied warranties of
+  * merchantability and fitness for a particular purpose.  The
+  * Linux Box Corporation shall not be liable for any damages, 
+  * including special, indirect, incidental, or consequential 
+  * damages, with respect to any claim arising out of or in 
+  * connection with the use of the software, even if it has been 
+  * or is hereafter advised of the possibility of such damages.
+  */
+ 
+ 
+ #include <afsconfig.h>
+ #include "afs/param.h"
+ 
+ #if defined(AFS_CACHE_BYPASS)
+ 
+ #include "afs/afs_bypasscache.h"
+ 
+ /*
+  * afs_bypasscache.c
+  *
+  */
+ #include "afs/sysincludes.h" /* Standard vendor system headers */
+ #include "afs/afsincludes.h" /* Afs-based standard headers */
+ #include "afs/afs_stats.h"   /* statistics */
+ #include "afs/nfsclient.h"  
+ #include "rx/rx_globals.h"
+ 
+ #if defined(AFS_LINUX26_ENV)
+ #define LockPage(pp) lock_page(pp)
+ #define UnlockPage(pp) unlock_page(pp)
+ #endif
+ #define AFS_KMAP_ATOMIC
+ 
+ #ifndef afs_min
+ #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
+ #endif
+ 
+ /* conditional GLOCK macros */
+ #define COND_GLOCK(var)	\
+ 	do { \
+ 		var = ISAFS_GLOCK(); \
+ 		if(!var) \
+ 			RX_AFS_GLOCK(); \
+ 	} while(0);
+ 	
+ #define COND_RE_GUNLOCK(var) \
+ 	do { \
+ 		if(var)	\
+ 			RX_AFS_GUNLOCK(); \
+ 	} while(0);
+ 
+ 
+ /* conditional GUNLOCK macros */
+ 
+ #define COND_GUNLOCK(var) \
+ 	do {	\
+ 		var = ISAFS_GLOCK(); \
+ 		if(var)	\
+ 			RX_AFS_GUNLOCK(); \
+ 	} while(0);
+ 
+ #define COND_RE_GLOCK(var) \
+ 	do { \
+ 		if(var)	\
+ 			RX_AFS_GLOCK();	\
+ 	} while(0);
+ 
+ 
+ int cache_bypass_strategy 	= 	NEVER_BYPASS_CACHE;
+ int cache_bypass_threshold  =  	AFS_CACHE_BYPASS_DISABLED; /* file size > threshold triggers bypass */
+ int cache_bypass_prefetch = 1;	/* Should we do prefetching ? */
+ 
+ extern afs_rwlock_t afs_xcbhash;
+ 
+ /*
+  * This is almost exactly like the PFlush() routine in afs_pioctl.c,
+  * but that routine is static.  We are about to change a file from
+  * normal caching to bypass it's caching.  Therefore, we want to
+  * free up any cache space in use by the file, and throw out any
+  * existing VM pages for the file.  We keep track of the number of
+  * times we go back and forth from caching to bypass.
+  */
+ void afs_TransitionToBypass(register struct vcache *avc, register struct AFS_UCRED *acred, int aflags)
+ {
+ 
+     afs_int32 code;
+     struct vrequest treq;
+     int setDesire = 0;
+     int setManual = 0;
+ 
+     if(!avc)
+ 	return;
+ 		
+     if(avc->states & FCSBypass)
+ 	osi_Panic("afs_TransitionToBypass: illegal transition to bypass--already FCSBypass\n");		
+ 		
+     if(aflags & TRANSChangeDesiredBit)
+ 	setDesire = 1;
+     if(aflags & TRANSSetManualBit)
+ 	setManual = 1;
+ 		
+ #ifdef AFS_BOZONLOCK_ENV
+     afs_BozonLock(&avc->pvnLock, avc);	/* Since afs_TryToSmush will do a pvn_vptrunc */
+ #else
+ 	AFS_GLOCK();	
+ #endif
+     ObtainWriteLock(&avc->lock, 925);
+ 	
+     /* If we never cached this, just change state */
+     if(setDesire && (!avc->cachingStates & FCSBypass)) {
+ 	avc->states |= FCSBypass;
+ 	goto done;
+     }
+ 	/* cg2v, try to store any chunks not written 20071204 */
+ 	if (avc->execsOrWriters > 0) { 
+ 		code = afs_InitReq(&treq, acred);
+ 		if(!code)
+ 			code = afs_StoreAllSegments(avc, &treq, AFS_SYNC | AFS_LASTSTORE); 
+ 	}
+ #if 0
+ 	/* also cg2v, don't dequeue the callback */
+     ObtainWriteLock(&afs_xcbhash, 956);	
+     afs_DequeueCallback(avc);
+ 	ReleaseWriteLock(&afs_xcbhash);
+ #endif	
+     avc->states &= ~(CStatd | CDirty);	/* next reference will re-stat cache entry */
+     /* now find the disk cache entries */
+     afs_TryToSmush(avc, acred, 1);
+     osi_dnlc_purgedp(avc);
+     if (avc->linkData && !(avc->states & CCore)) {
+ 	afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
+ 	avc->linkData = NULL;
+     }		
+ 	
+     avc->cachingStates |= FCSBypass;    /* Set the bypass flag */
+     if(setDesire)
+ 	avc->cachingStates |= FCSDesireBypass;
+     if(setManual)
+ 	avc->cachingStates |= FCSManuallySet;
+     avc->cachingTransitions++;
+ 
+ done:		
+     ReleaseWriteLock(&avc->lock);
+ #ifdef AFS_BOZONLOCK_ENV
+     afs_BozonUnlock(&avc->pvnLock, avc);
+ #else
+ 	AFS_GUNLOCK();
+ #endif
+ }
+ 
+ /*
+  * This is almost exactly like the PFlush() routine in afs_pioctl.c,
+  * but that routine is static.  We are about to change a file from
+  * bypassing caching to normal caching.  Therefore, we want to
+  * throw out any existing VM pages for the file.  We keep track of
+  * the number of times we go back and forth from caching to bypass.
+  */
+ void afs_TransitionToCaching(register struct vcache *avc, register struct AFS_UCRED *acred, int aflags)
+ {
+     int resetDesire = 0;
+     int setManual = 0;
+ 
+     if(!avc)
+ 	return;
+ 		
+     if(!avc->states & FCSBypass)
+ 	osi_Panic("afs_TransitionToCaching: illegal transition to caching--already caching\n");		
+ 		
+     if(aflags & TRANSChangeDesiredBit)
+ 	resetDesire = 1;
+     if(aflags & TRANSSetManualBit)
+ 	setManual = 1;
+ 
+ #ifdef AFS_BOZONLOCK_ENV
+     afs_BozonLock(&avc->pvnLock, avc);	/* Since afs_TryToSmush will do a pvn_vptrunc */
+ #else
+ 	AFS_GLOCK();	
+ #endif
+     ObtainWriteLock(&avc->lock, 926);
+ 	
+     /* Ok, we actually do need to flush */
+     ObtainWriteLock(&afs_xcbhash, 957);
+     afs_DequeueCallback(avc);
+     avc->states &= ~(CStatd | CDirty);	/* next reference will re-stat cache entry */
+     ReleaseWriteLock(&afs_xcbhash);
+     /* now find the disk cache entries */
+     afs_TryToSmush(avc, acred, 1);
+     osi_dnlc_purgedp(avc);
+     if (avc->linkData && !(avc->states & CCore)) {
+ 	afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
+ 	avc->linkData = NULL;
+     }
+ 		
+     avc->cachingStates &= ~(FCSBypass);    /* Reset the bypass flag */
+     if (resetDesire)
+ 	avc->cachingStates &= ~(FCSDesireBypass);
+     if (setManual)
+ 	avc->cachingStates |= FCSManuallySet;
+     avc->cachingTransitions++;
+ 
+     ReleaseWriteLock(&avc->lock);
+ #ifdef AFS_BOZONLOCK_ENV
+     afs_BozonUnlock(&avc->pvnLock, avc);
+ #else
+ 	AFS_GUNLOCK();
+ #endif
+ }
+ 
+ /* In the case where there's an error in afs_NoCacheFetchProc or
+  * afs_PrefetchNoCache, all of the pages they've been passed need
+  * to be unlocked.
+  */
+ #if defined(AFS_LINUX24_ENV)
+ #define unlock_pages(auio) \
+     do { \
+ 	struct iovec *ciov;	\
+ 	struct page *pp; \
+ 	afs_int32 iovmax; \
+ 	afs_int32 iovno = 0; \
+ 	ciov = auio->uio_iov; \
+ 	iovmax = auio->uio_iovcnt - 1;	\
+ 	pp = (struct page*) ciov->iov_base;	\
+ 	afs_warn("BYPASS: Unlocking pages...");	\
+ 	while(1) { \
+ 	    if(pp != NULL && PageLocked(pp)) \
+ 		UnlockPage(pp);	\
+ 	    iovno++; \
+ 	    if(iovno > iovmax) \
+ 		break; \
+ 	    ciov = (auio->uio_iov + iovno);	\
+ 	    pp = (struct page*) ciov->iov_base;	\
+ 	} \
+ 	afs_warn("Pages Unlocked.\n"); \
+     } while(0);
+ #else
+ #ifdef UKERNEL
+ #define unlock_pages(auio) \
+ 	 do { } while(0);
+ #else
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif
+ 
+ /* no-cache prefetch routine */
+ static afs_int32
+ afs_NoCacheFetchProc(register struct rx_call *acall, 
+                      register struct vcache *avc, 
+ 					 register uio_t *auio, 
+                      afs_int32 release_pages)
+ {
+     afs_int32 length;
+     afs_int32 code;
+     int tlen;
+     int moredata, iovno, iovoff, iovmax, clen, result, locked;
+     struct iovec *ciov;
+     struct page *pp;
+     char *address;
+ #ifdef AFS_KMAP_ATOMIC
+     char *page_buffer = osi_Alloc(PAGE_SIZE);
+ #else
+     char *page_buffer = NULL;
+ #endif
+ 
+     ciov = auio->uio_iov;
+     pp = (struct page*) ciov->iov_base;
+     iovmax = auio->uio_iovcnt - 1;
+     iovno = iovoff = result = 0;	
+     do {
+ 
+ 	COND_GUNLOCK(locked);
+ 	code = rx_Read(acall, (char *)&length, sizeof(afs_int32));
+ 	COND_RE_GLOCK(locked);
+ 
+ 	if (code != sizeof(afs_int32)) {
+ 	    result = 0;
+ 	    afs_warn("Preread error. code: %d instead of %d\n",
+ 		code, sizeof(afs_int32));
+ 	    unlock_pages(auio);
+ 	    goto done;
+ 	} else
+ 	    length = ntohl(length);		
+ 					
+ 	/*
+ 	 * The fetch protocol is extended for the AFS/DFS translator
+ 	 * to allow multiple blocks of data, each with its own length,
+ 	 * to be returned. As long as the top bit is set, there are more
+ 	 * blocks expected.
+ 	 *
+ 	 * We do not do this for AFS file servers because they sometimes
+ 	 * return large negative numbers as the transfer size.
+ 	 */
+ 	if (avc->states & CForeign) {
+ 	    moredata = length & 0x80000000;
+ 	    length &= ~0x80000000;
+ 	} else {
+ 	    moredata = 0;
+ 	}
+ 				
+ 	while (length > 0) {
+ 
+ 	    clen = ciov->iov_len - iovoff; 
+ 	    tlen = afs_min(length, clen);
+ #ifdef AFS_LINUX24_ENV
+ #ifndef AFS_KMAP_ATOMIC
+ 	    if(pp)
+ 		address = kmap(pp);
+ 	    else { 
+ 		/* rx doesn't provide an interface to simply advance
+ 		   or consume n bytes.  for now, allocate a PAGE_SIZE 
+ 		   region of memory to receive bytes in the case that 
+ 		   there were holes in readpages */
+ 		if(page_buffer == NULL)
+ 		    page_buffer = osi_Alloc(PAGE_SIZE);
+ 		    address = page_buffer;
+ 		}
+ #else
+ 	    address = page_buffer;
+ #endif
+ #else
+ #ifndef UKERNEL
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif /* LINUX24 */
+ 	    COND_GUNLOCK(locked);
+ 	    code = rx_Read(acall, address, tlen);
+ 	    COND_RE_GLOCK(locked);
+ 		
+ 	    if (code < 0) {
+ 	        afs_warn("afs_NoCacheFetchProc: rx_Read error. Return code was %d\n", code);
+ 		result = 0;
+ 		unlock_pages(auio);
+ 		goto done;
+ 	    } else if (code == 0) {
+ 		result = 0;
+ 		afs_warn("afs_NoCacheFetchProc: rx_Read returned zero. Aborting.\n");
+ 		unlock_pages(auio);
+ 		goto done;
+ 	    }
+ 	    length -= code;
+ 	    tlen -= code;
+ 		
+ 	    if(tlen > 0) {
+ 		iovoff += code;
+ 		address += code;
+ 			
+ 	    } else {
+ #ifdef AFS_LINUX24_ENV
+ #ifdef AFS_KMAP_ATOMIC
+ 		if(pp) {
+ 		    address = kmap_atomic(pp, KM_USER0);
+ 		    memcpy(address, page_buffer, PAGE_SIZE);
+ 		    kunmap_atomic(address, KM_USER0);
+ 		}
+ #endif
+ #else
+ #ifndef UKERNEL
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif /* LINUX 24 */
+ 			/* we filled a page, conditionally release it */
+ 			if(release_pages && ciov->iov_base) {
+ 				/* this is appropriate when no caller intends to unlock
+ 				 * and release the page */
+ #ifdef AFS_LINUX24_ENV
+ 				SetPageUptodate(pp);
+ 				if(PageLocked(pp))
+ 					UnlockPage(pp);	
+ 				else
+ 					afs_warn("afs_NoCacheFetchProc: page not locked at iovno %d!\n", iovno);
+ 				
+ #ifndef AFS_KMAP_ATOMIC
+ 				kunmap(pp);		
+ #endif
+ #else
+ #ifndef UKERNEL
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif /* LINUX24 */
+ 			}
+ 			/* and carry uio_iov */
+ 			iovno++;
+ 			if(iovno > iovmax) goto done;
+ 			
+ 			ciov = (auio->uio_iov + iovno);
+ 			pp = (struct page*) ciov->iov_base;
+ 			iovoff = 0;
+ 	    }
+ 	}
+     } while (moredata);
+ 	
+ done:
+     if(page_buffer)
+     	osi_Free(page_buffer, PAGE_SIZE);
+     return result;
+ }
+ 
+ 
+ /* dispatch a no-cache read request */
+ afs_int32
+ afs_ReadNoCache(register struct vcache *avc, 
+ 				register struct nocache_read_request *bparms, 
+ 				struct AFS_UCRED *acred)
+ {
+     afs_int32 code;
+     afs_int32 bcnt;
+     struct brequest *breq;
+     struct vrequest *areq;
+ 		
+     /* the reciever will free this */
+     areq = osi_Alloc(sizeof(struct vrequest));
+ 	
+     if (avc && avc->vc_error) {
+ 		code = EIO;
+ 		afs_warn("afs_ReadNoCache VCache Error!\n");
+ 		goto cleanup;
+     }
+     if ((code = afs_InitReq(areq, acred))) {
+ 		afs_warn("afs_ReadNoCache afs_InitReq error!\n");
+ 		goto cleanup;
+     }
+ 
+     AFS_GLOCK();		
+     code = afs_VerifyVCache(avc, areq);
+     AFS_GUNLOCK();
+ 	
+     if (code) {
+ 		code = afs_CheckCode(code, areq, 11);	/* failed to get it */
+ 		afs_warn("afs_ReadNoCache Failed to verify VCache!\n");
+ 		goto cleanup;
+     }
+ 	
+     bparms->areq = areq;
+ 	
+     /* and queue this one */
+     bcnt = 1;
+     AFS_GLOCK();
+     while(bcnt < 20) {
+     	breq = afs_BQueue(BOP_FETCH_NOCACHE, avc, B_DONTWAIT, 0, acred, 1, 1, bparms);
+ 		if(breq != 0) {
+ 			code = 0;
+ 			break;
+ 		}	
+ 		afs_osi_Wait(10 * bcnt, 0, 0);
+     }
+     AFS_GUNLOCK();
+     
+     if(!breq) {
+     	code = EBUSY;
+ 		goto cleanup;
+     }
+ 
+     return code;
+ 
+ cleanup:
+     /* If there's a problem before we queue the request, we need to
+      * do everything that would normally happen when the request was
+      * processed, like unlocking the pages and freeing memory.
+      */
+ #ifdef AFS_LINUX24_ENV
+     unlock_pages(bparms->auio);
+ #else
+ #ifndef UKERNEL
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif
+     osi_Free(areq, sizeof(struct vrequest));
+     osi_Free(bparms->auio->uio_iov, bparms->auio->uio_iovcnt * sizeof(struct iovec));	
+     osi_Free(bparms->auio, sizeof(uio_t));
+     osi_Free(bparms, sizeof(struct nocache_read_request));
+     return code;
+ 
+ }
+ 
+ 
+ /* Cannot have static linkage--called from BPrefetch (afs_daemons) */
+ afs_int32
+ afs_PrefetchNoCache(register struct vcache *avc, 
+ 					register struct AFS_UCRED *acred,
+ 					register struct nocache_read_request *bparms)
+ {
+     uio_t *auio;
+     struct iovec *iovecp;
+     struct vrequest *areq;
+     afs_int32 code, length_hi, bytes, locked;    
+ 	
+     register struct conn *tc;
+     afs_int32 i;
+     struct rx_call *tcall;
+     struct tlocal1 {
+ 		struct AFSVolSync tsync;
+ 		struct AFSFetchStatus OutStatus;
+ 		struct AFSCallBack CallBack;
+     };
+     struct tlocal1 *tcallspec;	
+ 			
+     auio = bparms->auio;
+     areq = bparms->areq;
+     iovecp = auio->uio_iov;	
+ 	
+     tcallspec = (struct tlocal1 *) osi_Alloc(sizeof(struct tlocal1));
+     do {
+ 		tc = afs_Conn(&avc->fid, areq, SHARED_LOCK /* ignored */);
+ 		if (tc) {
+ 			avc->callback = tc->srvr->server;
+ 			i = osi_Time();
+ 			tcall = rx_NewCall(tc->id);
+ #ifdef AFS_64BIT_CLIENT
+ 			if(!afs_serverHasNo64Bit(tc)) {
+ 				code = StartRXAFS_FetchData64(tcall,
+ 											  (struct AFSFid *) &avc->fid.Fid,
+ 											  auio->uio_offset, 
+ 											  bparms->length);
+ 				if (code == 0) {
+ 					
+ 					COND_GUNLOCK(locked);
+ 					bytes = rx_Read(tcall, (char *)&length_hi, sizeof(afs_int32));
+ 					COND_RE_GLOCK(locked);
+ 					
+ 					if (bytes != sizeof(afs_int32)) {
+ 						length_hi = 0;
+ 						code = rx_Error(tcall);
+ 						COND_GUNLOCK(locked);
+ 						code = rx_EndCall(tcall, code);
+ 						COND_RE_GLOCK(locked);
+ 						tcall = (struct rx_call *)0;
+ 					}
+ 				}					      
+ 				if (code == RXGEN_OPCODE || afs_serverHasNo64Bit(tc)) {
+ 					if (auio->uio_offset > 0x7FFFFFFF) {
+ 						code = EFBIG;
+ 					} else {
+ 						afs_int32 pos;
+ 						pos = auio->uio_offset;
+ 						COND_GUNLOCK(locked);
+ 						if (!tcall)
+ 							tcall = rx_NewCall(tc->id);						
+ 						code = StartRXAFS_FetchData(tcall,
+ 													(struct AFSFid *) &avc->fid.Fid,
+ 													pos, bparms->length);
+ 						COND_RE_GLOCK(locked);
+ 					}
+ 					afs_serverSetNo64Bit(tc);
+ 				}
+ 			} /* afs_serverHasNo64Bit */
+ #else
+ 			code = StartRXAFS_FetchData(tcall,
+ 										(struct AFSFid *) &avc->fid.Fid,
+ 										auio->uio_offset, bparms->length);
+ #endif
+ 
+ 			if (code == 0) {
+ 				code = afs_NoCacheFetchProc(tcall, avc, auio, 
+ 											1 /* release_pages */);
+ 			} else {
+ 				afs_warn("BYPASS: StartRXAFS_FetchData failed: %d\n", code);
+ 				unlock_pages(auio);
+ 				goto done;
+ 			}
+ 			if (code == 0) {
+ 				code = EndRXAFS_FetchData(tcall,
+ 										  &tcallspec->OutStatus,
+ 										  &tcallspec->CallBack,
+ 										  &tcallspec->tsync);
+ 			} else {
+ 				afs_warn("BYPASS: NoCacheFetchProc failed: %d\n", code);
+ 			}
+ 			code = rx_EndCall(tcall, code);
+ 		}
+ 		else {
+ 			afs_warn("BYPASS: No connection.\n");
+ 			code = -1;
+ #ifdef AFS_LINUX24_ENV
+ 			unlock_pages(auio);
+ #else
+ #ifndef UKERNEL
+ #error AFS_CACHE_BYPASS not implemented on this platform
+ #endif
+ #endif
+ 			goto done;
+ 		}
+     } while (afs_Analyze(tc, code, &avc->fid, areq,
+ 						 AFS_STATS_FS_RPCIDX_FETCHDATA,
+ 						 SHARED_LOCK,0));
+ done:
+     /*
+      * Copy appropriate fields into vcache
+      */
+ 
+     afs_ProcessFS(avc, &tcallspec->OutStatus, areq);
+ 
+     osi_Free(areq, sizeof(struct vrequest));
+     osi_Free(tcallspec, sizeof(struct tlocal1));
+     osi_Free(iovecp, auio->uio_iovcnt * sizeof(struct iovec));	
+     osi_Free(bparms, sizeof(struct nocache_read_request));
+     osi_Free(auio, sizeof(uio_t));
+     return code;
+ }
+ 
+ #endif /* AFS_CACHE_BYPASS */
Index: openafs/src/afs/afs_bypasscache.h
diff -c /dev/null openafs/src/afs/afs_bypasscache.h:1.1.2.2
*** /dev/null	Fri Sep 26 04:30:52 2008
--- openafs/src/afs/afs_bypasscache.h	Mon Sep 22 15:35:26 2008
***************
*** 0 ****
--- 1,153 ----
+ /*
+  * COPYRIGHT  ©  2000
+  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+  * ALL RIGHTS RESERVED
+  * 
+  * Permission is granted to use, copy, create derivative works
+  * and redistribute this software and such derivative works
+  * for any purpose, so long as the name of The University of
+  * Michigan is not used in any advertising or publicity
+  * pertaining to the use of distribution of this software
+  * without specific, written prior authorization.  If the
+  * above copyright notice or any other identification of the
+  * University of Michigan is included in any copy of any
+  * portion of this software, then the disclaimer below must
+  * also be included.
+  * 
+  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY O 
+  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGES.
+  */
+  
+  /*
+  * Portions Copyright (c) 2008
+  * The Linux Box Corporation
+  * ALL RIGHTS RESERVED
+  *
+  * Permission is granted to use, copy, create derivative works
+  * and redistribute this software and such derivative works
+  * for any purpose, so long as the name of the Linux Box
+  * Corporation is not used in any advertising or publicity
+  * pertaining to the use or distribution of this software
+  * without specific, written prior authorization.  If the
+  * above copyright notice or any other identification of the
+  * Linux Box Corporation is included in any copy of any
+  * portion of this software, then the disclaimer below must
+  * also be included.
+  *
+  * This software is provided as is, without representation
+  * from the Linux Box Corporation as to its fitness for any
+  * purpose, and without warranty by the Linux Box Corporation
+  * of any kind, either express or implied, including
+  * without limitation the implied warranties of
+  * merchantability and fitness for a particular purpose.  The
+  * Linux Box Corporation shall not be liable for any damages, 
+  * including special, indirect, incidental, or consequential 
+  * damages, with respect to any claim arising out of or in 
+  * connection with the use of the software, even if it has been 
+  * or is hereafter advised of the possibility of such damages.
+  */
+ 
+ 
+ #ifndef _AFS_BYPASSCACHE_H
+ #define _AFS_BYPASSCACHE_H
+ 
+ #if defined(AFS_CACHE_BYPASS)
+ 
+ #include <afsconfig.h>
+ #include "afs/param.h"
+ #include "afs/sysincludes.h"
+ #include "afsincludes.h"
+ 
+ #define AFS_CACHE_BYPASS_DISABLED -1
+ 
+ #ifdef UKERNEL
+ typedef struct uio uio_t;
+ #ifndef PAGE_SIZE
+ #define PAGE_SIZE 1024 * sizeof(long) / 8
+ #endif
+ #endif
+ 
+ /* A ptr to an object of the following type is expected to be passed
+  * as the ab->parm[0] to afs_BQueue */
+ struct nocache_read_request {
+     /* Why can't we all get along? */
+ #if defined(AFS_SUN5_ENV)
+     /* SOLARIS */
+     u_offset_t offset;
+     struct seg *segment;
+     caddr_t address;
+ #elif defined(AFS_SGI_ENV)
+     /* SGI (of some vintage) */
+     int32 offset;
+     int32 rem;
+     int32 pmp; /* mmm */
+     int32 length;
+ #elif defined(AFS_LINUX24_ENV) || defined(AFS_USR_LINUX24_ENV)
+     /* The tested platform, as CITI impl. just packs ab->parms */
+     uio_t * auio;
+     struct vrequest *areq;
+     afs_size_t offset;
+     afs_size_t length;
+ #endif
+ };
+ 
+ enum cache_bypass_strategies
+ {
+     ALWAYS_BYPASS_CACHE,
+     NEVER_BYPASS_CACHE,
+     LARGE_FILES_BYPASS_CACHE
+ };
+ 
+ extern int cache_bypass_prefetch;
+ extern int cache_bypass_strategy;
+ extern int cache_bypass_threshold;
+ 
+ void afs_TransitionToBypass(register struct vcache *, register struct AFS_UCRED *, int);
+ void afs_TransitionToCaching(register struct vcache *, register struct AFS_UCRED *, int);
+ 
+ /* Cache strategy permits vnode transition between caching and no-cache--
+  * currently, this means LARGE_FILES_BYPASS_CACHE.  Currently, no pioctl permits
+  * setting FCSBypass manually for a vnode */
+ #define variable_cache_strategy					\
+     (! ((cache_bypass_strategy == ALWAYS_BYPASS_CACHE) ||	\
+ 	(cache_bypass_strategy == NEVER_BYPASS_CACHE)) )
+ 
+ /* Cache-coherently toggle cache/no-cache for a vnode */
+ #define trydo_cache_transition(avc, credp, bypasscache)			\
+     do {								\
+ 	if(variable_cache_strategy) {					\
+ 	    if(bypasscache) {						\
+ 		if(!(avc->cachingStates & FCSBypass))			\
+ 		    afs_TransitionToBypass(avc, credp, TRANSChangeDesiredBit); \
+ 	    } else {							\
+ 		if(avc->cachingStates & FCSBypass)			\
+ 		    afs_TransitionToCaching(avc, credp, TRANSChangeDesiredBit);	\
+ 	    }								\
+ 	}								\
+     }									\
+     while(0);
+ 
+ /* dispatch a no-cache read request */
+ afs_int32
+ afs_ReadNoCache(register struct vcache *avc, register struct nocache_read_request *bparms, 
+ 		struct AFS_UCRED *acred);
+ 
+ /* no-cache prefetch routine */
+ afs_int32
+ afs_PrefetchNoCache(register struct vcache *avc, register struct AFS_UCRED *acred,
+ 			struct nocache_read_request *bparms);
+ 
+ 
+ #endif /* AFS_CACHE_BYPASS */
+ #endif /* _AFS_BYPASSCACHE_H */
+ 
Index: openafs/src/afs/afs_callback.c
diff -c openafs/src/afs/afs_callback.c:1.39.2.4 openafs/src/afs/afs_callback.c:1.39.2.5
*** openafs/src/afs/afs_callback.c:1.39.2.4	Mon Mar 10 18:32:32 2008
--- openafs/src/afs/afs_callback.c	Mon Sep 22 15:29:53 2008
***************
*** 17,23 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_callback.c,v 1.39.2.4 2008/03/10 22:32:32 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.39.2.5 2008/09/22 19:29:53 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 66,71 ****
--- 66,75 ----
      { "afsdb_client_lock", (char *)&afsdb_client_lock},
      { "afsdb_req_lock", (char *)&afsdb_req_lock},
  #endif
+ #ifdef AFS_DISCON_ENV
+     { "afs_discon_lock", (char *)&afs_discon_lock},
+     { "afs_DDirtyVCListLock", (char *)&afs_DDirtyVCListLock},
+ #endif
  };
  unsigned long lastCallBack_vnode;
  unsigned int lastCallBack_dv;
Index: openafs/src/afs/afs_conn.c
diff -c openafs/src/afs/afs_conn.c:1.14.8.3 openafs/src/afs/afs_conn.c:1.14.8.4
*** openafs/src/afs/afs_conn.c:1.14.8.3	Fri May 23 10:25:15 2008
--- openafs/src/afs/afs_conn.c	Mon Sep 22 15:29:54 2008
***************
*** 14,20 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_conn.c,v 1.14.8.3 2008/05/23 14:25:15 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
--- 14,20 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_conn.c,v 1.14.8.4 2008/09/22 19:29:54 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
***************
*** 159,165 ****
  	return NULL;
      }
      
!     if (AFS_IS_DISCONNECTED) {
          afs_warnuser("afs_ConnBySA: disconnected\n");
          ReleaseSharedLock(&afs_xconn);
          return NULL;
--- 159,165 ----
  	return NULL;
      }
      
!     if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
          afs_warnuser("afs_ConnBySA: disconnected\n");
          ReleaseSharedLock(&afs_xconn);
          return NULL;
***************
*** 276,282 ****
  
      AFS_STATCNT(afs_ConnByHost);
  
!     if (AFS_IS_DISCONNECTED) {
          afs_warnuser("afs_ConnByHost: disconnected\n");
          return NULL;
      }
--- 276,282 ----
  
      AFS_STATCNT(afs_ConnByHost);
  
!     if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
          afs_warnuser("afs_ConnByHost: disconnected\n");
          return NULL;
      }
Index: openafs/src/afs/afs_daemons.c
diff -c openafs/src/afs/afs_daemons.c:1.43.2.5 openafs/src/afs/afs_daemons.c:1.43.2.6
*** openafs/src/afs/afs_daemons.c:1.43.2.5	Fri May 23 10:25:15 2008
--- openafs/src/afs/afs_daemons.c	Mon Sep 22 15:35:26 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.43.2.5 2008/05/23 14:25:15 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.43.2.6 2008/09/22 19:35:26 shadow Exp $");
  
  #ifdef AFS_AIX51_ENV
  #define __FULL_PROTO
***************
*** 26,32 ****
  #include <sys/adspace.h>	/* for vm_att(), vm_det() */
  #endif
  
! 
  /* background request queue size */
  afs_lock_t afs_xbrs;		/* lock for brs */
  static int brsInit = 0;
--- 26,34 ----
  #include <sys/adspace.h>	/* for vm_att(), vm_det() */
  #endif
  
! #if defined(AFS_CACHE_BYPASS)
! #include "afs/afs_bypasscache.h"
! #endif// defined(AFS_CACHE_BYPASS)
  /* background request queue size */
  afs_lock_t afs_xbrs;		/* lock for brs */
  static int brsInit = 0;
***************
*** 516,521 ****
--- 518,544 ----
      }
  }
  
+ #if defined(AFS_CACHE_BYPASS)
+ #if 1 /* XXX Matt debugging */
+ static
+ #endif
+ void
+ BPrefetchNoCache(register struct brequest *ab)
+ {
+     struct vrequest treq;
+     afs_size_t len;
+ 	
+     if ((len = afs_InitReq(&treq, ab->cred)))
+ 	return;
+ 
+ #ifndef UKERNEL
+     /* OS-specific prefetch routine */
+     afs_PrefetchNoCache(ab->vc, ab->cred, (struct nocache_read_request *) ab->ptr_parm[0]);
+ #else
+ #warning Cache-bypass code path not implemented in UKERNEL
+ #endif
+ }
+ #endif
  
  static void
  BStore(register struct brequest *ab)
***************
*** 979,984 ****
--- 1002,1011 ----
  		       tb->opcode);
  	    if (tb->opcode == BOP_FETCH)
  		BPrefetch(tb);
+ #if defined(AFS_CACHE_BYPASS)		
+ 		else if (tb->opcode == BOP_FETCH_NOCACHE)
+ 		BPrefetchNoCache(tb);
+ #endif		
  	    else if (tb->opcode == BOP_STORE)
  		BStore(tb);
  	    else if (tb->opcode == BOP_PATH)
Index: openafs/src/afs/afs_dcache.c
diff -c openafs/src/afs/afs_dcache.c:1.64.4.8 openafs/src/afs/afs_dcache.c:1.64.4.11
*** openafs/src/afs/afs_dcache.c:1.64.4.8	Fri May 23 10:25:15 2008
--- openafs/src/afs/afs_dcache.c	Mon Sep 22 15:35:26 2008
***************
*** 14,20 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_dcache.c,v 1.64.4.8 2008/05/23 14:25:15 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
--- 14,20 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_dcache.c,v 1.64.4.11 2008/09/22 19:35:26 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 34,40 ****
  static void afs_DCSizeInit(void);
  static afs_int32 afs_DCWhichBucket(afs_int32, afs_int32);
  
- 
  /*
   * --------------------- Exported definitions ---------------------
   */
--- 34,39 ----
***************
*** 462,468 ****
  	adc->validPos = 0;
      newSize = ((newSize + afs_fsfragsize) ^ afs_fsfragsize) >> 10;	/* round up */
      afs_DCAdjustSize(adc, oldSize, newSize);
!     if (newSize > oldSize) {
  	/* We're growing the file, wakeup the daemon */
  	afs_MaybeWakeupTruncateDaemon();
      }
--- 461,468 ----
  	adc->validPos = 0;
      newSize = ((newSize + afs_fsfragsize) ^ afs_fsfragsize) >> 10;	/* round up */
      afs_DCAdjustSize(adc, oldSize, newSize);
!     if ((newSize > oldSize) && !AFS_IS_DISCONNECTED) {
! 
  	/* We're growing the file, wakeup the daemon */
  	afs_MaybeWakeupTruncateDaemon();
      }
***************
*** 515,522 ****
--- 515,528 ----
      afs_uint32 maxVictimPtr;	/* where it is */
      int discard;
      int curbucket;
+     int vfslocked;
+ 
+ #if defined(AFS_FBSD80_ENV) && !defined(UKERNEL)
+     vfslocked = VFS_LOCK_GIANT(afs_globalVFS);
+ #endif
  
      AFS_STATCNT(afs_GetDownD);
+ 
      if (CheckLock(&afs_xdcache) != -1)
  	osi_Panic("getdownd nolock");
      /* decrement anumber first for all dudes in free list */
***************
*** 524,532 ****
       * because we should try to free space even if anumber <=0 */
      if (!aneedSpace || *aneedSpace <= 0) {
  	anumber -= afs_freeDCCount;
! 	if (anumber <= 0)
  	    return;		/* enough already free */
      }
      /* bounds check parameter */
      if (anumber > MAXATONCE)
  	anumber = MAXATONCE;	/* all we can do */
--- 530,543 ----
       * because we should try to free space even if anumber <=0 */
      if (!aneedSpace || *aneedSpace <= 0) {
  	anumber -= afs_freeDCCount;
! 	if (anumber <= 0) {
! #if defined(AFS_FBSD80_ENV) && !defined(UKERNEL)
! 	  VFS_UNLOCK_GIANT(vfslocked);
! #endif
  	    return;		/* enough already free */
+ 	}
      }
+ 
      /* bounds check parameter */
      if (anumber > MAXATONCE)
  	anumber = MAXATONCE;	/* all we can do */
***************
*** 763,769 ****
  			       ICL_TYPE_INT32, tdc->index, ICL_TYPE_OFFSET,
  			       ICL_HANDLE_OFFSET(tchunkoffset));
  		    AFS_STATCNT(afs_gget);
! 		    afs_HashOutDCache(tdc);
  		    if (tdc->f.chunkBytes != 0) {
  			discard = 1;
  			if (aneedSpace)
--- 774,780 ----
  			       ICL_TYPE_INT32, tdc->index, ICL_TYPE_OFFSET,
  			       ICL_HANDLE_OFFSET(tchunkoffset));
  		    AFS_STATCNT(afs_gget);
! 		    afs_HashOutDCache(tdc, 1);
  		    if (tdc->f.chunkBytes != 0) {
  			discard = 1;
  			if (aneedSpace)
***************
*** 799,804 ****
--- 810,820 ----
  		break;
  	}
      }				/* big while loop */
+ 
+ #if defined(AFS_FBSD80_ENV) && !defined(UKERNEL)
+     VFS_UNLOCK_GIANT(vfslocked);
+ #endif
+ 
      return;
  
  }				/*afs_GetDownD */
***************
*** 809,825 ****
   * again by afs_FindDCache or afs_GetDCache.
   *
   * Parameters: adc -- pointer to dcache entry to remove from hash tables.
   *
   * Locks: Must have the afs_xdcache lock write-locked to call this function.
   */
  int
! afs_HashOutDCache(struct dcache *adc)
  {
      int i, us;
  
      AFS_STATCNT(afs_glink);
!     /* we know this guy's in the LRUQ.  We'll move dude into DCQ below */
!     DZap(adc);
      /* if this guy is in the hash table, pull him out */
      if (adc->f.fid.Fid.Volume != 0) {
  	/* remove entry from first hash chains */
--- 825,843 ----
   * again by afs_FindDCache or afs_GetDCache.
   *
   * Parameters: adc -- pointer to dcache entry to remove from hash tables.
+  *	       zap -- zap the given dcache ?
   *
   * Locks: Must have the afs_xdcache lock write-locked to call this function.
   */
  int
! afs_HashOutDCache(struct dcache *adc, int zap)
  {
      int i, us;
  
      AFS_STATCNT(afs_glink);
!     if (zap)
! 	/* we know this guy's in the LRUQ.  We'll move dude into DCQ below */
! 	DZap(adc);
      /* if this guy is in the hash table, pull him out */
      if (adc->f.fid.Fid.Volume != 0) {
  	/* remove entry from first hash chains */
***************
*** 862,881 ****
  	}
      }
  
!     /* prevent entry from being found on a reboot (it is already out of
!      * the hash table, but after a crash, we just look at fid fields of
!      * stable (old) entries).
!      */
!     adc->f.fid.Fid.Volume = 0;	/* invalid */
  
!     /* mark entry as modified */
!     adc->dflags |= DFEntryMod;
  
      /* all done */
      return 0;
  }				/*afs_HashOutDCache */
  
- 
  /*
   * afs_FlushDCache
   *
--- 880,900 ----
  	}
      }
  
!     if (zap) {
!     	/* prevent entry from being found on a reboot (it is already out of
!      	 * the hash table, but after a crash, we just look at fid fields of
!      	 * stable (old) entries).
!      	 */
!     	 adc->f.fid.Fid.Volume = 0;	/* invalid */
  
!     	/* mark entry as modified */
!     	adc->dflags |= DFEntryMod;
!     }
  
      /* all done */
      return 0;
  }				/*afs_HashOutDCache */
  
  /*
   * afs_FlushDCache
   *
***************
*** 901,907 ****
      afs_stats_cmperf.cacheFlushes++;
  
      /* remove from all hash tables */
!     afs_HashOutDCache(adc);
  
      /* Free its space; special case null operation, since truncate operation
       * in UFS is slow even in this case, and this allows us to pre-truncate
--- 920,926 ----
      afs_stats_cmperf.cacheFlushes++;
  
      /* remove from all hash tables */
!     afs_HashOutDCache(adc, 1);
  
      /* Free its space; special case null operation, since truncate operation
       * in UFS is slow even in this case, and this allows us to pre-truncate
***************
*** 1320,1337 ****
  afs_DCacheMissingChunks(struct vcache *avc)
  {
      int i, index;
!     afs_size_t totalLength;
!     afs_uint32 totalChunks;
      struct dcache *tdc;
  
      totalLength = avc->m.Length;
      if (avc->truncPos < totalLength)
          totalLength = avc->truncPos;
  
!     totalChunks = AFS_CHUNK(totalLength) + 1;
  
!     /*printf("Should have %d chunks for %d bytes\n", totalChunks, totalLength);*/
!     
      i = DVHash(&avc->fid);
      MObtainWriteLock(&afs_xdcache, 1001);
      for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
--- 1339,1367 ----
  afs_DCacheMissingChunks(struct vcache *avc)
  {
      int i, index;
!     afs_size_t totalLength = 0;
!     afs_uint32 totalChunks = 0;
      struct dcache *tdc;
  
      totalLength = avc->m.Length;
      if (avc->truncPos < totalLength)
          totalLength = avc->truncPos;
  
!     /* Length is 0, no chunk missing. */
!     if (totalLength == 0)
!     	return 0;
  
!     /* If totalLength is a multiple of chunksize, the last byte appears
!      * as being part of the next chunk, which does not exist.
!      * Decrementing totalLength by one fixes that.
!      */
!     totalLength--;
!     totalChunks = (AFS_CHUNK(totalLength) + 1);
! 
!     /*
!      printf("Should have %d chunks for %u bytes\n",
!     		totalChunks, (totalLength + 1));
!     */
      i = DVHash(&avc->fid);
      MObtainWriteLock(&afs_xdcache, 1001);
      for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
***************
*** 1621,1626 ****
--- 1651,1752 ----
  
  }				/* afs_UFSCacheFetchProc */
  
+ /*!
+  * Get a fresh dcache from the free or discarded list.
+  *
+  * \param avc Who's dcache is this going to be?
+  * \param chunk The position where it will be placed in.
+  * \param lock How are locks held.
+  * \param ashFid If this dcache going to be used for a shadow dir,
+  * 		this is it's fid.
+  *
+  * \note Required locks:
+  * 	- afs_xdcache (W)
+  * 	- avc (R if (lock & 1) set and W otherwise)
+  * \note It write locks the new dcache. The caller must unlock it.
+  *
+  * \return The new dcache.
+  */
+ struct dcache *afs_AllocDCache(struct vcache *avc,
+ 				afs_int32 chunk,
+ 				afs_int32 lock,
+ 				struct VenusFid *ashFid)
+ {
+     struct dcache *tdc = NULL;
+     afs_uint32 size = 0;
+     struct osi_file *file;
+ 
+     if (afs_discardDCList == NULLIDX
+ 	|| ((lock & 2) && afs_freeDCList != NULLIDX)) {
+ 
+ 	afs_indexFlags[afs_freeDCList] &= ~IFFree;
+ 	tdc = afs_GetDSlot(afs_freeDCList, 0);
+ 	osi_Assert(tdc->refCount == 1);
+ 	ReleaseReadLock(&tdc->tlock);
+ 	ObtainWriteLock(&tdc->lock, 604);
+ 	afs_freeDCList = afs_dvnextTbl[tdc->index];
+ 	afs_freeDCCount--;
+     } else {
+ 	afs_indexFlags[afs_discardDCList] &= ~IFDiscarded;
+ 	tdc = afs_GetDSlot(afs_discardDCList, 0);
+ 	osi_Assert(tdc->refCount == 1);
+ 	ReleaseReadLock(&tdc->tlock);
+ 	ObtainWriteLock(&tdc->lock, 605);
+ 	afs_discardDCList = afs_dvnextTbl[tdc->index];
+ 	afs_discardDCCount--;
+ 	size =
+ 	    ((tdc->f.chunkBytes +
+ 	      afs_fsfragsize) ^ afs_fsfragsize) >> 10;
+ 	tdc->f.states &= ~(DRO|DBackup|DRW);
+ 	afs_DCMoveBucket(tdc, size, 0);
+ 	afs_blocksDiscarded -= size;
+ 	afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
+ 	if (lock & 2) {
+ 	    /* Truncate the chunk so zeroes get filled properly */
+ 	    file = afs_CFileOpen(tdc->f.inode);
+ 	    afs_CFileTruncate(file, 0);
+ 	    afs_CFileClose(file);
+ 	    afs_AdjustSize(tdc, 0);
+ 	}
+     }
+ 
+     /*
+      * Locks held:
+      * avc->lock(R) if setLocks
+      * avc->lock(W) if !setLocks
+      * tdc->lock(W)
+      * afs_xdcache(W)
+      */
+ 
+     /*
+      * Fill in the newly-allocated dcache record.
+      */
+     afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages);
+     if (ashFid)
+     	/* Use shadow fid if provided. */
+ 	tdc->f.fid = *ashFid;
+     else
+     	/* Use normal vcache's fid otherwise. */
+     	tdc->f.fid = avc->fid;
+     if (avc->states & CRO)
+     	tdc->f.states = DRO;
+     else if (avc->states & CBackup)
+     	tdc->f.states = DBackup;
+     else
+     	tdc->f.states = DRW;
+     afs_DCMoveBucket(tdc, 0, afs_DCGetBucket(avc));
+     afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique;
+     if (!ashFid)
+     	hones(tdc->f.versionNo);	/* invalid value */
+     tdc->f.chunk = chunk;
+     tdc->validPos = AFS_CHUNKTOBASE(chunk);
+     /* XXX */
+     if (tdc->lruq.prev == &tdc->lruq)
+ 	osi_Panic("lruq 1");
+ 
+     return tdc;
+ }
+ 
  /*
   * afs_GetDCache
   *
***************
*** 1721,1727 ****
  #endif /* AFS_NOSTATS */
  
      AFS_STATCNT(afs_GetDCache);
- 
      if (dcacheDisabled)
  	return NULL;
  
--- 1847,1852 ----
***************
*** 1869,1885 ****
  	 * If we didn't find the entry, we'll create one.
  	 */
  	if (index == NULLIDX) {
- 	    /* If we're disconnected, we can't do anything */
-             if (AFS_IS_DISCONNECTED) {
-                 MReleaseWriteLock(&afs_xdcache);
-                 if (setLocks) {
-                     if (slowPass)
- 	                ReleaseWriteLock(&avc->lock);
- 	            else
- 		        ReleaseReadLock(&avc->lock);
-                 }
-                 return NULL;
-             }
  	    /*
  	     * Locks held:
  	     * avc->lock(R) if setLocks
--- 1994,1999 ----
***************
*** 1902,1909 ****
  			|| afs_freeDCList != NULLIDX)
  			break;
  		    /* If we can't get space for 5 mins we give up and panic */
! 		    if (++downDCount > 300)
  			osi_Panic("getdcache");
  		    MReleaseWriteLock(&afs_xdcache);
  		    /*
  		     * Locks held:
--- 2016,2027 ----
  			|| afs_freeDCList != NULLIDX)
  			break;
  		    /* If we can't get space for 5 mins we give up and panic */
! 		    if (++downDCount > 300) {
! #if defined(AFS_CACHE_BYPASS)
! 			afs_warn("GetDCache calling osi_Panic: No space in five minutes.\n downDCount: %d\n aoffset: %d alen: %d\n", downDCount, aoffset, alen);
! #endif
  			osi_Panic("getdcache");
+                     }
  		    MReleaseWriteLock(&afs_xdcache);
  		    /*
  		     * Locks held:
***************
*** 1915,1981 ****
  		}
  	    }
  
! 	    if (afs_discardDCList == NULLIDX
! 		|| ((aflags & 2) && afs_freeDCList != NULLIDX)) {
! 
! 		afs_indexFlags[afs_freeDCList] &= ~IFFree;
! 		tdc = afs_GetDSlot(afs_freeDCList, 0);
! 		osi_Assert(tdc->refCount == 1);
! 		ReleaseReadLock(&tdc->tlock);
! 		ObtainWriteLock(&tdc->lock, 604);
! 		afs_freeDCList = afs_dvnextTbl[tdc->index];
! 		afs_freeDCCount--;
! 	    } else {
! 		afs_indexFlags[afs_discardDCList] &= ~IFDiscarded;
! 		tdc = afs_GetDSlot(afs_discardDCList, 0);
! 		osi_Assert(tdc->refCount == 1);
! 		ReleaseReadLock(&tdc->tlock);
! 		ObtainWriteLock(&tdc->lock, 605);
! 		afs_discardDCList = afs_dvnextTbl[tdc->index];
! 		afs_discardDCCount--;
! 		size =
! 		    ((tdc->f.chunkBytes +
! 		      afs_fsfragsize) ^ afs_fsfragsize) >> 10;
! 		tdc->f.states &= ~(DRO|DBackup|DRW);
! 		afs_DCMoveBucket(tdc, size, 0);
! 		afs_blocksDiscarded -= size;
! 		afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
! 		if (aflags & 2) {
! 		    /* Truncate the chunk so zeroes get filled properly */
! 		    file = afs_CFileOpen(tdc->f.inode);
! 		    afs_CFileTruncate(file, 0);
! 		    afs_CFileClose(file);
! 		    afs_AdjustSize(tdc, 0);
! 		}
! 	    }
! 
! 	    /*
! 	     * Locks held:
! 	     * avc->lock(R) if setLocks
! 	     * avc->lock(W) if !setLocks
! 	     * tdc->lock(W)
! 	     * afs_xdcache(W)
! 	     */
! 
! 	    /*
! 	     * Fill in the newly-allocated dcache record.
! 	     */
! 	    afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages);
! 	    tdc->f.fid = avc->fid;
! 	    if (avc->states & CRO) 
! 		tdc->f.states = DRO;
! 	    else if (avc->states & CBackup) 
! 		tdc->f.states = DBackup;
! 	    else 
! 		tdc->f.states = DRW;
! 	    afs_DCMoveBucket(tdc, 0, afs_DCGetBucket(avc));
! 	    afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique;
! 	    hones(tdc->f.versionNo);	/* invalid value */
! 	    tdc->f.chunk = chunk;
! 	    tdc->validPos = AFS_CHUNKTOBASE(chunk);
! 	    /* XXX */
! 	    if (tdc->lruq.prev == &tdc->lruq)
! 		osi_Panic("lruq 1");
  
  	    /*
  	     * Now add to the two hash chains - note that i is still set
--- 2033,2039 ----
  		}
  	    }
  
! 	    tdc = afs_AllocDCache(avc, chunk, aflags, NULL);
  
  	    /*
  	     * Now add to the two hash chains - note that i is still set
***************
*** 2138,2144 ****
              }
              /* Flush the Dcache */
              afs_PutDCache(tdc);
!                 
              return NULL;
          }
  	UpgradeSToWLock(&tdc->lock, 609);
--- 2196,2202 ----
              }
              /* Flush the Dcache */
              afs_PutDCache(tdc);
! 
              return NULL;
          }
  	UpgradeSToWLock(&tdc->lock, 609);
***************
*** 3557,3559 ****
--- 3615,3825 ----
      QInit(&afs_DLRU);
  
  }
+ 
+ #if defined(AFS_DISCON_ENV)
+ 
+ /*!
+  * Make a shadow copy of a dir's dcaches. It's used for disconnected
+  * operations like remove/create/rename to keep the original directory data.
+  * On reconnection, we can diff the original data with the server and get the
+  * server changes and with the local data to get the local changes.
+  *
+  * \param avc The dir vnode.
+  *
+  * \return 0 for success.
+  *
+  * \note The only lock allowed to be set is the dir's vcache entry, and it
+  * must be set in write mode.
+  * \note The vcache entry must be write locked.
+  */
+ int afs_MakeShadowDir(struct vcache *avc)
+ {
+     int j, i, index, code, ret_code = 0, offset, trans_size, block;
+     struct dcache *tdc, *new_dc = NULL;
+     struct osi_file *tfile_src, *tfile_dst;
+     struct VenusFid shadow_fid;
+     char *data;
+     int lock_held = 0;
+ 
+     /* Is this a dir? */
+     if (vType(avc) != VDIR)
+     	return ENOTDIR;
+ 
+     /* Generate a fid for the shadow dir. */
+     shadow_fid.Cell = avc->fid.Cell;
+     shadow_fid.Fid.Volume = avc->fid.Fid.Volume;
+     afs_GenShadowFid(&shadow_fid);
+ 
+     /* For each dcache, do copy it into a new fresh one. */
+     i = DVHash(&avc->fid);
+     for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
+     	/* Making sure that this isn't going to get locked twice. */
+ 	if (!lock_held) {
+ 	    /* XXX: Moved it from outside of the loop.
+ 	     * Maybe it's not quite okay because of the use of
+ 	     * dvhashTbl (once) in the for statement.
+ 	     */
+ 	    ObtainWriteLock(&afs_xdcache, 716);
+ 	    lock_held = 1;
+ 	}
+ 
+         i = afs_dvnextTbl[index];
+         if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
+             tdc = afs_GetDSlot(index, NULL);
+ 
+ 	    ReleaseReadLock(&tdc->tlock);
+ 
+ 	    if (!FidCmp(&tdc->f.fid, &avc->fid)) {
+ 
+ 		/* Got a dir's dcache. */
+ 		lock_held = 0;
+ 
+ 		/* Get a fresh dcache. */
+ 		new_dc = afs_AllocDCache(avc, 0, 0, &shadow_fid);
+ 
+ 		/* Unlock hash for now. Don't need it during operations on the
+ 		 * dcache. Oh, and we can't use it because of the locking
+ 		 * hierarchy...
+ 		 */
+ 		/* XXX: So much for lock ierarchy, the afs_AllocDCache doesn't
+ 		 * respect it.
+ 		 */
+ 		//ReleaseWriteLock(&afs_xdcache);
+ 
+ 		ObtainReadLock(&tdc->lock);
+ 
+ 		/* Set up the new fid. */
+ 		/* Copy interesting data from original dir dcache. */
+ 		new_dc->mflags = tdc->mflags;
+ 		new_dc->dflags = tdc->dflags;
+ 		new_dc->f.modTime = tdc->f.modTime;
+ 		new_dc->f.versionNo = tdc->f.versionNo;
+ 		new_dc->f.states = tdc->f.states;
+ 		new_dc->f.chunk= tdc->f.chunk;
+ 		new_dc->f.chunkBytes = tdc->f.chunkBytes;
+ 
+ 		/*
+ 		 * Now add to the two hash chains - note that i is still set
+ 		 * from the above DCHash call.
+ 		 */
+ 		//ObtainWriteLock(&afs_xdcache, 713);
+ 
+ 		j = DCHash(&shadow_fid, 0);
+ 		afs_dcnextTbl[new_dc->index] = afs_dchashTbl[j];
+ 		afs_dchashTbl[j] = new_dc->index;
+ 
+ 		j = DVHash(&shadow_fid);
+ 		afs_dvnextTbl[new_dc->index] = afs_dvhashTbl[j];
+ 		afs_dvhashTbl[j] = new_dc->index;
+ 		afs_MaybeWakeupTruncateDaemon();
+ 
+ 		ReleaseWriteLock(&afs_xdcache);
+ 
+ 		/* Alloc a 4k block. */
+ 		data = (char *) afs_osi_Alloc(4096);
+ 		if (!data) {
+ 		    printf("afs_MakeShadowDir: could not alloc data\n");
+ 		    ret_code = ENOMEM;
+ 		    goto done;
+ 		}
+ 
+ 		/* Open the files. */
+ 		tfile_src = afs_CFileOpen(tdc->f.inode);
+ 		tfile_dst = afs_CFileOpen(new_dc->f.inode);
+ 
+ 		/* Init no of blocks to be read and offset. */
+ 		block = (tdc->f.chunkBytes / 4096);
+ 		offset = 0;
+ 
+ 		/* And now copy dir dcache data into this dcache,
+ 		 * 4k at a time.
+ 		 */
+ 		while (block >= 0) {
+ 
+ 		    /* Last chunk might have less bytes to transfer. */
+ 		    if (!block) {
+ 		    	/* Last block. */
+ 		    	trans_size = (tdc->f.chunkBytes % 4096);
+ 			if (!trans_size)
+ 			    /* An exact no of 4k blocks. */
+ 			    break;
+ 		    } else
+ 		    	trans_size = 4096;
+ 
+ 		    /* Read a chunk from the dcache. */
+ 		    code = afs_CFileRead(tfile_src, offset, data, trans_size);
+ 		    if (code < trans_size) {
+ 		    	/* Can't access file, stop doing stuff and return error. */
+ 		    	ret_code = EIO;
+ 		    	break;
+ 		    }
+ 
+ 		    /* Write it to the new dcache. */
+ 		    code = afs_CFileWrite(tfile_dst, offset, data, trans_size);
+ 		    if (code < trans_size) {
+ 		    	ret_code = EIO;
+ 		    	break;
+ 		    }
+ 
+ 		    block--;
+ 		    offset += 4096;
+ 		}		/* while (block) */
+ 
+ 		afs_CFileClose(tfile_dst);
+ 		afs_CFileClose(tfile_src);
+ 
+ 		afs_osi_Free(data, 4096);
+ 
+ 		ReleaseWriteLock(&new_dc->lock);
+ 		ReleaseReadLock(&tdc->lock);
+ 
+ 		afs_PutDCache(new_dc);
+ 	    }			/* if dcache fid match */
+             afs_PutDCache(tdc);
+         }			/* if unuiquifier match */
+     }
+ done:
+     if (lock_held)
+ 	ReleaseWriteLock(&afs_xdcache);
+ 
+     if (!ret_code) {
+     	if (!avc->ddirty_flags) {
+ 	    ObtainWriteLock(&afs_DDirtyVCListLock, 763);
+ 	    AFS_DISCON_ADD_DIRTY(avc);
+ 	    ReleaseWriteLock(&afs_DDirtyVCListLock);
+ 	}
+ 	avc->shVnode = shadow_fid.Fid.Vnode;
+ 	avc->shUnique = shadow_fid.Fid.Unique;
+ 	avc->ddirty_flags |= VDisconShadowed;
+     }
+ 
+     return ret_code;
+ }
+ 
+ /*!
+  * Delete the dcaches of a shadow dir.
+  *
+  * \param avc The vcache containing the shadow fid.
+  *
+  * \note avc must be write locked.
+  */
+ void afs_DeleteShadowDir(struct vcache *avc)
+ {
+     struct dcache *tdc;
+     struct VenusFid shadow_fid;
+ 
+     shadow_fid.Cell = avc->fid.Cell;
+     shadow_fid.Fid.Volume = avc->fid.Fid.Volume;
+     shadow_fid.Fid.Vnode = avc->shVnode;
+     shadow_fid.Fid.Unique = avc->shUnique;
+ 
+     tdc = afs_FindDCacheByFid(&shadow_fid);
+     if (tdc) {
+     	afs_HashOutDCache(tdc, 1);
+ 	afs_DiscardDCache(tdc);
+     	afs_PutDCache(tdc);
+     }
+     /* Remove shadowed dir flag. */
+     avc->ddirty_flags &= ~VDisconShadowed;
+ }
+ #endif
Index: openafs/src/afs/afs_disconnected.c
diff -c openafs/src/afs/afs_disconnected.c:1.2.2.2 openafs/src/afs/afs_disconnected.c:1.2.2.3
*** openafs/src/afs/afs_disconnected.c:1.2.2.2	Fri May 23 10:25:15 2008
--- openafs/src/afs/afs_disconnected.c	Mon Sep 22 15:29:54 2008
***************
*** 3,18 ****
   * License.  For details, see the LICENSE file in the top-level source
   * directory or online at http://www.openafs.org/dl/license10.html
   */
!  
  #include <afsconfig.h>
  #include "afs/param.h"
   
! RCSID("$Header: /cvs/openafs/src/afs/afs_disconnected.c,v 1.2.2.2 2008/05/23 14:25:15 shadow Exp $");
   
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
!  
  #ifdef AFS_DISCON_ENV
  
! /* Nothing here any more. Remove from the build unless stuff comes back! */
  #endif
--- 3,1486 ----
   * License.  For details, see the LICENSE file in the top-level source
   * directory or online at http://www.openafs.org/dl/license10.html
   */
! 
  #include <afsconfig.h>
  #include "afs/param.h"
   
! RCSID("$Header: /cvs/openafs/src/afs/afs_disconnected.c,v 1.2.2.3 2008/09/22 19:29:54 shadow Exp $");
   
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
! #include "afs/afs_stats.h"	/* statistics */
! #include "afs/lock.h"
! #include "afs/afs_cbqueue.h"
! 
  #ifdef AFS_DISCON_ENV
  
! #define dv_match(vc, fstat) 				 \
! 	((vc->m.DataVersion.low == fstat.DataVersion) && \
!      	(vc->m.DataVersion.high == fstat.dataVersionHigh))
! 
! /*! Global list of dirty vcaches. */
! /*! Last added element. */
! struct vcache *afs_DDirtyVCList = NULL;
! /*! Head of list. */
! struct vcache *afs_DDirtyVCListStart = NULL;
! /*! Previous element in the list. */
! struct vcache *afs_DDirtyVCListPrev = NULL;
! 
! /*! Locks list of dirty vcaches. */
! afs_rwlock_t afs_DDirtyVCListLock;
! 
! extern afs_int32 *afs_dvhashTbl;	/*Data cache hash table */
! extern afs_int32 *afs_dchashTbl;	/*Data cache hash table */
! extern afs_int32 *afs_dvnextTbl;	/*Dcache hash table links */
! extern afs_int32 *afs_dcnextTbl;	/*Dcache hash table links */
! extern struct dcache **afs_indexTable;	/*Pointers to dcache entries */
! 
! /*! Vnode number. On file creation, use the current
!  *  value and increment it.
!  */
! afs_uint32 afs_DisconVnode = 2;
! 
! /*! Conflict policy. */
! enum {
! 	CLIENT_WINS = 0,
! 	SERVER_WINS,
! 	LAST_CLOSER_WINS,
! 	ASK
! };
! 
! afs_int32 afs_ConflictPolicy = SERVER_WINS;
! 
! /*!
!  * Find the first dcache of a file that has the specified fid.
!  * Similar to afs_FindDCache, only that it takes a fid instead
!  * of a vcache and it can get the first dcache.
!  *
!  * \param afid
!  *
!  * \return The found dcache or NULL.
!  */
! struct dcache *afs_FindDCacheByFid(register struct VenusFid *afid)
! {
!     register afs_int32 i, index;
!     register struct dcache *tdc = NULL;
! 
!     i = DVHash(afid);
!     ObtainWriteLock(&afs_xdcache, 758);
!     for (index = afs_dvhashTbl[i]; index != NULLIDX;) {
! 	if (afs_indexUnique[index] == afid->Fid.Unique) {
! 	    tdc = afs_GetDSlot(index, NULL);
! 	    ReleaseReadLock(&tdc->tlock);
! 	    if (!FidCmp(&tdc->f.fid, afid)) {
! 		break;		/* leaving refCount high for caller */
! 	    }
! 	    afs_PutDCache(tdc);
! 	}
! 	index = afs_dvnextTbl[index];
!     }
!     ReleaseWriteLock(&afs_xdcache);
! 
!     if (index == NULLIDX)
!     	tdc = NULL;
!     return tdc;
! }
! 
! /*!
!  * Generate a store status from a dirty vcache entry.
!  *
!  * \param avc Dirty vcache entry.
!  * \param astat
!  *
!  * \note The vnode must be share locked. It is called only on resync,
!  * where the vnode is write locked locally and and the server.
!  *
!  * \return Mask of operations.
!  */
! int afs_GenStoreStatus(struct vcache *avc, struct AFSStoreStatus *astat)
! {
!     if (!avc || !astat || !avc->ddirty_flags)
!     	return 0;
! 
!     /* Clean up store stat. */
!     memset(astat, 0, sizeof(struct AFSStoreStatus));
! 
!     if (avc->ddirty_flags & VDisconSetTime) {
! 	/* Update timestamp. */
! 	astat->ClientModTime = avc->m.Date;
! 	astat->Mask |= AFS_SETMODTIME;
!     }
! 
!     if (avc->ddirty_flags & VDisconSetMode) {
! 	/* Copy the mode bits. */
! 	astat->UnixModeBits = avc->m.Mode;
! 	astat->Mask |= AFS_SETMODE;
!    }
! 
!    /* XXX: more to come... ?*/
! 
!    return astat->Mask;
! }
! 
! /*!
!  * Hook for filtering the local dir fid by searching the "." entry.
!  *
!  * \param hdata The fid to be filled.
!  */
! int get_parent_dir_fid_hook(void *hdata,
! 				char *aname,
! 				afs_int32 vnode,
! 				afs_int32 unique)
! {
!     struct VenusFid *tfid = (struct VenusFid *) hdata;
! 
!     if ((aname[0] == '.') && (aname[1] == '.') && !aname[2]) {
!     	tfid->Fid.Vnode = vnode;
! 	tfid->Fid.Unique = unique;
! 	return 1;
!     }
! 
!     return 0;
! }
! 
! /*!
!  * Get a the dir's fid by looking in the vcache for simple files and
!  * in the ".." entry for directories.
!  *
!  * \param avc The file's vhash entry.
!  * \param afid Put the fid here.
!  */
! int afs_GetParentDirFid(struct vcache *avc, struct VenusFid *afid)
! {
!     struct dcache *tdc;
! 
!     afid->Cell = avc->fid.Cell;
!     afid->Fid.Volume = avc->fid.Fid.Volume;
! 
!     if (vType(avc) == VREG) {
! 	/* Normal files have the dir fid embedded in the vcache. */
! 	afid->Fid.Vnode = avc->parentVnode;
! 	afid->Fid.Unique = avc->parentUnique;
! 
!     } else if (vType(avc) == VDIR) {
! 	/* If dir or parent dir created locally*/
! 	tdc = afs_FindDCacheByFid(&avc->fid);
!     	if (tdc) {
! 	    /* Lookup each entry for the fid. It should be the first. */
!     	    afs_dir_EnumerateDir(tdc, &get_parent_dir_fid_hook, afid);
!     	    afs_PutDCache(tdc);
! 	}
!     }
! 
!     return 0;
! }
! 
! struct NameAndFid {
!     struct VenusFid *fid;
!     char *name;
!     int name_len;
! };
! 
! /*!
!  * Hook that searches a certain fid's name.
!  *
!  * \param hdata NameAndFid structure containin a pointer to a fid
!  * and an allocate name. The name will be filled when hit.
!  */
! int get_vnode_name_hook(void *hdata,
! 				char *aname,
! 				afs_int32 vnode,
! 				afs_int32 unique)
! {
!     struct NameAndFid *nf = (struct NameAndFid *) hdata;
! 
!     if ((nf->fid->Fid.Vnode == vnode) &&
!     	(nf->fid->Fid.Unique == unique)) {
! 	nf->name_len = strlen(aname);
! 	memcpy(nf->name, aname, nf->name_len);
! 	nf->name[nf->name_len] = 0;
! 
! 	return 1;
!     }
! 
!     return 0;
! }
! 
! /*!
!  * Try to get a vnode's name by comparing all parent dir's entries
!  * to the given fid. It can also return the dir's dcache.
!  *
!  * \param avc The file's vcache.
!  * \param afid The parent dir's fid.
!  * \param aname A preallocated string for the name.
!  * \param deleted Has this file been deleted? If yes, use the shadow
!  * dir for looking up the name.
!  */
! int afs_GetVnodeName(struct vcache *avc,
! 			struct VenusFid *afid,
! 			char *aname,
! 			int deleted)
! {
!     int code = 0;
!     struct dcache *tdc;
!     struct vcache *parent_vc;
!     struct NameAndFid tnf;
!     struct VenusFid parent_fid;
!     struct VenusFid shadow_fid;
! 
!     /* List dir contents and get it's tdc. */
!     if (deleted) {
! 	/* For deleted files, get the shadow dir's tdc: */
! 
! 	/* Get the parent dir's vcache that contains the shadow fid. */
! 	parent_fid.Cell = avc->fid.Cell;
! 	parent_fid.Fid.Volume = avc->fid.Fid.Volume;
! 	if (avc->ddirty_flags & VDisconRename) {
! 	    /* For renames the old dir fid is needed. */
! 	    parent_fid.Fid.Vnode = avc->oldVnode;
! 	    parent_fid.Fid.Unique = avc->oldUnique;
! 	} else {
! 	    parent_fid.Fid.Vnode = afid->Fid.Vnode;
! 	    parent_fid.Fid.Unique = afid->Fid.Unique;
! 	}
! 
! 	/* Get the parent dir's vcache that contains the shadow fid. */
! 	ObtainSharedLock(&afs_xvcache, 755);
! 	parent_vc = afs_FindVCache(&parent_fid, 0, 1);
! 	ReleaseSharedLock(&afs_xvcache);
! 	if (!parent_vc) {
! 	    return ENOENT;
! 	}
! 
! 	shadow_fid.Cell = parent_vc->fid.Cell;
!     	shadow_fid.Fid.Volume = parent_vc->fid.Fid.Volume;
!     	shadow_fid.Fid.Vnode = parent_vc->shVnode;
!     	shadow_fid.Fid.Unique = parent_vc->shUnique;
! 
! 	afs_PutVCache(parent_vc);
! 
! 	/* Get shadow dir's dcache. */
! 	tdc = afs_FindDCacheByFid(&shadow_fid);
! 
!     } else {
! 
! 	/* For normal files, look into the current dir's entry. */
! 	tdc = afs_FindDCacheByFid(afid);
!     }			/* if (deleted) */
! 
!     if (tdc) {
! 	tnf.fid = &avc->fid;
!    	tnf.name_len = 0;
!     	tnf.name = aname;
!     	afs_dir_EnumerateDir(tdc, &get_vnode_name_hook, &tnf);
! 	afs_PutDCache(tdc);
!     } else {
!         code = ENOENT;
!     }
! 
!     return code;
! }
! 
! struct DirtyChildrenCount {
!     struct vcache *vc;
!     afs_uint32 count;
! };
! 
! /*!
!  * Lookup dirty deleted vnodes in this dir.
!  */
! int chk_del_children_hook(void *hdata,
! 				char *aname,
! 				afs_int32 vnode,
! 				afs_int32 unique)
! {
!     struct VenusFid tfid;
!     struct DirtyChildrenCount *v = (struct DirtyChildrenCount *) hdata;
!     struct vcache *tvc;
! 
!     if ((aname[0] == '.') && !aname[1])
!     	/* Skip processing this dir again.
! 	 * It would result in an endless loop.
! 	 */
! 	return 0;
! 
!     if ((aname[0] == '.') && (aname[1] == '.') && !aname[2])
!     	/* Don't process parent dir. */
!     	return 0;
! 
!     /* Get this file's vcache. */
!     tfid.Cell = v->vc->fid.Cell;
!     tfid.Fid.Volume = v->vc->fid.Fid.Volume;
!     tfid.Fid.Vnode = vnode;
!     tfid.Fid.Unique = unique;
! 
!     ObtainSharedLock(&afs_xvcache, 757);
!     tvc = afs_FindVCache(&tfid, 0, 1);
!     ReleaseSharedLock(&afs_xvcache);
! 
!     /* Count unfinished dirty children. VDisconShadowed can still be set,
!      * because we need it to remove the shadow dir.
!      */
!     if (tvc && tvc->ddirty_flags) {
! 	v->count++;
! 	afs_PutVCache(tvc);
!     }
! 
!     return 0;
! }
! 
! /*!
!  * Check if entries have been deleted in a vnode's shadow
!  * dir.
!  *
!  * \return Returns the number of dirty children.
!  *
!  * \note afs_DDirtyVCListLock must be write locked.
!  */
! int afs_CheckDeletedChildren(struct vcache *avc)
! {
!     struct dcache *tdc;
!     struct DirtyChildrenCount dcc;
!     struct VenusFid shadow_fid;
! 
!     if (!(avc->ddirty_flags & VDisconShadowed))
!     	/* Empty dir. */
!     	return 0;
! 
!     shadow_fid.Cell = avc->fid.Cell;
!     shadow_fid.Fid.Volume = avc->fid.Fid.Volume;
!     shadow_fid.Fid.Vnode = avc->shVnode;
!     shadow_fid.Fid.Unique = avc->shUnique;
! 
!     dcc.count = 0;
! 
!     /* Get shadow dir's dcache. */
!     tdc = afs_FindDCacheByFid(&shadow_fid);
!     if (tdc) {
! 	dcc.vc = avc;
! 	afs_dir_EnumerateDir(tdc, &chk_del_children_hook, &dcc);
! 	afs_PutDCache(tdc);
!     }
! 
!     return dcc.count;
! }
! 
! /*!
!  * Changes a file's parent fid references.
!  */
! int fix_children_fids_hook(void *hdata,
! 				char *aname,
! 				afs_int32 vnode,
! 				afs_int32 unique)
! {
!     struct VenusFid tfid;
!     struct VenusFid *afid = (struct VenusFid *) hdata;
!     struct vcache *tvc;
!     struct dcache *tdc = NULL;
! 
!     if ((aname[0] == '.') && !aname[1])
! 	return 0;
! 
!     if ((aname[0] == '.') && (aname[1] == '.') && !aname[2])
!     	return 0;
! 
!     tfid.Cell = afid->Cell;
!     tfid.Fid.Volume = afid->Fid.Volume;
!     tfid.Fid.Vnode = vnode;
!     tfid.Fid.Unique = unique;
! 
!     if (!(vnode % 2)) {
! 	/* vnode's parity indicates that it's a file. */
! 
! 	/* Get the vcache. */
! 	ObtainSharedLock(&afs_xvcache, 759);
! 	tvc = afs_FindVCache(&tfid, 0, 1);
! 	ReleaseSharedLock(&afs_xvcache);
! 
! 	/* Change the fields. */
! 	if (tvc) {
! 	    tvc->parentVnode = afid->Fid.Vnode;
! 	    tvc->parentUnique = afid->Fid.Unique;
! 
! 	    afs_PutVCache(tvc);
! 	}
!     } else {
!     	/* It's a dir. Fix this dir's .. entry to contain the new fid. */
! 	/* Seek the dir's dcache. */
!     	tdc = afs_FindDCacheByFid(&tfid);
! 	if (tdc) {
! 	    /* Change the .. entry fid. */
! 	    afs_dir_ChangeFid(tdc, "..", NULL, &afid->Fid.Vnode);
! 	    afs_PutDCache(tdc);
! 	}
!     }			/* if (!(vnode % 2))*/
! 
!     return 0;
! }
! 
! /*!
!  * Fixes the parentVnode and parentUnique fields of all
!  * files (not dirs) contained in the directory pointed by
!  * old_fid. This is useful on resync, when a locally created dir
!  * get's a new fid and all the children references must be updated
!  * to reflect the new fid.
!  *
!  * \note The dir's fid hasn't been changed yet, it is still referenced
!  * with the old fid.
!  *
!  * \param old_fid The current dir's fid.
!  * \param new_fid The new dir's fid.
!  */
! void afs_FixChildrenFids(struct VenusFid *old_fid, struct VenusFid *new_fid)
! {
!     struct dcache *tdc;
! 
!     /* Get shadow dir's dcache. */
!     tdc = afs_FindDCacheByFid(old_fid);
!     /* Change the fids. */
!     if (tdc) {
! 	afs_dir_EnumerateDir(tdc, &fix_children_fids_hook, new_fid);
! 	afs_PutDCache(tdc);
!     }
! }
! 
! int list_dir_hook(void *hdata, char *aname, afs_int32 vnode, afs_int32 unique)
! {
!     printf("list_dir_hook: %s v:%u u:%u\n", aname, vnode, unique);
!     return 0;
! }
! 
! void afs_DbgListDirEntries(struct VenusFid *afid)
! {
!     struct dcache *tdc;
! 
!     /* Get shadow dir's dcache. */
!     tdc = afs_FindDCacheByFid(afid);
!     if (tdc) {
! 	afs_dir_EnumerateDir(tdc, &list_dir_hook, NULL);
! 	afs_PutDCache(tdc);
!     }
! }
! 
! /*!
!  * Handles file renaming on reconnection:
!  * - Get the old name from the old dir's shadow dir.
!  * - Get the new name from the current dir.
!  * - Old dir fid and new dir fid are collected along the way.
!  * */
! int afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
! {
!     struct VenusFid old_pdir_fid, new_pdir_fid;
!     char *old_name, *new_name;
!     struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus;
!     struct AFSVolSync tsync;
!     struct conn *tc;
!     afs_uint32 code = 0;
!     XSTATS_DECLS;
! 
!     /* Get old dir vcache. */
!     old_pdir_fid.Cell = avc->fid.Cell;
!     old_pdir_fid.Fid.Volume = avc->fid.Fid.Volume;
!     old_pdir_fid.Fid.Vnode = avc->oldVnode;
!     old_pdir_fid.Fid.Unique = avc->oldUnique;
! 
!     /* Get old name. */
!     old_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
!     if (!old_name) {
! 	printf("afs_ProcessOpRename: Couldn't alloc space for old name.\n");
! 	return ENOMEM;
!     }
!     code = afs_GetVnodeName(avc, &old_pdir_fid, old_name, 1);
!     if (code) {
! 	printf("afs_ProcessOpRename: Couldn't find old name.\n");
! 	code = ENOENT;
! 	goto end2;
!     }
! 
!     /* Alloc data first. */
!     new_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
!     if (!new_name) {
! 	printf("afs_ProcessOpRename: Couldn't alloc space for new name.\n");
! 	code = ENOMEM;
! 	goto end2;
!     }
! 
!     if (avc->ddirty_flags & VDisconRenameSameDir) {
!     	/* If we're in the same dir, don't do the lookups all over again,
! 	 * just copy fid and vcache from the old dir.
! 	 */
! 	memcpy(&new_pdir_fid, &old_pdir_fid, sizeof(struct VenusFid));
!     } else {
! 	/* Get parent dir's FID.*/
!     	new_pdir_fid.Fid.Unique = 0;
!     	afs_GetParentDirFid(avc, &new_pdir_fid);
!     	if (!new_pdir_fid.Fid.Unique) {
! 	    printf("afs_ProcessOpRename: Couldn't find new parent dir FID.\n");
! 	    code = ENOENT;
! 	    goto end1;
!         }
!     }
! 
!     /* And finally get the new name. */
!     code = afs_GetVnodeName(avc, &new_pdir_fid, new_name, 0);
!     if (code) {
! 	printf("afs_ProcessOpRename: Couldn't find new name.\n");
! 	code = ENOENT;
! 	goto end1;
!     }
! 
!     /* Send to data to server. */
!     do {
!     	tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK);
!     	if (tc) {
! 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
! 	    RX_AFS_GUNLOCK();
! 	    code = RXAFS_Rename(tc->id,
! 	    	(struct AFSFid *)&old_pdir_fid.Fid,
! 		old_name,
! 		(struct AFSFid *)&new_pdir_fid.Fid,
! 		new_name,
! 		&OutOldDirStatus,
! 		&OutNewDirStatus,
! 		&tsync);
! 	    RX_AFS_GLOCK();
! 	    XSTATS_END_TIME;
!         } else
! 	    code = -1;
! 
!     } while (afs_Analyze(tc,
!     		code,
! 		&new_pdir_fid,
! 		areq,
! 		AFS_STATS_FS_RPCIDX_RENAME,
! 		SHARED_LOCK,
! 		NULL));
! 
!     if (code)
!     	printf("afs_ProcessOpRename: server code=%u\n", code);
! end1:
!     afs_osi_Free(new_name, AFSNAMEMAX);
! end2:
!     afs_osi_Free(old_name, AFSNAMEMAX);
!     return code;
! }
! 
! /*!
!  * Handles all the reconnection details:
!  * - Get all the details about the vnode: name, fid, and parent dir fid.
!  * - Send data to server.
!  * - Handle errors.
!  * - Reorder vhash and dcaches in their hashes, using the newly acquired fid.
!  */
! int afs_ProcessOpCreate(struct vcache *avc,
! 				struct vrequest *areq,
! 				struct AFS_UCRED *acred)
! {
!     char *tname = NULL;
!     struct AFSStoreStatus InStatus;
!     struct AFSFetchStatus OutFidStatus, OutDirStatus;
!     struct VenusFid pdir_fid, newFid;
!     struct server *hostp = NULL;
!     struct AFSCallBack CallBack;
!     struct AFSVolSync tsync;
!     struct vcache *tdp = NULL, *tvc = NULL;
!     struct dcache *tdc = NULL;
!     struct conn *tc;
!     afs_int32 now, hash, new_hash, index;
!     int code = 0;
!     XSTATS_DECLS;
! 
!     /* Get parent dir's FID. */
!     pdir_fid.Fid.Unique = 0;
!     afs_GetParentDirFid(avc, &pdir_fid);
!     if (!pdir_fid.Fid.Unique) {
! 	printf("afs_ProcessOpCreate: Couldn't find parent dir'sFID.\n");
! 	return ENOENT;
!     }
! 
!     tname = afs_osi_Alloc(AFSNAMEMAX);
!     if (!tname) {
! 	printf("afs_ProcessOpCreate: Couldn't find file name\n");
! 	return ENOMEM;
!     }
! 
!     /* Get vnode's name. */
!     code = afs_GetVnodeName(avc, &pdir_fid, tname, 0);
!     if (code) {
! 	printf("afs_ProcessOpCreate: Couldn't find file name\n");
! 	code = ENOENT;
! 	goto end;
!     }
! 
!     /* Get parent dir vcache. */
!     ObtainSharedLock(&afs_xvcache, 760);
!     tdp = afs_FindVCache(&pdir_fid, 0, 1);
!     ReleaseSharedLock(&afs_xvcache);
!     if (!tdp) {
! 	printf("afs_ProcessOpCreate: Couldn't find parent dir's vcache\n");
! 	code = ENOENT;
! 	goto end;
!     }
! 
!     if (tdp->ddirty_flags & VDisconCreate) {
!     	/* If the parent dir has been created locally, defer
! 	 * this vnode for later by moving it to the end.
! 	 */
! 	afs_DDirtyVCList->ddirty_next = avc;
! 	afs_DDirtyVCList = avc;
! 	printf("afs_ProcessOpRemove: deferring this vcache\n");
!     	code = ENOTEMPTY;
! 	goto end;
!     }
! 
!     /* Set status. */
!     InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
!     InStatus.ClientModTime = avc->m.Date;
!     InStatus.Owner = avc->m.Owner;
!     InStatus.Group = (afs_int32) acred->cr_gid;
!     /* Only care about protection bits. */
!     InStatus.UnixModeBits = avc->m.Mode & 0xffff;
! 
!     /* Connect to server. */
!     if (vType(avc) == VREG) {
!         /* Make file on server. */
!         do {
!             tc = afs_Conn(&tdp->fid, areq, SHARED_LOCK);
!             if (tc) {
! 		/* Remember for callback processing. */
!                 hostp = tc->srvr->server;
!                 now = osi_Time();
!                 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
!                 RX_AFS_GUNLOCK();
!                 code = RXAFS_CreateFile(tc->id,
!                                 (struct AFSFid *)&tdp->fid.Fid,
!                                 tname,
!                                 &InStatus,
!                                 (struct AFSFid *) &newFid.Fid,
!                                 &OutFidStatus,
!                                 &OutDirStatus,
!                                 &CallBack,
!                                 &tsync);
!                 RX_AFS_GLOCK();
!                 XSTATS_END_TIME;
!                 CallBack.ExpirationTime += now;
!             } else
!                 code = -1;
!         } while (afs_Analyze(tc,
!                         code,
!                         &tdp->fid,
!                         areq,
!                         AFS_STATS_FS_RPCIDX_CREATEFILE,
!                         SHARED_LOCK,
!                         NULL));
! 
!     } else if (vType(avc) == VDIR) {
!         /* Make dir on server. */
!         do {
!             tc = afs_Conn(&tdp->fid, areq, SHARED_LOCK);
!             if (tc) {
!                 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
!                 now = osi_Time();
!                 RX_AFS_GUNLOCK();
!                 code = RXAFS_MakeDir(tc->id,
!                                 (struct AFSFid *) &tdp->fid.Fid,
!                                 tname,
!                                 &InStatus,
!                                 (struct AFSFid *) &newFid.Fid,
!                                 &OutFidStatus,
!                                 &OutDirStatus,
!                                 &CallBack,
!                                 &tsync);
!                 RX_AFS_GLOCK();
!                 XSTATS_END_TIME;
!                 CallBack.ExpirationTime += now;
!                 /* DON'T forget to set the callback at some point. */
!             } else
!                code = -1;
!          } while (afs_Analyze(tc,
!                         code,
!                         &tdp->fid,
!                         areq,
!                         AFS_STATS_FS_RPCIDX_MAKEDIR,
!                         SHARED_LOCK,
!                         NULL));
!     }					/* Do server changes. */
! 
!     /* TODO: Handle errors. */
!     if (code) {
! 	printf("afs_ProcessOpCreate: error while creating vnode on server, code=%d .\n", code);
! 	code = EIO;
! 	goto end;
!     }
! 
!     /* The rpc doesn't set the cell number. */
!     newFid.Cell = avc->fid.Cell;
! 
!     /*
!      * Change the fid in the dir entry.
!      */
! 
!     /* Seek the dir's dcache. */
!     tdc = afs_FindDCacheByFid(&tdp->fid);
!     if (tdc) {
!     	/* And now change the fid in the parent dir entry. */
!     	afs_dir_ChangeFid(tdc, tname, &avc->fid.Fid.Vnode, &newFid.Fid.Vnode);
!     	afs_PutDCache(tdc);
!     }
! 
!     if (vType(avc) == VDIR) {
! 	/* Change fid in the dir for the "." entry. ".." has alredy been
! 	 * handled by afs_FixChildrenFids when processing the parent dir.
! 	 */
! 	tdc = afs_FindDCacheByFid(&avc->fid);
! 	if (tdc) {
!    	    afs_dir_ChangeFid(tdc, ".", &avc->fid.Fid.Vnode, &newFid.Fid.Vnode);
! 
! 	    if (avc->m.LinkCount >= 2)
! 	        /* For non empty dirs, fix children's parentVnode and parentUnique
! 	    	 * reference.
! 	     	 */
! 	    	afs_FixChildrenFids(&avc->fid, &newFid);
! 
! 	    afs_PutDCache(tdc);
! 	}
!     }
! 
!     /* Recompute hash chain positions for vnode and dcaches.
!      * Then change to the new FID.
!      */
! 
!     /* The vcache goes first. */
!     ObtainWriteLock(&afs_xvcache, 735);
! 
!     /* Old fid hash. */
!     hash = VCHash(&avc->fid);
!     /* New fid hash. */
!     new_hash = VCHash(&newFid);
! 
!     /* Remove hash from old position. */
!     /* XXX: not checking array element contents. It shouldn't be empty.
!      * If it oopses, then something else might be wrong.
!      */
!     if (afs_vhashT[hash] == avc) {
!         /* First in hash chain (might be the only one). */
! 	afs_vhashT[hash] = avc->hnext;
!     } else {
!         /* More elements in hash chain. */
!  	//for (tvc = afs_vhashT[hash]; tdp; tdp = tdp->hnext) {
!  	for (tvc = afs_vhashT[hash]; tvc; tvc = tvc->hnext) {
! 	    if (tvc->hnext == avc) {
! 		tvc->hnext = avc->hnext;
! 		break;
! 	    }
!         }
!     }                           /* if (!afs_vhashT[i]->hnext) */
!     QRemove(&afs_vhashTV[hash]);
! 
!     /* Insert hash in new position. */
!     avc->hnext = afs_vhashT[new_hash];
!     afs_vhashT[new_hash] = avc;
!     QAdd(&afs_vhashTV[new_hash], &avc->vhashq);
! 
!     ReleaseWriteLock(&afs_xvcache);
! 
!     /* Do the same thing for all dcaches. */
!     hash = DVHash(&avc->fid);
!     ObtainWriteLock(&afs_xdcache, 743);
!     for (index = afs_dvhashTbl[hash]; index != NULLIDX; index = hash) {
!         hash = afs_dvnextTbl[index];
!         tdc = afs_GetDSlot(index, NULL);
!         ReleaseReadLock(&tdc->tlock);
! 	if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
!             if (!FidCmp(&tdc->f.fid, &avc->fid)) {
! 
! 		/* Safer but slower. */
!  		afs_HashOutDCache(tdc, 0);
! 
!                 /* Put dcache in new positions in the dchash and dvhash. */
!  		new_hash = DCHash(&newFid, tdc->f.chunk);
!  		afs_dcnextTbl[tdc->index] = afs_dchashTbl[new_hash];
!  		afs_dchashTbl[new_hash] = tdc->index;
! 
!  		new_hash = DVHash(&newFid);
!  		afs_dvnextTbl[tdc->index] = afs_dvhashTbl[new_hash];
!  		afs_dvhashTbl[new_hash] = tdc->index;
! 
!  		afs_indexUnique[tdc->index] = newFid.Fid.Unique;
! 		memcpy(&tdc->f.fid, &newFid, sizeof(struct VenusFid));
!                 //afs_MaybeWakeupTruncateDaemon();
!            }                   /* if fid match */
! 	}                       /* if uniquifier match */
!     	if (tdc)
! 	    afs_PutDCache(tdc);
!     }                           /* for all dcaches in this hash bucket */
!     ReleaseWriteLock(&afs_xdcache);
! 
!     /* Now we can set the new fid. */
!     memcpy(&avc->fid, &newFid, sizeof(struct VenusFid));
! 
!     if (tdp) {
!     	/* Unset parent dir CStat flag, so it will get refreshed on next
! 	 * online stat.
! 	 */
! 	ObtainWriteLock(&tdp->lock, 745);
! 	tdp->states &= ~CStatd;
!     	ReleaseWriteLock(&tdp->lock);
!     }
! end:
!     if (tdp)
!     	afs_PutVCache(tdp);
!     afs_osi_Free(tname, AFSNAMEMAX);
!     return code;
! }
! 
! /*!
!  * Remove a vnode on the server, be it file or directory.
!  * Not much to do here only get the parent dir's fid and call the
!  * removel rpc.
!  *
!  * \param avc The deleted vcache
!  * \param areq
!  *
!  * \note The vcache refcount should be dropped because it points to
!  * a deleted vnode and has served it's purpouse, but we drop refcount
!  * on shadow dir deletio (we still need it for that).
!  *
!  * \note avc must be write locked.
!  */
! int afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
! {
!     char *tname = NULL;
!     struct AFSFetchStatus OutDirStatus;
!     struct VenusFid pdir_fid;
!     struct AFSVolSync tsync;
!     struct conn *tc;
!     struct vcache *tdp = NULL;
!     int code = 0;
!     XSTATS_DECLS;
! 
!     /* Get parent dir's FID. */
!     pdir_fid.Fid.Unique = 0;
!     afs_GetParentDirFid(avc, &pdir_fid);
!     if (!pdir_fid.Fid.Unique) {
! 	printf("afs_ProcessOpRemove: Couldn't find parent dir's FID.\n");
! 	return ENOENT;
!     }
! 
!     tname = afs_osi_Alloc(AFSNAMEMAX);
!     if (!tname) {
! 	printf("afs_ProcessOpRemove: Couldn't find file name\n");
! 	return ENOMEM;
!     }
! 
!     /* Get file name. */
!     code = afs_GetVnodeName(avc, &pdir_fid, tname, 1);
!     if (code) {
! 	printf("afs_ProcessOpRemove: Couldn't find file name\n");
! 	code = ENOENT;
! 	goto end;
!     }
! 
!     if ((vType(avc) == VDIR) && (afs_CheckDeletedChildren(avc))) {
! 	/* Deleted children of this dir remain unsynchronized.
! 	 * Defer this vcache.
! 	 */
! 	afs_DDirtyVCList->ddirty_next = avc;
! 	afs_DDirtyVCList = avc;
!     	code = ENOTEMPTY;
! 	goto end;
!     }
! 
!     if (vType(avc) == VREG) {
!     	/* Remove file on server. */
! 	do {
! 	    tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
! 		RX_AFS_GUNLOCK();
! 		code = RXAFS_RemoveFile(tc->id,
! 				&pdir_fid.Fid,
! 				tname,
! 				&OutDirStatus,
! 				&tsync);
! 
! 		RX_AFS_GLOCK();
! 		XSTATS_END_TIME;
! 	    } else
! 		code = -1;
! 	} while (afs_Analyze(tc,
! 			code,
! 			&pdir_fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_REMOVEFILE,
! 			SHARED_LOCK,
! 			NULL));
! 
!     } else if (vType(avc) == VDIR) {
!     	/* Remove dir on server. */
! 	do {
! 	    tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 		XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
! 		RX_AFS_GUNLOCK();
! 		code = RXAFS_RemoveDir(tc->id,
! 				&pdir_fid.Fid,
! 				tname,
! 				&OutDirStatus,
! 				&tsync);
! 		RX_AFS_GLOCK();
! 		XSTATS_END_TIME;
! 	   } else
! 		code = -1;
! 	} while (afs_Analyze(tc,
! 			code,
! 			&pdir_fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_REMOVEDIR,
! 			SHARED_LOCK,
! 			NULL));
! 
!     }				/* if (vType(avc) == VREG) */
! 
!     if (code)
!     	printf("afs_ProcessOpRemove: server returned code=%u\n", code);
! 
!     /* Remove the statd flag from parent dir's vcache. */
!     ObtainSharedLock(&afs_xvcache, 761);
!     tdp = afs_FindVCache(&pdir_fid, 0, 1);
!     ReleaseSharedLock(&afs_xvcache);
!     if (tdp) {
!     	ObtainWriteLock(&tdp->lock, 746);
! 	tdp->states &= ~CStatd;
! 	ReleaseWriteLock(&tdp->lock);
! 	afs_PutVCache(tdp);
!     }
! end:
!     afs_osi_Free(tname, AFSNAMEMAX);
!     return code;
! }
! 
! /*!
!  * Send disconnected file changes to the server.
!  *
!  * \note Call with vnode locked both locally and on the server.
!  *
!  * \param avc Vnode that gets synchronized to the server.
!  * \param areq Used for obtaining a conn struct.
!  *
!  * \return 0 for success. On failure, other error codes.
!  */
! int afs_SendChanges(struct vcache *avc, struct vrequest *areq)
! {
!     struct conn *tc;
!     struct AFSStoreStatus sstat;
!     struct AFSFetchStatus fstat;
!     struct AFSVolSync tsync;
!     int code = 0;
!     int flags = 0;
!     XSTATS_DECLS;
! 
!     /* Start multiplexing dirty operations from ddirty_flags field: */
!     if (avc->ddirty_flags & VDisconSetAttrMask) {
! 	/* Setattr OPS: */
! 	/* Turn dirty vc data into a new store status... */
! 	if (afs_GenStoreStatus(avc, &sstat) > 0) {
! 	    do {
! 		tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
! 		if (tc) {
! 		    /* ... and send it. */
! 		    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STORESTATUS);
! 		    RX_AFS_GUNLOCK();
! 		    code = RXAFS_StoreStatus(tc->id,
! 				(struct AFSFid *) &avc->fid.Fid,
! 				&sstat,
! 				&fstat,
! 				&tsync);
! 
! 		    RX_AFS_GLOCK();
! 		    XSTATS_END_TIME;
! 		} else
! 		    code = -1;
! 
! 	} while (afs_Analyze(tc,
! 			code,
! 			&avc->fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_STORESTATUS,
! 			SHARED_LOCK,
! 			NULL));
! 
! 	}		/* if (afs_GenStoreStatus() > 0)*/
!     }			/* disconnected SETATTR */
! 
!     if (code)
!     	return code;
! 
!     if (avc->ddirty_flags &
! 	(VDisconTrunc
! 	| VDisconWriteClose
! 	| VDisconWriteFlush
! 	| VDisconWriteOsiFlush)) {
! 
! 	/* Truncate OP: */
! 	do {
! 	    tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 		/* Set storing flags. XXX: A tad inefficient ... */
! 		if (avc->ddirty_flags & VDisconWriteClose)
! 		    flags |= AFS_LASTSTORE;
! 		if (avc->ddirty_flags & VDisconWriteOsiFlush)
! 		    flags |= (AFS_SYNC | AFS_LASTSTORE);
! 		if (avc->ddirty_flags & VDisconWriteFlush)
! 		    flags |= AFS_SYNC;
! 
! 		/* Try to send store to server. */
! 		/* XXX: AFS_LASTSTORE for writes? Or just AFS_SYNC for all? */
! 		code = afs_StoreAllSegments(avc, areq, flags);
! 	    } else
! 		code = -1;
! 
! 	} while (afs_Analyze(tc,
! 			code,
! 			&avc->fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_STOREDATA,
! 			SHARED_LOCK,
! 			NULL));
! 
!     }			/* disconnected TRUNC | WRITE */
! 
!     return code;
! }
! 
! /*!
!  * All files that have been dirty before disconnection are going to
!  * be replayed back to the server.
!  *
!  * \param areq Request from the user.
!  * \param acred User credentials.
!  *
!  * \return If all files synchronized succesfully, return 0, otherwise
!  * return 1.
!  *
!  * \note For now, it's the request from the PDiscon pioctl.
!  *
!  */
! int afs_ResyncDisconFiles(struct vrequest *areq, struct AFS_UCRED *acred)
! {
!     struct conn *tc;
!     struct vcache *tvc, *tmp;
!     struct AFSFetchStatus fstat;
!     struct AFSCallBack callback;
!     struct AFSVolSync tsync;
!     struct vcache *shList, *shListStart;
!     int code;
!     int sync_failed = 0;
!     int ret_code = 0;
!     int defered = 0;
!     afs_int32 start = 0;
!     XSTATS_DECLS;
!     //AFS_STATCNT(afs_ResyncDisconFiles);
! 
!     shList = shListStart = NULL;
! 
!     ObtainReadLock(&afs_DDirtyVCListLock);
! 
!     tvc = afs_DDirtyVCListStart;
!     while (tvc) {
! 
! 	/* Get local write lock. */
! 	ObtainWriteLock(&tvc->lock, 704);
!   	sync_failed = 0;
! 
! 	if ((tvc->ddirty_flags & VDisconRemove) &&
! 	    (tvc->ddirty_flags & VDisconCreate)) {
! 	   /* Data created and deleted locally. The server doesn't
! 	    * need to know about this, so we'll just skip this file
! 	    * from the dirty list.
! 	    */
! 	    goto skip_file;
! 
! 	} else if (tvc->ddirty_flags & VDisconRemove) {
! 	    /* Delete the file on the server and just move on
! 	     * to the next file. After all, it has been deleted
! 	     * we can't replay any other operation it.
! 	     */
! 	    code = afs_ProcessOpRemove(tvc, areq);
! 	    if (code == ENOTEMPTY)
! 	    	defered = 1;
! 	    goto skip_file;
! 
! 	} else if (tvc->ddirty_flags & VDisconCreate) {
! 	    /* For newly created files, we don't need a server lock. */
! 	    code = afs_ProcessOpCreate(tvc, areq, acred);
! 	    if (code == ENOTEMPTY)
! 	    	defered = 1;
! 	    if (code)
! 	    	goto skip_file;
! 	}
! 
!   	/* Get server write lock. */
!   	do {
! 	    tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
!   	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
!   		RX_AFS_GUNLOCK();
!   		code = RXAFS_SetLock(tc->id,
! 					(struct AFSFid *)&tvc->fid.Fid,
! 					LockWrite,
! 					&tsync);
! 		RX_AFS_GLOCK();
! 		XSTATS_END_TIME;
! 	   } else
! 		code = -1;
! 
! 	} while (afs_Analyze(tc,
! 			code,
! 			&tvc->fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_SETLOCK,
! 			SHARED_LOCK,
! 			NULL));
! 
! 	if (code) {
! 	    sync_failed = 1;
! 	    goto skip_file;
! 	}
! 
! 	if ((tvc->ddirty_flags & VDisconRename) &&
! 		!(tvc->ddirty_flags & VDisconCreate)) {
! 	    /* Rename file only if it hasn't been created locally. */
! 	    code = afs_ProcessOpRename(tvc, areq);
! 	    if (code)
! 	    	goto skip_file;
! 	}
! 
! 	/* Issue a FetchStatus to get info about DV and callbacks. */
! 	do {
! 	    tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 	    	tvc->callback = tc->srvr->server;
! 		start = osi_Time();
! 		XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
! 		RX_AFS_GUNLOCK();
! 		code = RXAFS_FetchStatus(tc->id,
! 				(struct AFSFid *)&tvc->fid.Fid,
! 				&fstat,
! 				&callback,
! 				&tsync);
! 		RX_AFS_GLOCK();
! 		XSTATS_END_TIME;
! 	    } else
! 		code = -1;
! 
! 	} while (afs_Analyze(tc,
! 			code,
! 			&tvc->fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_FETCHSTATUS,
! 			SHARED_LOCK,
! 			NULL));
! 
! 	if (code) {
! 	    sync_failed = 1;
! 	    goto unlock_srv_file;
! 	}
! 
! 	if ((dv_match(tvc, fstat) && (tvc->m.Date == fstat.ServerModTime)) ||
! 	    	(afs_ConflictPolicy == CLIENT_WINS) ||
! 		(tvc->ddirty_flags & VDisconCreate)) {
! 	    /*
! 	     * Send changes to the server if there's data version match, or
! 	     * client wins policy has been selected or file has been created
! 	     * but doesn't have it's the contents on to the server yet.
! 	     */
! 	   /*
! 	    * XXX: Checking server attr changes by timestamp might not the
! 	    * most elegant solution, but it's the most viable one that we could find.
! 	    */
! 	    afs_UpdateStatus(tvc, &tvc->fid, areq, &fstat, &callback, start);
! 	    code = afs_SendChanges(tvc, areq);
! 
! 	} else if (afs_ConflictPolicy == SERVER_WINS) {
! 	    /* DV mismatch, apply collision resolution policy. */
! 	    /* Dequeue whatever callback is on top (XXX: propably none). */
!       	    ObtainWriteLock(&afs_xcbhash, 706);
! 	    afs_DequeueCallback(tvc);
! 	    tvc->callback = NULL;
! 	    tvc->states &= ~(CStatd | CDirty | CUnique);
! 	    ReleaseWriteLock(&afs_xcbhash);
! 
! 	    /* Save metadata. File length gets updated as well because we
! 	     * just removed CDirty from the avc.
! 	     */
! 	    //afs_ProcessFS(tvc, &fstat, areq);
! 
! 	    /* Discard this files chunks and remove from current dir. */
! 	    afs_TryToSmush(tvc, acred, 1);
! 	    osi_dnlc_purgedp(tvc);
! 	    if (tvc->linkData && !(tvc->states & CCore)) {
! 		/* Take care of symlinks. */
! 		afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
! 		tvc->linkData = NULL;
! 	    }
! 
! 	    /* Otherwise file content's won't be synchronized. */
! 	    tvc->truncPos = AFS_NOTRUNC;
! 
! 	} else {
! 	    printf("afs_ResyncDisconFiles: no resolution policy selected.\n");
! 	}		/* if DV match or client wins policy */
! 
! 	if (code) {
! 	    sync_failed = 1;
! 	    printf("Sync FAILED.\n");
! 	}
! 
! unlock_srv_file:
! 	/* Release server write lock. */
! 	do {
! 	    tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
! 	    	RX_AFS_GUNLOCK();
! 		code = RXAFS_ReleaseLock(tc->id,
! 				(struct AFSFid *) &tvc->fid.Fid,
! 				&tsync);
! 		RX_AFS_GLOCK();
! 		XSTATS_END_TIME;
! 	    } else
! 		code = -1;
! 	} while (afs_Analyze(tc,
! 			code,
! 			&tvc->fid,
! 			areq,
! 			AFS_STATS_FS_RPCIDX_RELEASELOCK,
! 			SHARED_LOCK,
! 			NULL));
! 
! skip_file:
! 	/* Pop this dirty vc out. */
! 	tmp = tvc;
! 	tvc = tvc->ddirty_next;
! 
! 	if (!defered) {
! 	    /* Vnode not deferred. Clean it up. */
! 	    if (!sync_failed) {
! 	    	if (tmp->ddirty_flags == VDisconShadowed) {
! 		    /* Dirs that have only the shadow flag set might still
! 		     * be used so keep them in a different list, that gets
! 		     * deleted after resync is done.
! 		     */
! 		    if (!shListStart)
! 		    	shListStart = shList = tmp;
! 		    else {
! 		    	shList->ddirty_next = tmp;
! 			shList = tmp;
! 		    }
! 		} else if (tmp->ddirty_flags & VDisconShadowed)
! 	    	    /* We can discard the shadow dir now. */
! 	    	    afs_DeleteShadowDir(tmp);
! 
! 		if (tmp->ddirty_flags & VDisconRemove)
! 		    /* Drop the refcount on the deleted vnodes,
! 		     * because we don't need them anymore.
! 		     */
! 		    afs_PutVCache(tmp);
! 
! 	    	/* Only if sync was successfull,
! 		 * clear flags and dirty references.
! 		 */
! 	    	tmp->ddirty_next = NULL;
! 	    	tmp->ddirty_flags = 0;
! 	    } else
! 	    	ret_code = 1;
! 	} else {
! 	    tmp->ddirty_next = NULL;
! 	    defered = 0;
! 	}			/* if (!defered) */
! 
! 	/* Release local write lock. */
! 	ReleaseWriteLock(&tmp->lock);
!     }			/* while (tvc) */
! 
!     /* Delete the rest of shadow dirs. */
!     tvc = shListStart;
!     while (tvc) {
!     	ObtainWriteLock(&tvc->lock, 764);
! 
! 	afs_DeleteShadowDir(tvc);
! 	tvc->shVnode = 0;
! 	tvc->shUnique = 0;
! 
! 	tmp = tvc;
! 	tvc = tvc->ddirty_next;
! 	tmp->ddirty_next = NULL;
! 
! 	ReleaseWriteLock(&tmp->lock);
!     }				/* while (tvc) */
! 
!     if (ret_code == 0) {
!     	/* NULLIFY dirty list only if resync complete. */
! 	afs_DDirtyVCListStart = NULL;
! 	afs_DDirtyVCList = NULL;
!     }
!     ReleaseReadLock(&afs_DDirtyVCListLock);
! 
!     return ret_code;
! }
! 
! /*!
!  * Print list of disconnected files.
!  *
!  * \note Call with afs_DDirtyVCListLock read locked.
!  */
! void afs_DbgDisconFiles()
! {
!     struct vcache *tvc;
!     int i = 0;
! 
!     tvc = afs_DDirtyVCListStart;
!     printf("List of dirty files: \n");
!     while (tvc) {
! 	printf("Cell=%u Volume=%u VNode=%u Unique=%u\n",
! 		tvc->fid.Cell,
! 		tvc->fid.Fid.Volume,
! 		tvc->fid.Fid.Vnode,
! 		tvc->fid.Fid.Unique);
! 	tvc = tvc->ddirty_next;
! 	i++;
! 	if (i >= 30)
! 	    osi_Panic("afs_DbgDisconFiles: loop in dirty list\n");
!     }
! }
! 
! /*!
!  * Generate a fake fid for a disconnected shadow dir.
!  * Similar to afs_GenFakeFid, only that it uses the dhash
!  * to search for a uniquifier because a shadow dir lives only
!  * in the dcache.
!  *
!  * \param afid
!  *
!  * \note Don't forget to fill in afid with Cell and Volume.
!  */
! void afs_GenShadowFid(struct VenusFid *afid)
! {
!     afs_uint32 i, index, max_unique = 1;
!     struct vcache *tvc = NULL;
! 
!     /* Try generating a fid that isn't used in the vhash. */
!     do {
!     	afid->Fid.Vnode = afs_DisconVnode + 1;
! 
!     	i = DVHash(afid);
!     	ObtainWriteLock(&afs_xdcache, 737);
!     	for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
!             i = afs_dvnextTbl[index];
!             if (afs_indexUnique[index] > max_unique)
! 	    	max_unique = afs_indexUnique[index];
!     	}
! 
! 	ReleaseWriteLock(&afs_xdcache);
! 	afid->Fid.Unique = max_unique + 1;
! 	afs_DisconVnode += 2;
! 	if (!afs_DisconVnode)
!     	    afs_DisconVnode = 2;
! 
! 	/* Is this a used vnode? */
!     	ObtainSharedLock(&afs_xvcache, 762);
!     	tvc = afs_FindVCache(afid, 0, 1);
!     	ReleaseSharedLock(&afs_xvcache);
! 	if (tvc)
! 	    afs_PutVCache(tvc);
!     } while (tvc);
! }
! 
! /*!
!  * Generate a fake fid (vnode and uniquifier) for a vcache
!  * (either dir or normal file). The vnode is generated via
!  * afs_DisconVNode and the uniquifier by getting the highest
!  * uniquifier on a hash chain and incrementing it by one.
!  *
!  * \param avc afid The fid structre that will be filled.
!  * \param avtype Vnode type: VDIR/VREG.
!  *
!  * \note The cell number must be completed somewhere else.
!  */
! void afs_GenFakeFid(struct VenusFid *afid, afs_uint32 avtype)
! {
!     struct vcache *tvc;
!     afs_uint32 max_unique = 1, i;
! 
!     if (avtype == VDIR)
!     	afid->Fid.Vnode = afs_DisconVnode + 1;
!     else if (avtype == VREG)
!     	afid->Fid.Vnode = afs_DisconVnode;
! 
!     ObtainWriteLock(&afs_xvcache, 736);
!     i = VCHash(afid);
!     for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
!         if (tvc->fid.Fid.Unique > max_unique)
! 	    max_unique = tvc->fid.Fid.Unique;
!     }
!     ReleaseWriteLock(&afs_xvcache);
! 
!     afid->Fid.Unique = max_unique + 1;
!     afs_DisconVnode += 2;
!     if (!afs_DisconVnode)
!     	afs_DisconVnode = 2;
! }
! 
! /*!
!  * Fill in stats for a newly created file/directory.
!  *
!  * \param adp The parent dir's vcache.
!  * \param avc The created vnode.
!  * \param afid The new fid.
!  * \param attrs
!  * \param areq
!  * \param file_type Specify if file or directory.
!  *
!  * \note Call with avc write locked.
!  */
! void afs_GenDisconStatus(
!         struct vcache *adp,
!         struct vcache *avc,
! 	struct VenusFid *afid,
!         struct vattr *attrs,
!         struct vrequest *areq,
!         int file_type)
! {
!     memcpy(&avc->fid, afid, sizeof(struct VenusFid));
!     avc->m.Mode = attrs->va_mode;
!     /* Used to do this:
!      * avc->m.Owner = attrs->va_uid;
!      * But now we use the parent dir's ownership,
!      * there's no other way to get a server owner id.
!      * XXX: Does it really matter?
!      */
!     avc->m.Group = adp->m.Group;
!     avc->m.Owner = adp->m.Owner;
!     hset64(avc->m.DataVersion, 0, 0);
!     avc->m.Length = attrs->va_size;
!     avc->m.Date = osi_Time();
!     if (file_type == VREG) {
!         vSetType(avc, VREG);
!         avc->m.Mode |= S_IFREG;
! 	avc->m.LinkCount = 1;
!     } else if (file_type == VDIR) {
!         vSetType(avc, VDIR);
!         avc->m.Mode |= S_IFDIR;
! 	avc->m.LinkCount = 2;
!     }
! 
!     avc->anyAccess = adp->anyAccess;
!     afs_AddAxs(avc->Access, areq->uid, adp->Access->axess);
! 
!     avc->callback = NULL;
!     avc->states |= CStatd;
!     avc->states &= ~CBulkFetching;
! }
  #endif
Index: openafs/src/afs/afs_init.c
diff -c openafs/src/afs/afs_init.c:1.37.4.7 openafs/src/afs/afs_init.c:1.37.4.8
*** openafs/src/afs/afs_init.c:1.37.4.7	Thu Jun 12 13:24:38 2008
--- openafs/src/afs/afs_init.c	Mon Sep 22 15:29:54 2008
***************
*** 17,23 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_init.c,v 1.37.4.7 2008/06/12 17:24:38 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
--- 17,23 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_init.c,v 1.37.4.8 2008/09/22 19:29:54 shadow Exp $");
  
  #include "afs/stds.h"
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
***************
*** 47,52 ****
--- 47,53 ----
  #endif
  #if defined(AFS_DISCON_ENV)
  afs_rwlock_t afs_discon_lock;
+ extern afs_rwlock_t afs_DDirtyVCListLock;
  #endif
  
  /*
***************
*** 115,120 ****
--- 116,122 ----
      RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
  #ifdef AFS_DISCON_ENV
      RWLOCK_INIT(&afs_discon_lock, "afs_discon_lock");
+     RWLOCK_INIT(&afs_DDirtyVCListLock, "afs_DDirtyVCListLock");
  #endif
      osi_dnlc_init();
  
Index: openafs/src/afs/afs_osi.c
diff -c openafs/src/afs/afs_osi.c:1.58.2.6 openafs/src/afs/afs_osi.c:1.58.2.7
*** openafs/src/afs/afs_osi.c:1.58.2.6	Tue Feb  5 20:32:13 2008
--- openafs/src/afs/afs_osi.c	Tue Aug 26 10:01:31 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_osi.c,v 1.58.2.6 2008/02/06 01:32:13 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_osi.c,v 1.58.2.7 2008/08/26 14:01:31 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 91,96 ****
--- 91,101 ----
      usimple_lock_init(&afs_global_lock);
      afs_global_owner = (thread_t) 0;
  #elif defined(AFS_FBSD50_ENV)
+ #if defined(AFS_FBSD80_ENV) && defined(WITNESS)
+     /* "lock_initalized" (sic) can panic, checks a flag bit
+      * is unset _before_ init */
+     memset(&afs_global_mtx, 0, sizeof(struct mtx));
+ #endif
      mtx_init(&afs_global_mtx, "AFS global lock", NULL, MTX_DEF);
  #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
  #if !defined(AFS_DARWIN80_ENV)
Index: openafs/src/afs/afs_osi_alloc.c
diff -c openafs/src/afs/afs_osi_alloc.c:1.11.6.6 openafs/src/afs/afs_osi_alloc.c:1.11.6.7
*** openafs/src/afs/afs_osi_alloc.c:1.11.6.6	Tue May 20 15:50:41 2008
--- openafs/src/afs/afs_osi_alloc.c	Tue Aug 26 10:01:31 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_osi_alloc.c,v 1.11.6.6 2008/05/20 19:50:41 shadow Exp $");
  
  
  
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_osi_alloc.c,v 1.11.6.7 2008/08/26 14:01:31 shadow Exp $");
  
  
  
***************
*** 19,25 ****
  #include "afsincludes.h"	/* Afs-based standard headers */
  #include "afs/afs_stats.h"	/* afs statistics */
  
! #ifndef AFS_FBSD_ENV
  
  #ifdef AFS_AIX41_ENV
  #include "sys/lockl.h"
--- 19,25 ----
  #include "afsincludes.h"	/* Afs-based standard headers */
  #include "afs/afs_stats.h"	/* afs statistics */
  
! 
  
  #ifdef AFS_AIX41_ENV
  #include "sys/lockl.h"
***************
*** 257,260 ****
  		 afs_stats_cmperf.SmallBlocksActive);
      }
  }
! #endif
--- 257,260 ----
  		 afs_stats_cmperf.SmallBlocksActive);
      }
  }
! 
Index: openafs/src/afs/afs_osi_vm.c
diff -c openafs/src/afs/afs_osi_vm.c:1.1.2.2 openafs/src/afs/afs_osi_vm.c:1.1.2.4
*** openafs/src/afs/afs_osi_vm.c:1.1.2.2	Mon Jul 31 17:27:38 2006
--- openafs/src/afs/afs_osi_vm.c	Mon Sep 22 15:35:26 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_osi_vm.c,v 1.1.2.2 2006/07/31 21:27:38 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_osi_vm.c,v 1.1.2.4 2008/09/22 19:35:26 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 49,55 ****
--- 49,66 ----
  void
  osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
  {
+     int vfslocked;
      afs_hyper_t origDV;
+ #if defined(AFS_CACHE_BYPASS)
+     /* The optimization to check DV under read lock below is identical a 
+      * change in CITI cache bypass work.  The problem CITI found in 1999 
+      * was that this code and background daemon doing prefetching competed 
+      * for the vcache entry shared lock.  It's not clear to me from the 
+      * tech report, but it looks like CITI fixed the general prefetch code
+      * path as a bonus when experimenting on prefetch for cache bypass, see
+      * citi-tr-01-3.
+      */
+ #endif        
      ObtainReadLock(&avc->lock);
      /* If we've already purged this version, or if we're the ones
       * writing this version, don't flush it (could lose the
***************
*** 79,87 ****
--- 90,108 ----
  	       ICL_TYPE_INT32, origDV.low, ICL_TYPE_INT32, avc->m.Length);
  
      ReleaseWriteLock(&avc->lock);
+ #ifdef AFS_FBSD70_ENV
+     vfslocked = VFS_LOCK_GIANT(AFSTOV(avc)->v_mount);
+ #endif
+ #ifndef AFS_FBSD70_ENV
      AFS_GUNLOCK();
+ #endif
      osi_VM_FlushPages(avc, credp);
+ #ifndef AFS_FBSD70_ENV
      AFS_GLOCK();
+ #endif
+ #ifdef AFS_FBSD70_ENV
+     VFS_UNLOCK_GIANT(vfslocked);
+ #endif
      ObtainWriteLock(&avc->lock, 88);
  
      /* do this last, and to original version, since stores may occur
Index: openafs/src/afs/afs_osidnlc.c
diff -c openafs/src/afs/afs_osidnlc.c:1.13.2.1 openafs/src/afs/afs_osidnlc.c:1.13.2.2
*** openafs/src/afs/afs_osidnlc.c:1.13.2.1	Fri Oct 19 16:39:07 2007
--- openafs/src/afs/afs_osidnlc.c	Tue Aug 26 10:01:31 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_osidnlc.c,v 1.13.2.1 2007/10/19 20:39:07 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_osidnlc.c,v 1.13.2.2 2008/08/26 14:01:31 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 63,68 ****
--- 63,76 ----
  
  #define dnlcHash(ts, hval) for (hval=0; *ts; ts++) { hval *= 173;  hval  += *ts;   }
  
+ #if defined(AFS_FBSD80_ENV) && !defined(UKERNEL)
+ #define ma_critical_enter critical_enter
+ #define ma_critical_exit critical_exit
+ #else
+ #define ma_critical_enter() {}
+ #define ma_critical_exit() {}
+ #endif
+ 
  static struct nc *
  GetMeAnEntry(void)
  {
***************
*** 201,212 ****
      vnode_t tvp;
  #endif
  
!     if (!afs_usednlc)
! 	return 0;
  
      dnlcHash(ts, key);		/* leaves ts pointing at the NULL */
      if (ts - aname >= AFSNCNAMESIZE) {
! 	return 0;
      }
      skey = key & (NHSIZE - 1);
  
--- 209,225 ----
      vnode_t tvp;
  #endif
  
!     ma_critical_enter();
! 
!     if (!afs_usednlc) {
!       ma_critical_exit();
!       return 0;
!     }
  
      dnlcHash(ts, key);		/* leaves ts pointing at the NULL */
      if (ts - aname >= AFSNCNAMESIZE) {
!       ma_critical_exit();
!       return 0;
      }
      skey = key & (NHSIZE - 1);
  
***************
*** 231,236 ****
--- 244,250 ----
  	    ReleaseReadLock(&afs_xdnlc);
  	    ReleaseReadLock(&afs_xvcache);
  	    osi_dnlc_purge();
+ 	    ma_critical_exit();
  	    return (0);
  	}
      }
***************
*** 251,256 ****
--- 265,271 ----
  	    ReleaseReadLock(&afs_xvcache);
  	    dnlcstats.misses++;
  	    osi_dnlc_remove(adp, aname, tvc);
+ 	    ma_critical_exit();
  	    return 0;
  	}
  #ifdef	AFS_OSF_ENV
***************
*** 262,267 ****
--- 277,283 ----
  	    ReleaseReadLock(&afs_xvcache);
  	    dnlcstats.misses++;
  	    osi_dnlc_remove(adp, aname, tvc);
+ 	    ma_critical_exit();
  	    return 0;
  	}
  	if (vnode_ref(tvp)) {
***************
*** 271,280 ****
--- 287,304 ----
  	    AFS_GLOCK();
  	    dnlcstats.misses++;
  	    osi_dnlc_remove(adp, aname, tvc);
+ 	    ma_critical_exit();
  	    return 0;
  	}
  #else
+ #ifdef AFS_FBSD50_ENV
+ 	/* can't sleep in a critical section */
+ 	ma_critical_exit();
+ 	osi_vnhold(tvc, 0);
+ 	ma_critical_enter();
+ #else
  	osi_vnhold(tvc, 0);
+ #endif /* AFS_FBSD80_ENV */
  #endif
  #endif
  	ReleaseReadLock(&afs_xvcache);
***************
*** 313,318 ****
--- 337,343 ----
  #endif
      }
  
+     ma_critical_exit();
      return tvc;
  }
  
Index: openafs/src/afs/afs_pioctl.c
diff -c openafs/src/afs/afs_pioctl.c:1.110.2.18 openafs/src/afs/afs_pioctl.c:1.110.2.20
*** openafs/src/afs/afs_pioctl.c:1.110.2.18	Fri May 23 10:25:15 2008
--- openafs/src/afs/afs_pioctl.c	Mon Sep 22 15:35:26 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_pioctl.c,v 1.110.2.18 2008/05/23 14:25:15 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #ifdef AFS_OBSD_ENV
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_pioctl.c,v 1.110.2.20 2008/09/22 19:35:26 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #ifdef AFS_OBSD_ENV
***************
*** 23,28 ****
--- 23,29 ----
  #include "afsincludes.h"	/* Afs-based standard headers */
  #include "afs/afs_stats.h"	/* afs statistics */
  #include "afs/vice.h"
+ #include "afs/afs_bypasscache.h"
  #include "rx/rx_globals.h"
  
  struct VenusFid afs_rootFid;
***************
*** 33,38 ****
--- 34,44 ----
  #ifdef AFS_DISCON_ENV
  afs_int32 afs_is_disconnected;
  afs_int32 afs_is_logging;
+ afs_int32 afs_is_discon_rw;
+ /* On reconnection, turn this knob on until it finishes,
+  * then turn it off.
+  */
+ afs_int32 afs_in_sync = 0;
  #endif
  
  #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
***************
*** 99,104 ****
--- 105,114 ----
  DECL_PIOCTL(PNFSNukeCreds);
  DECL_PIOCTL(PNewUuid);
  DECL_PIOCTL(PPrecache); 
+ #if defined(AFS_CACHE_BYPASS)
+ DECL_PIOCTL(PSetCachingThreshold);
+ DECL_PIOCTL(PSetCachingBlkSize);
+ #endif
  
  /*
   * A macro that says whether we're going to need HandleClientContext().
***************
*** 214,220 ****
  
  static int (*(OpioctlSw[])) () = {
      PBogus,			/* 0 */
! 	PNFSNukeCreds,		/* 1 -- nuke all creds for NFS client */
  };
  
  #define PSetClientContext 99	/*  Special pioctl to setup caller's creds  */
--- 224,235 ----
  
  static int (*(OpioctlSw[])) () = {
      PBogus,			/* 0 */
!     PNFSNukeCreds,		/* 1 -- nuke all creds for NFS client */
! #if defined(AFS_CACHE_BYPASS)
!     PSetCachingThreshold        /* 2 -- get/set cache-bypass size threshold */
! #else
!     PNoop                       /* 2 -- get/set cache-bypass size threshold */
! #endif
  };
  
  #define PSetClientContext 99	/*  Special pioctl to setup caller's creds  */
***************
*** 3875,3880 ****
--- 3890,3940 ----
      return 0;
  }
  
+ #if defined(AFS_CACHE_BYPASS)
+ 
+ DECL_PIOCTL(PSetCachingThreshold)
+ {
+     afs_int32 getting;
+     afs_int32 setting;
+ 
+     setting = getting = 1;
+ 
+     if (ain == NULL || ainSize < sizeof(afs_int32))
+ 	setting = 0;
+ 
+     if (aout == NULL)
+ 	getting = 0;
+ 
+     if (setting == 0 && getting == 0)
+ 	return EINVAL;
+ 	
+     /* 
+      * If setting, set first, and return the value now in effect
+      */
+     if (setting) {
+ 	afs_int32 threshold;
+ 
+ 	if (!afs_osi_suser(*acred))
+ 	    return EPERM;
+ 	memcpy((char *)&threshold, ain, sizeof(afs_int32));
+ 	cache_bypass_threshold = threshold;
+         afs_warn("Cache Bypass Threshold set to: %d\n", threshold);		
+ 	/* TODO:  move to separate pioctl, or enhance pioctl */
+ 	cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
+     }
+ 	
+     if (getting) {
+ 	/* Return the current size threshold */
+ 	afs_int32 oldThreshold = cache_bypass_threshold;
+ 	memcpy(aout, (char *)&oldThreshold, sizeof(afs_int32));
+ 	*aoutSize = sizeof(afs_int32);
+     }
+ 
+     return(0);
+ }
+ 
+ #endif /* defined(AFS_CACHE_BYPASS) */
+ 
  DECL_PIOCTL(PCallBackAddr)
  {
  #ifndef UKERNEL
***************
*** 3976,4007 ****
  DECL_PIOCTL(PDiscon)
  {
  #ifdef AFS_DISCON_ENV
!     static afs_int32 mode = 4; /* Start up in 'full' */
  
!     if (ainSize == sizeof(afs_int32)) {
  
  	if (!afs_osi_suser(*acred))
  	    return EPERM;
  
! 	memcpy(&mode, ain, sizeof(afs_int32));
  
  	/*
  	 * All of these numbers are hard coded in fs.c. If they
  	 * change here, they should change there and vice versa
  	 */
  	switch (mode) {
! 	case 0: /* Disconnect, breaking all callbacks */
  	    if (!AFS_IS_DISCONNECTED) {
  		ObtainWriteLock(&afs_discon_lock, 999);
  		afs_DisconGiveUpCallbacks();
  		afs_RemoveAllConns();
  		afs_is_disconnected = 1;
  		ReleaseWriteLock(&afs_discon_lock);
  	    }
  	    break;
! 	case 4: /* Fully connected */
  	    ObtainWriteLock(&afs_discon_lock, 998);
! 	    afs_is_disconnected = 0;
  	    ReleaseWriteLock(&afs_discon_lock);
  	    break;
  	default:
--- 4036,4088 ----
  DECL_PIOCTL(PDiscon)
  {
  #ifdef AFS_DISCON_ENV
!     static afs_int32 mode = 1; /* Start up in 'off' */
!     afs_int32 force = 0;
!     int code = 0;
  
!     if (ainSize) {
  
  	if (!afs_osi_suser(*acred))
  	    return EPERM;
  
! 	if (ain[0])
! 	    mode = ain[0] - 1;
! 	if (ain[1])
! 	    afs_ConflictPolicy = ain[1] - 1;
! 	if (ain[2])
! 	    force = 1;
  
  	/*
  	 * All of these numbers are hard coded in fs.c. If they
  	 * change here, they should change there and vice versa
  	 */
  	switch (mode) {
! 	case 0: /* Disconnect ("offline" mode), breaking all callbacks */
  	    if (!AFS_IS_DISCONNECTED) {
  		ObtainWriteLock(&afs_discon_lock, 999);
  		afs_DisconGiveUpCallbacks();
  		afs_RemoveAllConns();
  		afs_is_disconnected = 1;
+ 		afs_is_discon_rw = 1;
  		ReleaseWriteLock(&afs_discon_lock);
  	    }
  	    break;
! 	case 1: /* Fully connected, ("online" mode). */
  	    ObtainWriteLock(&afs_discon_lock, 998);
! 
! 	    afs_in_sync = 1;
! 	    code = afs_ResyncDisconFiles(areq, *acred);
! 	    afs_in_sync = 0;
! 
! 	    if (code && !force) {
! 	    	printf("Files not synchronized properly, still in discon state. \
! 						Please retry or use \"force\".\n");
! 	    } else {
! 		afs_is_disconnected = 0;
! 		afs_is_discon_rw = 0;
! 		printf("\nSync succeeded. You are back online.\n");
! 	    }
! 
  	    ReleaseWriteLock(&afs_discon_lock);
  	    break;
  	default:
Index: openafs/src/afs/afs_prototypes.h
diff -c openafs/src/afs/afs_prototypes.h:1.74.2.17 openafs/src/afs/afs_prototypes.h:1.74.2.18
*** openafs/src/afs/afs_prototypes.h:1.74.2.17	Fri Jul 18 10:54:34 2008
--- openafs/src/afs/afs_prototypes.h	Mon Sep 22 15:29:54 2008
***************
*** 255,261 ****
  extern void afs_CacheTruncateDaemon(void);
  extern void afs_AdjustSize(register struct dcache *adc,
  			   register afs_int32 newSize);
! extern int afs_HashOutDCache(struct dcache *adc);
  extern int afs_MaybeFreeDiscardedDCache(void);
  extern int afs_RefDCache(struct dcache *adc);
  extern void afs_TryToSmush(register struct vcache *avc,
--- 255,261 ----
  extern void afs_CacheTruncateDaemon(void);
  extern void afs_AdjustSize(register struct dcache *adc,
  			   register afs_int32 newSize);
! extern int afs_HashOutDCache(struct dcache *adc, int zap);
  extern int afs_MaybeFreeDiscardedDCache(void);
  extern int afs_RefDCache(struct dcache *adc);
  extern void afs_TryToSmush(register struct vcache *avc,
Index: openafs/src/afs/afs_segments.c
diff -c openafs/src/afs/afs_segments.c:1.22.8.2 openafs/src/afs/afs_segments.c:1.22.8.3
*** openafs/src/afs/afs_segments.c:1.22.8.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/afs_segments.c	Mon Sep 22 15:29:54 2008
***************
*** 14,20 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_segments.c,v 1.22.8.2 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
--- 14,20 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_segments.c,v 1.22.8.3 2008/09/22 19:29:54 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 215,221 ****
  #endif
  	    osi_VM_StoreAllSegments(avc);
      }
!     if (AFS_IS_DISCONNECTED) {
          if (!AFS_IS_LOGGING) {
              /* This will probably make someone sad ... */
  	    /*printf("Net down in afs_StoreSegments\n");*/
--- 215,221 ----
  #endif
  	    osi_VM_StoreAllSegments(avc);
      }
!     if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
          if (!AFS_IS_LOGGING) {
              /* This will probably make someone sad ... */
  	    /*printf("Net down in afs_StoreSegments\n");*/
Index: openafs/src/afs/afs_stats.h
diff -c openafs/src/afs/afs_stats.h:1.14.6.1 openafs/src/afs/afs_stats.h:1.14.6.2
*** openafs/src/afs/afs_stats.h:1.14.6.1	Mon Mar 17 14:03:37 2008
--- openafs/src/afs/afs_stats.h	Mon Sep 22 15:35:26 2008
***************
*** 640,645 ****
--- 640,649 ----
      afs_int32 C_SRXAFSCB_GetCacheConfig;	/* afs_callback.c */
      afs_int32 C_SRXAFSCB_GetCE64;	/* afs_callback.c */
      afs_int32 C_SRXAFSCB_GetCellByNum;	/* afs_callback.c */
+ #if defined(AFS_CACHE_BYPASS)
+     afs_int32 C_BPrefetchNoCache;	/* afs_daemons.c */
+ 	afs_int32 C_afs_ReadNoCache;	/* osi_vnodeops.c */
+ #endif	
  };
  
  struct afs_CMMeanStats {
Index: openafs/src/afs/afs_vcache.c
diff -c openafs/src/afs/afs_vcache.c:1.114.2.9 openafs/src/afs/afs_vcache.c:1.114.2.12
*** openafs/src/afs/afs_vcache.c:1.114.2.9	Fri May 23 10:25:16 2008
--- openafs/src/afs/afs_vcache.c	Mon Sep 22 15:35:26 2008
***************
*** 19,24 ****
--- 19,25 ----
   * afs_FlushActiveVcaches
   * afs_VerifyVCache2
   * afs_WriteVCache
+  * afs_WriteVCacheDiscon
   * afs_SimpleVStat
   * afs_ProcessFS
   * TellALittleWhiteLie
***************
*** 26,31 ****
--- 27,33 ----
   * afs_GetVCache
   * afs_LookupVCache
   * afs_GetRootVCache
+  * afs_UpdateStatus
   * afs_FetchStatus
   * afs_StuffVcache
   * afs_PutVCache
***************
*** 39,45 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.114.2.9 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
--- 41,47 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.114.2.12 2008/09/22 19:35:26 shadow Exp $");
  
  #include "afs/sysincludes.h"	/*Standard vendor system headers */
  #include "afsincludes.h"	/*AFS-based standard headers */
***************
*** 942,947 ****
--- 944,953 ----
      tvc->Access = NULL;
      tvc->callback = serverp;    /* to minimize chance that clear
  				 * request is lost */
+ #if defined(AFS_DISCON_ENV)
+     tvc->ddirty_next = NULL;
+     tvc->ddirty_flags = 0;
+ #endif
  
      i = VCHash(afid);
      j = VCHashV(afid);
***************
*** 1033,1038 ****
--- 1039,1050 ----
      tvc->vmh = tvc->segid = NULL;
      tvc->credp = NULL;
  #endif
+ 
+ #if defined(AFS_CACHE_BYPASS)
+     tvc->cachingStates = 0;
+     tvc->cachingTransitions = 0;
+ #endif
+ 
  #ifdef AFS_BOZONLOCK_ENV
  #if	defined(AFS_SUN5_ENV)
      rw_init(&tvc->rwlock, "vcache rwlock", RW_DEFAULT, NULL);
***************
*** 1122,1127 ****
--- 1134,1144 ----
      insmntque(tvc, afs_globalVFS);
  #endif /* AFS_OSF_ENV */
  #endif /* AFS_DUX40_ENV */
+ #ifdef AFS_FBSD70_ENV
+ #ifndef AFS_FBSD80_ENV /* yup.  they put it back. */
+     insmntque(AFSTOV(tvc), afs_globalVFS);
+ #endif
+ #endif
  #if defined(AFS_SGI_ENV)
      VN_SET_DPAGES(&(tvc->v), (struct pfdat *)NULL);
      osi_Assert((tvc->v.v_flag & VINACT) == 0);
***************
*** 1502,1508 ****
      AFS_STATCNT(afs_WriteVCache);
      afs_Trace2(afs_iclSetp, CM_TRACE_WVCACHE, ICL_TYPE_POINTER, avc,
  	       ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
- 
      do {
  	tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
  	if (tc) {
--- 1519,1524 ----
***************
*** 1542,1547 ****
--- 1558,1655 ----
      return code;
  
  }				/*afs_WriteVCache */
+ #if defined(AFS_DISCON_ENV)
+ 
+ /*!
+  * Store status info only locally, set the proper disconnection flags
+  * and add to dirty list.
+  *
+  * \param avc The vcache to be written locally.
+  * \param astatus Get attr fields from local store.
+  * \param attrs This one is only of the vs_size.
+  *
+  * \note Must be called with a shared lock on the vnode
+  */
+ int afs_WriteVCacheDiscon(register struct vcache *avc,
+ 				register struct AFSStoreStatus *astatus,
+ 				struct vattr *attrs)
+ {
+     afs_int32 code = 0;
+     afs_int32 flags = 0;
+ 
+     UpgradeSToWLock(&avc->lock, 700);
+ 
+     if (!astatus->Mask) {
+ 
+ 	return code;
+ 
+     } else {
+ 
+     	/* Set attributes. */
+     	if (astatus->Mask & AFS_SETMODTIME) {
+ 		avc->m.Date = astatus->ClientModTime;
+ 		flags |= VDisconSetTime;
+ 	}
+ 
+ 	if (astatus->Mask & AFS_SETOWNER) {
+ 		printf("Not allowed yet. \n");
+ 		//avc->m.Owner = astatus->Owner;
+ 	}
+ 
+ 	if (astatus->Mask & AFS_SETGROUP) {
+ 		printf("Not allowed yet. \n");
+ 		//avc->m.Group =  astatus->Group;
+ 	}
+ 
+ 	if (astatus->Mask & AFS_SETMODE) {
+ 		avc->m.Mode = astatus->UnixModeBits;
+ 
+ #if 0 	/* XXX: Leaving this out, so it doesn't mess up the file type flag.*/
+ 
+ 		if (vType(avc) == VREG) {
+ 			avc->m.Mode |= S_IFREG;
+ 		} else if (vType(avc) == VDIR) {
+ 			avc->m.Mode |= S_IFDIR;
+ 		} else if (vType(avc) == VLNK) {
+ 			avc->m.Mode |= S_IFLNK;
+ 			if ((avc->m.Mode & 0111) == 0)
+ 				avc->mvstat = 1;
+ 		}
+ #endif
+ 		flags |= VDisconSetMode;
+ 	 } 		/* if(astatus.Mask & AFS_SETMODE) */
+ 
+      } 			/* if (!astatus->Mask) */
+ 
+      if (attrs->va_size > 0) {
+      	/* XXX: Do I need more checks? */
+      	/* Truncation operation. */
+      	flags |= VDisconTrunc;
+      }
+ 
+     ObtainWriteLock(&afs_DDirtyVCListLock, 701);
+ 
+     if (flags) {
+     	/* Add to disconnected dirty list and set dirty flag.*/
+ 	if (!avc->ddirty_flags ||
+ 		(avc->ddirty_flags == VDisconShadowed)) {
+ 		/* Not in dirty list. */
+ 		AFS_DISCON_ADD_DIRTY(avc);
+ 	}
+ 
+ 	avc->ddirty_flags |= flags;
+     }
+ 
+     ReleaseWriteLock(&afs_DDirtyVCListLock);
+ 
+     /* XXX: How about the rest of the fields? */
+ 
+     ConvertWToSLock(&avc->lock);
+ 
+     return code;
+ }
+ 
+ #endif
  
  /*
   * afs_ProcessFS
***************
*** 1822,1827 ****
--- 1930,1949 ----
  	  ObtainWriteLock(&tvc->lock, 954);
  	if (!iheldthelock)
  	    VOP_UNLOCK(vp, LK_EXCLUSIVE, current_proc());
+ #elif defined(AFS_FBSD80_ENV)
+ 	iheldthelock = VOP_ISLOCKED(vp);
+ 	if (!iheldthelock) {
+ 	    /* nosleep/sleep lock order reversal */
+ 	    int glocked = ISAFS_GLOCK();
+ 	    if (glocked)
+ 		AFS_GUNLOCK();
+ 	    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ 	    if (glocked)
+ 		AFS_GLOCK();
+ 	}
+ 	vinvalbuf(vp, V_SAVE, curthread, PINOD, 0);
+ 	if (!iheldthelock)
+ 	    VOP_UNLOCK(vp, 0);
  #elif defined(AFS_FBSD60_ENV)
  	iheldthelock = VOP_ISLOCKED(vp, curthread);
  	if (!iheldthelock)
***************
*** 1899,1910 ****
  	    tvc->parentUnique = OutStatus.ParentUnique;
  	    code = 0;
  	} else {
! 	    /* If we've got here and we're disconnected, then we can go
! 	     * no further
! 	     */
  	    if (AFS_IS_DISCONNECTED) {
! 		code = ENETDOWN;
! 		/*printf("Network is down in afs_GetCache");*/
  	    } else
  	        code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
  
--- 2021,2043 ----
  	    tvc->parentUnique = OutStatus.ParentUnique;
  	    code = 0;
  	} else {
! 
  	    if (AFS_IS_DISCONNECTED) {
! 		if (AFS_IS_DISCON_RW) {
! 		    /* Seek the vnode manually. */
! 		    ObtainSharedLock(&afs_xvcache, 738);
! 		    avc = afs_FindVCache(afid, NULL, 1);
! 		    ReleaseSharedLock(&afs_xvcache);
! 
! 		    if (vType(avc) == VDIR)
! 		    	OutStatus.FileType = Directory;
! 
! 		    code = tvc?0:ENOENT;
! 		} else {
! 		    /* Nothing to do otherwise...*/
! 		    code = ENETDOWN;
! 		    printf("Network is down in afs_GetCache");
! 		}
  	    } else
  	        code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
  
***************
*** 1996,2002 ****
      origCBs = afs_allCBs;	/* if anything changes, we don't have a cb */
      
      if (AFS_IS_DISCONNECTED) {
! 	/*printf("Network is down in afs_LookupVcache\n");*/
          code = ENETDOWN;
      } else 
          code =
--- 2129,2135 ----
      origCBs = afs_allCBs;	/* if anything changes, we don't have a cb */
      
      if (AFS_IS_DISCONNECTED) {
! 	printf("Network is down in afs_LookupVcache\n");
          code = ENETDOWN;
      } else 
          code =
***************
*** 2357,2362 ****
--- 2490,2556 ----
  }
  
  
+ /*!
+  * Update callback status and (sometimes) attributes of a vnode.
+  * Called after doing a fetch status RPC. Whilst disconnected, attributes
+  * shouldn't be written to the vcache here.
+  *
+  * \param avc
+  * \param afid
+  * \param areq
+  * \param Outsp Server status after rpc call.
+  * \param acb Callback for this vnode.
+  *
+  * \note The vcache must be write locked.
+  */
+ void
+ afs_UpdateStatus(struct vcache *avc,
+ 			struct VenusFid *afid,
+ 			struct vrequest *areq,
+ 			struct AFSFetchStatus *Outsp,
+ 			struct AFSCallBack *acb,
+ 			afs_uint32 start)
+ {
+     struct volume *volp;
+ 
+     if (!AFS_IN_SYNC)
+ 	/* Dont write status in vcache if resyncing after a disconnection. */
+ 	afs_ProcessFS(avc, Outsp, areq);
+ 
+     volp = afs_GetVolume(afid, areq, READ_LOCK);
+     ObtainWriteLock(&afs_xcbhash, 469);
+     avc->states |= CTruth;
+     if (avc->callback /* check for race */ ) {
+ 	if (acb->ExpirationTime != 0) {
+ 	    avc->cbExpires = acb->ExpirationTime + start;
+ 	    avc->states |= CStatd;
+ 	    avc->states &= ~CBulkFetching;
+ 	    afs_QueueCallback(avc, CBHash(acb->ExpirationTime), volp);
+     	} else if (avc->states & CRO) {
+ 	    /* ordinary callback on a read-only volume -- AFS 3.2 style */
+ 	    avc->cbExpires = 3600 + start;
+ 	    avc->states |= CStatd;
+ 	    avc->states &= ~CBulkFetching;
+ 	    afs_QueueCallback(avc, CBHash(3600), volp);
+     	} else {
+ 	    afs_DequeueCallback(avc);
+ 	    avc->callback = NULL;
+ 	    avc->states &= ~(CStatd | CUnique);
+ 	    if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
+ 	    	osi_dnlc_purgedp(avc);	/* if it (could be) a directory */
+     	}
+     } else {
+     	afs_DequeueCallback(avc);
+     	avc->callback = NULL;
+     	avc->states &= ~(CStatd | CUnique);
+     	if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
+ 	    osi_dnlc_purgedp(avc);	/* if it (could be) a directory */
+     }
+     ReleaseWriteLock(&afs_xcbhash);
+     if (volp)
+     	afs_PutVolume(volp, READ_LOCK);
+ 
+ }
  
  /*
   * must be called with avc write-locked
***************
*** 2372,2378 ****
      register struct conn *tc;
      struct AFSCallBack CallBack;
      struct AFSVolSync tsync;
-     struct volume *volp;
      XSTATS_DECLS;
      do {
  	tc = afs_Conn(afid, areq, SHARED_LOCK);
--- 2566,2571 ----
***************
*** 2396,2433 ****
  	      SHARED_LOCK, NULL));
  
      if (!code) {
! 	afs_ProcessFS(avc, Outsp, areq);
! 	volp = afs_GetVolume(afid, areq, READ_LOCK);
! 	ObtainWriteLock(&afs_xcbhash, 469);
! 	avc->states |= CTruth;
! 	if (avc->callback /* check for race */ ) {
! 	    if (CallBack.ExpirationTime != 0) {
! 		avc->cbExpires = CallBack.ExpirationTime + start;
! 		avc->states |= CStatd;
! 		avc->states &= ~CBulkFetching;
! 		afs_QueueCallback(avc, CBHash(CallBack.ExpirationTime), volp);
! 	    } else if (avc->states & CRO) {	/* ordinary callback on a read-only volume -- AFS 3.2 style */
! 		avc->cbExpires = 3600 + start;
! 		avc->states |= CStatd;
! 		avc->states &= ~CBulkFetching;
! 		afs_QueueCallback(avc, CBHash(3600), volp);
! 	    } else {
! 		afs_DequeueCallback(avc);
! 		avc->callback = NULL;
! 		avc->states &= ~(CStatd | CUnique);
! 		if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
! 		    osi_dnlc_purgedp(avc);	/* if it (could be) a directory */
! 	    }
! 	} else {
! 	    afs_DequeueCallback(avc);
! 	    avc->callback = NULL;
! 	    avc->states &= ~(CStatd | CUnique);
! 	    if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
! 		osi_dnlc_purgedp(avc);	/* if it (could be) a directory */
! 	}
! 	ReleaseWriteLock(&afs_xcbhash);
! 	if (volp)
! 	    afs_PutVolume(volp, READ_LOCK);
      } else {
  	/* used to undo the local callback, but that's too extreme.
  	 * There are plenty of good reasons that fetchstatus might return
--- 2589,2595 ----
  	      SHARED_LOCK, NULL));
  
      if (!code) {
! 	afs_UpdateStatus(avc, afid, areq, Outsp, &CallBack, start);
      } else {
  	/* used to undo the local callback, but that's too extreme.
  	 * There are plenty of good reasons that fetchstatus might return
Index: openafs/src/afs/discon.h
diff -c openafs/src/afs/discon.h:1.2.2.2 openafs/src/afs/discon.h:1.2.2.3
*** openafs/src/afs/discon.h:1.2.2.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/discon.h	Mon Sep 22 15:29:54 2008
***************
*** 4,22 ****
--- 4,80 ----
  #ifndef AFS_DISCON_ENV
  #define AFS_IS_DISCONNECTED 0
  #define AFS_IS_LOGGING 0
+ #define AFS_IS_DISCON_RW 0
+ #define AFS_IN_SYNC 0
  #define AFS_DISCON_LOCK()
  #define AFS_DISCON_UNLOCK()
  
+ #define AFS_DISCON_ADD_DIRTY(avc)
+ 
  #else
  
  extern afs_int32    afs_is_disconnected;
  extern afs_int32    afs_is_logging;
+ extern afs_int32    afs_is_discon_rw;
+ extern afs_int32    afs_in_sync;
  extern afs_rwlock_t afs_discon_lock;
  
+ extern struct vcache *afs_DDirtyVCList;
+ extern struct vcache *afs_DDirtyVCListStart;
+ extern struct vcache *afs_DDirtyVCListPrev;
+ extern afs_rwlock_t afs_DDirtyVCListLock;
+ extern afs_int32 afs_ConflictPolicy;
+ 
+ extern void afs_RemoveAllConns();
+ extern afs_uint32 afs_DisconVnode; /* XXX: not protected. */
+ 
+ /* For afs_GenFakeFid. */
+ extern struct vcache *afs_FindVCache(struct VenusFid *afid,
+ 					afs_int32 *retry,
+ 					afs_int32 flag);
+ 
+ extern int afs_WriteVCacheDiscon(register struct vcache *avc,
+ 					register struct AFSStoreStatus *astatus,
+ 					struct vattr *attrs);
+ extern int afs_ResyncDisconFiles(struct vrequest *areq,
+ 					struct AFS_UCRED *acred);
+ extern void afs_RemoveAllConns();
+ extern void afs_GenFakeFid(struct VenusFid *afid, afs_uint32 avtype);
+ extern void afs_GenShadowFid(struct VenusFid *afid);
+ extern void afs_GenDisconStatus(struct vcache *adp,
+ 					struct vcache *avc,
+ 					struct VenusFid *afid,
+ 					struct vattr *attrs,
+ 					struct vrequest *areq,
+ 					int file_type);
+ extern int afs_HashOutDCache(struct dcache *adc, int zap);
+ extern int afs_MakeShadowDir(struct vcache *avc);
+ extern void afs_DeleteShadowDir(struct vcache *avc);
+ extern struct dcache *afs_FindDCacheByFid(register struct VenusFid *afid);
+ extern void afs_UpdateStatus(struct vcache *avc,
+ 					struct VenusFid *afid,
+ 					struct vrequest *areq,
+ 					struct AFSFetchStatus *Outsp,
+ 					struct AFSCallBack *acb,
+ 					afs_uint32 start);
+ extern void afs_RemoveAllConns();
+ 
  #define AFS_IS_DISCONNECTED (afs_is_disconnected)
  #define AFS_IS_LOGGING (afs_is_logging)
+ #define AFS_IS_DISCON_RW (afs_is_discon_rw)
+ #define AFS_IN_SYNC (afs_in_sync)
  #define AFS_DISCON_LOCK() ObtainReadLock(&afs_discon_lock)
  #define AFS_DISCON_UNLOCK() ReleaseReadLock(&afs_discon_lock)
  
+ #define AFS_DISCON_ADD_DIRTY(avc)				\
+ do {								\
+     if (!afs_DDirtyVCListStart) {				\
+     	afs_DDirtyVCListStart = afs_DDirtyVCList = avc;		\
+     } else {							\
+     	afs_DDirtyVCList->ddirty_next = avc;			\
+ 	afs_DDirtyVCList = avc;					\
+     }								\
+ } while(0);
+ 
  #endif /* AFS_DISCON_ENV */
  #endif /* _DISCON_H */
Index: openafs/src/afs/lock.h
diff -c openafs/src/afs/lock.h:1.17.4.6 openafs/src/afs/lock.h:1.17.4.7
*** openafs/src/afs/lock.h:1.17.4.6	Fri Nov  9 14:20:29 2007
--- openafs/src/afs/lock.h	Mon Sep 22 15:29:54 2008
***************
*** 31,37 ****
  /* This is the max lock number in use. Please update it if you add any new
   * lock numbers.
   */
! #define MAX_LOCK_NUMBER 700
  #endif
  
  struct afs_bozoLock {
--- 31,37 ----
  /* This is the max lock number in use. Please update it if you add any new
   * lock numbers.
   */
! #define MAX_LOCK_NUMBER 760
  #endif
  
  struct afs_bozoLock {
Index: openafs/src/afs/DARWIN/osi_vfsops.c
diff -c openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.1 openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.2
*** openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.1	Thu Jan  4 17:17:57 2007
--- openafs/src/afs/DARWIN/osi_vfsops.c	Fri Aug 22 15:26:48 2008
***************
*** 5,11 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v 1.17.4.1 2007/01/04 22:17:57 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.17.4.2 2008/08/22 19:26:48 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 383,389 ****
      abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
  	abp->f_ffree = 
  #ifdef AFS_DARWIN80_ENV
! 	2147483648
  #else
  	2000000
  #endif
--- 383,389 ----
      abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
  	abp->f_ffree = 
  #ifdef AFS_DARWIN80_ENV
!         0xffffffffffffffff
  #else
  	2000000
  #endif
Index: openafs/src/afs/FBSD/osi_file.c
diff -c openafs/src/afs/FBSD/osi_file.c:1.13.14.2 openafs/src/afs/FBSD/osi_file.c:1.13.14.3
*** openafs/src/afs/FBSD/osi_file.c:1.13.14.2	Thu Dec 13 14:18:32 2007
--- openafs/src/afs/FBSD/osi_file.c	Tue Aug 26 10:01:33 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_file.c,v 1.13.14.2 2007/12/13 19:18:32 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/FBSD/osi_file.c,v 1.13.14.3 2008/08/26 14:01:33 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 50,56 ****
  	osi_FreeSmallSpace(afile);
  	osi_Panic("UFSOpen: igetinode failed");
      }
! #if defined(AFS_FBSD50_ENV)
      VOP_UNLOCK(vp, 0, curthread);
  #else
      VOP_UNLOCK(vp, 0, curproc);
--- 50,58 ----
  	osi_FreeSmallSpace(afile);
  	osi_Panic("UFSOpen: igetinode failed");
      }
! #if defined(AFS_FBSD80_ENV)
!     VOP_UNLOCK(vp, 0);
! #elif defined(AFS_FBSD50_ENV)
      VOP_UNLOCK(vp, 0, curthread);
  #else
      VOP_UNLOCK(vp, 0, curproc);
***************
*** 71,77 ****
      AFS_STATCNT(osi_Stat);
      MObtainWriteLock(&afs_xosi, 320);
      AFS_GUNLOCK();
! #if defined(AFS_FBSD50_ENV)
      vn_lock(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
      code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
      VOP_UNLOCK(afile->vnode, LK_EXCLUSIVE, curthread);
--- 73,83 ----
      AFS_STATCNT(osi_Stat);
      MObtainWriteLock(&afs_xosi, 320);
      AFS_GUNLOCK();
! #if defined(AFS_FBSD80_ENV)
!     vn_lock(afile->vnode, LK_EXCLUSIVE | LK_RETRY);
!     code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
!     VOP_UNLOCK(afile->vnode, 0);
! #elif defined(AFS_FBSD50_ENV)
      vn_lock(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
      code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
      VOP_UNLOCK(afile->vnode, LK_EXCLUSIVE, curthread);
***************
*** 105,111 ****
  {
      struct vattr tvattr;
      struct vnode *vp;
!     register afs_int32 code;
      AFS_STATCNT(osi_Truncate);
  
      MObtainWriteLock(&afs_xosi, 321);
--- 111,117 ----
  {
      struct vattr tvattr;
      struct vnode *vp;
!     register afs_int32 code, glocked;
      AFS_STATCNT(osi_Truncate);
  
      MObtainWriteLock(&afs_xosi, 321);
***************
*** 115,122 ****
       * have very slow truncates, even when the file is already
       * small enough.  Check now and save some time.
       */
!     AFS_GUNLOCK();
! #if defined(AFS_FBSD50_ENV)
      vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
      code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
  #else
--- 121,133 ----
       * have very slow truncates, even when the file is already
       * small enough.  Check now and save some time.
       */
!     glocked = ISAFS_GLOCK();
!     if (glocked)
!       AFS_GUNLOCK();
! #if defined(AFS_FBSD80_ENV)
!     vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
!     code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
! #elif defined(AFS_FBSD50_ENV)
      vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
      code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
  #else
***************
*** 135,146 ****
  #endif
  
  out:
! #if defined(AFS_FBSD50_ENV)
      VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
  #else
      VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
  #endif
!     AFS_GLOCK();
      MReleaseWriteLock(&afs_xosi);
      return code;
  }
--- 146,160 ----
  #endif
  
  out:
! #if defined(AFS_FBSD80_ENV)
!     VOP_UNLOCK(vp, 0);
! #elif defined(AFS_FBSD50_ENV)
      VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
  #else
      VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
  #endif
!     if (glocked)
!       AFS_GLOCK();
      MReleaseWriteLock(&afs_xosi);
      return code;
  }
Index: openafs/src/afs/FBSD/osi_machdep.h
diff -c openafs/src/afs/FBSD/osi_machdep.h:1.13.4.2 openafs/src/afs/FBSD/osi_machdep.h:1.13.4.3
*** openafs/src/afs/FBSD/osi_machdep.h:1.13.4.2	Thu Nov  9 19:11:06 2006
--- openafs/src/afs/FBSD/osi_machdep.h	Tue Aug 26 10:01:33 2008
***************
*** 59,65 ****
  #undef afs_osi_Alloc_NoSleep
  #define afs_osi_Alloc_NoSleep(size) osi_fbsd_alloc((size), 0)
  
! #define VN_RELE(vp)		vrele(vp)
  #define VN_HOLD(vp)		VREF(vp)
  
  #ifdef AFS_FBSD60_ENV
--- 59,72 ----
  #undef afs_osi_Alloc_NoSleep
  #define afs_osi_Alloc_NoSleep(size) osi_fbsd_alloc((size), 0)
  
! #ifdef AFS_FBSD80_ENV
! #define VN_RELE(vp)				\
!   do {						\
!     vrele(vp);					\
!   } while(0);
! #else
! #define VN_RELE(vp)             vrele(vp)
! #endif
  #define VN_HOLD(vp)		VREF(vp)
  
  #ifdef AFS_FBSD60_ENV
***************
*** 84,93 ****
  #define AFS_GLOCK() mtx_lock(&afs_global_mtx)
  #define AFS_GUNLOCK() mtx_unlock(&afs_global_mtx)
  #define ISAFS_GLOCK() (mtx_owned(&afs_global_mtx))
- 
  #else /* FBSD50 */
  extern struct lock afs_global_lock;
- 
  #define osi_curcred()	(curproc->p_cred->pc_ucred)
  #define afs_suser(x)	(!suser(curproc))
  #define osi_getpid()	(curproc->p_pid)
--- 91,98 ----
Index: openafs/src/afs/FBSD/osi_misc.c
diff -c openafs/src/afs/FBSD/osi_misc.c:1.10 openafs/src/afs/FBSD/osi_misc.c:1.10.6.1
*** openafs/src/afs/FBSD/osi_misc.c:1.10	Tue Mar  8 16:57:53 2005
--- openafs/src/afs/FBSD/osi_misc.c	Tue Aug 26 10:01:33 2008
***************
*** 18,24 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_misc.c,v 1.10 2005/03/08 21:57:53 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/FBSD/osi_misc.c,v 1.10.6.1 2008/08/26 14:01:33 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 35,46 ****
  	       struct vnode **vpp)
  {
      struct nameidata n;
!     int flags, error, wasowned;
  
  #ifdef AFS_FBSD50_ENV
!     wasowned = mtx_owned(&afs_global_mtx);
!     if (wasowned)
! 	mtx_unlock(&afs_global_mtx);
  #endif
  
      flags = 0;
--- 35,46 ----
  	       struct vnode **vpp)
  {
      struct nameidata n;
!     int flags, error, glocked;
  
  #ifdef AFS_FBSD50_ENV
!     glocked = ISAFS_GLOCK();
!     if (glocked)
! 	AFS_GUNLOCK();
  #endif
  
      flags = 0;
***************
*** 49,69 ****
  	flags |= FOLLOW;
      else
  	flags |= NOFOLLOW;
      NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
      if ((error = namei(&n)) != 0) {
  #ifdef AFS_FBSD50_ENV
! 	if (wasowned)
! 	    mtx_lock(&afs_global_mtx);
  #endif
  	return error;
      }
      *vpp = n.ni_vp;
!     /* should we do this? */
      VOP_UNLOCK(n.ni_vp, 0, curproc);
      NDFREE(&n, NDF_ONLY_PNBUF);
  #ifdef AFS_FBSD50_ENV
!     if (wasowned)
! 	mtx_lock(&afs_global_mtx);
  #endif
      return 0;
  }
--- 49,78 ----
  	flags |= FOLLOW;
      else
  	flags |= NOFOLLOW;
+ #ifdef AFS_FBSD80_ENV
+     flags |= MPSAFE; /* namei must take GIANT if needed */
+ #endif
      NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
      if ((error = namei(&n)) != 0) {
  #ifdef AFS_FBSD50_ENV
! 	if (glocked)
! 	    AFS_GLOCK();
  #endif
  	return error;
      }
      *vpp = n.ni_vp;
!     /* XXX should we do this?  Usually NOT (matt) */
! #if defined(AFS_FBSD80_ENV)
!     /*VOP_UNLOCK(n.ni_vp, 0);*/
! #elif defined(AFS_FBSD50_ENV)
!     VOP_UNLOCK(n.ni_vp, 0, curthread);
! #else
      VOP_UNLOCK(n.ni_vp, 0, curproc);
+ #endif
      NDFREE(&n, NDF_ONLY_PNBUF);
  #ifdef AFS_FBSD50_ENV
!     if (glocked)
! 	AFS_GLOCK();
  #endif
      return 0;
  }
***************
*** 105,122 ****
  {
  	void *rv;
  #ifdef AFS_FBSD50_ENV
! 	int wasowned;
  
  	if (dropglobal) {
! 		wasowned = mtx_owned(&afs_global_mtx);
! 		if (wasowned)
! 			mtx_unlock(&afs_global_mtx);
! 		rv = malloc(size, M_AFS, M_WAITOK);
! 		if (wasowned)
! 			mtx_lock(&afs_global_mtx);
  	} else
  #endif
! 		rv = malloc(size, M_AFS, M_NOWAIT);
  
  	return (rv);
  }
--- 114,131 ----
  {
  	void *rv;
  #ifdef AFS_FBSD50_ENV
! 	int glocked;
  
  	if (dropglobal) {
! 	    glocked = ISAFS_GLOCK();
! 	    if (glocked)
! 		AFS_GUNLOCK();
! 	    rv = malloc(size, M_AFS, M_WAITOK);
! 	    if (glocked)
! 		AFS_GLOCK();
  	} else
  #endif
! 	    rv = malloc(size, M_AFS, M_NOWAIT);
  
  	return (rv);
  }
***************
*** 124,169 ****
  void
  osi_fbsd_free(void *p)
  {
! 
! 	free(p, M_AFS);
! }
! 
! void
! osi_AllocMoreSSpace(afs_int32 preallocs)
! {
! 	;
! }
! 
! void
! osi_FreeLargeSpace(void *p)
! {
! 	osi_fbsd_free(p);
! }
! 
! void
! osi_FreeSmallSpace(void *p)
! {
! 	osi_fbsd_free(p);
! }
! 
! void *
! osi_AllocLargeSpace(size_t size)
! {
! 	AFS_ASSERT_GLOCK();
! 	AFS_STATCNT(osi_AllocLargeSpace);
! 	return (osi_fbsd_alloc(size, 1));
! }
! 
! void *
! osi_AllocSmallSpace(size_t size)
! {
! 	AFS_ASSERT_GLOCK();
! 	AFS_STATCNT(osi_AllocSmallSpace);
! 	return (osi_fbsd_alloc(size, 1));
! }
! 
! void
! shutdown_osinet(void)
! {
! 	;
  }
--- 133,137 ----
  void
  osi_fbsd_free(void *p)
  {
!        free(p, M_AFS);
  }
Index: openafs/src/afs/FBSD/osi_vfsops.c
diff -c openafs/src/afs/FBSD/osi_vfsops.c:1.21 openafs/src/afs/FBSD/osi_vfsops.c:1.21.4.1
*** openafs/src/afs/FBSD/osi_vfsops.c:1.21	Fri Jul  8 12:53:43 2005
--- openafs/src/afs/FBSD/osi_vfsops.c	Tue Aug 26 10:01:33 2008
***************
*** 2,8 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vfsops.c,v 1.21 2005/07/08 16:53:43 rees Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
--- 2,8 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vfsops.c,v 1.21.4.1 2008/08/26 14:01:33 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 98,103 ****
--- 98,108 ----
      afs_globalVFS = mp;
      mp->vfs_bsize = 8192;
      vfs_getnewfsid(mp);
+ #ifdef AFS_FBSD70_ENV /* XXX 70? */
+     MNT_ILOCK(mp);
+     mp->mnt_flag &= ~MNT_LOCAL;
+     mp->mnt_kern_flag |= MNTK_MPSAFE; /* solid steel */
+ #endif
      mp->mnt_stat.f_iosize = 8192;
  
      if (path != NULL)
***************
*** 109,116 ****
--- 114,125 ----
      strcpy(mp->mnt_stat.f_mntfromname, "AFS");
      /* null terminated string "AFS" will fit, just leave it be. */
      strcpy(mp->mnt_stat.f_fstypename, "afs");
+ #ifdef AFS_FBSD70_ENV
+     MNT_IUNLOCK(mp);
+ #endif
      AFS_GUNLOCK();
      afs_statfs(mp, &mp->mnt_stat, p);
+ 
      return 0;
  }
  
***************
*** 140,146 ****
       * the root vnode (this is just a guess right now).
       * This has to be done outside the global lock.
       */
! #ifdef AFS_FBSD53_ENV
      vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0, p);
  #else
      vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
--- 149,157 ----
       * the root vnode (this is just a guess right now).
       * This has to be done outside the global lock.
       */
! #if defined(AFS_FBSD80_ENV)
!   /* do nothing */
! #elif defined(AFS_FBSD53_ENV)
      vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0, p);
  #else
      vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
***************
*** 184,195 ****
  	error = 0;
      } else {
  tryagain:
  	if (afs_globalVp) {
  	    afs_PutVCache(afs_globalVp);
  	    /* vrele() needed here or not? */
  	    afs_globalVp = NULL;
  	}
! 
  	if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
  	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
  	    /* we really want this to stay around */
--- 195,207 ----
  	error = 0;
      } else {
  tryagain:
+ #ifndef AFS_FBSD80_ENV
  	if (afs_globalVp) {
  	    afs_PutVCache(afs_globalVp);
  	    /* vrele() needed here or not? */
  	    afs_globalVp = NULL;
  	}
! #endif
  	if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
  	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
  	    /* we really want this to stay around */
Index: openafs/src/afs/FBSD/osi_vm.c
diff -c openafs/src/afs/FBSD/osi_vm.c:1.15 openafs/src/afs/FBSD/osi_vm.c:1.15.4.1
*** openafs/src/afs/FBSD/osi_vm.c:1.15	Mon May 23 17:04:08 2005
--- openafs/src/afs/FBSD/osi_vm.c	Tue Aug 26 10:01:33 2008
***************
*** 20,28 ****
  
  #include <afsconfig.h>
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vm.c,v 1.15 2005/05/23 21:04:08 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 20,34 ----
  
  #include <afsconfig.h>
  #include "afs/param.h"
+ #ifdef AFS_FBSD70_ENV
+ #include <sys/param.h>
+ #include <sys/vnode.h>
+      void
+      vgonel(struct vnode *vp, struct thread *td);
+ #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vm.c,v 1.15.4.1 2008/08/26 14:01:33 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 52,58 ****
  #define VOP_GETVOBJECT(vp, objp) (*(objp) = (vp)->v_object)
  #endif
  
! #ifdef AFS_FBSD50_ENV
  #define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curthread)
  #define unlock_vnode(v)	VOP_UNLOCK((v), 0, curthread)
  #else
--- 58,67 ----
  #define VOP_GETVOBJECT(vp, objp) (*(objp) = (vp)->v_object)
  #endif
  
! #if defined(AFS_FBSD80_ENV)
! #define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY)
! #define unlock_vnode(v)	VOP_UNLOCK((v), 0)
! #elif defined(AFS_FBSD50_ENV)
  #define	lock_vnode(v)	vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curthread)
  #define unlock_vnode(v)	VOP_UNLOCK((v), 0, curthread)
  #else
***************
*** 96,118 ****
      if (CheckLock(&avc->lock))
  	return EBUSY;
  
      AFS_GUNLOCK();
      vp = AFSTOV(avc);
      lock_vnode(vp);
      if (VOP_GETVOBJECT(vp, &obj) == 0) {
  	VM_OBJECT_LOCK(obj);
  	vm_object_page_remove(obj, 0, 0, FALSE);
! #if 0
  	if (obj->ref_count == 0) {
- 	    vgonel(vp, curproc);
  	    simple_lock(&vp->v_interlock);
  	    vp->v_tag = VT_AFS;
  	    SetAfsVnode(vp);
  	}
  #endif
  	VM_OBJECT_UNLOCK(obj);
      }
      unlock_vnode(vp);
      AFS_GLOCK();
  
      return 0;
--- 105,133 ----
      if (CheckLock(&avc->lock))
  	return EBUSY;
  
+     return(0);
+ 
      AFS_GUNLOCK();
      vp = AFSTOV(avc);
+ #ifndef AFS_FBSD70_ENV
      lock_vnode(vp);
+ #endif
      if (VOP_GETVOBJECT(vp, &obj) == 0) {
  	VM_OBJECT_LOCK(obj);
  	vm_object_page_remove(obj, 0, 0, FALSE);
! #if 1
  	if (obj->ref_count == 0) {
  	    simple_lock(&vp->v_interlock);
+ 	    vgonel(vp, curthread);
  	    vp->v_tag = VT_AFS;
  	    SetAfsVnode(vp);
  	}
  #endif
  	VM_OBJECT_UNLOCK(obj);
      }
+ #ifndef AFS_FBSD70_ENV
      unlock_vnode(vp);
+ #endif
      AFS_GLOCK();
  
      return 0;
***************
*** 146,170 ****
       */
      do {
  	anyio = 0;
  	lock_vnode(vp);
  	if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
! 	    /* XXX - obj locking? */
  	    unlock_vnode(vp);
  #ifdef AFS_FBSD50_ENV
  	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
  #else
! 	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
  #endif
! 		if (VOP_GETVOBJECT(vp, &obj) == 0) {
! 		    VM_OBJECT_LOCK(obj);
! 		    vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
! 		    VM_OBJECT_UNLOCK(obj);
! 		    anyio = 1;
  		}
- 		vput(vp);
  	    }
! 	} else
! 	    unlock_vnode(vp);
      } while (anyio && (--tries > 0));
      AFS_GLOCK();
      ObtainWriteLock(&avc->lock, 94);
--- 161,191 ----
       */
      do {
  	anyio = 0;
+ #ifdef AFS_FBSD80_ENV
  	lock_vnode(vp);
+ #endif
  	if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
! #ifdef AFS_FBSD80_ENV
  	    unlock_vnode(vp);
+ #endif
  #ifdef AFS_FBSD50_ENV
  	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
  #else
! 		if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
  #endif
! 		    if (VOP_GETVOBJECT(vp, &obj) == 0) {
! 			VM_OBJECT_LOCK(obj);
! 			vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
! 			VM_OBJECT_UNLOCK(obj);
! 			anyio = 1;
! 		    }
! 		    vput(vp);
  		}
  	    }
! #ifdef AFS_FBSD80_ENV
! 	    else
! 		unlock_vnode(vp);
! #endif
      } while (anyio && (--tries > 0));
      AFS_GLOCK();
      ObtainWriteLock(&avc->lock, 94);
***************
*** 184,235 ****
  {
      struct vnode *vp;
      struct vm_object *obj;
!     int anyio, tries;
  
-     ReleaseWriteLock(&avc->lock);
-     AFS_GUNLOCK();
-     tries = 5;
      vp = AFSTOV(avc);
!     do {
! 	anyio = 0;
! 	lock_vnode(vp);
! 	/* See the comments above. */
! 	if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
! 	    /* XXX - obj locking */
! 	    unlock_vnode(vp);
! #ifdef AFS_FBSD50_ENV
! 	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
! #else
! 	    if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
! #endif
! 		if (VOP_GETVOBJECT(vp, &obj) == 0) {
! 		    VM_OBJECT_LOCK(obj);
! 		    /*
! 		     * Do we really want OBJPC_SYNC?  OBJPC_INVAL would be
! 		     * faster, if invalidation is really what we are being
! 		     * asked to do.  (It would make more sense, too, since
! 		     * otherwise this function is practically identical to
! 		     * osi_VM_StoreAllSegments().)  -GAW
! 		     */
! 		    vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
! 		    VM_OBJECT_UNLOCK(obj);
! 		    anyio = 1;
! 		}
! 		vput(vp);
! 	    }
! 	} else
! 	    unlock_vnode(vp);
!     } while (anyio && (--tries > 0));
!     lock_vnode(vp);
!     if (VOP_GETVOBJECT(vp, &obj) == 0) {
! 	VM_OBJECT_LOCK(obj);
! 	vm_object_page_remove(obj, 0, 0, FALSE);
! 	VM_OBJECT_UNLOCK(obj);
      }
!     unlock_vnode(vp);
!     /*vinvalbuf(AFSTOV(avc),0, NOCRED, curproc, 0,0); */
!     AFS_GLOCK();
!     ObtainWriteLock(&avc->lock, 59);
  }
  
  /* Purge VM for a file when its callback is revoked.
--- 205,248 ----
  {
      struct vnode *vp;
      struct vm_object *obj;
!     int anyio, tries, code;
! 
!     SPLVAR;
  
      vp = AFSTOV(avc);
! 
!     if (vp->v_iflag & VI_DOOMED) {
!       USERPRI;
!       return 0;
      }
! 
!     if (vp->v_bufobj.bo_object != NULL) {
!       VM_OBJECT_LOCK(vp->v_bufobj.bo_object);
!       /*
!        * Do we really want OBJPC_SYNC?  OBJPC_INVAL would be
!        * faster, if invalidation is really what we are being
!        * asked to do.  (It would make more sense, too, since
!        * otherwise this function is practically identical to
!        * osi_VM_StoreAllSegments().)  -GAW
!        */
! 
!       /*
!        * Dunno.  We no longer resemble osi_VM_StoreAllSegments,
!        * though maybe that's wrong, now.  And OBJPC_SYNC is the
!        * common thing in 70 file systems, it seems.  Matt.
!        */
! 
!       vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
!       VM_OBJECT_UNLOCK(vp->v_bufobj.bo_object);
!     }
! 
!     tries = 5;
!     code = vinvalbuf(vp, V_SAVE, curthread, PCATCH, 0);
!     while (code && (tries > 0)) {
!       code = vinvalbuf(vp, V_SAVE, curthread, PCATCH, 0);
!       --tries;
!     }
!     USERPRI;
  }
  
  /* Purge VM for a file when its callback is revoked.
Index: openafs/src/afs/FBSD/osi_vnodeops.c
diff -c openafs/src/afs/FBSD/osi_vnodeops.c:1.22.6.1 openafs/src/afs/FBSD/osi_vnodeops.c:1.22.6.2
*** openafs/src/afs/FBSD/osi_vnodeops.c:1.22.6.1	Tue Jan 15 01:09:11 2008
--- openafs/src/afs/FBSD/osi_vnodeops.c	Tue Aug 26 10:01:33 2008
***************
*** 48,54 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vnodeops.c,v 1.22.6.1 2008/01/15 06:09:11 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
--- 48,54 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/FBSD/osi_vnodeops.c,v 1.22.6.2 2008/08/26 14:01:33 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 95,100 ****
--- 95,105 ----
  static vop_strategy_t	afs_vop_strategy;
  static vop_symlink_t	afs_vop_symlink;
  static vop_write_t	afs_vop_write;
+ #if defined(AFS_FBSD70_ENV) && !defined(AFS_FBSD90_ENV)
+ static vop_lock1_t      afs_vop_lock;
+ static vop_unlock_t     afs_vop_unlock;
+ static vop_islocked_t   afs_vop_islocked;
+ #endif
  
  struct vop_vector afs_vnodeops = {
  	.vop_default =		&default_vnodeops,
***************
*** 128,133 ****
--- 133,143 ----
  	.vop_strategy =		afs_vop_strategy,
  	.vop_symlink =		afs_vop_symlink,
  	.vop_write =		afs_vop_write,
+ #if defined(AFS_FBSD70_ENV) && !defined(AFS_FBSD90_ENV)
+ 	.vop_lock1 =            afs_vop_lock,
+ 	.vop_unlock =           afs_vop_unlock,
+ 	.vop_islocked =         afs_vop_islocked,
+ #endif
  };
  
  #else /* AFS_FBSD60_ENV */
***************
*** 213,218 ****
--- 223,233 ----
      {&vop_write_desc, (vop_t *) afs_vop_write},	/* write */
      {&vop_ioctl_desc, (vop_t *) afs_vop_ioctl},	/* XXX ioctl */
      /*{ &vop_seek_desc, afs_vop_seek }, *//* seek */
+ #if defined(AFS_FBSD70_ENV) && !defined(AFS_FBSD90_ENV)
+     {&vop_lock1_desc, (vop_t *) afs_vop_lock}, /* lock */
+     {&vop_unlock_desc, (vop_t *) afs_vop_unlock}, /* unlock */
+     {&vop_islocked_desc, (vop_t *) afs_vop_islocked}, /* islocked */
+ #endif
      {NULL, NULL}
  };
  struct vnodeopv_desc afs_vnodeop_opv_desc =
***************
*** 233,238 ****
--- 248,370 ----
  #define a_p a_td
  #endif
  
+ #if defined(AFS_FBSD80_ENV)
+ #define ma_vn_lock(vp, flags, p) (vn_lock(vp, flags))
+ #define MA_VOP_LOCK(vp, flags, p) (VOP_LOCK(vp, flags))
+ #define MA_VOP_UNLOCK(vp, flags, p) (VOP_UNLOCK(vp, flags))
+ #else
+ #define ma_vn_lock(vp, flags, p) (vn_lock(vp, flags, p))
+ #define MA_VOP_LOCK(vp, flags, p) (VOP_LOCK(vp, flags, p))
+ #define MA_VOP_UNLOCK(vp, flags, p) (VOP_UNLOCK(vp, flags, p))
+ #endif
+ 
+ #ifdef AFS_FBSD70_ENV
+ #ifndef AFS_FBSD80_ENV
+ /* From kern_lock.c */
+ #define	COUNT(td, x)	if ((td)) (td)->td_locks += (x)
+ #define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \
+ 	LK_SHARE_NONZERO | LK_WAIT_NONZERO)
+ 
+ static __inline void
+ sharelock(struct thread *td, struct lock *lkp, int incr) {
+ 	lkp->lk_flags |= LK_SHARE_NONZERO;
+ 	lkp->lk_sharecount += incr;
+ 	COUNT(td, incr);
+ }
+ #endif
+ 
+ /*
+  * Standard lock, unlock and islocked functions.
+  */
+ int
+ afs_vop_lock(ap)
+     struct vop_lock1_args /* {
+ 			     struct vnode *a_vp;
+ 			     int a_flags;
+ 			     struct thread *a_td;
+ 			     char *file;
+ 			     int line;
+ 			     } */ *ap;
+ {
+     struct vnode *vp = ap->a_vp;
+     struct lock *lkp = vp->v_vnlock;
+ 
+ #if 0 && defined(AFS_FBSD80_ENV) && !defined(UKERNEL)
+     afs_warn("afs_vop_lock: tid %d pid %d \"%s\"\n", curthread->td_tid,
+ 	     curthread->td_proc->p_pid, curthread->td_name);
+     kdb_backtrace();
+ #endif
+ 
+ #ifdef AFS_FBSD80_ENV
+     return (_lockmgr_args(lkp, ap->a_flags, VI_MTX(vp),
+ 			  LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT,
+ 			  ap->a_file, ap->a_line));
+ #else
+     return (_lockmgr(lkp, ap->a_flags, VI_MTX(vp), ap->a_td, ap->a_file, ap->a_line));
+ #endif
+ }
+ 
+ /* See above. */
+ int
+ afs_vop_unlock(ap)
+     struct vop_unlock_args /* {
+ 			      struct vnode *a_vp;
+ 			      int a_flags;
+ 			      struct thread *a_td;
+ 			      } */ *ap;
+ {
+     struct vnode *vp = ap->a_vp;
+     struct lock *lkp = vp->v_vnlock;
+ 
+ #ifdef AFS_FBSD80_ENV
+     int code;
+     u_int op;
+     op = ((ap->a_flags) | LK_RELEASE) & LK_TYPE_MASK;
+     int glocked = ISAFS_GLOCK();
+     if (glocked)
+ 	AFS_GUNLOCK();
+     if ((op & (op - 1)) != 0) {
+       afs_warn("afs_vop_unlock: Shit.\n");
+       goto done;
+     }
+     code = lockmgr(lkp, ap->a_flags | LK_RELEASE, VI_MTX(vp));
+  done:
+     if (glocked)
+ 	AFS_GLOCK();
+     return(code);
+ #else
+     /* possibly in current code path where this
+      * forces trace, we should have had a (shared? not
+      * necessarily, see _lockmgr in kern_lock.c) lock
+      * and that's the real bug.  but. 
+      */
+     critical_enter();
+     if ((lkp->lk_exclusivecount == 0) &&
+ 	(!(lkp->lk_flags & LK_SHARE_NONZERO))) {
+ 	sharelock(ap->a_td, lkp, 1);
+     }
+     critical_exit();
+     return (lockmgr(lkp, ap->a_flags | LK_RELEASE, VI_MTX(vp),
+ 		    ap->a_td));
+ #endif
+ }
+ 
+ /* See above. */
+ int
+ afs_vop_islocked(ap)
+     struct vop_islocked_args /* {
+ 				struct vnode *a_vp;
+ 				struct thread *a_td; (not in 80)
+ 				} */ *ap;
+ {
+ #ifdef AFS_FBSD80_ENV
+     return (lockstatus(ap->a_vp->v_vnlock));
+ #else
+     return (lockstatus(ap->a_vp->v_vnlock, ap->a_td));
+ #endif
+ }
+ #endif /* 70 */
+ 
  /*
   * Mosty copied from sys/ufs/ufs/ufs_vnops.c:ufs_pathconf().
   * We should know the correct answers to these questions with
***************
*** 346,370 ****
  #else
      struct proc *p = ap->a_cnp->cn_proc;
  #endif
      GETNAME();
  
      lockparent = flags & LOCKPARENT;
      wantparent = flags & (LOCKPARENT | WANTPARENT);
  
!     if (ap->a_dvp->v_type != VDIR) {
! 	*ap->a_vpp = 0;
! 	DROPNAME();
! 	return ENOTDIR;
!     }
!     dvp = ap->a_dvp;
      if (flags & ISDOTDOT)
  	VOP_UNLOCK(dvp, 0, p);
      AFS_GLOCK();
      error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
      AFS_GUNLOCK();
      if (error) {
  	if (flags & ISDOTDOT)
! 	    VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
  	if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
  	    && (flags & ISLASTCN) && error == ENOENT)
  	    error = EJUSTRETURN;
--- 478,516 ----
  #else
      struct proc *p = ap->a_cnp->cn_proc;
  #endif
+ 
+     dvp = ap->a_dvp;
+     if (dvp->v_type != VDIR) {
+ #ifndef AFS_FBSD70_ENV
+ 	*ap->a_vpp = 0;
+ #endif
+ 	return ENOTDIR;
+     }
+ 
+     if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT))
+ 	return EIO;
+ 
      GETNAME();
  
      lockparent = flags & LOCKPARENT;
      wantparent = flags & (LOCKPARENT | WANTPARENT);
  
! #ifdef AFS_FBSD80_ENV
!     cnp->cn_flags |= MPSAFE; /* steel */
! #endif
! 
! #ifndef AFS_FBSD70_ENV
      if (flags & ISDOTDOT)
  	VOP_UNLOCK(dvp, 0, p);
+ #endif
+ 
      AFS_GLOCK();
      error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
      AFS_GUNLOCK();
+ 
      if (error) {
  	if (flags & ISDOTDOT)
! 	    MA_VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
  	if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
  	    && (flags & ISLASTCN) && error == ENOENT)
  	    error = EJUSTRETURN;
***************
*** 381,390 ****
       * we also always return the vnode locked. */
  
      if (flags & ISDOTDOT) {
! 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  	/* always return the child locked */
  	if (lockparent && (flags & ISLASTCN)
! 	    && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
  	    vput(vp);
  	    DROPNAME();
  	    return (error);
--- 527,536 ----
       * we also always return the vnode locked. */
  
      if (flags & ISDOTDOT) {
! 	ma_vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  	/* always return the child locked */
  	if (lockparent && (flags & ISLASTCN)
! 	    && (error = ma_vn_lock(dvp, LK_EXCLUSIVE, p))) {
  	    vput(vp);
  	    DROPNAME();
  	    return (error);
***************
*** 393,401 ****
  	/* they're the same; afs_lookup() already ref'ed the leaf.
  	 * It came in locked, so we don't need to ref OR lock it */
      } else {
! 	if (!lockparent || !(flags & ISLASTCN))
! 	    VOP_UNLOCK(dvp, 0, p);	/* done with parent. */
! 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  	/* always return the child locked */
      }
      *ap->a_vpp = vp;
--- 539,550 ----
  	/* they're the same; afs_lookup() already ref'ed the leaf.
  	 * It came in locked, so we don't need to ref OR lock it */
      } else {
! 	if (!lockparent || !(flags & ISLASTCN)) {
! #ifndef AFS_FBSD70_ENV /* 6 too? */
! 	    MA_VOP_UNLOCK(dvp, 0, p);	/* done with parent. */
! #endif
! 	}
! 	ma_vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  	/* always return the child locked */
      }
      *ap->a_vpp = vp;
***************
*** 440,446 ****
  
      if (vcp) {
  	*ap->a_vpp = AFSTOV(vcp);
! 	vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
      } else
  	*ap->a_vpp = 0;
  
--- 589,595 ----
  
      if (vcp) {
  	*ap->a_vpp = AFSTOV(vcp);
! 	ma_vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
      } else
  	*ap->a_vpp = 0;
  
***************
*** 747,753 ****
  	     */
  	    if (!code) {
  #if defined(AFS_FBSD70_ENV)
! 		if(0) /* XXXX fixme for 7.0 */
  #else
  		if (m->flags & PG_WANTED)
  #endif
--- 896,902 ----
  	     */
  	    if (!code) {
  #if defined(AFS_FBSD70_ENV)
! 		if (m->oflags & VPO_WANTED)
  #else
  		if (m->flags & PG_WANTED)
  #endif
***************
*** 1012,1025 ****
  	error = EISDIR;
  	goto out;
      }
!     if ((error = vn_lock(vp, LK_EXCLUSIVE, p)) != 0) {
  	goto out;
      }
      AFS_GLOCK();
      error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
      AFS_GUNLOCK();
      if (dvp != vp)
! 	VOP_UNLOCK(vp, 0, p);
    out:
      DROPNAME();
      return error;
--- 1161,1174 ----
  	error = EISDIR;
  	goto out;
      }
!     if ((error = ma_vn_lock(vp, LK_EXCLUSIVE, p)) != 0) {
  	goto out;
      }
      AFS_GLOCK();
      error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
      AFS_GUNLOCK();
      if (dvp != vp)
! 	MA_VOP_UNLOCK(vp, 0, p);
    out:
      DROPNAME();
      return error;
***************
*** 1108,1114 ****
  	vput(fvp);
  	return (error);
      }
!     if ((error = vn_lock(fvp, LK_EXCLUSIVE, p)) != 0)
  	goto abortit;
  
      MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
--- 1257,1263 ----
  	vput(fvp);
  	return (error);
      }
!     if ((error = ma_vn_lock(fvp, LK_EXCLUSIVE, p)) != 0)
  	goto abortit;
  
      MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
***************
*** 1171,1177 ****
      }
      if (vcp) {
  	*ap->a_vpp = AFSTOV(vcp);
! 	vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
      } else
  	*ap->a_vpp = 0;
      DROPNAME();
--- 1320,1326 ----
      }
      if (vcp) {
  	*ap->a_vpp = AFSTOV(vcp);
! 	ma_vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
      } else
  	*ap->a_vpp = 0;
      DROPNAME();
***************
*** 1226,1234 ****
  	if (error == 0) {
  	    newvp = AFSTOV(vcp);
  #ifdef AFS_FBSD50_ENV
! 	    vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_thread);
  #else
! 	    vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_proc);
  #endif
  	}
      }
--- 1375,1383 ----
  	if (error == 0) {
  	    newvp = AFSTOV(vcp);
  #ifdef AFS_FBSD50_ENV
! 	    ma_vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_thread);
  #else
! 	    ma_vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_proc);
  #endif
  	}
      }
***************
*** 1321,1327 ****
      AFS_GLOCK();
      afs_InactiveVCache(VTOAFS(vp), 0);	/* decrs ref counts */
      AFS_GUNLOCK();
!     VOP_UNLOCK(vp, 0, ap->a_p);
      return 0;
  }
  
--- 1470,1478 ----
      AFS_GLOCK();
      afs_InactiveVCache(VTOAFS(vp), 0);	/* decrs ref counts */
      AFS_GUNLOCK();
! #ifndef AFS_FBSD80_ENV
!     MA_VOP_UNLOCK(vp, 0, ap->a_p);
! #endif
      return 0;
  }
  
***************
*** 1362,1369 ****
      if (code)
  	printf("afs_vop_reclaim: afs_FlushVCache failed code %d\n", code);
  #ifdef AFS_FBSD60_ENV
!     else
  	vnode_destroy_vobject(vp);
  #endif
      return 0;
  }
--- 1513,1525 ----
      if (code)
  	printf("afs_vop_reclaim: afs_FlushVCache failed code %d\n", code);
  #ifdef AFS_FBSD60_ENV
!     else {
  	vnode_destroy_vobject(vp);
+ #ifndef AFS_FBSD70_ENV
+ 	vfs_hash_remove(vp);
+ #endif
+ 	vp->v_data = 0;
+     }
  #endif
      return 0;
  }
Index: openafs/src/afs/LINUX/osi_alloc.c
diff -c openafs/src/afs/LINUX/osi_alloc.c:1.23.8.1 openafs/src/afs/LINUX/osi_alloc.c:1.23.8.2
*** openafs/src/afs/LINUX/osi_alloc.c:1.23.8.1	Wed Apr 18 14:02:47 2007
--- openafs/src/afs/LINUX/osi_alloc.c	Mon Sep 22 15:35:26 2008
***************
*** 15,21 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_alloc.c,v 1.23.8.1 2007/04/18 18:02:47 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
--- 15,21 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_alloc.c,v 1.23.8.2 2008/09/22 19:35:26 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
***************
*** 366,371 ****
--- 366,372 ----
  	afs_atomlist_put(al_mem_pool, lmp);	/* return osi_linux_mem struct to pool */
  	afs_linux_cur_allocs--;
      } else {
+ 	BUG();
  	printf("osi_linux_free: failed to remove chunk from hashtable\n");
      }
  
Index: openafs/src/afs/LINUX/osi_module.c
diff -c openafs/src/afs/LINUX/osi_module.c:1.74.2.9 openafs/src/afs/LINUX/osi_module.c:1.74.2.10
*** openafs/src/afs/LINUX/osi_module.c:1.74.2.9	Wed Oct 24 14:22:21 2007
--- openafs/src/afs/LINUX/osi_module.c	Mon Sep 22 15:35:26 2008
***************
*** 15,21 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_module.c,v 1.74.2.9 2007/10/24 18:22:21 shadow Exp $");
  
  #include <linux/module.h> /* early to avoid printf->printk mapping */
  #include "afs/sysincludes.h"
--- 15,21 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_module.c,v 1.74.2.10 2008/09/22 19:35:26 shadow Exp $");
  
  #include <linux/module.h> /* early to avoid printf->printk mapping */
  #include "afs/sysincludes.h"
***************
*** 111,117 ****
      osi_proc_init();
      osi_ioctl_init();
  #endif
! 
      return 0;
  }
  
--- 111,119 ----
      osi_proc_init();
      osi_ioctl_init();
  #endif
! #if defined(AFS_CACHE_BYPASS)
!     afs_warn("Cache bypass patched libafs module init.\n");
! #endif
      return 0;
  }
  
***************
*** 123,128 ****
--- 125,133 ----
  cleanup_module(void)
  #endif
  {
+ #if defined(AFS_CACHE_BYPASS)
+     afs_warn("Cache bypass patched libafs module cleaning up.\n");
+ #endif
  #ifdef LINUX_KEYRING_SUPPORT
      osi_keyring_shutdown();
  #endif
Index: openafs/src/afs/LINUX/osi_vnodeops.c
diff -c openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.28 openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.31
*** openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.28	Mon Jul  7 12:53:59 2008
--- openafs/src/afs/LINUX/osi_vnodeops.c	Thu Sep 25 07:42:43 2008
***************
*** 22,28 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.126.2.28 2008/07/07 16:53:59 shadow 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.126.2.31 2008/09/25 11:42:43 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
***************
*** 37,42 ****
--- 37,47 ----
  #endif
  #if defined(AFS_LINUX26_ENV)
  #include "h/writeback.h"
+ #include "h/pagevec.h"
+ #endif
+ #if defined(AFS_CACHE_BYPASS)
+ #include "afs/lock.h"
+ #include "afs/afs_bypasscache.h"
  #endif
  
  #ifdef pgoff2loff
***************
*** 46,55 ****
--- 51,79 ----
  #endif
  
  #if defined(AFS_LINUX26_ENV)
+ #define LockPage(pp) lock_page(pp)
  #define UnlockPage(pp) unlock_page(pp)
  #endif
  
  extern struct vcache *afs_globalVp;
+ #if defined(AFS_LINUX26_ENV)
+ /* Some uses of BKL are perhaps not needed for bypass or memcache--
+  * why don't we try it out? */
+ extern struct afs_cacheOps afs_UfsCacheOps;
+ #define maybe_lock_kernel()			\
+     do {					       \
+ 	if(afs_cacheType == &afs_UfsCacheOps)	       \
+ 	    lock_kernel();			       \
+     } while(0);
+ 
+ 
+ #define maybe_unlock_kernel()			\
+     do {					       \
+ 	if(afs_cacheType == &afs_UfsCacheOps)	       \
+ 	    unlock_kernel();			       \
+     } while(0);
+ #endif /* AFS_CACHE_BYPASS */
+ 
  static ssize_t
  afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
  {
***************
*** 57,68 ****
      struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
      cred_t *credp = crref();
      struct vrequest treq;
! 
      AFS_GLOCK();
      afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
  	       99999);
- 
      /* get a validated vcache entry */
      code = afs_InitReq(&treq, credp);
      if (!code)
--- 81,91 ----
      struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
      cred_t *credp = crref();
      struct vrequest treq;
!     afs_size_t isize, offindex;
      AFS_GLOCK();
      afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
  	       99999);
      /* get a validated vcache entry */
      code = afs_InitReq(&treq, credp);
      if (!code)
***************
*** 71,76 ****
--- 94,106 ----
      if (code)
  	code = -code;
      else {
+         isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
+         offindex = *offp >> PAGE_CACHE_SHIFT;
+         if(offindex > isize) {
+             code=0;
+             goto done;
+         }
+ 
  	    osi_FlushPages(vcp, credp);	/* ensure stale pages are gone */
  	    AFS_GUNLOCK();
  #ifdef DO_SYNC_READ
***************
*** 84,90 ****
      afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
  	       code);
! 
      AFS_GUNLOCK();
      crfree(credp);
      return code;
--- 114,120 ----
      afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
  	       code);
! done:
      AFS_GUNLOCK();
      crfree(credp);
      return code;
***************
*** 167,173 ****
      struct afs_fakestat_state fakestat;
  
  #if defined(AFS_LINUX26_ENV)
!     lock_kernel();
  #endif
      AFS_GLOCK();
      AFS_STATCNT(afs_readdir);
--- 197,203 ----
      struct afs_fakestat_state fakestat;
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      AFS_STATCNT(afs_readdir);
***************
*** 325,331 ****
  out1:
      AFS_GUNLOCK();
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
      return code;
  }
--- 355,361 ----
  out1:
      AFS_GUNLOCK();
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
      return code;
  }
***************
*** 399,411 ****
      int code;
  
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_open(&vcp, fp->f_flags, credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
  
      crfree(credp);
--- 429,441 ----
      int code;
  
  #ifdef AFS_LINUX24_ENV
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_open(&vcp, fp->f_flags, credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     maybe_unlock_kernel();
  #endif
  
      crfree(credp);
***************
*** 420,432 ****
      int code = 0;
  
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_close(vcp, fp->f_flags, credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
  
      crfree(credp);
--- 450,462 ----
      int code = 0;
  
  #ifdef AFS_LINUX24_ENV
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_close(vcp, fp->f_flags, credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     maybe_unlock_kernel();
  #endif
  
      crfree(credp);
***************
*** 445,457 ****
      cred_t *credp = crref();
  
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_fsync(VTOAFS(ip), credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
      crfree(credp);
      return -code;
--- 475,487 ----
      cred_t *credp = crref();
  
  #ifdef AFS_LINUX24_ENV
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_fsync(VTOAFS(ip), credp);
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
      return -code;
***************
*** 585,590 ****
--- 615,623 ----
      struct vcache *vcp;
      cred_t *credp;
      int code;
+ #if defined(AFS_CACHE_BYPASS)
+     int bypasscache;
+ #endif
  
      AFS_GLOCK();
  
***************
*** 593,615 ****
  	return 0;
      }
  
      credp = crref();
      vcp = VTOAFS(FILE_INODE(fp));
  
      code = afs_InitReq(&treq, credp);
      if (code)
  	goto out;
  
      ObtainSharedLock(&vcp->lock, 535);
      if ((vcp->execsOrWriters > 0) && (file_count(fp) == 1)) {
  	UpgradeSToWLock(&vcp->lock, 536);
! 	code = afs_StoreAllSegments(vcp, &treq, AFS_SYNC | AFS_LASTSTORE);
  	ConvertWToSLock(&vcp->lock);
      }
      code = afs_CheckCode(code, &treq, 54);
      ReleaseSharedLock(&vcp->lock);
  
  out:
      AFS_GUNLOCK();
  
      crfree(credp);
--- 626,684 ----
  	return 0;
      }
  
+     AFS_DISCON_LOCK();
+ 
      credp = crref();
      vcp = VTOAFS(FILE_INODE(fp));
  
      code = afs_InitReq(&treq, credp);
      if (code)
  	goto out;
+ #if defined(AFS_CACHE_BYPASS)
+ 	/* If caching is bypassed for this file, or globally, just return 0 */
+ 	if(cache_bypass_strategy == ALWAYS_BYPASS_CACHE)
+ 		bypasscache = 1;
+ 	else {
+ 		ObtainReadLock(&vcp->lock);
+ 		if(vcp->cachingStates & FCSBypass)
+ 			bypasscache = 1;
+ 		ReleaseReadLock(&vcp->lock);
+ 	}
+ 	if(bypasscache) {
+             /* future proof: don't rely on 0 return from afs_InitReq */
+             code = 0; goto out;
+         }
+ #endif
  
      ObtainSharedLock(&vcp->lock, 535);
      if ((vcp->execsOrWriters > 0) && (file_count(fp) == 1)) {
  	UpgradeSToWLock(&vcp->lock, 536);
! 	if (!AFS_IS_DISCONNECTED) {
! 		code = afs_StoreAllSegments(vcp,
! 				&treq,
! 				AFS_SYNC | AFS_LASTSTORE);
! 	} else {
! #if defined(AFS_DISCON_ENV)
! 		if (!vcp->ddirty_flags ||
! 		    (vcp->ddirty_flags == VDisconShadowed)) {
! 
! 		    ObtainWriteLock(&afs_DDirtyVCListLock, 710);
! 		    AFS_DISCON_ADD_DIRTY(vcp);
! 		    ReleaseWriteLock(&afs_DDirtyVCListLock);
! 		}
! 
! 		/* Set disconnected write flag. */
! 		vcp->ddirty_flags |= VDisconWriteOsiFlush;
! #endif
! 	}
! 
  	ConvertWToSLock(&vcp->lock);
      }
      code = afs_CheckCode(code, &treq, 54);
      ReleaseSharedLock(&vcp->lock);
  
  out:
+     AFS_DISCON_UNLOCK();
      AFS_GUNLOCK();
  
      crfree(credp);
***************
*** 740,746 ****
      int code;
  
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
      AFS_GLOCK();
  
--- 809,815 ----
      int code;
  
  #ifdef AFS_LINUX24_ENV
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
  
***************
*** 766,772 ****
  
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
      crfree(credp);
  
--- 835,841 ----
  
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
  
***************
*** 809,815 ****
      int valid;
  
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
      AFS_GLOCK();
  
--- 878,884 ----
      int valid;
  
  #ifdef AFS_LINUX24_ENV
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
  
***************
*** 897,903 ****
  	d_drop(dp);
      }
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
      return valid;
  
--- 966,972 ----
  	d_drop(dp);
      }
  #ifdef AFS_LINUX24_ENV
!     maybe_unlock_kernel();
  #endif
      return valid;
  
***************
*** 973,979 ****
      vattr.va_type = mode & S_IFMT;
  
  #if defined(AFS_LINUX26_ENV)
!     lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
--- 1042,1048 ----
      vattr.va_type = mode & S_IFMT;
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
***************
*** 992,998 ****
      AFS_GUNLOCK();
  
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
      crfree(credp);
      return -code;
--- 1061,1067 ----
      AFS_GUNLOCK();
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
      return -code;
***************
*** 1022,1028 ****
      int code;
  
  #if defined(AFS_LINUX26_ENV)
!     lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_lookup(VTOAFS(dip), comp, &vcp, credp);
--- 1091,1097 ----
      int code;
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_lock_kernel();
  #endif
      AFS_GLOCK();
      code = afs_lookup(VTOAFS(dip), comp, &vcp, credp);
***************
*** 1080,1086 ****
  #endif
  
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
      crfree(credp);
  
--- 1149,1155 ----
  #endif
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
  
***************
*** 1134,1140 ****
      struct vcache *tvc = VTOAFS(dp->d_inode);
  
  #if defined(AFS_LINUX26_ENV)
!     lock_kernel();
  #endif
      if (VREFCOUNT(tvc) > 1 && tvc->opens > 0
  				&& !(tvc->states & CUnlinked)) {
--- 1203,1209 ----
      struct vcache *tvc = VTOAFS(dp->d_inode);
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_lock_kernel();
  #endif
      if (VREFCOUNT(tvc) > 1 && tvc->opens > 0
  				&& !(tvc->states & CUnlinked)) {
***************
*** 1199,1205 ****
  	d_drop(dp);
  out:
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
      crfree(credp);
      return -code;
--- 1268,1274 ----
  	d_drop(dp);
  out:
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
      return -code;
***************
*** 1237,1243 ****
      const char *name = dp->d_name.name;
  
  #if defined(AFS_LINUX26_ENV)
!     lock_kernel();
  #endif
      VATTR_NULL(&vattr);
      vattr.va_mask = ATTR_MODE;
--- 1306,1312 ----
      const char *name = dp->d_name.name;
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_lock_kernel();
  #endif
      VATTR_NULL(&vattr);
      vattr.va_mask = ATTR_MODE;
***************
*** 1258,1264 ****
      AFS_GUNLOCK();
  
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
      crfree(credp);
      return -code;
--- 1327,1333 ----
      AFS_GUNLOCK();
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
      crfree(credp);
      return -code;
***************
*** 1306,1312 ****
  
  #if defined(AFS_LINUX26_ENV)
      /* Prevent any new references during rename operation. */
!     lock_kernel();
  
      if (!d_unhashed(newdp)) {
  	d_drop(newdp);
--- 1375,1381 ----
  
  #if defined(AFS_LINUX26_ENV)
      /* Prevent any new references during rename operation. */
!     maybe_lock_kernel();
  
      if (!d_unhashed(newdp)) {
  	d_drop(newdp);
***************
*** 1335,1341 ****
  	d_rehash(rehash);
  
  #if defined(AFS_LINUX26_ENV)
!     unlock_kernel();
  #endif
  
      crfree(credp);
--- 1404,1410 ----
  	d_rehash(rehash);
  
  #if defined(AFS_LINUX26_ENV)
!     maybe_unlock_kernel();
  #endif
  
      crfree(credp);
***************
*** 1451,1544 ****
  #endif /* AFS_LINUX24_ENV */
  #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
  
  /* afs_linux_readpage
   * all reads come through here. A strategy-like read call.
   */
  static int
  afs_linux_readpage(struct file *fp, struct page *pp)
  {
!     int code;
!     cred_t *credp = crref();
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
!     char *address;
!     afs_offs_t offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
  #else
!     ulong address = afs_linux_page_address(pp);
!     afs_offs_t offset = pageoff(pp);
  #endif
!     uio_t tuio;
!     struct iovec iovec;
!     struct inode *ip = FILE_INODE(fp);
!     int cnt = page_count(pp);
!     struct vcache *avc = VTOAFS(ip);
! 
  
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
!     address = kmap(pp);
!     ClearPageError(pp);
  #else
!     atomic_add(1, &pp->count);
!     set_bit(PG_locked, &pp->flags);	/* other bits? See mm.h */
!     clear_bit(PG_error, &pp->flags);
! #endif
  
!     setup_uio(&tuio, &iovec, (char *)address, offset, PAGE_SIZE, UIO_READ,
! 	      AFS_UIOSYS);
  #ifdef AFS_LINUX24_ENV
!     lock_kernel();
  #endif
!     AFS_GLOCK();
!     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip, ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32, 99999);	/* not a possible code value */
!     code = afs_rdwr(avc, &tuio, UIO_READ, 0, credp);
!     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
! 	       ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
! 	       code);
!     AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
!     unlock_kernel();
  #endif
  
-     if (!code) {
- 	if (tuio.uio_resid)	/* zero remainder of page */
- 	    memset((void *)(address + (PAGE_SIZE - tuio.uio_resid)), 0,
- 		   tuio.uio_resid);
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
! 	flush_dcache_page(pp);
! 	SetPageUptodate(pp);
  #else
! 	set_bit(PG_uptodate, &pp->flags);
  #endif
!     }
  
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
!     kunmap(pp);
!     UnlockPage(pp);
  #else
!     clear_bit(PG_locked, &pp->flags);
!     wake_up(&pp->wait);
!     free_page(address);
  #endif
  
!     if (!code && AFS_CHUNKOFFSET(offset) == 0) {
! 	struct dcache *tdc;
! 	struct vrequest treq;
  
! 	AFS_GLOCK();
! 	code = afs_InitReq(&treq, credp);
! 	if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
! 	    tdc = afs_FindDCache(avc, offset);
! 	    if (tdc) {
! 		if (!(tdc->mflags & DFNextStarted))
! 		    afs_PrefetchChunk(avc, tdc, credp, &treq);
! 		afs_PutDCache(tdc);
! 	    }
! 	    ReleaseWriteLock(&avc->lock);
! 	}
! 	AFS_GUNLOCK();
!     }
  
!     crfree(credp);
!     return -code;
  }
  
  
--- 1520,1839 ----
  #endif /* AFS_LINUX24_ENV */
  #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
  
+ #if defined(AFS_CACHE_BYPASS)
+ 
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ 
+ /* The kernel calls readpages before trying readpage, with a list of 
+  * pages.  The readahead algorithm expands num_pages when it thinks
+  * the application will benefit.  Unlike readpage, the pages are not
+  * necessarily allocated.  If we do not a) allocate required pages and 
+  * b) remove them from page_list, linux will re-enter at afs_linux_readpage
+  * for each required page (and the page will be pre-allocated) */	
+ 
+ static int
+ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ 		    struct list_head *page_list, unsigned num_pages)
+ {
+     afs_int32 page_ix;
+     uio_t *auio;
+     afs_offs_t offset;
+     struct iovec* iovecp;
+     struct nocache_read_request *ancr;
+     struct page *pp, *ppt;
+     struct pagevec lrupv;
+     afs_int32 code = 0;	
+ 
+     cred_t *credp;
+     struct inode *ip = FILE_INODE(fp);
+     struct vcache *avc = VTOAFS(ip);
+     afs_int32 bypasscache = 0; /* bypass for this read */
+     afs_int32 base_index = 0;
+     afs_int32 page_count = 0;
+     afs_int32 isize;
+ 	
+     credp = crref();
+ 	
+     switch(cache_bypass_strategy) {
+     case NEVER_BYPASS_CACHE:
+ 	break;	
+     case ALWAYS_BYPASS_CACHE:
+ 	bypasscache = 1;
+ 	break;
+     case LARGE_FILES_BYPASS_CACHE:
+ 	if(i_size_read(ip) > cache_bypass_threshold) {
+ 	    bypasscache = 1;
+ 	}
+ 	break;
+     default:
+ 	break;
+     }
+ 	
+     /* In the new incarnation of selective caching, a file's caching policy 
+      *  can change, eg because file size exceeds threshold, etc. */
+     trydo_cache_transition(avc, credp, bypasscache);	
+ 	 
+     if(!bypasscache) {
+ 	while(!list_empty(page_list)) {
+ 	    pp = list_entry(page_list->prev, struct page, lru);
+ 	    list_del(&pp->lru);
+ 	}
+ 	goto out;
+     }
+     /* background thread must free: iovecp, auio, ancr */
+     iovecp = osi_Alloc(num_pages * sizeof(struct iovec));
+ 
+     auio = osi_Alloc(sizeof(uio_t));
+     auio->uio_iov = iovecp;	
+     auio->uio_iovcnt = num_pages;
+     auio->uio_flag = UIO_READ;
+     auio->uio_seg = AFS_UIOSYS;
+     auio->uio_resid = num_pages * PAGE_SIZE;
+ 	
+     ancr = osi_Alloc(sizeof(struct nocache_read_request));
+     ancr->auio = auio;
+     ancr->offset = auio->uio_offset;
+     ancr->length = auio->uio_resid;
+ 	
+     pagevec_init(&lrupv, 0);	
+ 	
+     for(page_ix = 0; page_ix < num_pages; ++page_ix) {
+ 	
+ 	if(list_empty(page_list))
+ 	    break;
+ 
+ 	pp = list_entry(page_list->prev, struct page, lru);
+ 	/* If we allocate a page and don't remove it from page_list,
+ 	 * the page cache gets upset. */
+ 	list_del(&pp->lru);
+ 	isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
+ 	if(pp->index > isize) {
+ 	    if(PageLocked(pp))
+ 		UnlockPage(pp);
+ 	    continue;
+ 	}
+ 
+ 	if(page_ix == 0) {
+ 	    offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
+ 	    auio->uio_offset = offset;
+ 	    base_index = pp->index;
+ 	}
+         iovecp[page_ix].iov_len = PAGE_SIZE;
+         code = add_to_page_cache(pp, mapping, pp->index, GFP_KERNEL);
+         if(base_index != pp->index) {   
+             if(PageLocked(pp))
+ 				 UnlockPage(pp);
+             page_cache_release(pp);
+ 	    iovecp[page_ix].iov_base = (void *) 0;
+ 	    base_index++;
+             continue;
+         }
+         base_index++;
+         if(code) {
+ 	    if(PageLocked(pp))
+ 		UnlockPage(pp);
+ 	    page_cache_release(pp);
+ 	    iovecp[page_ix].iov_base = (void *) 0;
+ 	} else {
+ 	    page_count++;
+ 	    if(!PageLocked(pp)) {
+ 		LockPage(pp);
+ 	    }	
+ 	    
+ 	    /* save the page for background map */
+             iovecp[page_ix].iov_base = (void*) pp;
+ 
+ 	    /* and put it on the LRU cache */
+ 	    if (!pagevec_add(&lrupv, pp))
+ 		__pagevec_lru_add(&lrupv);
+         }
+     }
+ 
+     /* If there were useful pages in the page list, make sure all pages
+      * are in the LRU cache, then schedule the read */
+     if(page_count) {
+         pagevec_lru_add(&lrupv);
+         code = afs_ReadNoCache(avc, ancr, credp);
+     } else {
+         /* If there is nothing for the background thread to handle,
+          * it won't be freeing the things that we never gave it */
+         osi_Free(iovecp, num_pages * sizeof(struct iovec));
+         osi_Free(auio, sizeof(uio_t));
+         osi_Free(ancr, sizeof(struct nocache_read_request));
+     }
+     /* we do not flush, release, or unmap pages--that will be 
+      * done for us by the background thread as each page comes in
+      * from the fileserver */
+     crfree(credp);
+ 	
+ out:	
+     return -code;
+ }
+ 
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
+ #endif /* defined(AFS_CACHE_BYPASS */
+ 
+ 
  /* afs_linux_readpage
   * all reads come through here. A strategy-like read call.
   */
  static int
  afs_linux_readpage(struct file *fp, struct page *pp)
  {
! 	 afs_int32 code;
! 	 cred_t *credp = crref();
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
! 	 char *address;
! 	 afs_offs_t offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
  #else
! 	 ulong address = afs_linux_page_address(pp);
! 	 afs_offs_t offset = pageoff(pp);
  #endif
! #if defined(AFS_CACHE_BYPASS)
! 	 afs_int32 bypasscache = 0; /* bypass for this read */
! 	 struct nocache_read_request *ancr;
! #endif
! 	 afs_int32 isize;	
! 	 uio_t *auio;
! 	 struct iovec *iovecp;
! 	 struct inode *ip = FILE_INODE(fp);
! 	 afs_int32 cnt = page_count(pp);
! 	 struct vcache *avc = VTOAFS(ip);
  
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
! 	 address = kmap(pp);
! 	 ClearPageError(pp);
  #else
! 	 atomic_add(1, &pp->count);
! 	 set_bit(PG_locked, &pp->flags);	/* other bits? See mm.h */
! 	 clear_bit(PG_error, &pp->flags);
! #endif
! 	 /* If the page is past the end of the file, skip it */
! 	 isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
! 	 if(pp->index > isize) {
! 		  if(PageLocked(pp))
! 			   UnlockPage(pp);
! 		  goto done;
! 	 }
! 	 /* if bypasscache, receiver frees, else we do */
! 	 auio = osi_Alloc(sizeof(uio_t));
! 	 iovecp = osi_Alloc(sizeof(struct iovec));
! 	
! 	 setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
! 			   AFS_UIOSYS);
  
! #if defined(AFS_CACHE_BYPASS)
! 
! 	 switch(cache_bypass_strategy) {
! 	 case NEVER_BYPASS_CACHE:
! 		  break;	
! 	 case ALWAYS_BYPASS_CACHE:
! 		  bypasscache = 1;
! 		  break;
! 	 case LARGE_FILES_BYPASS_CACHE:
! 		  if(i_size_read(ip) > cache_bypass_threshold) {
! 			   bypasscache = 1;
! 		  }
! 		  break;
! 	 default:
! 		  break;
! 	 }
! 
! 	 /* In the new incarnation of selective caching, a file's caching policy 
! 	  * can change, eg because file size exceeds threshold, etc. */
! 	 trydo_cache_transition(avc, credp, bypasscache);
! 		
! 	 if(bypasscache) {
! 		  if(address)
! 			   kunmap(pp);
! 		  /* save the page for background map */
! 		  auio->uio_iov->iov_base = (void*) pp;
! 		  /* the background thread will free this */
! 		  ancr = osi_Alloc(sizeof(struct nocache_read_request));
! 		  ancr->auio = auio;
! 		  ancr->offset = offset;
! 		  ancr->length = PAGE_SIZE;
! 	
! 		  maybe_lock_kernel();
! 		  code = afs_ReadNoCache(avc, ancr, credp);
! 		  maybe_unlock_kernel();
! 	
! 		  goto done; /* skips release page, doing it in bg thread */
! 	 }
! #endif 
! 		  
  #ifdef AFS_LINUX24_ENV
! 	 maybe_lock_kernel();
  #endif
! 	 AFS_GLOCK();
! 	 afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip, ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32, 99999);	/* not a possible code value */
! 
! 	 code = afs_rdwr(avc, auio, UIO_READ, 0, credp);
! 	
! 	 afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
! 				ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
! 				code);
! 	 AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
! 	 maybe_unlock_kernel();
  #endif
+ 	 if (!code) {	
+ 		  /* XXX valid for no-cache also?  Check last bits of files... :) 
+ 		   * Cognate code goes in afs_NoCacheFetchProc.  */
+ 		  if (auio->uio_resid)	/* zero remainder of page */
+ 			   memset((void *)(address + (PAGE_SIZE - auio->uio_resid)), 0,
+ 					  auio->uio_resid);
  
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
! 		  flush_dcache_page(pp);
! 		  SetPageUptodate(pp);
  #else
! 		  set_bit(PG_uptodate, &pp->flags);
  #endif
! 	 } /* !code */
  
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
! 	 kunmap(pp);
! 	 UnlockPage(pp);
  #else
! 	 clear_bit(PG_locked, &pp->flags);
! 	 wake_up(&pp->wait);
! 	 free_page(address);
  #endif
  
! #if defined(AFS_CACHE_BYPASS)
  
! /* do not call afs_GetDCache if cache is bypassed */
! 	 if(bypasscache)
! 		  goto done;
! 	
! #endif
  
! 	 /* free if not bypassing cache */
! 	 osi_Free(auio, sizeof(uio_t));
! 	 osi_Free(iovecp, sizeof(struct iovec));
! 
! 	 if (!code && AFS_CHUNKOFFSET(offset) == 0) {
! 		  struct dcache *tdc;
! 		  struct vrequest treq;
! 
! 		  AFS_GLOCK();
! 		  code = afs_InitReq(&treq, credp);
! 		  if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
! 			   tdc = afs_FindDCache(avc, offset);
! 			   if (tdc) {
! 					if (!(tdc->mflags & DFNextStarted))
! 						 afs_PrefetchChunk(avc, tdc, credp, &treq);
! 					afs_PutDCache(tdc);
! 			   }
! 			   ReleaseWriteLock(&avc->lock);
! 		  }
! 		  AFS_GUNLOCK();
! 	 }
! 
! done:
! 	 crfree(credp);
! 	 return -code;
  }
  
  
***************
*** 1560,1566 ****
      base = (((loff_t) pp->index) << PAGE_CACHE_SHIFT)  + offset;
  
      credp = crref();
!     lock_kernel();
      AFS_GLOCK();
      afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
--- 1855,1861 ----
      base = (((loff_t) pp->index) << PAGE_CACHE_SHIFT)  + offset;
  
      credp = crref();
!     maybe_lock_kernel();
      AFS_GLOCK();
      afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
  	       ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
***************
*** 1588,1594 ****
  	       ICL_TYPE_INT32, code);
  
      AFS_GUNLOCK();
!     unlock_kernel();
      crfree(credp);
      kunmap(pp);
  
--- 1883,1889 ----
  	       ICL_TYPE_INT32, code);
  
      AFS_GUNLOCK();
!     maybe_unlock_kernel();
      crfree(credp);
      kunmap(pp);
  
***************
*** 1769,1775 ****
    .setattr =		afs_notify_change,
  #else
    .default_file_ops =	&afs_file_fops,
!   .readpage =		afs_linux_readpage,
    .revalidate =		afs_linux_revalidate,
    .updatepage =		afs_linux_updatepage,
  #endif
--- 2064,2070 ----
    .setattr =		afs_notify_change,
  #else
    .default_file_ops =	&afs_file_fops,
!   .readpage =		afs_linux_readpage,  
    .revalidate =		afs_linux_revalidate,
    .updatepage =		afs_linux_updatepage,
  #endif
***************
*** 1778,1783 ****
--- 2073,2081 ----
  #if defined(AFS_LINUX24_ENV)
  static struct address_space_operations afs_file_aops = {
    .readpage =		afs_linux_readpage,
+ #if defined(AFS_CACHE_BYPASS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+   .readpages =		afs_linux_readpages,
+ #endif  
    .writepage =		afs_linux_writepage,
    .commit_write =	afs_linux_commit_write,
    .prepare_write =	afs_linux_prepare_write,
***************
*** 1822,1828 ****
      char *p = (char *)kmap(page);
      int code;
  
!     lock_kernel();
      AFS_GLOCK();
      code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
      AFS_GUNLOCK();
--- 2120,2126 ----
      char *p = (char *)kmap(page);
      int code;
  
!     maybe_lock_kernel();
      AFS_GLOCK();
      code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
      AFS_GUNLOCK();
***************
*** 1830,1836 ****
      if (code < 0)
  	goto fail;
      p[code] = '\0';		/* null terminate? */
!     unlock_kernel();
  
      SetPageUptodate(page);
      kunmap(page);
--- 2128,2134 ----
      if (code < 0)
  	goto fail;
      p[code] = '\0';		/* null terminate? */
!     maybe_unlock_kernel();
  
      SetPageUptodate(page);
      kunmap(page);
***************
*** 1838,1844 ****
      return 0;
  
    fail:
!     unlock_kernel();
  
      SetPageError(page);
      kunmap(page);
--- 2136,2142 ----
      return 0;
  
    fail:
!     maybe_unlock_kernel();
  
      SetPageError(page);
      kunmap(page);
Index: openafs/src/afs/VNOPS/afs_vnop_access.c
diff -c openafs/src/afs/VNOPS/afs_vnop_access.c:1.11.8.6 openafs/src/afs/VNOPS/afs_vnop_access.c:1.11.8.7
*** openafs/src/afs/VNOPS/afs_vnop_access.c:1.11.8.6	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_access.c	Mon Sep 22 15:29:55 2008
***************
*** 23,29 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.11.8.6 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 23,29 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.11.8.7 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 246,255 ****
      }
      
      /* If we're looking for write access, and we're disconnected without logging, forget it */
!     if ((amode & VWRITE) && (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING)) {
          afs_PutFakeStat(&fakestate);
  	AFS_DISCON_UNLOCK();
! 	/*printf("Network is down in afs_vnop_access\n");*/
          return ENETDOWN;
      }
      
--- 246,255 ----
      }
      
      /* If we're looking for write access, and we're disconnected without logging, forget it */
!     if ((amode & VWRITE) && (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW)) {
          afs_PutFakeStat(&fakestate);
  	AFS_DISCON_UNLOCK();
! 	printf("Network is down in afs_vnop_access\n");
          return ENETDOWN;
      }
      
Index: openafs/src/afs/VNOPS/afs_vnop_attrs.c
diff -c openafs/src/afs/VNOPS/afs_vnop_attrs.c:1.41.2.2 openafs/src/afs/VNOPS/afs_vnop_attrs.c:1.41.2.3
*** openafs/src/afs/VNOPS/afs_vnop_attrs.c:1.41.2.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_attrs.c	Mon Sep 22 15:29:55 2008
***************
*** 24,30 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.41.2.2 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 24,30 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.41.2.3 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 40,45 ****
--- 40,46 ----
  extern struct vfs *afs_globalVFS;
  #endif
  
+ 
  /* copy out attributes from cache entry */
  int
  afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
***************
*** 509,515 ****
  	}
      }
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
          code = ENETDOWN;
          goto done;
      }
--- 510,516 ----
  	}
      }
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
          code = ENETDOWN;
          goto done;
      }
***************
*** 542,547 ****
--- 543,549 ----
  	afs_size_t tsize = attrs->va_size;
  	ObtainWriteLock(&avc->lock, 128);
  	avc->states |= CDirty;
+ 
  	code = afs_TruncateAllSegments(avc, tsize, &treq, acred);
  	/* if date not explicitly set by this call, set it ourselves, since we
  	 * changed the data */
***************
*** 549,560 ****
  	    astat.Mask |= AFS_SETMODTIME;
  	    astat.ClientModTime = osi_Time();
  	}
  	if (code == 0) {
  	    if (((avc->execsOrWriters <= 0) && (avc->states & CCreating) == 0)
  		|| (avc->execsOrWriters == 1 && AFS_NFSXLATORREQ(acred))) {
! 		code = afs_StoreAllSegments(avc, &treq, AFS_ASYNC);
! 		if (!code)
! 		    avc->states &= ~CDirty;
  	    }
  	} else
  	    avc->states &= ~CDirty;
--- 551,568 ----
  	    astat.Mask |= AFS_SETMODTIME;
  	    astat.ClientModTime = osi_Time();
  	}
+ 
  	if (code == 0) {
  	    if (((avc->execsOrWriters <= 0) && (avc->states & CCreating) == 0)
  		|| (avc->execsOrWriters == 1 && AFS_NFSXLATORREQ(acred))) {
! 
! 		/* Store files now if not disconnected. */
! 		/* XXX: AFS_IS_DISCON_RW handled. */
! 		if (!AFS_IS_DISCONNECTED) {
! 			code = afs_StoreAllSegments(avc, &treq, AFS_ASYNC);
! 			if (!code)
! 		    		avc->states &= ~CDirty;
! 		}
  	    }
  	} else
  	    avc->states &= ~CDirty;
***************
*** 579,588 ****
  	        osi_dnlc_purgedp(avc);
  	    /* error?  erase any changes we made to vcache entry */
          }
      } else {
!         /* Must be logging - but not implemented yet ... */
!         code = ENETDOWN;
!     }
  #if	defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
      if (AFS_NFSXLATORREQ(acred)) {
  	avc->execsOrWriters--;
--- 587,603 ----
  	        osi_dnlc_purgedp(avc);
  	    /* error?  erase any changes we made to vcache entry */
          }
+ 
+ #if defined(AFS_DISCON_ENV)
      } else {
! 
! 	ObtainSharedLock(&avc->lock, 712);
! 	/* Write changes locally. */
! 	code = afs_WriteVCacheDiscon(avc, &astat, attrs);
! 	ReleaseSharedLock(&avc->lock);
! #endif
!     }		/* if (!AFS_IS_DISCONNECTED) */
! 
  #if	defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
      if (AFS_NFSXLATORREQ(acred)) {
  	avc->execsOrWriters--;
Index: openafs/src/afs/VNOPS/afs_vnop_create.c
diff -c openafs/src/afs/VNOPS/afs_vnop_create.c:1.23.4.4 openafs/src/afs/VNOPS/afs_vnop_create.c:1.23.4.6
*** openafs/src/afs/VNOPS/afs_vnop_create.c:1.23.4.4	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_create.c	Thu Sep 25 05:02:56 2008
***************
*** 17,23 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_create.c,v 1.23.4.4 2008/05/23 14:25:16 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/VNOPS/afs_vnop_create.c,v 1.23.4.6 2008/09/25 09:02:56 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 122,128 ****
  	goto done;
      }
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
          code = ENETDOWN;
          goto done;
      }
--- 122,128 ----
  	goto done;
      }
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
          code = ENETDOWN;
          goto done;
      }
***************
*** 260,270 ****
  	}
      }
      
-     if (AFS_IS_DISCONNECTED) {
-         /* XXX - If we get here, logging must be enabled (as we bypassed the
-          * earlier check. So - do that logging thang, then return */
-     }       
- 
      /* if we create the file, we don't do any access checks, since
       * that's how O_CREAT is supposed to work */
      if (adp->states & CForeign) {
--- 260,265 ----
***************
*** 296,369 ****
  		attrs->va_mode = 0x1b6;	/* XXX default mode: rw-rw-rw XXX */
  	}
      }
!     InStatus.UnixModeBits = attrs->va_mode & 0xffff;	/* only care about protection bits */
!     do {
! 	tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	if (tc) {
! 	    hostp = tc->srvr->server;	/* remember for callback processing */
! 	    now = osi_Time();
! 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
! 	    RX_AFS_GUNLOCK();
! 	    code =
! 		RXAFS_CreateFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
  				 aname, &InStatus, (struct AFSFid *)
  				 &newFid.Fid, &OutFidStatus, &OutDirStatus,
  				 &CallBack, &tsync);
! 	    RX_AFS_GLOCK();
! 	    XSTATS_END_TIME;
! 	    CallBack.ExpirationTime += now;
! 	} else
! 	    code = -1;
!     } while (afs_Analyze
! 	     (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_CREATEFILE,
! 	      SHARED_LOCK, NULL));
  
!     if ((code == EEXIST || code == UAEEXIST) &&
  #ifdef AFS_SGI64_ENV
!     !(flags & VEXCL)
  #else /* AFS_SGI64_ENV */
!     aexcl == NONEXCL
  #endif
!     ) {
! 	/* if we get an EEXIST in nonexcl mode, just do a lookup */
! 	if (tdc) {
! 	    ReleaseSharedLock(&tdc->lock);
! 	    afs_PutDCache(tdc);
! 	}
! 	ReleaseWriteLock(&adp->lock);
  #if !(defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV))
  #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
  #if defined(AFS_SGI64_ENV)
! 	code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t *) adp), aname, avcp, 
! 			  NULL, 0, NULL, acred);
  #else
! 	code = afs_lookup(adp, aname, avcp, NULL, 0, NULL, acred);
  #endif /* AFS_SGI64_ENV */
  #else /* SUN5 || SGI */
! 	code = afs_lookup(adp, aname, avcp, acred);
  #endif /* SUN5 || SGI */
  #endif /* !(AFS_OSF_ENV || AFS_DARWIN_ENV) */
  	goto done;
!     }
!     if (code) {
! 	if (code < 0) {
! 	    ObtainWriteLock(&afs_xcbhash, 488);
! 	    afs_DequeueCallback(adp);
! 	    adp->states &= ~CStatd;
! 	    ReleaseWriteLock(&afs_xcbhash);
! 	    osi_dnlc_purgedp(adp);
! 	}
! 	ReleaseWriteLock(&adp->lock);
! 	if (tdc) {
! 	    ReleaseSharedLock(&tdc->lock);
! 	    afs_PutDCache(tdc);
! 	}
  	goto done;
!     }
      /* otherwise, we should see if we can make the change to the dir locally */
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 631);
!     if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	ObtainWriteLock(&afs_xdcache, 291);
  	code = afs_dir_Create(tdc, aname, &newFid.Fid);
--- 291,379 ----
  		attrs->va_mode = 0x1b6;	/* XXX default mode: rw-rw-rw XXX */
  	}
      }
! 
!     if (!AFS_IS_DISCONNECTED) {
! 	/* If not disconnected, connect to the server.*/
! 
!     	InStatus.UnixModeBits = attrs->va_mode & 0xffff;	/* only care about protection bits */
!     	do {
! 	    tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	    if (tc) {
! 	    	hostp = tc->srvr->server;	/* remember for callback processing */
! 	    	now = osi_Time();
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
! 	    	RX_AFS_GUNLOCK();
! 	    	code =
! 		    RXAFS_CreateFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
  				 aname, &InStatus, (struct AFSFid *)
  				 &newFid.Fid, &OutFidStatus, &OutDirStatus,
  				 &CallBack, &tsync);
! 	    	RX_AFS_GLOCK();
! 	    	XSTATS_END_TIME;
! 	    	CallBack.ExpirationTime += now;
! 	    } else
! 	    	code = -1;
!     	} while (afs_Analyze
! 	         (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_CREATEFILE,
! 	          SHARED_LOCK, NULL));
  
! 	if ((code == EEXIST || code == UAEEXIST) &&
  #ifdef AFS_SGI64_ENV
!     	!(flags & VEXCL)
  #else /* AFS_SGI64_ENV */
!     	aexcl == NONEXCL
  #endif
!     	) {
! 	    /* if we get an EEXIST in nonexcl mode, just do a lookup */
! 	    if (tdc) {
! 	    	ReleaseSharedLock(&tdc->lock);
! 	    	afs_PutDCache(tdc);
! 	    }
! 	    ReleaseWriteLock(&adp->lock);
  #if !(defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV))
  #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
  #if defined(AFS_SGI64_ENV)
! 	    code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t *) adp), aname, avcp,
! 				  NULL, 0, NULL, acred);
  #else
! 	    code = afs_lookup(adp, aname, avcp, NULL, 0, NULL, acred);
  #endif /* AFS_SGI64_ENV */
  #else /* SUN5 || SGI */
! 	    code = afs_lookup(adp, aname, avcp, acred);
  #endif /* SUN5 || SGI */
  #endif /* !(AFS_OSF_ENV || AFS_DARWIN_ENV) */
  	goto done;
!         }
! 
! 	if (code) {
! 	    if (code < 0) {
! 	    	ObtainWriteLock(&afs_xcbhash, 488);
! 	    	afs_DequeueCallback(adp);
! 	    	adp->states &= ~CStatd;
! 	    	ReleaseWriteLock(&afs_xcbhash);
! 	    	osi_dnlc_purgedp(adp);
! 	    }
! 	    ReleaseWriteLock(&adp->lock);
! 	    if (tdc) {
! 	    	ReleaseSharedLock(&tdc->lock);
! 	    	afs_PutDCache(tdc);
! 	    }
  	goto done;
! 	}
! 
!     } else {
! #if defined(AFS_DISCON_ENV)
! 	/* Generate a fake FID for disconnected mode. */
! 	newFid.Cell = adp->fid.Cell;
! 	newFid.Fid.Volume = adp->fid.Fid.Volume;
! 	afs_GenFakeFid(&newFid, VREG);
! #endif
!     }				/* if (!AFS_IS_DISCON_RW) */
! 
      /* otherwise, we should see if we can make the change to the dir locally */
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 631);
!     if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	ObtainWriteLock(&afs_xdcache, 291);
  	code = afs_dir_Create(tdc, aname, &newFid.Fid);
***************
*** 436,447 ****
  		    osi_dnlc_purgedp(tvc);
  	    }
  	    ReleaseWriteLock(&afs_xcbhash);
! 	    afs_ProcessFS(tvc, &OutFidStatus, &treq);
  	    tvc->parentVnode = adp->fid.Fid.Vnode;
  	    tvc->parentUnique = adp->fid.Fid.Unique;
  	    ReleaseWriteLock(&tvc->lock);
  	    *avcp = tvc;
  	    code = 0;
  	} else
  	    code = ENOENT;
      } else {
--- 446,481 ----
  		    osi_dnlc_purgedp(tvc);
  	    }
  	    ReleaseWriteLock(&afs_xcbhash);
! 	    if (!AFS_IS_DISCON_RW)
! 	    	afs_ProcessFS(tvc, &OutFidStatus, &treq);
  	    tvc->parentVnode = adp->fid.Fid.Vnode;
  	    tvc->parentUnique = adp->fid.Fid.Unique;
  	    ReleaseWriteLock(&tvc->lock);
  	    *avcp = tvc;
  	    code = 0;
+ 
+ 	    if (AFS_IS_DISCON_RW) {
+ #if defined(AFS_DISCON_ENV)
+ 	    	/* After tvc has been created, we can do various ops on it. */
+ 		/* Add to dirty list. */
+ 		if (!tvc->ddirty_flags ||
+ 			(tvc->ddirty_flags == VDisconShadowed)) {
+ 	    	    /* Put it in the list only if it's fresh. */
+ 	    	    ObtainWriteLock(&afs_DDirtyVCListLock, 729);
+ 	    	    AFS_DISCON_ADD_DIRTY(tvc);
+ 	    	    ReleaseWriteLock(&afs_DDirtyVCListLock);
+ 		}
+ 
+ 		/* Set create flag. */
+ 		ObtainWriteLock(&tvc->lock, 730);
+ 		afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VREG);
+ 		tvc->ddirty_flags |= VDisconCreate;
+ 		ReleaseWriteLock(&tvc->lock);
+ 
+ #endif				/* #ifdef AFS_DISCON_ENV */
+     	    }			/* if (AFS_IS_DISCON_RW) */
+ 
+ 
  	} else
  	    code = ENOENT;
      } else {
Index: openafs/src/afs/VNOPS/afs_vnop_dirops.c
diff -c openafs/src/afs/VNOPS/afs_vnop_dirops.c:1.21.4.2 openafs/src/afs/VNOPS/afs_vnop_dirops.c:1.21.4.3
*** openafs/src/afs/VNOPS/afs_vnop_dirops.c:1.21.4.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_dirops.c	Mon Sep 22 15:29:55 2008
***************
*** 21,27 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_dirops.c,v 1.21.4.2 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 21,27 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_dirops.c,v 1.21.4.3 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 44,49 ****
--- 44,50 ----
      register struct conn *tc;
      struct VenusFid newFid;
      register struct dcache *tdc;
+     struct dcache *new_dc;
      afs_size_t offset, len;
      register struct vcache *tvc;
      struct AFSStoreStatus InStatus;
***************
*** 90,144 ****
  	goto done;
      }
     
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
  	/*printf("Network is down in afs_mkdir\n");*/
  	code = ENETDOWN;
-     }
- 
      InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
      InStatus.ClientModTime = osi_Time();
      InStatus.UnixModeBits = attrs->va_mode & 0xffff;	/* only care about protection bits */
      InStatus.Group = (afs_int32) acred->cr_gid;
      tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
      ObtainWriteLock(&adp->lock, 153);
!     do {
! 	tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	if (tc) {
! 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
! 	    now = osi_Time();
! 	    RX_AFS_GUNLOCK();
! 	    code =
! 		RXAFS_MakeDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
! 			      &InStatus, (struct AFSFid *)&newFid.Fid,
! 			      &OutFidStatus, &OutDirStatus, &CallBack,
! 			      &tsync);
! 	    RX_AFS_GLOCK();
! 	    XSTATS_END_TIME;
! 	    CallBack.ExpirationTime += now;
! 	    /* DON'T forget to Set the callback value... */
! 	} else
! 	    code = -1;
!     } while (afs_Analyze
! 	     (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_MAKEDIR,
! 	      SHARED_LOCK, NULL));
! 
!     if (code) {
! 	if (code < 0) {
! 	    ObtainWriteLock(&afs_xcbhash, 490);
! 	    afs_DequeueCallback(adp);
! 	    adp->states &= ~CStatd;
! 	    ReleaseWriteLock(&afs_xcbhash);
! 	    osi_dnlc_purgedp(adp);
! 	}
! 	ReleaseWriteLock(&adp->lock);
! 	if (tdc)
! 	    afs_PutDCache(tdc);
! 	goto done;
!     }
      /* otherwise, we should see if we can make the change to the dir locally */
      if (tdc)
  	ObtainWriteLock(&tdc->lock, 632);
!     if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	ObtainWriteLock(&afs_xdcache, 294);
  	code = afs_dir_Create(tdc, aname, &newFid.Fid);
--- 91,171 ----
  	goto done;
      }
     
!     if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW)
  	/*printf("Network is down in afs_mkdir\n");*/
  	code = ENETDOWN;
      InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
      InStatus.ClientModTime = osi_Time();
      InStatus.UnixModeBits = attrs->va_mode & 0xffff;	/* only care about protection bits */
      InStatus.Group = (afs_int32) acred->cr_gid;
      tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
      ObtainWriteLock(&adp->lock, 153);
! 
!     if (!AFS_IS_DISCON_RW) {
! 
!     	do {
! 	    tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
! 	    	now = osi_Time();
! 	    	RX_AFS_GUNLOCK();
! 	    	code =
! 		    RXAFS_MakeDir(tc->id,
! 		    		(struct AFSFid *)&adp->fid.Fid,
! 				aname,
! 				&InStatus,
! 				(struct AFSFid *)&newFid.Fid,
! 				&OutFidStatus,
! 				&OutDirStatus,
! 				&CallBack,
! 				&tsync);
! 	    	RX_AFS_GLOCK();
! 	    	XSTATS_END_TIME;
! 	    	CallBack.ExpirationTime += now;
! 	    	/* DON'T forget to Set the callback value... */
! 	    } else
! 	    	code = -1;
!     	} while (afs_Analyze
! 		    (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_MAKEDIR,
! 		     SHARED_LOCK, NULL));
! 
!     	if (code) {
! 	    if (code < 0) {
! 	    	ObtainWriteLock(&afs_xcbhash, 490);
! 	    	afs_DequeueCallback(adp);
! 	    	adp->states &= ~CStatd;
! 	    	ReleaseWriteLock(&afs_xcbhash);
! 	    	osi_dnlc_purgedp(adp);
! 	    }
! 	    ReleaseWriteLock(&adp->lock);
! 	    if (tdc)
! 	    	afs_PutDCache(tdc);
! 	    goto done;
!         }
! 
!     } else {
! #if defined(AFS_DISCON_ENV)
!     	/* Disconnected. */
! 
! 	/* We have the dir entry now, we can use it while disconnected. */
! 	if (adp->mvid == NULL) {
! 	    /* If not mount point, generate a new fid. */
! 	    newFid.Cell = adp->fid.Cell;
!     	    newFid.Fid.Volume = adp->fid.Fid.Volume;
! 	    afs_GenFakeFid(&newFid, VDIR);
! 	}
!     	/* XXX: If mount point???*/
! 
! 	/* Operations with the actual dir's cache entry are further
! 	 * down, where the dir entry gets created.
! 	 */
! #endif
!     }			/* if (!AFS_IS_DISCON_RW) */
! 
      /* otherwise, we should see if we can make the change to the dir locally */
      if (tdc)
  	ObtainWriteLock(&tdc->lock, 632);
!     if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	ObtainWriteLock(&afs_xdcache, 294);
  	code = afs_dir_Create(tdc, aname, &newFid.Fid);
***************
*** 152,168 ****
  	ReleaseWriteLock(&tdc->lock);
  	afs_PutDCache(tdc);
      }
!     adp->m.LinkCount = OutDirStatus.LinkCount;
      newFid.Cell = adp->fid.Cell;
      newFid.Fid.Volume = adp->fid.Fid.Volume;
      ReleaseWriteLock(&adp->lock);
!     /* now we're done with parent dir, create the real dir's cache entry */
!     tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
!     if (tvc) {
! 	code = 0;
! 	*avcp = tvc;
!     } else
! 	code = ENOENT;
    done:
      AFS_DISCON_UNLOCK();
    done3:
--- 179,255 ----
  	ReleaseWriteLock(&tdc->lock);
  	afs_PutDCache(tdc);
      }
! 
!     if (AFS_IS_DISCON_RW)
! 	/* We will have to settle with the local link count. */
! 	adp->m.LinkCount++;
!     else
! 	adp->m.LinkCount = OutDirStatus.LinkCount;
      newFid.Cell = adp->fid.Cell;
      newFid.Fid.Volume = adp->fid.Fid.Volume;
      ReleaseWriteLock(&adp->lock);
!     if (AFS_IS_DISCON_RW) {
! #if defined(AFS_DISCON_ENV)
!     	/* When disconnected, we have to create the full dir here. */
! 
! 	/* Generate a new vcache and fill it. */
! 	tvc = afs_NewVCache(&newFid, NULL);
! 	if (tvc) {
! 	    code = 0;
! 	    *avcp = tvc;
! 	} else {
! 	    code = ENOENT;
! 	    goto done;
! 	}
! 
! 	ObtainWriteLock(&tvc->lock, 738);
! 	afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VDIR);
! 	ReleaseWriteLock(&tvc->lock);
! 
! 	/* And now make an empty dir, containing . and .. : */
! 	/* Get a new dcache for it first. */
! 	new_dc = afs_GetDCache(tvc, (afs_size_t) 0, &treq, &offset, &len, 1);
! 	if (!new_dc) {
! 	    printf("afs_mkdir: can't get new dcache for dir.\n");
! 	    code = ENOENT;
! 	    goto done;
! 	}
! 
! 	ObtainWriteLock(&afs_xdcache, 739);
! 	code = afs_dir_MakeDir(new_dc,
! 				(afs_int32 *) &newFid.Fid,
! 				(afs_int32) &adp->fid.Fid);
! 	ReleaseWriteLock(&afs_xdcache);
! 	if (code)
! 	    printf("afs_mkdir: afs_dirMakeDir code = %u\n", code);
! 
! 	/* Add to dirty list. */
! 	if (!tvc->ddirty_flags ||
! 		(tvc->ddirty_flags == VDisconShadowed)) {
! 
! 	    /* Put it in the list only if it's fresh. */
! 	    ObtainWriteLock(&afs_DDirtyVCListLock, 730);
! 	    AFS_DISCON_ADD_DIRTY(tvc);
! 	    ReleaseWriteLock(&afs_DDirtyVCListLock);
! 	}
! 
! 	ObtainWriteLock(&tvc->lock, 731);
! 	/* Update length in the vcache. */
! 	tvc->m.Length = new_dc->f.chunkBytes;
! 	/* Set create flag. */
! 	tvc->ddirty_flags |= VDisconCreate;
! 	ReleaseWriteLock(&tvc->lock);
! #endif				/* #ifdef AFS_DISCON_ENV */
!     } else {
!     	/* now we're done with parent dir, create the real dir's cache entry */
!     	tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
!     	if (tvc) {
! 	    code = 0;
! 	    *avcp = tvc;
!     	} else
! 	    code = ENOENT;
!     }				/* if (AFS_DISCON_RW) */
! 
    done:
      AFS_DISCON_UNLOCK();
    done3:
***************
*** 226,236 ****
  	goto done;
      }
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
          code = ENETDOWN;
          goto done;
      }
!     
      tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);	/* test for error below */
      ObtainWriteLock(&adp->lock, 154);
      if (tdc)
--- 313,324 ----
  	goto done;
      }
  
!    if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
!     	/* Disconnected read only mode. */
          code = ENETDOWN;
          goto done;
      }
! 
      tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);	/* test for error below */
      ObtainWriteLock(&adp->lock, 154);
      if (tdc)
***************
*** 256,297 ****
  	}
      }
  
!     do {
! 	tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	if (tc) {
! 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
! 	    RX_AFS_GUNLOCK();
! 	    code =
! 		RXAFS_RemoveDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
! 				&OutDirStatus, &tsync);
! 	    RX_AFS_GLOCK();
! 	    XSTATS_END_TIME;
! 	} else
! 	    code = -1;
!     } while (afs_Analyze
! 	     (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_REMOVEDIR,
! 	      SHARED_LOCK, NULL));
  
!     if (code) {
! 	if (tdc) {
  	    ReleaseSharedLock(&tdc->lock);
! 	    afs_PutDCache(tdc);
  	}
! 	if (code < 0) {
! 	    ObtainWriteLock(&afs_xcbhash, 491);
! 	    afs_DequeueCallback(adp);
! 	    adp->states &= ~CStatd;
! 	    ReleaseWriteLock(&afs_xcbhash);
! 	    osi_dnlc_purgedp(adp);
  	}
! 	ReleaseWriteLock(&adp->lock);
! 	goto done;
!     }
!     /* here if rpc worked; update the in-core link count */
!     adp->m.LinkCount = OutDirStatus.LinkCount;
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 634);
!     if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	code = afs_dir_Delete(tdc, aname);
  	if (code) {
--- 344,460 ----
  	}
      }
  
!     if (!AFS_IS_DISCON_RW) {
! 	/* Not disconnected, can connect to server. */
!     	do {
! 	    tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
! 	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
! 	    	RX_AFS_GUNLOCK();
! 	    	code =
! 		    RXAFS_RemoveDir(tc->id,
! 		    		(struct AFSFid *)&adp->fid.Fid,
! 				aname,
! 				&OutDirStatus,
! 				&tsync);
! 	    	RX_AFS_GLOCK();
! 	    	XSTATS_END_TIME;
! 	    } else
! 	    	code = -1;
!     	} while (afs_Analyze
! 	         (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_REMOVEDIR,
! 	         SHARED_LOCK, NULL));
! 
!     	if (code) {
! 	    if (tdc) {
! 	    	ReleaseSharedLock(&tdc->lock);
! 	    	afs_PutDCache(tdc);
! 	    }
  
! 	    if (code < 0) {
! 	    	ObtainWriteLock(&afs_xcbhash, 491);
! 	    	afs_DequeueCallback(adp);
! 	    	adp->states &= ~CStatd;
! 	    	ReleaseWriteLock(&afs_xcbhash);
! 	    	osi_dnlc_purgedp(adp);
! 	    }
! 	    ReleaseWriteLock(&adp->lock);
! 	    goto done;
!     	}
! 
!     	/* here if rpc worked; update the in-core link count */
!     	adp->m.LinkCount = OutDirStatus.LinkCount;
! 
!     } else {
! #if defined(AFS_DISCON_ENV)
!     	/* Disconnected. */
! 
! 	if (!tvc) {
! 	    /* Find the vcache. */
! 	    struct VenusFid tfid;
! 
! 	    tfid.Cell = adp->fid.Cell;
! 	    tfid.Fid.Volume = adp->fid.Fid.Volume;
! 	    code = afs_dir_Lookup(tdc, aname, &tfid.Fid);
! 
! 	    ObtainSharedLock(&afs_xvcache, 764);
! 	    tvc = afs_FindVCache(&tfid, 0, 1 /* do xstats */ );
! 	    ReleaseSharedLock(&afs_xvcache);
! 
! 	    if (!tvc) {
! 		printf("afs_rmdir: Can't find dir's vcache!\n");
! 		ReleaseSharedLock(&tdc->lock);
! 		afs_PutDCache(tdc);	/* drop ref count */
!     		ReleaseWriteLock(&adp->lock);
! 	    	goto done;
! 	    }
! 	}
! 
! 	if (tvc->m.LinkCount > 2) {
! 	    /* This dir contains more than . and .., thus it can't be
! 	     * deleted.
! 	     */
  	    ReleaseSharedLock(&tdc->lock);
! 	    code = ENOTEMPTY;
! 	    goto done;
  	}
! 
!     	/* Make a shadow copy of the parent dir (if not done already).
! 	 * There's no need to make a shadow copy of the deleted directory
! 	 * because a dir must be empty in order to be rmdir'ed.
! 	 * If the deleted dir has no shadow, it means that it was empty.
! 	 */
! 	if (!(adp->ddirty_flags & VDisconShadowed)) {
! 	    /* If tdc available, then it is locked.
! 	     * afs_MakeShadowDir unlocks it.
! 	     */
! 	    if (tdc)
! 	    	ReleaseSharedLock(&tdc->lock);
! 	    afs_MakeShadowDir(adp);
! 	    if (tdc)
! 	    	ObtainSharedLock(&tdc->lock, 732);
  	}
! 
! 	if (!tvc->ddirty_flags ||
! 		(tvc->ddirty_flags == VDisconShadowed)) {
! 	    /* Put it in the list only if it's fresh or has only been shadowed. */
! 	    ObtainWriteLock(&afs_DDirtyVCListLock, 728);
! 	    AFS_DISCON_ADD_DIRTY(tvc);
! 	    ReleaseWriteLock(&afs_DDirtyVCListLock);
! 	}
! 
! 	/* Now add the vcache to the dirty list. */
! 	ObtainWriteLock(&tvc->lock, 727);
! 	tvc->ddirty_flags |= VDisconRemove;
! 	ReleaseWriteLock(&tvc->lock);
! 
! 	adp->m.LinkCount--;
! #endif				/* #ifdef AFS_DISCON_ENV */
!     }				/* if (!AFS_IS_DISCON_RW) */
! 
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 634);
!     if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	code = afs_dir_Delete(tdc, aname);
  	if (code) {
***************
*** 314,320 ****
  	ObtainWriteLock(&tvc->lock, 155);
  	tvc->states &= ~CUnique;	/* For the dfs xlator */
  	ReleaseWriteLock(&tvc->lock);
! 	afs_PutVCache(tvc);
      }
      ReleaseWriteLock(&adp->lock);
      /* don't worry about link count since dirs can not be hardlinked */
--- 477,485 ----
  	ObtainWriteLock(&tvc->lock, 155);
  	tvc->states &= ~CUnique;	/* For the dfs xlator */
  	ReleaseWriteLock(&tvc->lock);
! 	/* If disconnected, keep this vcache around for resync. */
! 	if (!AFS_IS_DISCON_RW)
! 	    afs_PutVCache(tvc);
      }
      ReleaseWriteLock(&adp->lock);
      /* don't worry about link count since dirs can not be hardlinked */
Index: openafs/src/afs/VNOPS/afs_vnop_lookup.c
diff -c openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.72.2.7 openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.72.2.9
*** openafs/src/afs/VNOPS/afs_vnop_lookup.c:1.72.2.7	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_lookup.c	Mon Sep 22 15:29:55 2008
***************
*** 18,24 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_lookup.c,v 1.72.2.7 2008/05/23 14:25:16 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.72.2.9 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 1232,1239 ****
      afs_InitFakeStat(&fakestate);
  
      AFS_DISCON_LOCK();
- 
-     /*printf("Looking up %s\n", aname);*/
      
      if ((code = afs_InitReq(&treq, acred)))
  	goto done;
--- 1232,1237 ----
***************
*** 1431,1437 ****
--- 1429,1437 ----
      if (tvc) {
  	if (no_read_access && vType(tvc) != VDIR && vType(tvc) != VLNK) {
  	    /* need read access on dir to stat non-directory / non-link */
+ #ifndef AFS_FBSD80_ENV
  	    afs_PutVCache(tvc);
+ #endif
  	    *avcp = NULL;
  	    code = EACCES;
  	    goto done;
***************
*** 1588,1594 ****
  
  	    /* if the vcache isn't usable, release it */
  	    if (tvc && !(tvc->states & CStatd)) {
! 		afs_PutVCache(tvc);
  		tvc = NULL;
  	    }
  	} else {
--- 1588,1596 ----
  
  	    /* if the vcache isn't usable, release it */
  	    if (tvc && !(tvc->states & CStatd)) {
! #ifndef  AFS_FBSD80_ENV
! 	      afs_PutVCache(tvc);
! #endif
  		tvc = NULL;
  	    }
  	} else {
***************
*** 1651,1657 ****
--- 1653,1661 ----
  		ReleaseWriteLock(&tvc->lock);
  
  		if (code) {
+ #ifndef AFS_FBSD80_ENV
  		    afs_PutVCache(tvc);
+ #endif
  		    if (tvolp)
  			afs_PutVolume(tvolp, WRITE_LOCK);
  		    goto done;
***************
*** 1673,1679 ****
--- 1677,1685 ----
  		    } else {
  			tvc = afs_GetVCache(tvc->mvid, &treq, NULL, NULL);
  		    }
+ #ifndef AFS_FBSD80_ENV
  		    afs_PutVCache(uvc);	/* we're done with it */
+ #endif
  
  		    if (!tvc) {
  			code = ENOENT;
***************
*** 1698,1704 ****
--- 1704,1712 ----
  			afs_PutVolume(tvolp, WRITE_LOCK);
  		    }
  		} else {
+ #ifndef AFS_FBSD80_ENV
  		    afs_PutVCache(tvc);
+ #endif
  		    code = ENOENT;
  		    if (tvolp)
  			afs_PutVolume(tvolp, WRITE_LOCK);
***************
*** 1736,1742 ****
  	    }
  	    code = ENOENT;
  	} else {
! 	    /*printf("Network down in afs_lookup\n");*/
  	    code = ENETDOWN;
  	}
      }
--- 1744,1750 ----
  	    }
  	    code = ENOENT;
  	} else {
! 	    printf("Network down in afs_lookup\n");
  	    code = ENETDOWN;
  	}
      }
Index: openafs/src/afs/VNOPS/afs_vnop_open.c
diff -c openafs/src/afs/VNOPS/afs_vnop_open.c:1.11.6.2 openafs/src/afs/VNOPS/afs_vnop_open.c:1.11.6.3
*** openafs/src/afs/VNOPS/afs_vnop_open.c:1.11.6.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_open.c	Mon Sep 22 15:29:55 2008
***************
*** 18,24 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_open.c,v 1.11.6.2 2008/05/23 14:25:16 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_open.c,v 1.11.6.3 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 74,80 ****
  #ifdef AFS_DISCON_ENV
      if (AFS_IS_DISCONNECTED && (afs_DCacheMissingChunks(tvc) != 0)) {
         ReleaseReadLock(&tvc->lock);
!        /*printf("Network is down in afs_open: missing chunks\n");*/
         code = ENETDOWN;
         goto done;
      }
--- 74,80 ----
  #ifdef AFS_DISCON_ENV
      if (AFS_IS_DISCONNECTED && (afs_DCacheMissingChunks(tvc) != 0)) {
         ReleaseReadLock(&tvc->lock);
!        printf("Network is down in afs_open: missing chunks\n");
         code = ENETDOWN;
         goto done;
      }
***************
*** 96,101 ****
--- 96,102 ----
  		(tvc, ((tvc->states & CForeign) ? PRSFS_READ : PRSFS_LOOKUP),
  		 &treq, CHECK_MODE_BITS)) {
  		code = EACCES;
+ 		printf("afs_Open: no access for dir\n");
  		goto done;
  	    }
  	}
Index: openafs/src/afs/VNOPS/afs_vnop_read.c
diff -c openafs/src/afs/VNOPS/afs_vnop_read.c:1.34.2.4 openafs/src/afs/VNOPS/afs_vnop_read.c:1.34.2.6
*** openafs/src/afs/VNOPS/afs_vnop_read.c:1.34.2.4	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_read.c	Mon Sep 22 15:29:55 2008
***************
*** 19,25 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_read.c,v 1.34.2.4 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 19,25 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_read.c,v 1.34.2.6 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 636,642 ****
  	    tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
  #ifdef AFS_DISCON_ENV
  	    if (!tdc) {
! 		/*printf("Network down in afs_read");*/
  	        error = ENETDOWN;
  	        break;
  	    }
--- 636,642 ----
  	    tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
  #ifdef AFS_DISCON_ENV
  	    if (!tdc) {
! 		printf("Network down in afs_read");
  	        error = ENETDOWN;
  	        break;
  	    }
***************
*** 903,908 ****
--- 903,914 ----
  	    code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
  	    VOP_UNLOCK(tfile->vnode, 0, current_proc());
  	    AFS_GLOCK();
+ #elif defined(AFS_FBSD80_ENV)
+ 	    AFS_GUNLOCK();
+ 	    VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
+ 	    code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
+ 	    VOP_UNLOCK(tfile->vnode, 0);
+ 	    AFS_GLOCK();
  #elif defined(AFS_FBSD50_ENV)
  	    AFS_GUNLOCK();
  	    VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
Index: openafs/src/afs/VNOPS/afs_vnop_remove.c
diff -c openafs/src/afs/VNOPS/afs_vnop_remove.c:1.52.2.5 openafs/src/afs/VNOPS/afs_vnop_remove.c:1.52.2.6
*** openafs/src/afs/VNOPS/afs_vnop_remove.c:1.52.2.5	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_remove.c	Mon Sep 22 15:29:55 2008
***************
*** 21,27 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_remove.c,v 1.52.2.5 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 21,27 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_remove.c,v 1.52.2.6 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 109,115 ****
      struct AFSFetchStatus OutDirStatus;
      struct AFSVolSync tsync;
      XSTATS_DECLS;
-     
      if (!AFS_IS_DISCONNECTED) {
          do {
  	    tc = afs_Conn(&adp->fid, treqp, SHARED_LOCK);
--- 109,114 ----
***************
*** 135,140 ****
--- 134,140 ----
  	    ReleaseSharedLock(&tdc->lock);
  	    afs_PutDCache(tdc);
  	}
+ 
  	if (tvc)
  	    afs_PutVCache(tvc);
  
***************
*** 151,157 ****
      }
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 637);
!     if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	code = afs_dir_Delete(tdc, aname);
  	if (code) {
--- 151,157 ----
      }
      if (tdc)
  	UpgradeSToWLock(&tdc->lock, 637);
!     if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
  	/* we can do it locally */
  	code = afs_dir_Delete(tdc, aname);
  	if (code) {
***************
*** 187,193 ****
  #ifdef AFS_BOZONLOCK_ENV
  	afs_BozonUnlock(&tvc->pvnLock, tvc);
  #endif
! 	afs_PutVCache(tvc);
      }
      return (0);
  }
--- 187,197 ----
  #ifdef AFS_BOZONLOCK_ENV
  	afs_BozonUnlock(&tvc->pvnLock, tvc);
  #endif
! 	/* Don't decrease refcount for this vcache if disconnected, we will
! 	 * need it during replay.
! 	 */
! 	if (!AFS_IS_DISCON_RW)
! 	    afs_PutVCache(tvc);
      }
      return (0);
  }
***************
*** 308,314 ****
      }
  
      /* If we're running disconnected without logging, go no further... */
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
  #ifdef  AFS_OSF_ENV
          afs_PutVCache(tvc);
  #endif
--- 312,318 ----
      }
  
      /* If we're running disconnected without logging, go no further... */
!     if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
  #ifdef  AFS_OSF_ENV
          afs_PutVCache(tvc);
  #endif
***************
*** 319,324 ****
--- 323,333 ----
      
      tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);	/* test for error below */
      ObtainWriteLock(&adp->lock, 142);
+ #if defined(AFS_DISCON_ENV)
+     if (AFS_IS_DISCON_RW && !(adp->ddirty_flags & VDisconShadowed))
+ 	/* Make shadow copy of parent dir. */
+     	afs_MakeShadowDir(adp);
+ #endif
      if (tdc)
  	ObtainSharedLock(&tdc->lock, 638);
  
***************
*** 341,347 ****
  	tvc = osi_dnlc_lookup(adp, aname, WRITE_LOCK);
      }
      /* This should not be necessary since afs_lookup() has already
!      * done the work */
      if (!tvc)
  	if (tdc) {
  	    code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
--- 350,357 ----
  	tvc = osi_dnlc_lookup(adp, aname, WRITE_LOCK);
      }
      /* This should not be necessary since afs_lookup() has already
!      * done the work.
!      */
      if (!tvc)
  	if (tdc) {
  	    code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
***************
*** 362,367 ****
--- 372,399 ----
  	    }
  	}
  
+ #if defined(AFS_DISCON_ENV)
+     if (AFS_IS_DISCON_RW) {
+ 	/* Add removed file vcache to dirty list. */
+ 
+ 	if (!tvc->ddirty_flags ||
+ 		(tvc->ddirty_flags == VDisconShadowed)) {
+ 	    /* Add to list only if fresh. */
+ 	    ObtainWriteLock(&afs_DDirtyVCListLock, 725);
+ 	    AFS_DISCON_ADD_DIRTY(tvc);
+ 	    ReleaseWriteLock(&afs_DDirtyVCListLock);
+ 	}
+ 
+ 	ObtainWriteLock(&tvc->lock, 726);
+ 	tvc->ddirty_flags |= VDisconRemove;
+ 	ReleaseWriteLock(&tvc->lock);
+ 
+ 	//ObtainWriteLock(&adp->lock, 751);
+ 	adp->m.LinkCount--;
+ 	//ReleaseWriteLock(&adp->lock);
+     }
+ #endif
+ 
      if (tvc && osi_Active(tvc)) {
  	/* about to delete whole file, prefetch it first */
  	ReleaseWriteLock(&adp->lock);
***************
*** 426,432 ****
  	}
  	if (tdc)
  	    afs_PutDCache(tdc);
! 	afs_PutVCache(tvc);
      } else {
  	code = afsremove(adp, tdc, tvc, aname, acred, &treq);
      }
--- 458,468 ----
  	}
  	if (tdc)
  	    afs_PutDCache(tdc);
! 	/* Don't decrease refcount for this vcache if disconnected, we will
! 	 * need it during replay.
! 	 */
! 	if (!AFS_IS_DISCON_RW)
! 	    afs_PutVCache(tvc);
      } else {
  	code = afsremove(adp, tdc, tvc, aname, acred, &treq);
      }
Index: openafs/src/afs/VNOPS/afs_vnop_rename.c
diff -c openafs/src/afs/VNOPS/afs_vnop_rename.c:1.28.4.2 openafs/src/afs/VNOPS/afs_vnop_rename.c:1.28.4.3
*** openafs/src/afs/VNOPS/afs_vnop_rename.c:1.28.4.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_rename.c	Mon Sep 22 15:29:55 2008
***************
*** 18,24 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_rename.c,v 1.28.4.2 2008/05/23 14:25:16 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_rename.c,v 1.28.4.3 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 37,43 ****
  	  char *aname2, struct AFS_UCRED *acred, struct vrequest *areq)
  {
      register struct conn *tc;
!     register afs_int32 code;
      afs_int32 returnCode;
      int oneDir, doLocally;
      afs_size_t offset, len;
--- 37,43 ----
  	  char *aname2, struct AFS_UCRED *acred, struct vrequest *areq)
  {
      register struct conn *tc;
!     register afs_int32 code = 0;
      afs_int32 returnCode;
      int oneDir, doLocally;
      afs_size_t offset, len;
***************
*** 83,89 ****
  	    goto done;
  	}
  	
! 	if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
  	    code = ENETDOWN;
  	    goto done;
  	}
--- 83,89 ----
  	    goto done;
  	}
  	
! 	if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
  	    code = ENETDOWN;
  	    goto done;
  	}
***************
*** 167,190 ****
  	goto done;
      }
  
!     do {
! 	tc = afs_Conn(&aodp->fid, areq, SHARED_LOCK);
! 	if (tc) {
! 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
! 	    RX_AFS_GUNLOCK();
! 	    code =
! 		RXAFS_Rename(tc->id, (struct AFSFid *)&aodp->fid.Fid, aname1,
! 			     (struct AFSFid *)&andp->fid.Fid, aname2,
! 			     &OutOldDirStatus, &OutNewDirStatus, &tsync);
! 	    RX_AFS_GLOCK();
! 	    XSTATS_END_TIME;
! 	} else
! 	    code = -1;
  
!     } while (afs_Analyze
  	     (tc, code, &andp->fid, areq, AFS_STATS_FS_RPCIDX_RENAME,
  	      SHARED_LOCK, NULL));
  
      returnCode = code;		/* remember for later */
  
      /* Now we try to do things locally.  This is really loathsome code. */
--- 167,256 ----
  	goto done;
      }
  
!     if (!AFS_IS_DISCON_RW) {
!     	/* Connected. */
! 	do {
! 	    tc = afs_Conn(&aodp->fid, areq, SHARED_LOCK);
! 	    if (tc) {
! 	    	XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
! 	    	RX_AFS_GUNLOCK();
! 	    	code =
! 		    RXAFS_Rename(tc->id,
! 		    			(struct AFSFid *)&aodp->fid.Fid,
! 					aname1,
! 					(struct AFSFid *)&andp->fid.Fid,
! 					aname2,
! 					&OutOldDirStatus,
! 					&OutNewDirStatus,
! 					&tsync);
! 	        RX_AFS_GLOCK();
! 	        XSTATS_END_TIME;
! 	    } else
! 	    	code = -1;
  
! 	} while (afs_Analyze
  	     (tc, code, &andp->fid, areq, AFS_STATS_FS_RPCIDX_RENAME,
  	      SHARED_LOCK, NULL));
  
+     } else {
+ #if defined(AFS_DISCON_ENV)
+ 	/* Disconnected. */
+ 
+ 	/* Seek moved file vcache. */
+ 	fileFid.Cell = aodp->fid.Cell;
+ 	fileFid.Fid.Volume = aodp->fid.Fid.Volume;
+ 	ObtainSharedLock(&afs_xvcache, 754);
+ 	tvc = afs_FindVCache(&fileFid, 0 , 1);
+ 	ReleaseSharedLock(&afs_xvcache);
+ 
+ 	if (tvc) {
+ 	    if (!(tvc->ddirty_flags & VDisconRename)) {
+ 		/* We only care about vnodes that haven't been
+ 		 * renamed. Those that have been renamed at least once
+ 		 * already have an asociated shadow dir and the flags set
+ 		 * for the first old location, which is what interests us
+ 		 * when reconnecting.
+ 		 */
+ 
+ 	    	if (!(aodp->ddirty_flags & VDisconShadowed) &&
+ 			!(tvc->ddirty_flags & VDisconCreate)) {
+ 	    	    /*
+ 		     * Make shadow copy of parent dir only.
+ 		     * Files that are created locally and renamed,
+ 		     * don't need a shadow dir, so skip this step.
+ 		     */
+ 		    if (tdc1)
+ 	    	    	ReleaseWriteLock(&tdc1->lock);
+     	    	    afs_MakeShadowDir(aodp);
+ 	    	    if (tdc1)
+ 	    	    	ObtainWriteLock(&tdc1->lock, 753);
+ 	        }
+ 
+ 		if (!tvc->ddirty_flags ||
+ 			(tvc->ddirty_flags == VDisconShadowed)) {
+ 	    	    /* Add in dirty list.*/
+ 	 	    ObtainWriteLock(&afs_DDirtyVCListLock, 751);
+ 	    	    AFS_DISCON_ADD_DIRTY(tvc);
+ 	    	    ReleaseWriteLock(&afs_DDirtyVCListLock);
+ 		}
+ 
+ 	    	ObtainWriteLock(&tvc->lock, 750);
+ 	    	/* Save old parent dir fid so it will be searchable
+ 	     	 * in the shadow dir.
+ 	     	 */
+     	    	tvc->oldVnode = aodp->fid.Fid.Vnode;
+ 	    	tvc->oldUnique = aodp->fid.Fid.Unique;
+ 	    	/* Set discon state flag. */
+ 	    	tvc->ddirty_flags |= VDisconRename;
+ 	    	if (oneDir)
+ 		    tvc->ddirty_flags |= VDisconRenameSameDir;
+ 	    	ReleaseWriteLock(&tvc->lock);
+ 	    }			/* if not previously renamed */
+ 	} else {
+ 	    code = ENOENT;
+ 	}			/* if (tvc) */
+ #endif
+     }				/* if !(AFS_IS_DISCON_RW)*/
      returnCode = code;		/* remember for later */
  
      /* Now we try to do things locally.  This is really loathsome code. */
***************
*** 194,221 ****
  	 * in the cache; if it isn't, we won't do the update locally.  */
  	/* see if version numbers increased properly */
  	doLocally = 1;
! 	if (oneDir) {
! 	    /* number increases by 1 for whole rename operation */
! 	    if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1)) {
! 		doLocally = 0;
! 	    }
! 	} else {
! 	    /* two separate dirs, each increasing by 1 */
! 	    if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1))
! 		doLocally = 0;
! 	    if (!afs_LocalHero(andp, tdc2, &OutNewDirStatus, 1))
! 		doLocally = 0;
! 	    if (!doLocally) {
! 		if (tdc1) {
! 		    ZapDCE(tdc1);
! 		    DZap(tdc1);
! 		}
! 		if (tdc2) {
! 		    ZapDCE(tdc2);
! 		    DZap(tdc2);
! 		}
  	    }
! 	}
  	/* now really do the work */
  	if (doLocally) {
  	    /* first lookup the fid of the dude we're moving */
--- 260,290 ----
  	 * in the cache; if it isn't, we won't do the update locally.  */
  	/* see if version numbers increased properly */
  	doLocally = 1;
! 	if (!AFS_IS_DISCON_RW) {
! 	    if (oneDir) {
! 	    	/* number increases by 1 for whole rename operation */
! 	    	if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1)) {
! 		    doLocally = 0;
! 	    	}
! 	    } else {
! 	    	/* two separate dirs, each increasing by 1 */
! 	    	if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1))
! 		    doLocally = 0;
! 	    	if (!afs_LocalHero(andp, tdc2, &OutNewDirStatus, 1))
! 		    doLocally = 0;
! 	    	if (!doLocally) {
! 		    if (tdc1) {
! 		    	ZapDCE(tdc1);
! 		    	DZap(tdc1);
! 		    }
! 		    if (tdc2) {
! 		    	ZapDCE(tdc2);
! 		    	DZap(tdc2);
! 		    }
! 	        }
  	    }
! 	}			/* if (!AFS_IS_DISCON_RW) */
! 
  	/* now really do the work */
  	if (doLocally) {
  	    /* first lookup the fid of the dude we're moving */
***************
*** 247,255 ****
  	}
  
  	/* update dir link counts */
! 	aodp->m.LinkCount = OutOldDirStatus.LinkCount;
  	if (!oneDir)
! 	    andp->m.LinkCount = OutNewDirStatus.LinkCount;
  
      } else {			/* operation failed (code != 0) */
  	if (code < 0) {
--- 316,326 ----
  	}
  
  	/* update dir link counts */
! 	aodp->m.LinkCount = AFS_IS_DISCON_RW ?
! 			(aodp->m.LinkCount - 1):OutOldDirStatus.LinkCount;
  	if (!oneDir)
! 	    andp->m.LinkCount = AFS_IS_DISCON_RW ?
! 	    		(andp->m.LinkCount + 1):OutNewDirStatus.LinkCount;
  
      } else {			/* operation failed (code != 0) */
  	if (code < 0) {
***************
*** 280,286 ****
      ReleaseWriteLock(&aodp->lock);
      if (!oneDir)
  	ReleaseWriteLock(&andp->lock);
- 
      if (returnCode) {
  	code = returnCode;
  	goto done;
--- 351,356 ----
***************
*** 294,299 ****
--- 364,370 ----
       * the data as having an "unknown" version (effectively discarding the ".."
       * entry */
      if (unlinkFid.Fid.Vnode) {
+ 
  	unlinkFid.Fid.Volume = aodp->fid.Fid.Volume;
  	unlinkFid.Cell = aodp->fid.Cell;
  	tvc = NULL;
***************
*** 342,356 ****
  	    ObtainWriteLock(&tvc->lock, 152);
  	    tdc1 = afs_FindDCache(tvc, (afs_size_t) 0);
  	    if (tdc1) {
! 		ObtainWriteLock(&tdc1->lock, 648);
! 		ZapDCE(tdc1);	/* mark as unknown */
! 		DZap(tdc1);
! 		ReleaseWriteLock(&tdc1->lock);
! 		afs_PutDCache(tdc1);	/* put it back */
  	    }
  	    osi_dnlc_remove(tvc, "..", 0);
  	    ReleaseWriteLock(&tvc->lock);
  	    afs_PutVCache(tvc);
  	} else if (tvc) {
  	    /* True we shouldn't come here since tvc SHOULD be a dir, but we
  	     * 'syntactically' need to unless  we change the 'if' above...
--- 413,440 ----
  	    ObtainWriteLock(&tvc->lock, 152);
  	    tdc1 = afs_FindDCache(tvc, (afs_size_t) 0);
  	    if (tdc1) {
! 		if (AFS_IS_DISCON_RW) {
! #if defined(AFS_DISCON_ENV)
! 		    /* If disconnected, we need to fix (not discard) the "..".*/
! 		    afs_dir_ChangeFid(tdc1,
! 		    	"..",
! 		    	&aodp->fid.Fid.Vnode,
! 			&andp->fid.Fid.Vnode);
! #endif
! 		} else {
! 		    ObtainWriteLock(&tdc1->lock, 648);
! 		    ZapDCE(tdc1);	/* mark as unknown */
! 		    DZap(tdc1);
! 		    ReleaseWriteLock(&tdc1->lock);
! 		    afs_PutDCache(tdc1);	/* put it back */
! 		}
  	    }
  	    osi_dnlc_remove(tvc, "..", 0);
  	    ReleaseWriteLock(&tvc->lock);
  	    afs_PutVCache(tvc);
+ 	} else if (AFS_IS_DISCON_RW && tvc && (vType(tvc) == VREG)) {
+ 	    tvc->parentVnode = andp->fid.Fid.Vnode;
+ 	    tvc->parentUnique = andp->fid.Fid.Unique;
  	} else if (tvc) {
  	    /* True we shouldn't come here since tvc SHOULD be a dir, but we
  	     * 'syntactically' need to unless  we change the 'if' above...
Index: openafs/src/afs/VNOPS/afs_vnop_write.c
diff -c openafs/src/afs/VNOPS/afs_vnop_write.c:1.50.2.2 openafs/src/afs/VNOPS/afs_vnop_write.c:1.50.2.4
*** openafs/src/afs/VNOPS/afs_vnop_write.c:1.50.2.2	Fri May 23 10:25:16 2008
--- openafs/src/afs/VNOPS/afs_vnop_write.c	Mon Sep 22 15:29:55 2008
***************
*** 21,27 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_write.c,v 1.50.2.2 2008/05/23 14:25:16 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
--- 21,27 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_write.c,v 1.50.2.4 2008/09/22 19:29:55 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 64,87 ****
  	crfree((struct AFS_UCRED *)avc->linkData);	/* "crheld" in afs_FakeClose */
  	avc->linkData = NULL;
      }
!     /* Now, send the file back.  Used to require 0 writers left, but now do
!      * it on every close for write, since two closes in a row are harmless
!      * since first will clean all chunks, and second will be noop.  Note that
!      * this will also save confusion when someone keeps a file open 
!      * inadvertently, since with old system, writes to the server would never
!      * happen again. 
!      */
!     code = afs_StoreAllSegments(avc, treq, AFS_LASTSTORE /*!sync-to-disk */ );
!     /*
!      * We have to do these after the above store in done: in some systems like
!      * aix they'll need to flush all the vm dirty pages to the disk via the
!      * strategy routine. During that all procedure (done under no avc locks)
!      * opens, refcounts would be zero, since it didn't reach the afs_{rd,wr}
!      * routines which means the vcache is a perfect candidate for flushing!
!      */
  #if defined(AFS_SGI_ENV)
      osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
  #endif
      avc->opens--;
      avc->execsOrWriters--;
      return code;
--- 64,109 ----
  	crfree((struct AFS_UCRED *)avc->linkData);	/* "crheld" in afs_FakeClose */
  	avc->linkData = NULL;
      }
! 
!     if (!AFS_IS_DISCONNECTED) {
! 	/* Connected. */
! 
! 	/* Now, send the file back.  Used to require 0 writers left, but now do
! 	 * it on every close for write, since two closes in a row are harmless
! 	 * since first will clean all chunks, and second will be noop.  Note that
! 	 * this will also save confusion when someone keeps a file open
! 	 * inadvertently, since with old system, writes to the server would never
! 	 * happen again.
! 	 */
! 	code = afs_StoreAllSegments(avc, treq, AFS_LASTSTORE /*!sync-to-disk */ );
! 	/*
! 	 * We have to do these after the above store in done: in some systems
! 	 * like aix they'll need to flush all the vm dirty pages to the disk via
! 	 * the strategy routine. During that all procedure (done under no avc
! 	 * locks) opens, refcounts would be zero, since it didn't reach the
! 	 * afs_{rd,wr} routines which means the vcache is a perfect candidate
! 	 * for flushing!
! 	 */
! 
! #ifdef AFS_DISCON_ENV
!      } else if (AFS_IS_DISCON_RW) {
! 	/* Disconnected. */
! 
! 	if (!avc->ddirty_flags ||
! 		(avc->ddirty_flags == VDisconShadowed)) {
!   	    /* Add to disconnected dirty list. */
! 	    AFS_DISCON_ADD_DIRTY(avc);
!   	}
! 
! 	/* Set disconnected write flag. */
! 	avc->ddirty_flags |= VDisconWriteClose;
! #endif
!     }		/* if not disconnected */
! 
  #if defined(AFS_SGI_ENV)
      osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
  #endif
+ 
      avc->opens--;
      avc->execsOrWriters--;
      return code;
***************
*** 382,388 ****
      if (avc->vc_error)
  	return avc->vc_error;
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING)
  	return ENETDOWN;
      
      startDate = osi_Time();
--- 404,410 ----
      if (avc->vc_error)
  	return avc->vc_error;
  
!     if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW)
  	return ENETDOWN;
      
      startDate = osi_Time();
***************
*** 613,618 ****
--- 635,646 ----
  	code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
  	VOP_UNLOCK(tfile->vnode, 0, current_proc());
  	AFS_GLOCK();
+ #elif defined(AFS_FBSD80_ENV)
+ 	AFS_GUNLOCK();
+ 	VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
+ 	code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
+ 	VOP_UNLOCK(tfile->vnode, 0);
+ 	AFS_GLOCK();
  #elif defined(AFS_FBSD50_ENV)
  	AFS_GUNLOCK();
  	VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
***************
*** 737,742 ****
--- 765,771 ----
      /* otherwise, call afs_StoreDCache (later try to do this async, if possible) */
      afs_Trace2(afs_iclSetp, CM_TRACE_PARTIALWRITE, ICL_TYPE_POINTER, avc,
  	       ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
+ 
  #if	defined(AFS_SUN5_ENV)
      code = afs_StoreAllSegments(avc, areq, AFS_ASYNC | AFS_VMSYNC_INVAL);
  #else
***************
*** 866,871 ****
--- 895,901 ----
  	afs_PutFakeStat(&fakestat);
  	return code;
      }
+     AFS_DISCON_LOCK();
  #ifdef	AFS_SUN5_ENV
      if (avc->flockCount) {
  	HandleFlock(avc, LOCK_UN, &treq, 0, 1 /*onlymine */ );
***************
*** 874,879 ****
--- 904,910 ----
  #if defined(AFS_SGI_ENV)
      if (!lastclose) {
  	afs_PutFakeStat(&fakestat);
+         AFS_DISCON_UNLOCK();
  	return 0;
      }
      /* unlock any locks for pid - could be wrong for child .. */
***************
*** 896,901 ****
--- 927,933 ----
      if (count > 1) {
  	/* The vfs layer may call this repeatedly with higher "count"; only on the last close (i.e. count = 1) we should actually proceed with the close. */
  	afs_PutFakeStat(&fakestat);
+ 	AFS_DISCON_UNLOCK();
  	return 0;
      }
  #else /* AFS_SGI_ENV */
***************
*** 908,914 ****
      }
  #endif /* AFS_SGI_ENV */
      if (aflags & (FWRITE | FTRUNC)) {
! 	if (afs_BBusy() || (AFS_NFSXLATORREQ(acred))) {
  	    /* do it yourself if daemons are all busy */
  	    ObtainWriteLock(&avc->lock, 124);
  	    code = afs_StoreOnLastReference(avc, &treq);
--- 940,946 ----
      }
  #endif /* AFS_SGI_ENV */
      if (aflags & (FWRITE | FTRUNC)) {
! 	if (afs_BBusy() || (AFS_NFSXLATORREQ(acred)) || AFS_IS_DISCONNECTED) {
  	    /* do it yourself if daemons are all busy */
  	    ObtainWriteLock(&avc->lock, 124);
  	    code = afs_StoreOnLastReference(avc, &treq);
***************
*** 949,954 ****
--- 981,987 ----
  #ifdef AFS_AIX32_ENV
  	    osi_ReleaseVM(avc, acred);
  #endif
+ 	    printf("avc->vc_error=%d\n", avc->vc_error);
  	    code = avc->vc_error;
  	    avc->vc_error = 0;
  	}
***************
*** 998,1003 ****
--- 1031,1037 ----
  	afs_remunlink(avc, 1);	/* ignore any return code */
      }
  #endif
+     AFS_DISCON_UNLOCK();
      afs_PutFakeStat(&fakestat);
      code = afs_CheckCode(code, &treq, 5);
      return code;
***************
*** 1036,1042 ****
      afs_Trace1(afs_iclSetp, CM_TRACE_FSYNC, ICL_TYPE_POINTER, avc);
      if ((code = afs_InitReq(&treq, acred)))
  	return code;
! 
  #if defined(AFS_SGI_ENV)
      AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
      if (flag & FSYNC_INVAL)
--- 1070,1076 ----
      afs_Trace1(afs_iclSetp, CM_TRACE_FSYNC, ICL_TYPE_POINTER, avc);
      if ((code = afs_InitReq(&treq, acred)))
  	return code;
!     AFS_DISCON_LOCK();
  #if defined(AFS_SGI_ENV)
      AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
      if (flag & FSYNC_INVAL)
***************
*** 1046,1056 ****
      ObtainSharedLock(&avc->lock, 18);
      code = 0;
      if (avc->execsOrWriters > 0) {
! 	/* put the file back */
! 	UpgradeSToWLock(&avc->lock, 41);
! 	code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
! 	ConvertWToSLock(&avc->lock);
!     }
  #if defined(AFS_SGI_ENV)
      AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
      if (code == VNOVNODE) {
--- 1080,1116 ----
      ObtainSharedLock(&avc->lock, 18);
      code = 0;
      if (avc->execsOrWriters > 0) {
! 
!     	if (!AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
! 		/* Your average flush. */
! 
! 		/* put the file back */
! 		UpgradeSToWLock(&avc->lock, 41);
! 		code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
! 		ConvertWToSLock(&avc->lock);
! 
! #if defined(AFS_DISCON_ENV)
! 	} else {
! 	    /* Disconnected flush. */
! 	    ObtainWriteLock(&afs_DDirtyVCListLock, 708);
! 
! 	    if (!avc->ddirty_flags ||
! 	    	(avc->ddirty_flags == VDisconShadowed)) {
! 
! 		/* Add to disconnected dirty list. */
! 		AFS_DISCON_ADD_DIRTY(avc);
! 	    }
! 
! 	    UpgradeSToWLock(&avc->lock, 711);
! 	    /* Set disconnected write flag. */
! 	    avc->ddirty_flags |= VDisconWriteFlush;
! 	    ConvertWToSLock(&avc->lock);
! 
! 	    ReleaseWriteLock(&afs_DDirtyVCListLock);
! #endif
!     	}		/* if not disconnected */
!     }			/* if (avc->execsOrWriters > 0) */
! 
  #if defined(AFS_SGI_ENV)
      AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
      if (code == VNOVNODE) {
***************
*** 1060,1066 ****
  	code = ENOENT;
      }
  #endif
! 
      code = afs_CheckCode(code, &treq, 33);
      ReleaseSharedLock(&avc->lock);
      return code;
--- 1120,1126 ----
  	code = ENOENT;
      }
  #endif
!     AFS_DISCON_UNLOCK();
      code = afs_CheckCode(code, &treq, 33);
      ReleaseSharedLock(&avc->lock);
      return code;
Index: openafs/src/afsd/afsd.c
diff -c openafs/src/afsd/afsd.c:1.60.2.10 openafs/src/afsd/afsd.c:1.60.2.11
*** openafs/src/afsd/afsd.c:1.60.2.10	Wed Oct 31 18:31:59 2007
--- openafs/src/afsd/afsd.c	Mon Sep 22 15:35:27 2008
***************
*** 58,64 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afsd/afsd.c,v 1.60.2.10 2007/10/31 22:31:59 shadow Exp $");
  
  #define VFS 1
  
--- 58,64 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afsd/afsd.c,v 1.60.2.11 2008/09/22 19:35:27 shadow Exp $");
  
  #define VFS 1
  
***************
*** 292,298 ****
  int ownerRWmode = 0600;		/*Read/write OK by owner */
  static int filesSet = 0;	/*True if number of files explicitly set */
  static int nFilesPerDir = 2048;	/* # files per cache dir */
! static int nDaemons = 2;	/* Number of background daemons */
  static int chunkSize = 0;	/* 2^chunkSize bytes per chunk */
  static int dCacheSize;		/* # of dcache entries */
  static int vCacheSize = 200;	/* # of volume cache entries */
--- 292,303 ----
  int ownerRWmode = 0600;		/*Read/write OK by owner */
  static int filesSet = 0;	/*True if number of files explicitly set */
  static int nFilesPerDir = 2048;	/* # files per cache dir */
! #if defined(AFS_CACHE_BYPASS)
! #define AFSD_NDAEMONS 4
! #else
! #define AFSD_NDAEMONS 2
! #endif
! static int nDaemons = AFSD_NDAEMONS;	/* Number of background daemons */
  static int chunkSize = 0;	/* 2^chunkSize bytes per chunk */
  static int dCacheSize;		/* # of dcache entries */
  static int vCacheSize = 200;	/* # of volume cache entries */
Index: openafs/src/afsd/rc.afs.rs_aix
diff -c openafs/src/afsd/rc.afs.rs_aix:1.3 openafs/src/afsd/rc.afs.rs_aix:1.3.14.1
*** openafs/src/afsd/rc.afs.rs_aix:1.3	Tue Jul  1 14:37:25 2003
--- openafs/src/afsd/rc.afs.rs_aix	Wed Sep  3 14:27:24 2008
***************
*** 49,69 ****
  # find out whether we have 32 or 64 bit kernel
  
  kernel=32
! if [ -x /bin/w64 ]; then
!     /bin/w64 >/dev/null 2>&1
!     if [ $? -eq 0 ]; then
!         kernel=64
!     fi
  fi
  
  # Load AFS into the kernel
  
  cd /usr/vice/etc/dkload
  if [ $kernel -eq 32 ]; then
-     echo "32-bit kernel found"
      ./cfgexport -a export.ext${ExportExt} && ./cfgafs -a afs.ext.32
  else
-     echo "64-bit kernel assumed"
      ./cfgexport64 -a export64.ext${ExportExt} && ./cfgafs64 -a afs.ext.64
  fi
  if [ $? -ne 0 ]; then
--- 49,65 ----
  # find out whether we have 32 or 64 bit kernel
  
  kernel=32
! if [ -x /usr/sbin/bootinfo ]; then
! 	kernel=`/usr/sbin/bootinfo -K`
  fi
  
  # Load AFS into the kernel
  
+ echo "$0: Loading $kernel bit kernel AFS modules"
  cd /usr/vice/etc/dkload
  if [ $kernel -eq 32 ]; then
      ./cfgexport -a export.ext${ExportExt} && ./cfgafs -a afs.ext.32
  else
      ./cfgexport64 -a export64.ext${ExportExt} && ./cfgafs64 -a afs.ext.64
  fi
  if [ $? -ne 0 ]; then
Index: openafs/src/bozo/bosserver.c
diff -c openafs/src/bozo/bosserver.c:1.32.2.10 openafs/src/bozo/bosserver.c:1.32.2.11
*** openafs/src/bozo/bosserver.c:1.32.2.10	Mon Mar 10 18:32:32 2008
--- openafs/src/bozo/bosserver.c	Wed Sep 24 17:36:54 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/bozo/bosserver.c,v 1.32.2.10 2008/03/10 22:32:32 shadow Exp $");
  
  #include <afs/stds.h>
  #include <sys/types.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/bozo/bosserver.c,v 1.32.2.11 2008/09/24 21:36:54 shadow Exp $");
  
  #include <afs/stds.h>
  #include <sys/types.h>
***************
*** 1068,1075 ****
      rx_SetStackSize(tservice, BOZO_LWP_STACKSIZE);	/* so gethostbyname works (in cell stuff) */
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK, 
!                                     NULL);
      }
  
      tservice =
--- 1068,1074 ----
      rx_SetStackSize(tservice, BOZO_LWP_STACKSIZE);	/* so gethostbyname works (in cell stuff) */
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
      }
  
      tservice =
Index: openafs/src/cf/osconf.m4
diff -c openafs/src/cf/osconf.m4:1.83.2.11 openafs/src/cf/osconf.m4:1.83.2.12
*** openafs/src/cf/osconf.m4:1.83.2.11	Sat Jul 19 02:15:02 2008
--- openafs/src/cf/osconf.m4	Wed Sep  3 14:27:23 2008
***************
*** 568,573 ****
--- 568,574 ----
  		XCFLAGS="-K -D_NONSTD_TYPES -D_MBI=void"
  		XLIBS="${LIB_AFSDB} -ldl"
  		SHLIB_LINKER="${MT_CC} -bM:SRE -berok"
+ 		AIX32=""
  		AIX64="#"
  		;;
  
***************
*** 584,589 ****
--- 585,591 ----
  		XCFLAGS="-K -D_NONSTD_TYPES -D_MBI=void"
  		XLIBS="${LIB_AFSDB} -ldl"
  		SHLIB_LINKER="${MT_CC} -bM:SRE -berok"
+ 		AIX32=""
  		AIX64=""
  		;;
  
***************
*** 599,604 ****
--- 601,607 ----
  		XCFLAGS="-K -D_NONSTD_TYPES -D_MBI=void"
  		XLIBS="${LIB_AFSDB} -ldl"
  		SHLIB_LINKER="${MT_CC} -bM:SRE -berok"
+ 		AIX32=""
  		AIX64=""
  		;;
  
***************
*** 614,619 ****
--- 617,639 ----
  		XCFLAGS="-K -D_NONSTD_TYPES -D_MBI=void"
  		XLIBS="${LIB_AFSDB} -ldl"
  		SHLIB_LINKER="${MT_CC} -bM:SRE -berok"
+ 		AIX32=""
+ 		AIX64=""
+ 		;;
+ 
+ 	rs_aix61)	
+ 		DBG="-g"
+ 		LEX="lex"
+ 		LIBSYS_AIX_EXP="afsl.exp"
+ 		MT_CC="xlc_r"
+ 		MT_CFLAGS='-DAFS_PTHREAD_ENV ${XCFLAGS}'
+ 		MT_LIBS="-lpthreads"
+ 		SHLIB_SUFFIX="o"
+ 		TXLIBS="-lcurses"
+ 		XCFLAGS="-K -D_NONSTD_TYPES -D_MBI=void"
+ 		XLIBS="${LIB_AFSDB} -ldl"
+ 		SHLIB_LINKER="${MT_CC} -bM:SRE -berok"
+ 		AIX32="#"
  		AIX64=""
  		;;
  
***************
*** 1122,1127 ****
--- 1142,1148 ----
  AC_SUBST(CCOBJ)
  AC_SUBST(AFSD_LIBS)
  AC_SUBST(AFSD_LDFLAGS)
+ AC_SUBST(AIX32)
  AC_SUBST(AIX64)
  AC_SUBST(AR)
  AC_SUBST(AS)
Index: openafs/src/config/afs_sysnames.h
diff -c openafs/src/config/afs_sysnames.h:1.77.2.5 openafs/src/config/afs_sysnames.h:1.77.2.7
*** openafs/src/config/afs_sysnames.h:1.77.2.5	Tue Jan 15 01:09:12 2008
--- openafs/src/config/afs_sysnames.h	Wed Sep  3 14:27:23 2008
***************
*** 73,78 ****
--- 73,79 ----
  #define SYS_NAME_ID_rs_aix43		 705
  #define SYS_NAME_ID_rs_aix52		 706
  #define SYS_NAME_ID_rs_aix53		 707
+ #define SYS_NAME_ID_rs_aix61		 708
  
  #define SYS_NAME_ID_sun3_411		 906
  #define SYS_NAME_ID_sun3x_411		 912
***************
*** 186,191 ****
--- 187,193 ----
  #define SYS_NAME_ID_i386_fbsd_61        2113
  #define SYS_NAME_ID_i386_fbsd_62        2114
  #define SYS_NAME_ID_i386_fbsd_70        2115
+ #define SYS_NAME_ID_i386_fbsd_80        2116
  
  #define SYS_NAME_ID_ia64_linux2		2200
  #define SYS_NAME_ID_ia64_linux22	2201
Index: openafs/src/config/param.rs_aix61.h
diff -c /dev/null openafs/src/config/param.rs_aix61.h:1.1.2.2
*** /dev/null	Fri Sep 26 04:30:56 2008
--- openafs/src/config/param.rs_aix61.h	Wed Sep  3 14:27:23 2008
***************
*** 0 ****
--- 1,181 ----
+ #ifndef UKERNEL
+ /* This section for kernel libafs compiles only */
+ 
+ /*
+  * Copyright 2000, International Business Machines Corporation and others.
+  * All Rights Reserved.
+  * 
+  * This software has been released under the terms of the IBM Public
+  * License.  For details, see the LICENSE file in the top-level source
+  * directory or online at http://www.openafs.org/dl/license10.html
+  */
+ 
+ #ifndef	AFS_PARAM_H
+ #define	AFS_PARAM_H
+ 
+ #define	AFS_AIX_ENV		1
+ #define	AFS_AIX32_ENV		1
+ #define	AFS_AIX41_ENV		1
+ #define AFS_AIX42_ENV		1
+ #define AFS_AIX51_ENV		1
+ #define AFS_AIX52_ENV		1
+ #define AFS_AIX53_ENV		1
+ #define AFS_AIX61_ENV		1
+ 
+ #define AFS_64BIT_ENV		1
+ #define AFS_64BIT_CLIENT	1
+ #define AFS_NAMEI_ENV		1
+ #ifdef AFS_NAMEI_ENV
+ #define AFS_64BIT_IOPS_ENV	1
+ #endif
+ 
+ #define AFS_HAVE_FLOCK_SYSID    1
+ 
+ #include <afs/afs_sysnames.h>
+ 
+ /* Global lock in AFS part of client. */
+ #define AFS_GLOBAL_SUNLOCK 1
+ #define AFS_GCPAGS		1	/* if nonzero, garbage collect PAGs */
+ 
+ /* File system entry (used if vmount.h doesn't define MNT_AFS */
+ #define AFS_MOUNT_AFS	4
+ #define AFS_SYSCALL    31
+ 
+ /* Machine / Operating system information */
+ #define SYS_NAME	"rs_aix61"
+ #define SYS_NAME_ID	SYS_NAME_ID_rs_aix61
+ #define AFSBIG_ENDIAN	1
+ #define RIOS		1	/* POWERseries 6000. (sj/pc)    */
+ #define AFS_VM_RDWR_ENV 1	/* read/write implemented via VM */
+ #define AFS_USE_GETTIMEOFDAY 1	/* use gettimeofday to implement rx clock */
+ #define AFS_HAVE_STATVFS	1	/* System supports statvfs */
+ 
+ #ifndef _POWER
+ #define _POWER		1	/* _POWERseries!                */
+ #endif
+ #ifndef COMPAT_43
+ #define COMPAT_43
+ #endif
+ 
+ #define KERNEL_HAVE_UERROR 1
+ #define KERNEL_HAVE_PIN 1
+ 
+ /* Extra kernel definitions (from kdefs file) */
+ #ifdef _KERNEL
+ #define	AFS_SHORTGID	1
+ #define	AFS_UIOFMODE	1
+ #define	afsio_iov	uio_iov
+ #define	afsio_iovcnt	uio_iovcnt
+ #define	afsio_offset	uio_offset
+ #define	afsio_seg	uio_segflg
+ #define	afsio_fmode	uio_fmode
+ #define	afsio_resid	uio_resid
+ #define	AFS_UIOSYS	UIO_SYSSPACE
+ #define	AFS_UIOUSER	UIO_USERSPACE
+ #define	AFS_CLBYTES	CLBYTES
+ #define	AFS_MINCHANGE	2
+ #define osi_GetTime(x)          do {curtime(x); (x)->tv_usec = (x)->tv_usec/1000;} while (0)
+ #define	osi_GTime(x)	time	/* something for the silly time(0)?? */
+ #define	AFS_KALLOC	kmem_alloc
+ #define	AFS_KFREE	kmem_free
+ #define	VATTR_NULL(V)	memset((void*)V, -1, sizeof(*(V)))
+ #define va_nodeid	va_serialno
+ #endif /* !_KERNEL      */
+ #define	AFS_DIRENT
+ #endif /* AFS_PARAM_H */
+ 
+ #else /* !defined(UKERNEL) */
+ 
+ /* This section for user space compiles only */
+ 
+ /*
+  * Copyright 2000, International Business Machines Corporation and others.
+  * All Rights Reserved.
+  * 
+  * This software has been released under the terms of the IBM Public
+  * License.  For details, see the LICENSE file in the top-level source
+  * directory or online at http://www.openafs.org/dl/license10.html
+  */
+ 
+ #ifndef	AFS_PARAM_H
+ #define	AFS_PARAM_H
+ 
+ #define AFS_64BIT_ENV           1
+ #define AFS_64BIT_CLIENT        1
+ #define AFS_NAMEI_ENV           1
+ #ifdef AFS_NAMEI_ENV
+ #define AFS_64BIT_IOPS_ENV	1
+ #endif
+ #define BITMAP_LATER            1
+ #define FAST_RESTART            1
+ 
+ #define AFS_VFS_ENV	1
+ /* Used only in vfsck code; is it needed any more???? */
+ #define RXK_LISTENER_ENV	1
+ #define AFS_USERSPACE_IP_ADDR	1
+ #define AFS_GCPAGS		0	/* if nonzero, garbage collect PAGs */
+ 
+ #ifdef KERNEL
+ 
+ #define UKERNEL			1	/* user space kernel */
+ #define AFS_ENV			1
+ #define AFS_USR_AIX_ENV		1
+ #define AFS_USR_AIX41_ENV	1
+ #define AFS_USR_AIX42_ENV	1
+ #define AFS_USR_AIX51_ENV		1
+ 
+ #else /* KERNEL */
+ 
+ #define	AFS_AIX_ENV		1
+ #define	AFS_AIX32_ENV		1
+ #define	AFS_AIX41_ENV		1
+ #define AFS_AIX42_ENV		1
+ #define AFS_AIX51_ENV		1
+ 
+ #define AFS_HAVE_FLOCK_SYSID    1
+ 
+ #endif /* KERNEL */
+ 
+ #include <afs/afs_sysnames.h>
+ 
+ 													       /*#define AFS_GLOBAL_SUNLOCK    1 *//* For global locking */
+ 
+ #define	AFS_3DISPARES		1	/* Utilize the 3 available disk inode 'spares' */
+ #define	AFS_SYSCALL		105
+ 
+ /* File system entry (used if mount.h doesn't define MOUNT_AFS */
+ #define AFS_MOUNT_AFS	 4
+ 
+ /* Machine / Operating system information */
+ #define sys_rs_aix51	1
+ #define SYS_NAME	"rs_aix51"
+ #define SYS_NAME_ID	SYS_NAME_ID_rs_aix51
+ #define AFSBIG_ENDIAN	1
+ #define AFS_HAVE_FFS            1	/* Use system's ffs. */
+ #define AFS_HAVE_STATVFS	0	/* System doesn't support statvfs */
+ 
+ /* Extra kernel definitions (from kdefs file) */
+ #ifdef KERNEL
+ #define	AFS_UIOFMODE		1	/* Only in afs/afs_vnodeops.c (afs_ustrategy) */
+ #define	AFS_SYSVLOCK		1	/* sys v locking supported */
+ /*#define	AFS_USEBUFFERS	1*/
+ #define	afsio_iov	uio_iov
+ #define	afsio_iovcnt	uio_iovcnt
+ #define	afsio_offset	uio_offset
+ #define	afsio_seg	uio_segflg
+ #define	afsio_fmode	uio_fmode
+ #define	afsio_resid	uio_resid
+ #define	AFS_UIOSYS	1
+ #define	AFS_UIOUSER	UIO_USERSPACE
+ #define	AFS_CLBYTES	MCLBYTES
+ #define	AFS_MINCHANGE	2
+ #define	VATTR_NULL	usr_vattr_null
+ #endif /* KERNEL */
+ #define	AFS_DIRENT
+ #ifndef CMSERVERPREF
+ #define CMSERVERPREF
+ #endif
+ 
+ #endif /* AFS_PARAM_H */
+ 
+ #endif /* !defined(UKERNEL) */
Index: openafs/src/config/stds.h
diff -c openafs/src/config/stds.h:1.23.2.3 openafs/src/config/stds.h:1.23.2.4
*** openafs/src/config/stds.h:1.23.2.3	Wed Aug 13 19:44:29 2008
--- openafs/src/config/stds.h	Wed Sep 24 17:34:35 2008
***************
*** 276,279 ****
--- 276,287 ----
  #define AFS_DEMAND_ATTACH_FS 1
  #endif
  
+ #ifdef AFS_HPUX_ENV
+ #define static_inline static __inline
+ #elif defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
+ #define static_inline static
+ #else
+ #define static_inline static inline
+ #endif
+ 
  #endif /* OPENAFS_CONFIG_AFS_STDS_H */
Index: openafs/src/config/venus.h
diff -c openafs/src/config/venus.h:1.12.2.5 openafs/src/config/venus.h:1.12.2.6
*** openafs/src/config/venus.h:1.12.2.5	Tue May 20 17:59:00 2008
--- openafs/src/config/venus.h	Mon Sep 22 15:35:28 2008
***************
*** 188,191 ****
--- 188,196 ----
  /* OpenAFS-specific 'O' pioctl's */
  #define VIOC_NFS_NUKE_CREDS	_OVICEIOCTL(1)	/* nuke creds for all PAG's */
  
+ #if defined(AFS_CACHE_BYPASS)
+ /* Uncoordinated 'O' pioctls */
+ #define VIOC_SETBYPASS_THRESH	_OVICEIOCTL(2) /* cache-bypass size thresh */
+ #endif
+ 
  #endif /* AFS_VENUS_H */
Index: openafs/src/des/NTMakefile
diff -c openafs/src/des/NTMakefile:1.8.4.2 openafs/src/des/NTMakefile:1.8.4.3
*** openafs/src/des/NTMakefile:1.8.4.2	Fri Nov  2 21:07:29 2007
--- openafs/src/des/NTMakefile	Sat Aug 16 15:19:02 2008
***************
*** 120,153 ****
--- 120,161 ----
  $(OUT)\make_keyperm.exe: $(OUT)\make_keyperm.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_p_table.exe: $(OUT)\make_p_table.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_s_table.exe: $(OUT)\make_s_table.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_odd.exe: $(OUT)\make_odd.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_p.exe: $(OUT)\make_p.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_s.exe: $(OUT)\make_s.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_fp.exe: $(OUT)\make_fp.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\make_ip.exe: $(OUT)\make_ip.obj $(OUT)\misc.obj $(OUT)\main.obj
  	$(EXECONLINK)
   	$(_VC_MANIFEST_EMBED_EXE)
+         $(CODESIGN_USERLAND)
  
  GENOBJS = $(OUT)\make_keyperm.obj \
      $(OUT)\make_p_table.obj \
Index: openafs/src/des/test/NTMakefile
diff -c openafs/src/des/test/NTMakefile:1.4 openafs/src/des/test/NTMakefile:1.4.14.1
*** openafs/src/des/test/NTMakefile:1.4	Fri Nov 21 03:00:39 2003
--- openafs/src/des/test/NTMakefile	Sat Aug 16 15:19:05 2008
***************
*** 10,21 ****
--- 10,24 ----
  
  $(OUT)\testit.exe: $(OUT)\testit.obj $(DESTDIR)\lib\afsdes.lib $(DESTDIR)\lib\afs\afsutil.lib
  	$(EXECONLINK)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\verify.exe: $(OUT)\verify.obj $(DESTDIR)\lib\afsdes.lib $(DESTDIR)\lib\afs\afsutil.lib
  	$(EXECONLINK)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\key_test.exe: $(OUT)\key_test.obj $(DESTDIR)\lib\afsdes.lib $(DESTDIR)\lib\afs\afsutil.lib
  	$(EXECONLINK)
+         $(CODESIGN_USERLAND)
  
  $(OUT)\tests: $(OUT)\testit.exe $(OUT)\verify.exe $(OUT)\key_test.exe
  
Index: openafs/src/dir/dir.c
diff -c openafs/src/dir/dir.c:1.24.4.4 openafs/src/dir/dir.c:1.24.4.5
*** openafs/src/dir/dir.c:1.24.4.4	Tue Oct 30 11:16:39 2007
--- openafs/src/dir/dir.c	Mon Sep 22 15:29:55 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/dir/dir.c,v 1.24.4.4 2007/10/30 15:16:39 shadow Exp $");
  
  #ifdef KERNEL
  #if !defined(UKERNEL)
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/dir/dir.c,v 1.24.4.5 2008/09/22 19:29:55 shadow Exp $");
  
  #ifdef KERNEL
  #if !defined(UKERNEL)
***************
*** 86,91 ****
--- 86,96 ----
  #define	LookupOffset	afs_dir_LookupOffset
  #define	EnumerateDir	afs_dir_EnumerateDir
  #define	IsEmpty		afs_dir_IsEmpty
+ 
+ #if defined(AFS_DISCON_ENV)
+ #define ChangeFid	afs_dir_ChangeFid
+ #endif
+ 
  #else /* KERNEL */
  
  # ifdef HAVE_UNISTD_H
***************
*** 390,404 ****
  int
  EnumerateDir(void *dir, int (*hookproc) (), void *hook)
  {
!     /* Enumerate the contents of a directory. */
      register int i;
      int num;
      register struct DirHeader *dhp;
      register struct DirEntry *ep;
  
      dhp = (struct DirHeader *)DRead(dir, 0);
      if (!dhp)
  	return EIO;		/* first page should be there */
      for (i = 0; i < NHASHENT; i++) {
  	/* For each hash chain, enumerate everyone on the list. */
  	num = ntohs(dhp->hashTable[i]);
--- 395,413 ----
  int
  EnumerateDir(void *dir, int (*hookproc) (), void *hook)
  {
!     /* Enumerate the contents of a directory.
!      * Break when hook function returns non 0.
!      */
      register int i;
      int num;
      register struct DirHeader *dhp;
      register struct DirEntry *ep;
+     int code = 0;
  
      dhp = (struct DirHeader *)DRead(dir, 0);
      if (!dhp)
  	return EIO;		/* first page should be there */
+ 
      for (i = 0; i < NHASHENT; i++) {
  	/* For each hash chain, enumerate everyone on the list. */
  	num = ntohs(dhp->hashTable[i]);
***************
*** 414,423 ****
  		}
  		break;
  	    }
  	    num = ntohs(ep->next);
! 	    (*hookproc) (hook, ep->name, ntohl(ep->fid.vnode),
  			 ntohl(ep->fid.vunique));
  	    DRelease(ep, 0);
  	}
      }
      DRelease(dhp, 0);
--- 423,435 ----
  		}
  		break;
  	    }
+ 
  	    num = ntohs(ep->next);
! 	    code = (*hookproc) (hook, ep->name, ntohl(ep->fid.vnode),
  			 ntohl(ep->fid.vunique));
  	    DRelease(ep, 0);
+ 	    if (code)
+ 	    	break;
  	}
      }
      DRelease(dhp, 0);
***************
*** 531,533 ****
--- 543,586 ----
  	}
      }
  }
+ 
+ #if defined(AFS_DISCON_ENV)
+ /*!
+  * Change an entry fid.
+  *
+  * \param dir
+  * \param entry The entry name.
+  * \param old_fid The old find in MKFid format (host order).
+  * It can be omitted if you don't need a safety check...
+  * \param new_fid The new find in MKFid format (host order).
+  */
+ int ChangeFid(void *dir,
+ 		char *entry,
+ 		afs_uint32 *old_fid,
+ 		afs_uint32 *new_fid)
+ {
+     struct DirEntry *firstitem;
+     unsigned short *previtem;
+     struct MKFid *fid_old = (struct MKFid *) old_fid;
+     struct MKFid *fid_new = (struct MKFid *) new_fid;
+ 
+     /* Find entry. */
+     firstitem = FindItem(dir, entry, &previtem);
+     if (firstitem == 0) {
+ 	return ENOENT;
+     }
+     DRelease(previtem, 1);
+     /* Replace fid. */
+     if (!old_fid ||
+     	((htonl(fid_old->vnode) == firstitem->fid.vnode) &&
+     	(htonl(fid_old->vunique) == firstitem->fid.vunique))) {
+ 
+ 	firstitem->fid.vnode = htonl(fid_new->vnode);
+ 	firstitem->fid.vunique = htonl(fid_new->vunique);
+     }
+ 
+     DRelease(firstitem, 1);
+ 
+     return 0;
+ }
+ #endif
Index: openafs/src/dir/dir.h
diff -c openafs/src/dir/dir.h:1.10 openafs/src/dir/dir.h:1.10.14.1
*** openafs/src/dir/dir.h:1.10	Fri Jan 23 11:53:35 2004
--- openafs/src/dir/dir.h	Fri Sep 26 04:24:00 2008
***************
*** 131,136 ****
--- 131,140 ----
  						 afs_int32 unique),
  				void *hook);
  extern int afs_dir_IsEmpty(void *dir);
+ #ifdef AFS_DISCON_ENV
+ extern int afs_dir_ChangeFid(void *dir, char *entry, afs_uint32 *old_fid,
+                		     afs_uint32 *new_fid);
+ #endif
  extern struct DirEntry *afs_dir_GetBlob(void *dir, afs_int32 blobno);
  #endif
  
Index: openafs/src/export/Makefile.in
diff -c openafs/src/export/Makefile.in:1.20.4.1 openafs/src/export/Makefile.in:1.20.4.4
*** openafs/src/export/Makefile.in:1.20.4.1	Tue Jun 20 17:40:04 2006
--- openafs/src/export/Makefile.in	Sat Sep  6 07:59:13 2008
***************
*** 12,48 ****
    IMPORTS = /lib/kernex.exp /lib/syscalls.exp ${srcdir}/extras.exp
       KOBJ = export.o symtab.o
  
! include ../config/Makefile.version
  
! all: ${TOP_LIBDIR}/export.exp ${TOP_LIBDIR}/export64.exp ${TOP_LIBDIR}/extras.exp cfgexport cfgafs
! 	${INSTALL} ${srcdir}/export.h ${KERNELDIR}
! 	${INSTALL} export.exp ${KERNELDIR}
! 	${INSTALL} export64.exp ${KERNELDIR}
! 	${INSTALL} ${srcdir}/export.h ${UKERNELDIR}
! 	${INSTALL} export64.exp ${UKERNELDIR}
! 	${INSTALL} export.exp ${UKERNELDIR}
  
! noversion system: install
  
! install:    ${DESTDIR}${afskerneldir}/export.ext \
! 	${DESTDIR}${afskerneldir}/export.ext.nonfs \
! 	${DESTDIR}${afskerneldir}/export64.ext.nonfs \
! 	${DESTDIR}${libdir}/afs/export.exp \
! 	${DESTDIR}${libdir}/afs/export64.exp \
! 	${DESTDIR}${libdir}/afs/extras.exp \
! 	${DESTDIR}${afskerneldir}/cfgexport \
! 	${DESTDIR}${afskerneldir}/cfgafs \
! 	${DESTDIR}${afskerneldir}/export64.ext \
! 	${DESTDIR}${afskerneldir}/cfgexport64 \
! 	${DESTDIR}${afskerneldir}/cfgafs64 
  
  export.exp: ${srcdir}/export4.exp ${srcdir}/export5.exp
  	case ${SYS_NAME} in \
  	rs_aix4* ) \
! 		cp -p ${srcdir}/export4.exp export.exp ; \
  		cp -p ${srcdir}/export4-64.exp export64.exp ;; \
  	rs_aix5* ) \
! 		cp -p ${srcdir}/export5.exp export.exp ; \
  		cp -p ${srcdir}/export5-64.exp export64.exp ;; \
  	esac
  
--- 12,56 ----
    IMPORTS = /lib/kernex.exp /lib/syscalls.exp ${srcdir}/extras.exp
       KOBJ = export.o symtab.o
  
! EXPORTS32 = @AIX32@export.exp export.ext.nonfs export.ext cfgexport cfgafs
! EXPORTS64 = @AIX64@export64.exp export64.ext.nonfs export64.ext cfgexport64 cfgafs64
! TOPEXP32  = @AIX32@${TOP_LIBDIR}/export.exp
! TOPEXP64  = @AIX64@${TOP_LIBDIR}/export64.exp
! 
! all: $(TOPEXP32) $(TOPEXP64) ${TOP_LIBDIR}/extras.exp
! 	${INSTALL} ${srcdir}/export.h ${KERNELDIR}/export.h
! 	@AIX32@${INSTALL} export.exp ${KERNELDIR}/export.exp
! 	@AIX64@${INSTALL} export64.exp ${KERNELDIR}/export64.exp
! 	${INSTALL} ${srcdir}/export.h ${UKERNELDIR}/export.h
! 	@AIX32@${INSTALL} export.exp ${UKERNELDIR}/export.exp
! 	@AIX64@${INSTALL} export64.exp ${UKERNELDIR}/export64.exp
  
! ${TOP_LIBDIR}/export.exp: export.exp
! 	${INSTALL} $? $@
  
! ${TOP_LIBDIR}/export64.exp: export64.exp
! 	${INSTALL} $? $@
  
! ${TOP_LIBDIR}/extras.exp: ${srcdir}/extras.exp
! 	${INSTALL} $? $@
! 
! noversion system: install
  
  export.exp: ${srcdir}/export4.exp ${srcdir}/export5.exp
  	case ${SYS_NAME} in \
  	rs_aix4* ) \
! 		cp -p ${srcdir}/export4.exp export.exp ;; \
! 	rs_aix5* ) \
! 		cp -p ${srcdir}/export5.exp export.exp ;; \
! 	esac
! 
! export64.exp: ${srcdir}/export4-64.exp ${srcdir}/export5-64.exp
! 	case ${SYS_NAME} in \
! 	rs_aix4* ) \
  		cp -p ${srcdir}/export4-64.exp export64.exp ;; \
  	rs_aix5* ) \
! 		cp -p ${srcdir}/export5-64.exp export64.exp ;; \
! 	rs_aix6* ) \
  		cp -p ${srcdir}/export5-64.exp export64.exp ;; \
  	esac
  
***************
*** 69,74 ****
--- 77,85 ----
  		${CC} ${CFLAGS} -q64 -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_AIX51_ENV -c ${srcdir}/symtab.c ; \
  		mv symtab.o symtab64.o ; \
  		${CC} ${CFLAGS} -DAFS_AIX51_ENV -c ${srcdir}/symtab.c ;; \
+ 	rs_aix6* ) \
+ 		${CC} ${CFLAGS} -q64 -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_AIX51_ENV -c ${srcdir}/symtab.c ; \
+ 		mv symtab.o symtab64.o ;; \
  	esac
  
  export.o export64.o: ${srcdir}/export.c
***************
*** 79,96 ****
  		${CC} ${CFLAGS} -q64 -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
  		mv export.o export64.o ; \
  		${CC} ${CFLAGS} -DAFS_AIX51_ENV -c ${srcdir}/export.c ;; \
  	esac
!                
  export.nonfs.o export64.nonfs.o: ${srcdir}/export.c
  	case ${SYS_NAME} in \
  	rs_aix4* ) \
! 		${CC} ${INCS} -DAFS_NONFSTRANS -c ${srcdir}/export.c ;; \
  	rs_aix5* ) \
  		${CC} -q64 ${INCS} -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_NONFSTRANS -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
  		mv export.o export64.nonfs.o ; \
! 		${CC} ${INCS} -DAFS_NONFSTRANS -DAFS_AIX51_ENV -c ${srcdir}/export.c ;; \
  	esac
- 	-mv export.o export.nonfs.o
  
  cfgexport: cfgexport.o
  	${CC} -g ${INCS} -o cfgexport cfgexport.o
--- 90,114 ----
  		${CC} ${CFLAGS} -q64 -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
  		mv export.o export64.o ; \
  		${CC} ${CFLAGS} -DAFS_AIX51_ENV -c ${srcdir}/export.c ;; \
+ 	rs_aix6* ) \
+ 		${CC} ${CFLAGS} -q64 -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
+ 		mv export.o export64.o ;; \
  	esac
! 
  export.nonfs.o export64.nonfs.o: ${srcdir}/export.c
  	case ${SYS_NAME} in \
  	rs_aix4* ) \
! 		${CC} ${INCS} -DAFS_NONFSTRANS -c ${srcdir}/export.c ; \
! 		mv export.o export.nonfs.o ;; \
  	rs_aix5* ) \
  		${CC} -q64 ${INCS} -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_NONFSTRANS -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
  		mv export.o export64.nonfs.o ; \
! 		${CC} ${INCS} -DAFS_NONFSTRANS -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
! 		mv export.o export.nonfs.o ;; \
! 	rs_aix6* ) \
! 		${CC} -q64 ${INCS} -D__XCOFF64__ -DAFS_64BIT_KERNEL -DAFS_NONFSTRANS -DAFS_AIX51_ENV -c ${srcdir}/export.c ; \
! 		mv export.o export64.nonfs.o ;; \
  	esac
  
  cfgexport: cfgexport.o
  	${CC} -g ${INCS} -o cfgexport cfgexport.o
***************
*** 119,209 ****
  	$(RM) -f cfgafs cfgafs64
  	$(RM) -f *.ext *.ext.nonfs
  
! ${DEST}/root.client/usr/vice/etc/dkload/export.ext: export.ext
! 	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/export64.ext: @AIX64@export64.ext
! @AIX64@	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/export.ext.nonfs: export.ext.nonfs
! 	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/export64.ext.nonfs: @AIX64@export64.ext.nonfs
! @AIX64@	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/export.ext: export.ext
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/export64.ext: @AIX64@export64.ext
! @AIX64@	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/export.ext.nonfs: export.ext.nonfs
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/export64.ext.nonfs: @AIX64@export64.ext.nonfs
! @AIX64@	${INSTALL} $? $@
! 
! ${DEST}/lib/afs/export.exp: export.exp
! 	${INSTALL} $? $@
  
! ${DEST}/lib/afs/export64.exp: export64.exp
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${libdir}/afs/export.exp: export.exp
! 	${INSTALL} $? $@ 
! 
! ${DESTDIR}${libdir}/afs/export64.exp: export64.exp
! 	${INSTALL} $? $@ 
! 
! ${TOP_LIBDIR}/export.exp: export.exp
! 	${INSTALL} $? $@
! 
! ${TOP_LIBDIR}/export64.exp: export64.exp
! 	${INSTALL} $? $@
! 
! ${DEST}/lib/afs/extras.exp: ${srcdir}/extras.exp
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${libdir}/afs/extras.exp: ${srcdir}/extras.exp
! 	${INSTALL} $? $@
! 
! 
! ${TOP_LIBDIR}/extras.exp: ${srcdir}/extras.exp
! 	${INSTALL} $? $@
! 
! 
! ${DEST}/root.client/usr/vice/etc/dkload/cfgexport: cfgexport
! 	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/cfgexport64: @AIX64@cfgexport64
! @AIX64@	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/cfgafs: cfgafs
! 	${INSTALL} $? $@
! 
! ${DEST}/root.client/usr/vice/etc/dkload/cfgafs64: @AIX64@cfgafs64
! @AIX64@	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/cfgexport: cfgexport
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/cfgexport64: @AIX64@cfgexport64
! @AIX64@	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/cfgafs: cfgafs
! 	${INSTALL} $? $@
! 
! ${DESTDIR}${afskerneldir}/cfgafs64: @AIX64@cfgafs64
! @AIX64@	${INSTALL} $? $@
! 
! dest:    ${DEST}/root.client/usr/vice/etc/dkload/export.ext \
! 	${DEST}/root.client/usr/vice/etc/dkload/export.ext.nonfs \
! 	${DEST}/root.client/usr/vice/etc/dkload/export64.ext.nonfs \
! 	${DEST}/lib/afs/export.exp \
! 	${DEST}/lib/afs/export64.exp \
! 	${DEST}/lib/afs/extras.exp \
! 	${DEST}/root.client/usr/vice/etc/dkload/cfgexport \
! 	${DEST}/root.client/usr/vice/etc/dkload/cfgafs \
! 	${DEST}/root.client/usr/vice/etc/dkload/export64.ext \
! 	${DEST}/root.client/usr/vice/etc/dkload/cfgexport64 \
! 	${DEST}/root.client/usr/vice/etc/dkload/cfgafs64 
--- 137,166 ----
  	$(RM) -f cfgafs cfgafs64
  	$(RM) -f *.ext *.ext.nonfs
  
! install: $(EXPORTS32) $(EXPORTS64)
! 	${INSTALL} ${srcdir}/extras.exp ${DESTDIR}${libdir}/afs/extras.exp
! 	@AIX32@${INSTALL} export.exp ${DESTDIR}${libdir}/afs/export.exp
! 	@AIX32@${INSTALL} export.ext ${DESTDIR}${afskerneldir}/export.ext
! 	@AIX32@${INSTALL} export.ext.nonfs ${DESTDIR}${afskerneldir}/export.ext.nonfs
! 	@AIX32@${INSTALL} cfgexport ${DESTDIR}${afskerneldir}/cfgexport
! 	@AIX32@${INSTALL} cfgafs ${DESTDIR}${afskerneldir}/cfgafs
! 	@AIX64@${INSTALL} export64.exp ${DESTDIR}${libdir}/afs/export64.exp
! 	@AIX64@${INSTALL} export64.ext ${DESTDIR}${afskerneldir}/export64.ext
! 	@AIX64@${INSTALL} export64.ext.nonfs ${DESTDIR}${afskerneldir}/export64.ext.nonfs
! 	@AIX64@${INSTALL} cfgexport64 ${DESTDIR}${afskerneldir}/cfgexport64
! 	@AIX64@${INSTALL} cfgafs64 ${DESTDIR}${afskerneldir}/cfgafs64
! 
! dest: $(EXPORTS32) $(EXPORTS64)
! 	${INSTALL} ${srcdir}/extras.exp ${DEST}/lib/afs/extras.exp
! 	@AIX32@${INSTALL} export.exp ${DEST}/lib/afs/export.exp
! 	@AIX32@${INSTALL} export.ext ${DEST}/root.client/usr/vice/etc/dkload/export.ext
! 	@AIX32@${INSTALL} export.ext.nonfs ${DEST}/root.client/usr/vice/etc/dkload/export.ext.nonfs
! 	@AIX32@${INSTALL} cfgexport ${DEST}/root.client/usr/vice/etc/dkload/cfgexport
! 	@AIX32@${INSTALL} cfgafs ${DEST}/root.client/usr/vice/etc/dkload/cfgafs
! 	@AIX64@${INSTALL} export64.exp ${DEST}/lib/afs/export64.exp
! 	@AIX64@${INSTALL} export64.ext ${DEST}/root.client/usr/vice/etc/dkload/export64.ext
! 	@AIX64@${INSTALL} export64.ext.nonfs ${DEST}/root.client/usr/vice/etc/dkload/export64.ext.nonfs
! 	@AIX64@${INSTALL} cfgexport64 ${DEST}/root.client/usr/vice/etc/dkload/cfgexport64
! 	@AIX64@${INSTALL} cfgafs64 ${DEST}/root.client/usr/vice/etc/dkload/cfgafs64
  
! include ../config/Makefile.version
Index: openafs/src/export/cfgexport.c
diff -c openafs/src/export/cfgexport.c:1.12 openafs/src/export/cfgexport.c:1.12.8.1
*** openafs/src/export/cfgexport.c:1.12	Tue Dec  7 11:49:07 2004
--- openafs/src/export/cfgexport.c	Wed Sep  3 14:27:24 2008
***************
*** 14,20 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/export/cfgexport.c,v 1.12 2004/12/07 16:49:07 shadow Exp $");
  
  #include <errno.h>
  #include <stdio.h>
--- 14,20 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/export/cfgexport.c,v 1.12.8.1 2008/09/03 18:27:24 shadow Exp $");
  
  #include <errno.h>
  #include <stdio.h>
***************
*** 377,383 ****
   *	strp	-	^ to ^ to EXPORT string table
   *	szp	-	^ to EXPORT string table size
   */
! #define SYMBUFSIZE 262144
  xlate_xtok(xp, kp, strp, szp)
       register struct syment *xp;
       register sym_t *kp;
--- 377,383 ----
   *	strp	-	^ to ^ to EXPORT string table
   *	szp	-	^ to EXPORT string table size
   */
! #define SYMBUFSIZE 1048576
  xlate_xtok(xp, kp, strp, szp)
       register struct syment *xp;
       register sym_t *kp;
***************
*** 420,431 ****
--- 420,437 ----
  	 */
  	len = strlen(xstrings + xp->n_offset) + 1;
  	while (len >= left) {
+ 	    fprintf(stderr, "cfgexport: Out of memory. Increase SYMBUFSIZE and recompile\n");
+ 	    exit(1);
+ #if 0
+ 	    /* Something is broken with this code, after being here
+ 	       cfgexport segfaults */
  	    export_strings = (char *)realloc(*strp, sz += SYMBUFSIZE);
  	    if (!export_strings)
  		error("no memory for EXPORT string table");
  	    *strp = export_strings;
  	    left += SYMBUFSIZE;
  	    prev = "";		/* lazy */
+ #endif
  	}
  
  	strcpy(prev = *strp + offset, xstrings + xp->n_offset);
Index: openafs/src/libadmin/adminutil/afs_utilAdmin.c
diff -c openafs/src/libadmin/adminutil/afs_utilAdmin.c:1.9.4.1 openafs/src/libadmin/adminutil/afs_utilAdmin.c:1.9.4.2
*** openafs/src/libadmin/adminutil/afs_utilAdmin.c:1.9.4.1	Tue Apr 10 14:39:53 2007
--- openafs/src/libadmin/adminutil/afs_utilAdmin.c	Thu Sep 25 16:16:26 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/libadmin/adminutil/afs_utilAdmin.c,v 1.9.4.1 2007/04/10 18:39:53 shadow Exp $");
  
  #include <afs/stds.h>
  #include <afs/afs_Admin.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/libadmin/adminutil/afs_utilAdmin.c,v 1.9.4.2 2008/09/25 20:16:26 shadow Exp $");
  
  #include <afs/stds.h>
  #include <afs/afs_Admin.h>
***************
*** 2508,2514 ****
   */
  
  int ADMINAPI
! util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_stats *stats,
  		    afs_uint32 * supportedValues, afs_status_p st)
  {
      int rc = 0;
--- 2508,2514 ----
   */
  
  int ADMINAPI
! util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
  		    afs_uint32 * supportedValues, afs_status_p st)
  {
      int rc = 0;
Index: openafs/src/libadmin/adminutil/afs_utilAdmin.h
diff -c openafs/src/libadmin/adminutil/afs_utilAdmin.h:1.6 openafs/src/libadmin/adminutil/afs_utilAdmin.h:1.6.14.1
*** openafs/src/libadmin/adminutil/afs_utilAdmin.h:1.6	Tue Jul 15 19:15:23 2003
--- openafs/src/libadmin/adminutil/afs_utilAdmin.h	Thu Sep 25 16:16:26 2008
***************
*** 136,142 ****
  					   afs_status_p st);
  
  extern int ADMINAPI util_RXDebugRxStats(rxdebugHandle_p handle,
! 					struct rx_stats *stats,
  					afs_uint32 * supportedStats,
  					afs_status_p st);
  
--- 136,142 ----
  					   afs_status_p st);
  
  extern int ADMINAPI util_RXDebugRxStats(rxdebugHandle_p handle,
! 					struct rx_statistics *stats,
  					afs_uint32 * supportedStats,
  					afs_status_p st);
  
Index: openafs/src/libadmin/samples/rxdebug_rx_stats.c
diff -c openafs/src/libadmin/samples/rxdebug_rx_stats.c:1.7.14.1 openafs/src/libadmin/samples/rxdebug_rx_stats.c:1.7.14.2
*** openafs/src/libadmin/samples/rxdebug_rx_stats.c:1.7.14.1	Tue Oct 30 11:16:41 2007
--- openafs/src/libadmin/samples/rxdebug_rx_stats.c	Thu Sep 25 16:16:29 2008
***************
*** 17,23 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/libadmin/samples/rxdebug_rx_stats.c,v 1.7.14.1 2007/10/30 15:16:41 shadow Exp $");
  
  #ifdef AFS_NT40_ENV
  #include <winsock2.h>
--- 17,23 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/libadmin/samples/rxdebug_rx_stats.c,v 1.7.14.2 2008/09/25 20:16:29 shadow Exp $");
  
  #ifdef AFS_NT40_ENV
  #include <winsock2.h>
***************
*** 68,74 ****
      rxdebugHandle_p handle;
      char *srvrName;
      long srvrPort;
!     struct rx_stats stats;
      afs_uint32 supportedStats;
      char tstr[32];
      int i;
--- 68,74 ----
      rxdebugHandle_p handle;
      char *srvrName;
      long srvrPort;
!     struct rx_statistics stats;
      afs_uint32 supportedStats;
      char tstr[32];
      int i;
Index: openafs/src/libafs/Makefile.common.in
diff -c openafs/src/libafs/Makefile.common.in:1.24.2.7 openafs/src/libafs/Makefile.common.in:1.24.2.8
*** openafs/src/libafs/Makefile.common.in:1.24.2.7	Mon Jun 30 23:35:24 2008
--- openafs/src/libafs/Makefile.common.in	Mon Sep 22 15:35:28 2008
***************
*** 77,82 ****
--- 77,83 ----
  	afs_analyze.o \
  	afs_axscache.o  \
  	afs_buffer.o	\
+ 	afs_bypasscache.o \
  	afs_callback.o	\
  	afs_cbqueue.o    \
  	afs_cell.o \
***************
*** 242,247 ****
--- 243,250 ----
  	$(CRULE_OPT)
  afs_buffer.o: $(TOP_SRC_AFS)/afs_buffer.c
  	$(CRULE_OPT)
+ afs_bypasscache.o: $(TOP_SRC_AFS)/afs_bypasscache.c
+ 	$(CRULE_OPT)
  afs_cell.o: $(TOP_SRC_AFS)/afs_cell.c
  	$(CRULE_OPT)
  afs_conn.o: $(TOP_SRC_AFS)/afs_conn.c
Index: openafs/src/libafs/MakefileProto.AIX.in
diff -c openafs/src/libafs/MakefileProto.AIX.in:1.25.4.1 openafs/src/libafs/MakefileProto.AIX.in:1.25.4.2
*** openafs/src/libafs/MakefileProto.AIX.in:1.25.4.1	Tue Jun 20 17:40:07 2006
--- openafs/src/libafs/MakefileProto.AIX.in	Wed Sep  3 14:27:24 2008
***************
*** 76,81 ****
--- 76,83 ----
  KMODS=32 
  <rs_aix50 rs_aix51 rs_aix52 rs_aix53>
  KMODS=32 64
+ <rs_aix61>
+ KMODS=64
  <all>
  
  include Makefile.common
Index: openafs/src/libafs/MakefileProto.FBSD.in
diff -c openafs/src/libafs/MakefileProto.FBSD.in:1.27.4.1 openafs/src/libafs/MakefileProto.FBSD.in:1.27.4.2
*** openafs/src/libafs/MakefileProto.FBSD.in:1.27.4.1	Tue Jan 15 01:09:13 2008
--- openafs/src/libafs/MakefileProto.FBSD.in	Tue Aug 26 10:01:38 2008
***************
*** 72,78 ****
--- 72,82 ----
  	-ln -fs ${KSRC}/@HOST_CPU@/include machine
  	-ln -fs ${KSRC}/netinet netinet
  	-ln -fs ${KSRC}/nfs nfs
+ <all -i386_fbsd_80>
  	-ln -fs /usr/include/rpc rpc
+ <i386_fbsd_80>
+ 	-ln -fs ${KSRC}/rpc rpc
+ <all>
  	-ln -fs ${KSRC}/sys sys
  	-ln -fs ${KSRC}/ufs/ufs ufs
  	-ln -fs ${KSRC}/sys h
Index: openafs/src/libafs/MakefileProto.LINUX.in
diff -c openafs/src/libafs/MakefileProto.LINUX.in:1.54.4.5 openafs/src/libafs/MakefileProto.LINUX.in:1.54.4.6
*** openafs/src/libafs/MakefileProto.LINUX.in:1.54.4.5	Tue Jul  1 18:51:54 2008
--- openafs/src/libafs/MakefileProto.LINUX.in	Wed Sep  3 12:59:18 2008
***************
*** 75,100 ****
  CCFLAGS = $(COMMON_KERN_CFLAGS) @P5PLUS_KOPTS@
  DEFINES = $(COMMON_DEFINES) -DCPU=586
  
! <amd64_linux24 amd64_linux26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -mcmodel=kernel -mno-red-zone
  DEFINES = $(COMMON_DEFINES) 
  
! <i386_umlinux22 i386_umlinux24 i386_umlinux26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) @P5PLUS_KOPTS@ -Wno-strict-prototypes -I$(LINUX_KERNEL_PATH)/arch/um/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/tt/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/skas/include
  DEFINES = $(COMMON_DEFINES) -DCPU=586
  
  <i386_umlinux26>
  EXTRA_CFLAGS = -I$(LINUX_KERNEL_PATH)/arch/um/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/tt/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/skas/include
  
! <alpha_linux_22 alpha_linux_24 alpha_linux_26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -mno-fp-regs -ffixed-8
  DEFINES = $(COMMON_DEFINES)
  
! <s390_linux22 s390_linux24 s390_linux26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char
  DEFINES = $(COMMON_DEFINES) -D__s390__ 
  
! <s390x_linux22 s390x_linux24 s390x_linux26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char
  DEFINES = $(COMMON_DEFINES) -D__s390x__ 
  
--- 75,100 ----
  CCFLAGS = $(COMMON_KERN_CFLAGS) @P5PLUS_KOPTS@
  DEFINES = $(COMMON_DEFINES) -DCPU=586
  
! <amd64_linux22 amd64_linux24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -mcmodel=kernel -mno-red-zone
  DEFINES = $(COMMON_DEFINES) 
  
! <i386_umlinux22 i386_umlinux24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) @P5PLUS_KOPTS@ -Wno-strict-prototypes -I$(LINUX_KERNEL_PATH)/arch/um/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/tt/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/skas/include
  DEFINES = $(COMMON_DEFINES) -DCPU=586
  
  <i386_umlinux26>
  EXTRA_CFLAGS = -I$(LINUX_KERNEL_PATH)/arch/um/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/tt/include -I$(LINUX_KERNEL_PATH)/arch/um/kernel/skas/include
  
! <alpha_linux_22 alpha_linux_24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -mno-fp-regs -ffixed-8
  DEFINES = $(COMMON_DEFINES)
  
! <s390_linux22 s390_linux24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char
  DEFINES = $(COMMON_DEFINES) -D__s390__ 
  
! <s390x_linux22 s390x_linux24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char
  DEFINES = $(COMMON_DEFINES) -D__s390x__ 
  
***************
*** 110,116 ****
        -mcpu=ultrasparc -m64 -mno-fpu -mcmodel=medlow -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
  DEFINES = $(COMMON_DEFINES) -DCPU=sparc64
  
! <ppc_linux22 ppc_linux24 ppc64_linux24 ppc64_linux26>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char -msoft-float -fno-builtin -ffixed-r2
  DEFINES = $(COMMON_DEFINES) -D__powerpc__
  
--- 110,116 ----
        -mcpu=ultrasparc -m64 -mno-fpu -mcmodel=medlow -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
  DEFINES = $(COMMON_DEFINES) -DCPU=sparc64
  
! <ppc_linux22 ppc_linux24 ppc64_linux22 ppc64_linux24>
  CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char -msoft-float -fno-builtin -ffixed-r2
  DEFINES = $(COMMON_DEFINES) -D__powerpc__
  
Index: openafs/src/libuafs/Makefile.common.in
diff -c openafs/src/libuafs/Makefile.common.in:1.13.4.7 openafs/src/libuafs/Makefile.common.in:1.13.4.8
*** openafs/src/libuafs/Makefile.common.in:1.13.4.7	Tue Jul  1 13:45:13 2008
--- openafs/src/libuafs/Makefile.common.in	Mon Sep 22 15:35:29 2008
***************
*** 90,95 ****
--- 90,96 ----
  	$(UOBJ)/afs_error.o \
  	$(UOBJ)/afs_axscache.o  \
  	$(UOBJ)/afs_buffer.o	\
+ 	$(UOBJ)/afs_bypasscache.o \
  	$(UOBJ)/afs_callback.o	\
  	$(UOBJ)/afs_cbqueue.o    \
  	$(UOBJ)/afs_cell.o \
***************
*** 217,222 ****
--- 218,224 ----
  	$(WEBOBJ)/afs_error.o \
  	$(WEBOBJ)/afs_axscache.o \
  	$(WEBOBJ)/afs_buffer.o \
+ 	$(WEBOBJ)/afs_bypasscache.o \
  	$(WEBOBJ)/afs_callback.o \
  	$(WEBOBJ)/afs_cbqueue.o \
  	$(WEBOBJ)/afs_cell.o \
***************
*** 345,350 ****
--- 347,353 ----
  	$(WEBOBJ)/afs_error.o \
  	$(WEBOBJ)/afs_axscache.o \
  	$(WEBOBJ)/afs_buffer.o \
+ 	$(WEBOBJ)/afs_bypasscache.o \
  	$(WEBOBJ)/afs_callback.o \
  	$(WEBOBJ)/afs_cbqueue.o \
  	$(WEBOBJ)/afs_cell.o \
***************
*** 468,473 ****
--- 471,477 ----
  	$(JUAFS)/afs_error.o \
  	$(JUAFS)/afs_axscache.o  \
  	$(JUAFS)/afs_buffer.o	\
+ 	$(JUAFS)/afs_bypasscache.o \
  	$(JUAFS)/afs_callback.o	\
  	$(JUAFS)/afs_cbqueue.o    \
  	$(JUAFS)/afs_cell.o \
***************
*** 600,605 ****
--- 604,611 ----
  	$(CRULE1)
  $(UOBJ)/afs_buffer.o: $(TOP_SRC_AFS)/afs_buffer.c
  	$(CRULE1)
+ $(UOBJ)/afs_bypasscache.o: $(TOP_SRC_AFS)/afs_bypasscache.c
+ 	$(CRULE1)
  $(UOBJ)/afs_cell.o: $(TOP_SRC_AFS)/afs_cell.c
  	$(CRULE1)
  $(UOBJ)/afs_conn.o: $(TOP_SRC_AFS)/afs_conn.c
***************
*** 861,866 ****
--- 867,874 ----
  	$(CRULE2)
  $(WEBOBJ)/afs_buffer.o: $(TOP_SRC_AFS)/afs_buffer.c
  	$(CRULE2)
+ $(WEBOBJ)/afs_bypasscache.o: $(TOP_SRC_AFS)/afs_bypasscache.c
+ 	$(CRULE2)
  $(WEBOBJ)/afs_cell.o: $(TOP_SRC_AFS)/afs_cell.c
  	$(CRULE2)
  $(WEBOBJ)/afs_conn.o: $(TOP_SRC_AFS)/afs_conn.c
***************
*** 1126,1131 ****
--- 1134,1141 ----
  	$(CRULE1)
  $(JUAFS)/afs_buffer.o: $(TOP_SRC_AFS)/afs_buffer.c
  	$(CRULE1)
+ $(JUAFS)/afs_bypasscache.o: $(TOP_SRC_AFS)/afs_bypasscache.c
+ 	$(CRULE1)
  $(JUAFS)/afs_cell.o: $(TOP_SRC_AFS)/afs_cell.c
  	$(CRULE1)
  $(JUAFS)/afs_conn.o: $(TOP_SRC_AFS)/afs_conn.c
Index: openafs/src/libuafs/MakefileProto.FBSD.in
diff -c openafs/src/libuafs/MakefileProto.FBSD.in:1.11.14.1 openafs/src/libuafs/MakefileProto.FBSD.in:1.11.14.2
*** openafs/src/libuafs/MakefileProto.FBSD.in:1.11.14.1	Tue Jan 15 01:09:13 2008
--- openafs/src/libuafs/MakefileProto.FBSD.in	Tue Aug 26 10:01:37 2008
***************
*** 19,27 ****
  
  TEST_CFLAGS=-D_REENTRANT -DAFS_PTHREAD_ENV -DAFS_FBSD40_ENV
  TEST_LDFLAGS=
! <all -i386_fbsd_62 -i386_fbsd_70>
  TEST_LIBS=-lc_r
! <i386_fbsd_62 -i386_fbsd_70>
  TEST_LIBS=-lpthread
  <all>
  
--- 19,27 ----
  
  TEST_CFLAGS=-D_REENTRANT -DAFS_PTHREAD_ENV -DAFS_FBSD40_ENV
  TEST_LDFLAGS=
! <all -i386_fbsd_62 -i386_fbsd_70 -i386_fbsd_80>
  TEST_LIBS=-lc_r
! <i386_fbsd_62 i386_fbsd_70 i386_fbsd_80>
  TEST_LIBS=-lpthread
  <all>
  
Index: openafs/src/packaging/MacOS/afslogo.jpg
Index: openafs/src/packaging/MacOS/background.jpg
Index: openafs/src/packaging/MacOS/decode-panic
diff -c openafs/src/packaging/MacOS/decode-panic:1.1.2.2 openafs/src/packaging/MacOS/decode-panic:1.1.2.3
*** openafs/src/packaging/MacOS/decode-panic:1.1.2.2	Sun Jan 27 13:46:14 2008
--- openafs/src/packaging/MacOS/decode-panic	Sun Sep 21 09:03:31 2008
***************
*** 113,119 ****
          chomp $line;
      
          #skip lines until "Backtrace" is seen
!         $line =~ /^\s*(Backtrace,|Backtrace:)/;
          $backtrace = $1;
          last if $backtrace;
      }
--- 113,119 ----
          chomp $line;
      
          #skip lines until "Backtrace" is seen
!         $line =~ /^\s*(Backtrace,|Backtrace:|Backtrace \()/;
          $backtrace = $1;
          last if $backtrace;
      }
***************
*** 257,263 ****
  
  =head1 VERSION
  
! This documentation refers to decode-panic version $Revision: 1.1.2.2 $
  
  =head1 SYNOPSIS
   
--- 257,263 ----
  
  =head1 VERSION
  
! This documentation refers to decode-panic version $Revision: 1.1.2.3 $
  
  =head1 SYNOPSIS
   
Index: openafs/src/packaging/RedHat/mockbuild.pl
diff -c openafs/src/packaging/RedHat/mockbuild.pl:1.1.4.4 openafs/src/packaging/RedHat/mockbuild.pl:1.1.4.5
*** openafs/src/packaging/RedHat/mockbuild.pl:1.1.4.4	Tue Apr 22 08:50:38 2008
--- openafs/src/packaging/RedHat/mockbuild.pl	Fri Sep 12 09:07:40 2008
***************
*** 68,129 ****
  				      kmod => '1',
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => 'fc5/i386' },
  		 "fedora-5-x86_64" => { osver => "fc5",
  				       kmod => '1',
  				       basearch => 'x86_64',
  				       updaterepo => 'updates-released',
! 				       results => 'fc5/x86_64' },
  		 "fedora-6-i386" => { osver => "fc6", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fc6/i386" },
  		 "fedora-6-x86_64" => { osver => "fc6",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fc6/x86_64" },
  		 "fedora-7-i386" => { osver => "fc7", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fc7/i386" },
  		 "fedora-7-x86_64" => { osver => "fc7",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fc7/x86_64" },
  		 "fedora-8-i386" => { osver => "fc8", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fc8/i386" },
  		 "fedora-8-x86_64" => { osver => "fc8",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fc8/x86_64" },
  		 "centos-4-i386" => { osver => "el4",
  				     kmod => '1',
  				     basearch => 'i386',
  				     updaterepo => 'update',
! 				     results => 'el4/i386' },
  		 "centos-4-x86_64" => { osver => "el4",
  				       kmod => '1',
  				       basearch => 'x86_64',
  				       updaterepo => 'update',
! 				       results => "el4/x86_64" },
  		 "centos-5-i386" => { osver => "el5", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'update',
! 				      results => "el5/i386" },
  		 "centos-5-x86_64" => { osver => "el5",
  					kmod => '1',
  				   	basearch => 'x86_64',
  				        updaterepo => 'update',
! 					results => "el5/x86_64" },
  		 "fedora-development-i386" => { osver => "fcd",
  					  kmod => '1',
  					  basearch => 'i386',
--- 68,139 ----
  				      kmod => '1',
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => 'fedora-5/i386' },
  		 "fedora-5-x86_64" => { osver => "fc5",
  				       kmod => '1',
  				       basearch => 'x86_64',
  				       updaterepo => 'updates-released',
! 				       results => 'fedora-5/x86_64' },
  		 "fedora-6-i386" => { osver => "fc6", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fedora-6/i386" },
  		 "fedora-6-x86_64" => { osver => "fc6",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fedora-6/x86_64" },
  		 "fedora-7-i386" => { osver => "fc7", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fedora-7/i386" },
  		 "fedora-7-x86_64" => { osver => "fc7",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fedora-7/x86_64" },
  		 "fedora-8-i386" => { osver => "fc8", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'updates-released',
! 				      results => "fedora-8/i386" },
  		 "fedora-8-x86_64" => { osver => "fc8",
  					kmod => '1',
  					basearch => 'x86_64',
  				        updaterepo => 'updates-released',
! 					results => "fedora-8/x86_64" },
  		 "centos-4-i386" => { osver => "el4",
  				     kmod => '1',
  				     basearch => 'i386',
  				     updaterepo => 'update',
! 				     results => 'rhel4/i386' },
  		 "centos-4-x86_64" => { osver => "el4",
  				       kmod => '1',
  				       basearch => 'x86_64',
  				       updaterepo => 'update',
! 				       results => "rhel4/x86_64" },
  		 "centos-5-i386" => { osver => "el5", 
  				      kmod => '1', 
  				      basearch => 'i386',
  				      updaterepo => 'update',
! 				      results => "rhel5/i386" },
  		 "centos-5-x86_64" => { osver => "el5",
  					kmod => '1',
  				   	basearch => 'x86_64',
  				        updaterepo => 'update',
! 					results => "rhel5/x86_64" },
! 		 "fedora-9-i386" => { osver => "fc9",
! 				      kmod => '1',
! 				      basearch => 'i386',
! 				      updaterepo => "updates-released",
! 				      results => 'fedora-9/i386' },
! 		 "fedora-9-x86_64" => { osver => "fc9",
! 					kmod => "1",
! 					basearch => "x86_64",
! 					updaterepo => "updates-released",
! 					results => "fedora-9/x86_64" },
  		 "fedora-development-i386" => { osver => "fcd",
  					  kmod => '1',
  					  basearch => 'i386',
***************
*** 177,183 ****
    my $osver = $platconf{$platform}{'osver'};
    my $root = $rootbase.$platform."/root";
    my $mockresults = $rootbase.$platform."/result";
!   my $resultdir = $resultbase.$platconf{$platform}{'results'};
    my $basearch = $platconf{$platform}{'basearch'};
    my $rpmstashdir = $stashbase.$platconf{$platform}{'results'}."/";
  
--- 187,193 ----
    my $osver = $platconf{$platform}{'osver'};
    my $root = $rootbase.$platform."/root";
    my $mockresults = $rootbase.$platform."/result";
!   my $resultdir = $resultbase."/".$platconf{$platform}{'results'};
    my $basearch = $platconf{$platform}{'basearch'};
    my $rpmstashdir = $stashbase.$platconf{$platform}{'results'}."/";
  
***************
*** 240,256 ****
  
    print "-------------------------------------------------------------------\n";
    print "Building the userland RPMs\n";
!   my @rpms = ('', '-authlibs', '-authlibs-devel', '-client', '-compat',
! 	      '-debuginfo', '-devel', '-docs', '-kernel-source', '-kpasswd',
! 	      '-krb5', '-server');
  
    my $missing = 0;
    foreach my $rpm (@rpms) {
!     if (! -f $resultdir."/openafs".$rpm."-".$oafsversion."-".$osver.".".
  	     $oafsrelease.".".$basearch.".rpm") {
        $missing++;
!       print $resultdir."/openafs".$rpm."-".$oafsversion."-".$osver.".".
! 	    $oafsrelease.".".$basearch.".rpm is missing!\n"
      }
    }
    if ($missing) {
--- 250,270 ----
  
    print "-------------------------------------------------------------------\n";
    print "Building the userland RPMs\n";
!   my @rpms = ('openafs', 'openafs-authlibs', 'openafs-authlibs-devel', 
! 	      'openafs-client', 'openafs-compat', 'openafs-debuginfo', 
! 	      'openafs-devel', 'openafs-docs', 'openafs-kernel-source', 
! 	      'openafs-kpasswd', 'openafs-krb5', 'openafs-server',
! 	      'dkms-openafs');
!   my @missingrpms=();
  
    my $missing = 0;
    foreach my $rpm (@rpms) {
!     if (! -f $resultdir."/".$rpm."-".$oafsversion."-".$osver.".".
  	     $oafsrelease.".".$basearch.".rpm") {
        $missing++;
!       print $resultdir."/".$rpm."-".$oafsversion."-".$osver.".".
! 	    $oafsrelease.".".$basearch.".rpm is missing!\n";
!       push @missingrpms, $rpm;
      }
    }
    if ($missing) {
***************
*** 263,274 ****
  		        ' --define "build_authlibs 1" '.
  		        $srpm) == 0
        or die "build failed with : $!\n";
!     foreach my $rpm (@rpms) {
!       system("cp ".$mockresults."/openafs".$rpm."-".$oafsversion."-".
  		   $osver.".".$oafsrelease.".".$basearch.".rpm ".
  		   $resultdir) == 0
            or die "Copy failed with : $!\n";
!       push @newrpms, $mockresults."/openafs".$rpm."-".$oafsversion."-".
  		     $osver.".".$oafsrelease.".".$basearch.".rpm";
      }
    } else {
--- 277,288 ----
  		        ' --define "build_authlibs 1" '.
  		        $srpm) == 0
        or die "build failed with : $!\n";
!     foreach my $rpm (@missingrpms) {
!       system("cp ".$mockresults."/".$rpm."-".$oafsversion."-".
  		   $osver.".".$oafsrelease.".".$basearch.".rpm ".
  		   $resultdir) == 0
            or die "Copy failed with : $!\n";
!       push @newrpms, $mockresults."/".$rpm."-".$oafsversion."-".
  		     $osver.".".$oafsrelease.".".$basearch.".rpm";
      }
    } else {
Index: openafs/src/packaging/RedHat/openafs.spec.in
diff -c openafs/src/packaging/RedHat/openafs.spec.in:1.2.2.24 openafs/src/packaging/RedHat/openafs.spec.in:1.2.2.26
*** openafs/src/packaging/RedHat/openafs.spec.in:1.2.2.24	Mon Jul  7 12:42:29 2008
--- openafs/src/packaging/RedHat/openafs.spec.in	Tue Aug 26 09:44:43 2008
***************
*** 1,4 ****
! # Openafs Spec $Revision: 1.2.2.24 $
  
  %define afsvers @VERSION@
  %define pkgvers @LINUX_PKGVER@
--- 1,4 ----
! # Openafs Spec $Revision: 1.2.2.26 $
  
  %define afsvers @VERSION@
  %define pkgvers @LINUX_PKGVER@
***************
*** 19,24 ****
--- 19,25 ----
  %define kernvers_on_cmdline %{?kernvers:1}%{!?kernvers:0}
  %define build_userspace_on_cmdline %{?build_userspace:1}%{!?build_userspace:0}
  %define build_modules_on_cmdline %{?build_modules:1}%{!?build_modules:0}
+ %define build_authlibs_on_cmdline %{?build_authlibs:1}%{!?build_authlibs:0}
  
  # Determine the version of the kernel to build against
  # - automatically select running kernel if there are sources in /lib/modules
***************
*** 231,236 ****
--- 232,245 ----
  %endif
  %endif
  
+ %if !%{build_authlibs_on_cmdline}
+ %if %{build_userspace_on_cmdline}
+ %define build_authlibs 1
+ %else
+ %define build_authlibs 0
+ %endif
+ %endif
+ 
  # Make sure RPM doesn't complain about installed but non-packaged files.
  #define __check_files  %{nil}
  
***************
*** 1353,1359 ****
  dkms install -m %{name} -v %{dkms_version} --rpm_safe_upgrade
  
  %preun -n dkms-%{name}
! dkms remove -m %{namee} -v %{dkms_version} --rpm_safe_upgrade --all ||:
  %endif
  %endif
  
--- 1362,1368 ----
  dkms install -m %{name} -v %{dkms_version} --rpm_safe_upgrade
  
  %preun -n dkms-%{name}
! dkms remove -m %{name} -v %{dkms_version} --rpm_safe_upgrade --all ||:
  %endif
  %endif
  
Index: openafs/src/pam/afs_auth.c
diff -c openafs/src/pam/afs_auth.c:1.13 openafs/src/pam/afs_auth.c:1.13.4.1
*** openafs/src/pam/afs_auth.c:1.13	Sun May 29 23:35:52 2005
--- openafs/src/pam/afs_auth.c	Tue Aug 26 10:11:46 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/pam/afs_auth.c,v 1.13 2005/05/30 03:35:52 shadow Exp $");
  
  #include <syslog.h>
  #include <stdlib.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/pam/afs_auth.c,v 1.13.4.1 2008/08/26 14:11:46 shadow Exp $");
  
  #include <syslog.h>
  #include <stdlib.h>
***************
*** 192,197 ****
--- 192,199 ----
  #else
  #if     defined(AFS_LINUX20_ENV) || defined(AFS_FBSD_ENV) || defined(AFS_NBSD_ENV)
      upwd = getpwnam(user);
+ #elif   defined(_POSIX_PTHREAD_SEMANTICS) && defined(AFS_SUN5_ENV)
+     getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf), &upwd);
  #else
      upwd = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
  #endif
Index: openafs/src/ptserver/ptserver.c
diff -c openafs/src/ptserver/ptserver.c:1.25.2.8 openafs/src/ptserver/ptserver.c:1.25.2.10
*** openafs/src/ptserver/ptserver.c:1.25.2.8	Wed Apr  2 15:51:56 2008
--- openafs/src/ptserver/ptserver.c	Wed Sep 24 17:36:54 2008
***************
*** 112,118 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/ptserver/ptserver.c,v 1.25.2.8 2008/04/02 19:51:56 shadow Exp $");
  
  #include <afs/stds.h>
  #ifdef	AFS_AIX32_ENV
--- 112,118 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/ptserver/ptserver.c,v 1.25.2.10 2008/09/24 21:36:54 shadow Exp $");
  
  #include <afs/stds.h>
  #ifdef	AFS_AIX32_ENV
***************
*** 160,165 ****
--- 160,166 ----
  int pr_realmNameLen;
  char *pr_realmName;
  
+ int debuglevel = 0;
  int restricted = 0;
  int rxMaxMTU = -1;
  int rxBind = 0;
***************
*** 280,285 ****
--- 281,293 ----
  	if ((strncmp(arg, "-database", alen) == 0)
  	    || (strncmp(arg, "-db", alen) == 0)) {
  	    pr_dbaseName = argv[++a];	/* specify a database */
+ 	} else if (strcmp(argv[a], "-d") == 0) {
+ 	    if ((a + 1) >= argc) {
+ 		fprintf(stderr, "missing argument for -d\n"); 
+ 		return -1; 
+ 	    }
+ 	    debuglevel = atoi(argv[++a]);
+ 	    LogLevel = debuglevel;
  	} else if (strncmp(arg, "-p", alen) == 0) {
  	    lwps = atoi(argv[++a]);
  	    if (lwps > 16) {	/* maximum of 16 */
***************
*** 378,384 ****
  #ifndef AFS_NT40_ENV
  	    printf("Usage: ptserver [-database <db path>] "
  		   "[-auditlog <log path>] "
! 		   "[-syslog[=FACILITY]] "
  		   "[-p <number of processes>] [-rebuild] "
  		   "[-groupdepth <depth>] "
  		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
--- 386,392 ----
  #ifndef AFS_NT40_ENV
  	    printf("Usage: ptserver [-database <db path>] "
  		   "[-auditlog <log path>] "
! 		   "[-syslog[=FACILITY]] [-d <debug level>] "
  		   "[-p <number of processes>] [-rebuild] "
  		   "[-groupdepth <depth>] "
  		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
***************
*** 388,394 ****
  		   "[-help]\n");
  #else /* AFS_NT40_ENV */
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] "
  		   "[-p <number of processes>] [-rebuild] [-rxbind] "
  		   "[-allow-dotted-principals] "
  		   "[-default_access default_user_access default_group_access] "
--- 396,402 ----
  		   "[-help]\n");
  #else /* AFS_NT40_ENV */
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] [-d <debug level>] "
  		   "[-p <number of processes>] [-rebuild] [-rxbind] "
  		   "[-allow-dotted-principals] "
  		   "[-default_access default_user_access default_group_access] "
***************
*** 398,404 ****
  #else
  #ifndef AFS_NT40_ENV
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-p <number of processes>] [-rebuild] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
--- 406,412 ----
  #else
  #ifndef AFS_NT40_ENV
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] [-d <debug level>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-p <number of processes>] [-rebuild] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
***************
*** 408,414 ****
  		   "[-help]\n");
  #else /* AFS_NT40_ENV */
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] "
  		   "[-default_access default_user_access default_group_access] "
  		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
  		   "[-allow-dotted-principals] "
--- 416,422 ----
  		   "[-help]\n");
  #else /* AFS_NT40_ENV */
  	    printf("Usage: ptserver [-database <db path>] "
! 		   "[-auditlog <log path>] [-d <debug level>] "
  		   "[-default_access default_user_access default_group_access] "
  		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
  		   "[-allow-dotted-principals] "
***************
*** 566,573 ****
      rx_SetMaxProcs(tservice, lwps);
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK,
!                                     NULL);
      }
  
      tservice =
--- 574,580 ----
      rx_SetMaxProcs(tservice, lwps);
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
      }
  
      tservice =
Index: openafs/src/rx/rx.c
diff -c openafs/src/rx/rx.c:1.97.2.27 openafs/src/rx/rx.c:1.97.2.37
*** openafs/src/rx/rx.c:1.97.2.27	Tue Jul 22 00:18:28 2008
--- openafs/src/rx/rx.c	Thu Sep 25 16:17:54 2008
***************
*** 17,23 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx.c,v 1.97.2.27 2008/07/22 04:18:28 jaltman Exp $");
  
  #ifdef KERNEL
  #include "afs/sysincludes.h"
--- 17,23 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx.c,v 1.97.2.37 2008/09/25 20:17:54 shadow Exp $");
  
  #ifdef KERNEL
  #include "afs/sysincludes.h"
***************
*** 85,90 ****
--- 85,91 ----
  #else /* KERNEL */
  # include <sys/types.h>
  # include <string.h>
+ # include <stdarg.h>
  # include <errno.h>
  #ifdef AFS_NT40_ENV
  # include <stdlib.h>
***************
*** 108,115 ****
  # include <afs/rxgen_consts.h>
  #endif /* KERNEL */
  
! int (*registerProgram) () = 0;
! int (*swapNameProgram) () = 0;
  
  /* Local static routines */
  static void rxi_DestroyConnectionNoLock(register struct rx_connection *conn);
--- 109,125 ----
  # include <afs/rxgen_consts.h>
  #endif /* KERNEL */
  
! #ifndef KERNEL
! #ifdef AFS_PTHREAD_ENV
! #ifndef AFS_NT40_ENV
! int (*registerProgram) (pid_t, char *) = 0;
! int (*swapNameProgram) (pid_t, const char *, char *) = 0;
! #endif
! #else
! int (*registerProgram) (PROCESS, char *) = 0;
! int (*swapNameProgram) (PROCESS, const char *, char *) = 0;
! #endif
! #endif
  
  /* Local static routines */
  static void rxi_DestroyConnectionNoLock(register struct rx_connection *conn);
***************
*** 172,177 ****
--- 182,188 ----
  static pthread_mutex_t epoch_mutex;
  static pthread_mutex_t rx_init_mutex;
  static pthread_mutex_t rx_debug_mutex;
+ static pthread_mutex_t rx_rpc_stats;
  
  static void
  rxi_InitPthread(void)
***************
*** 217,222 ****
--- 228,252 ----
      assert(pthread_key_create(&rx_ts_info_key, NULL) == 0);
   
      rxkad_global_stats_init();
+ 
+     MUTEX_INIT(&rx_rpc_stats, "rx_rpc_stats", MUTEX_DEFAULT, 0);
+     MUTEX_INIT(&rx_freePktQ_lock, "rx_freePktQ_lock", MUTEX_DEFAULT, 0);
+ #ifdef	RX_ENABLE_LOCKS
+ #ifdef RX_LOCKS_DB
+     rxdb_init();
+ #endif /* RX_LOCKS_DB */
+     MUTEX_INIT(&freeSQEList_lock, "freeSQEList lock", MUTEX_DEFAULT, 0);
+     MUTEX_INIT(&rx_freeCallQueue_lock, "rx_freeCallQueue_lock", MUTEX_DEFAULT,
+ 	       0);
+     CV_INIT(&rx_waitingForPackets_cv, "rx_waitingForPackets_cv", CV_DEFAULT,
+ 	    0);
+     MUTEX_INIT(&rx_peerHashTable_lock, "rx_peerHashTable_lock", MUTEX_DEFAULT,
+ 	       0);
+     MUTEX_INIT(&rx_connHashTable_lock, "rx_connHashTable_lock", MUTEX_DEFAULT,
+ 	       0);
+     MUTEX_INIT(&rx_serverPool_lock, "rx_serverPool_lock", MUTEX_DEFAULT, 0);
+     MUTEX_INIT(&rxi_keyCreate_lock, "rxi_keyCreate_lock", MUTEX_DEFAULT, 0);
+ #endif /* RX_ENABLE_LOCKS */
  }
  
  pthread_once_t rx_once_init = PTHREAD_ONCE_INIT;
***************
*** 264,272 ****
   * to manipulate the queue.
   */
  
! #ifdef RX_ENABLE_LOCKS
  static afs_kmutex_t rx_rpc_stats;
! void rxi_StartUnlocked();
  #endif
  
  /* We keep a "last conn pointer" in rxi_FindConnection. The odds are 
--- 294,303 ----
   * to manipulate the queue.
   */
  
! #if defined(RX_ENABLE_LOCKS) && defined(KERNEL)
  static afs_kmutex_t rx_rpc_stats;
! void rxi_StartUnlocked(struct rxevent *event, void *call,
!                        void *arg1, int istack);
  #endif
  
  /* We keep a "last conn pointer" in rxi_FindConnection. The odds are 
***************
*** 423,429 ****
  	UNLOCK_RX_INIT;
  	return RX_ADDRINUSE;
      }
! #ifdef	RX_ENABLE_LOCKS
  #ifdef RX_LOCKS_DB
      rxdb_init();
  #endif /* RX_LOCKS_DB */
--- 454,460 ----
  	UNLOCK_RX_INIT;
  	return RX_ADDRINUSE;
      }
! #if defined(RX_ENABLE_LOCKS) && defined(KERNEL)
  #ifdef RX_LOCKS_DB
      rxdb_init();
  #endif /* RX_LOCKS_DB */
***************
*** 440,458 ****
      MUTEX_INIT(&rx_connHashTable_lock, "rx_connHashTable_lock", MUTEX_DEFAULT,
  	       0);
      MUTEX_INIT(&rx_serverPool_lock, "rx_serverPool_lock", MUTEX_DEFAULT, 0);
! #ifndef KERNEL
!     MUTEX_INIT(&rxi_keyCreate_lock, "rxi_keyCreate_lock", MUTEX_DEFAULT, 0);
! #endif /* !KERNEL */
! #if defined(KERNEL) && defined(AFS_HPUX110_ENV)
      if (!uniprocessor)
  	rx_sleepLock = alloc_spinlock(LAST_HELD_ORDER - 10, "rx_sleepLock");
! #endif /* KERNEL && AFS_HPUX110_ENV */
! #endif /* RX_ENABLE_LOCKS */
  
      rxi_nCalls = 0;
      rx_connDeadTime = 12;
      rx_tranquil = 0;		/* reset flag */
!     memset((char *)&rx_stats, 0, sizeof(struct rx_stats));
      htable = (char *)
  	osi_Alloc(rx_hashTableSize * sizeof(struct rx_connection *));
      PIN(htable, rx_hashTableSize * sizeof(struct rx_connection *));	/* XXXXX */
--- 471,486 ----
      MUTEX_INIT(&rx_connHashTable_lock, "rx_connHashTable_lock", MUTEX_DEFAULT,
  	       0);
      MUTEX_INIT(&rx_serverPool_lock, "rx_serverPool_lock", MUTEX_DEFAULT, 0);
! #if defined(AFS_HPUX110_ENV)
      if (!uniprocessor)
  	rx_sleepLock = alloc_spinlock(LAST_HELD_ORDER - 10, "rx_sleepLock");
! #endif /* AFS_HPUX110_ENV */
! #endif /* RX_ENABLE_LOCKS && KERNEL */
  
      rxi_nCalls = 0;
      rx_connDeadTime = 12;
      rx_tranquil = 0;		/* reset flag */
!     memset((char *)&rx_stats, 0, sizeof(struct rx_statistics));
      htable = (char *)
  	osi_Alloc(rx_hashTableSize * sizeof(struct rx_connection *));
      PIN(htable, rx_hashTableSize * sizeof(struct rx_connection *));	/* XXXXX */
***************
*** 493,499 ****
  	rx_port = 0;
  #else
  	struct sockaddr_in addr;
! 	int addrlen = sizeof(addr);
  	if (getsockname((int)rx_socket, (struct sockaddr *)&addr, &addrlen)) {
  	    rx_Finalize();
  	    return -1;
--- 521,531 ----
  	rx_port = 0;
  #else
  	struct sockaddr_in addr;
! #ifdef AFS_NT40_ENV
!         int addrlen = sizeof(addr);
! #else
! 	socklen_t addrlen = sizeof(addr);
! #endif
  	if (getsockname((int)rx_socket, (struct sockaddr *)&addr, &addrlen)) {
  	    rx_Finalize();
  	    return -1;
***************
*** 708,714 ****
      }
  
      /* Turn on reaping of idle server connections */
!     rxi_ReapConnections();
  
      USERPRI;
  
--- 740,746 ----
      }
  
      /* Turn on reaping of idle server connections */
!     rxi_ReapConnections(NULL, NULL, NULL);
  
      USERPRI;
  
***************
*** 763,769 ****
      conn = rxi_AllocConnection();
  #ifdef	RX_ENABLE_LOCKS
      MUTEX_INIT(&conn->conn_call_lock, "conn call lock", MUTEX_DEFAULT, 0);
!     MUTEX_INIT(&conn->conn_data_lock, "conn call lock", MUTEX_DEFAULT, 0);
      CV_INIT(&conn->conn_call_cv, "conn call cv", CV_DEFAULT, 0);
  #endif
      NETPRI;
--- 795,801 ----
      conn = rxi_AllocConnection();
  #ifdef	RX_ENABLE_LOCKS
      MUTEX_INIT(&conn->conn_call_lock, "conn call lock", MUTEX_DEFAULT, 0);
!     MUTEX_INIT(&conn->conn_data_lock, "conn data lock", MUTEX_DEFAULT, 0);
      CV_INIT(&conn->conn_call_cv, "conn call cv", CV_DEFAULT, 0);
  #endif
      NETPRI;
***************
*** 1041,1046 ****
--- 1073,1079 ----
      USERPRI;
  }
  
+ #ifdef  AFS_GLOBAL_RXLOCK_KERNEL
  /* Wait for the transmit queue to no longer be busy. 
   * requires the call->lock to be held */
  static void rxi_WaitforTQBusy(struct rx_call *call) {
***************
*** 1059,1064 ****
--- 1092,1099 ----
  	}
      }
  }
+ #endif
+ 
  /* Start a new rx remote procedure call, on the specified connection.
   * If wait is set to 1, wait for a free call channel; otherwise return
   * 0.  Maxtime gives the maximum number of seconds this call may take,
***************
*** 1186,1193 ****
      MUTEX_ENTER(&call->lock);
      rxi_WaitforTQBusy(call);
      if (call->flags & RX_CALL_TQ_CLEARME) {
! 	rxi_ClearTransmitQueue(call, 0);
! 	queue_Init(&call->tq);
      }
      MUTEX_EXIT(&call->lock);
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
--- 1221,1228 ----
      MUTEX_ENTER(&call->lock);
      rxi_WaitforTQBusy(call);
      if (call->flags & RX_CALL_TQ_CLEARME) {
! 	rxi_ClearTransmitQueue(call, 1);
! 	/*queue_Init(&call->tq);*/
      }
      MUTEX_EXIT(&call->lock);
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
***************
*** 1970,1976 ****
       * kernel version, and may interrupt the macros rx_Read or
       * rx_Write, which run at normal priority for efficiency. */
      if (call->currentPacket) {
! 	queue_Prepend(&call->iovq, call->currentPacket);
  	call->currentPacket = (struct rx_packet *)0;
      }
  	
--- 2005,2012 ----
       * kernel version, and may interrupt the macros rx_Read or
       * rx_Write, which run at normal priority for efficiency. */
      if (call->currentPacket) {
!         call->currentPacket->flags &= ~RX_PKTFLAG_CP;
! 	rxi_FreePacket(call->currentPacket);
  	call->currentPacket = (struct rx_packet *)0;
      }
  	
***************
*** 2138,2153 ****
  #ifdef	AFS_GLOBAL_RXLOCK_KERNEL
  	/* Now, if TQ wasn't cleared earlier, do it now. */
  	if (call->flags & RX_CALL_TQ_CLEARME) {
! 	    rxi_ClearTransmitQueue(call, 0);
! 	    queue_Init(&call->tq);
  	}
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
  	/* Bind the call to its connection structure */
  	call->conn = conn;
  	rxi_ResetCall(call, 1);
      } else {
- 	call = (struct rx_call *)rxi_Alloc(sizeof(struct rx_call));
  
  	MUTEX_EXIT(&rx_freeCallQueue_lock);
  	MUTEX_INIT(&call->lock, "call lock", MUTEX_DEFAULT, NULL);
  	MUTEX_ENTER(&call->lock);
--- 2174,2190 ----
  #ifdef	AFS_GLOBAL_RXLOCK_KERNEL
  	/* Now, if TQ wasn't cleared earlier, do it now. */
  	if (call->flags & RX_CALL_TQ_CLEARME) {
! 	    rxi_ClearTransmitQueue(call, 1);
! 	    /*queue_Init(&call->tq);*/
  	}
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
  	/* Bind the call to its connection structure */
  	call->conn = conn;
  	rxi_ResetCall(call, 1);
      } else {
  
+ 	call = (struct rx_call *)rxi_Alloc(sizeof(struct rx_call));
+         rx_MutexIncrement(rx_stats.nCallStructs, rx_stats_mutex);
  	MUTEX_EXIT(&rx_freeCallQueue_lock);
  	MUTEX_INIT(&call->lock, "call lock", MUTEX_DEFAULT, NULL);
  	MUTEX_ENTER(&call->lock);
***************
*** 2155,2161 ****
  	CV_INIT(&call->cv_rq, "call rq", CV_DEFAULT, 0);
  	CV_INIT(&call->cv_tq, "call tq", CV_DEFAULT, 0);
  
-         rx_MutexIncrement(rx_stats.nFreeCallStructs, rx_stats_mutex);
  	/* Initialize once-only items */
  	queue_Init(&call->tq);
  	queue_Init(&call->rq);
--- 2192,2197 ----
***************
*** 2254,2261 ****
      register char *p;
  
      rx_MutexAdd1Increment2(rxi_Allocsize, (afs_int32)size, rxi_Alloccnt, rx_stats_mutex);
-     p = (char *)osi_Alloc(size);
  
      if (!p)
  	osi_Panic("rxi_Alloc error");
      memset(p, 0, size);
--- 2290,2302 ----
      register char *p;
  
      rx_MutexAdd1Increment2(rxi_Allocsize, (afs_int32)size, rxi_Alloccnt, rx_stats_mutex);
  
+ p = (char *)
+ #if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_FBSD80_ENV)
+   afs_osi_Alloc_NoSleep(size);
+ #else
+   osi_Alloc(size);
+ #endif
      if (!p)
  	osi_Panic("rxi_Alloc error");
      memset(p, 0, size);
***************
*** 2292,2298 ****
             }
         }
      } else {
!        struct rx_peer *peer, *next;
         hashIndex = PEER_HASH(host, port);
         for (peer = rx_peerHashTable[hashIndex]; peer; peer = peer->next) {
             if ((peer->host == host) && (peer->port == port)) {
--- 2333,2339 ----
             }
         }
      } else {
!        struct rx_peer *peer;
         hashIndex = PEER_HASH(host, port);
         for (peer = rx_peerHashTable[hashIndex]; peer; peer = peer->next) {
             if ((peer->host == host) && (peer->port == port)) {
***************
*** 2465,2472 ****
   * containing the network address.  Both can be modified.  The return value, if
   * non-zero, indicates that the packet should be dropped.  */
  
! int (*rx_justReceived) () = 0;
! int (*rx_almostSent) () = 0;
  
  /* A packet has been received off the interface.  Np is the packet, socket is
   * the socket number it was received from (useful in determining which service
--- 2506,2513 ----
   * containing the network address.  Both can be modified.  The return value, if
   * non-zero, indicates that the packet should be dropped.  */
  
! int (*rx_justReceived) (struct rx_packet *, struct sockaddr_in *) = 0;
! int (*rx_almostSent) (struct rx_packet *, struct sockaddr_in *) = 0;
  
  /* A packet has been received off the interface.  Np is the packet, socket is
   * the socket number it was received from (useful in determining which service
***************
*** 3016,3024 ****
  #endif /* KERNEL */
  
  static void
! rxi_CheckReachEvent(struct rxevent *event, struct rx_connection *conn,
! 		    struct rx_call *acall)
  {
      struct rx_call *call = acall;
      struct clock when, now;
      int i, waiting;
--- 3057,3066 ----
  #endif /* KERNEL */
  
  static void
! rxi_CheckReachEvent(struct rxevent *event, void *arg1, void *arg2)
  {
+     struct rx_connection *conn = arg1;
+     struct rx_call *acall = arg2;
      struct rx_call *call = acall;
      struct clock when, now;
      int i, waiting;
***************
*** 3233,3238 ****
--- 3275,3281 ----
  	    /* It's the next packet. Stick it on the receive queue
  	     * for this call. Set newPackets to make sure we wake
  	     * the reader once all packets have been processed */
+ 	    np->flags |= RX_PKTFLAG_RQ;
  	    queue_Prepend(&call->rq, np);
  	    call->nSoftAcks++;
  	    np = NULL;		/* We can't use this anymore */
***************
*** 3679,3684 ****
--- 3722,3728 ----
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
  	{
  	    queue_Remove(tp);
+ 	    tp->flags &= ~RX_PKTFLAG_TQ;
  	    rxi_FreePacket(tp);	/* rxi_FreePacket mustn't wake up anyone, preemptively. */
  	}
      }
***************
*** 4218,4226 ****
  }
  
  void
! rxi_SendDelayedAck(struct rxevent *event, register struct rx_call *call,
! 		   char *dummy)
  {
  #ifdef RX_ENABLE_LOCKS
      if (event) {
  	MUTEX_ENTER(&call->lock);
--- 4262,4270 ----
  }
  
  void
! rxi_SendDelayedAck(struct rxevent *event, void *arg1, void *unused)
  {
+     struct rx_call *call = arg1;
  #ifdef RX_ENABLE_LOCKS
      if (event) {
  	MUTEX_ENTER(&call->lock);
***************
*** 4457,4463 ****
      if (call->error)
  	error = call->error;
  
! #ifdef RX_GLOBAL_RXLOCK_KERNEL
      if (!((call->flags & RX_CALL_TQ_BUSY) || (call->tqWaiters > 0))) {
  	rxi_ResetCall(call, 0);
      }
--- 4501,4507 ----
      if (call->error)
  	error = call->error;
  
! #ifdef AFS_GLOBAL_RXLOCK_KERNEL
      if (!((call->flags & RX_CALL_TQ_BUSY) || (call->tqWaiters > 0))) {
  	rxi_ResetCall(call, 0);
      }
***************
*** 4534,4540 ****
      MUTEX_EXIT(&peer->peer_lock);
  
      flags = call->flags;
-     rxi_ClearReceiveQueue(call);
  #ifdef	AFS_GLOBAL_RXLOCK_KERNEL
      if (flags & RX_CALL_TQ_BUSY) {
  	call->flags = RX_CALL_TQ_CLEARME | RX_CALL_TQ_BUSY;
--- 4578,4583 ----
***************
*** 4542,4549 ****
      } else
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
      {
! 	rxi_ClearTransmitQueue(call, 0);
! 	queue_Init(&call->tq);
  	if (call->tqWaiters || (flags & RX_CALL_TQ_WAIT)) {
  	    dpf(("rcall %x has %d waiters and flags %d\n", call, call->tqWaiters, call->flags));
  	}
--- 4585,4592 ----
      } else
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
      {
! 	rxi_ClearTransmitQueue(call, 1);
! 	/* why init the queue if you just emptied it? queue_Init(&call->tq); */
  	if (call->tqWaiters || (flags & RX_CALL_TQ_WAIT)) {
  	    dpf(("rcall %x has %d waiters and flags %d\n", call, call->tqWaiters, call->flags));
  	}
***************
*** 4557,4563 ****
  	    call->tqWaiters--;
  	}
      }
!     queue_Init(&call->rq);
      call->error = 0;
      call->twind = call->conn->twind[call->channel];
      call->rwind = call->conn->rwind[call->channel];
--- 4600,4618 ----
  	    call->tqWaiters--;
  	}
      }
! 
!     rxi_ClearReceiveQueue(call);
!     /* why init the queue if you just emptied it? queue_Init(&call->rq); */
!     
!     if (call->currentPacket) {
!         call->currentPacket->flags &= ~RX_PKTFLAG_CP;
! 	rxi_FreePacket(call->currentPacket);
! 	call->currentPacket = (struct rx_packet *)0;
!     }
!     call->curlen = call->nLeft = call->nFree = 0;
! 
!     rxi_FreePackets(0, &call->iovq);
! 
      call->error = 0;
      call->twind = call->conn->twind[call->channel];
      call->rwind = call->conn->rwind[call->channel];
***************
*** 5073,5081 ****
  #ifdef	RX_ENABLE_LOCKS
  /* Call rxi_Start, below, but with the call lock held. */
  void
! rxi_StartUnlocked(struct rxevent *event, register struct rx_call *call,
! 		  void *arg1, int istack)
  {
      MUTEX_ENTER(&call->lock);
      rxi_Start(event, call, arg1, istack);
      MUTEX_EXIT(&call->lock);
--- 5128,5138 ----
  #ifdef	RX_ENABLE_LOCKS
  /* Call rxi_Start, below, but with the call lock held. */
  void
! rxi_StartUnlocked(struct rxevent *event, 
! 		  void *arg0, void *arg1, int istack)
  {
+     struct rx_call *call = arg0;
+     
      MUTEX_ENTER(&call->lock);
      rxi_Start(event, call, arg1, istack);
      MUTEX_EXIT(&call->lock);
***************
*** 5088,5096 ****
   * better optimized for new packets, the usual case, now that we've
   * got rid of queues of send packets. XXXXXXXXXXX */
  void
! rxi_Start(struct rxevent *event, register struct rx_call *call,
! 	  void *arg1, int istack)
  {
      struct rx_packet *p;
      register struct rx_packet *nxp;	/* Next pointer for queue_Scan */
      struct rx_peer *peer = call->conn->peer;
--- 5145,5155 ----
   * better optimized for new packets, the usual case, now that we've
   * got rid of queues of send packets. XXXXXXXXXXX */
  void
! rxi_Start(struct rxevent *event, 
!           void *arg0, void *arg1, int istack)
  {
+     struct rx_call *call = arg0;
+     
      struct rx_packet *p;
      register struct rx_packet *nxp;	/* Next pointer for queue_Scan */
      struct rx_peer *peer = call->conn->peer;
***************
*** 5200,5206 ****
  		nXmitPackets = 0;
  		maxXmitPackets = MIN(call->twind, call->cwind);
  		xmitList = (struct rx_packet **)
! 		    osi_Alloc(maxXmitPackets * sizeof(struct rx_packet *));
  		if (xmitList == NULL)
  		    osi_Panic("rxi_Start, failed to allocate xmit list");
  		for (queue_Scan(&call->tq, p, nxp, rx_packet)) {
--- 5259,5270 ----
  		nXmitPackets = 0;
  		maxXmitPackets = MIN(call->twind, call->cwind);
  		xmitList = (struct rx_packet **)
! #if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_FBSD80_ENV)
! 		    /* XXXX else we must drop any mtx we hold */
! 		    afs_osi_Alloc_NoSleep(maxXmitPackets * sizeof(struct rx_packet *));
! #else
! 		osi_Alloc(maxXmitPackets * sizeof(struct rx_packet *));
! #endif
  		if (xmitList == NULL)
  		    osi_Panic("rxi_Start, failed to allocate xmit list");
  		for (queue_Scan(&call->tq, p, nxp, rx_packet)) {
***************
*** 5317,5322 ****
--- 5381,5387 ----
  			if (p->header.seq < call->tfirst
  			    && (p->flags & RX_PKTFLAG_ACKED)) {
  			    queue_Remove(p);
+ 			    p->flags &= ~RX_PKTFLAG_TQ;
  			    rxi_FreePacket(p);
  			} else
  			    missing = 1;
***************
*** 5458,5464 ****
      afs_uint32 now;
      afs_uint32 deadTime;
  
! #ifdef RX_GLOBAL_RXLOCK_KERNEL
      if (call->flags & RX_CALL_TQ_BUSY) {
  	/* Call is active and will be reset by rxi_Start if it's
  	 * in an error state.
--- 5523,5529 ----
      afs_uint32 now;
      afs_uint32 deadTime;
  
! #ifdef AFS_GLOBAL_RXLOCK_KERNEL
      if (call->flags & RX_CALL_TQ_BUSY) {
  	/* Call is active and will be reset by rxi_Start if it's
  	 * in an error state.
***************
*** 5560,5568 ****
   * keep-alive packet (if we're actually trying to keep the call alive)
   */
  void
! rxi_KeepAliveEvent(struct rxevent *event, register struct rx_call *call,
! 		   char *dummy)
  {
      struct rx_connection *conn;
      afs_uint32 now;
  
--- 5625,5633 ----
   * keep-alive packet (if we're actually trying to keep the call alive)
   */
  void
! rxi_KeepAliveEvent(struct rxevent *event, void *arg1, void *dummy)
  {
+     struct rx_call *call = arg1;
      struct rx_connection *conn;
      afs_uint32 now;
  
***************
*** 5631,5638 ****
   * that have been delayed to throttle looping clients. */
  void
  rxi_SendDelayedConnAbort(struct rxevent *event,
! 			 register struct rx_connection *conn, char *dummy)
  {
      afs_int32 error;
      struct rx_packet *packet;
  
--- 5696,5705 ----
   * that have been delayed to throttle looping clients. */
  void
  rxi_SendDelayedConnAbort(struct rxevent *event,
! 			 void *arg1, void *unused)
  {
+     struct rx_connection *conn = arg1;
+     
      afs_int32 error;
      struct rx_packet *packet;
  
***************
*** 5654,5662 ****
  /* This routine is called to send call abort messages
   * that have been delayed to throttle looping clients. */
  void
! rxi_SendDelayedCallAbort(struct rxevent *event, register struct rx_call *call,
! 			 char *dummy)
  {
      afs_int32 error;
      struct rx_packet *packet;
  
--- 5721,5731 ----
  /* This routine is called to send call abort messages
   * that have been delayed to throttle looping clients. */
  void
! rxi_SendDelayedCallAbort(struct rxevent *event, 
! 			 void *arg1, void *dummy)
  {
+     struct rx_call *call = arg1;
+     
      afs_int32 error;
      struct rx_packet *packet;
  
***************
*** 5680,5688 ****
   * issues a challenge to the client, which is obtained from the
   * security object associated with the connection */
  void
! rxi_ChallengeEvent(struct rxevent *event, register struct rx_connection *conn,
! 		   void *arg1, int tries)
  {
      conn->challengeEvent = NULL;
      if (RXS_CheckAuthentication(conn->securityObject, conn) != 0) {
  	register struct rx_packet *packet;
--- 5749,5759 ----
   * issues a challenge to the client, which is obtained from the
   * security object associated with the connection */
  void
! rxi_ChallengeEvent(struct rxevent *event, 
! 		   void *arg0, void *arg1, int tries)
  {
+     struct rx_connection *conn = arg0;
+     
      conn->challengeEvent = NULL;
      if (RXS_CheckAuthentication(conn->securityObject, conn) != 0) {
  	register struct rx_packet *packet;
***************
*** 5843,5849 ****
  /* Find all server connections that have not been active for a long time, and
   * toss them */
  void
! rxi_ReapConnections(void)
  {
      struct clock now, when;
      clock_GetTime(&now);
--- 5914,5920 ----
  /* Find all server connections that have not been active for a long time, and
   * toss them */
  void
! rxi_ReapConnections(struct rxevent *unused, void *unused1, void *unused2)
  {
      struct clock now, when;
      clock_GetTime(&now);
***************
*** 6245,6259 ****
   * checking.
   */
  void
! rx_PrintTheseStats(FILE * file, struct rx_stats *s, int size,
  		   afs_int32 freePackets, char version)
  {
      int i;
  
!     if (size != sizeof(struct rx_stats)) {
  	fprintf(file,
! 		"Unexpected size of stats structure: was %d, expected %d\n",
! 		size, sizeof(struct rx_stats));
      }
  
      fprintf(file, "rx stats: free packets %d, allocs %d, ", (int)freePackets,
--- 6316,6330 ----
   * checking.
   */
  void
! rx_PrintTheseStats(FILE * file, struct rx_statistics *s, int size,
  		   afs_int32 freePackets, char version)
  {
      int i;
  
!     if (size != sizeof(struct rx_statistics)) {
  	fprintf(file,
! 		"Unexpected size of stats structure: was %d, expected %lud\n",
! 		size, sizeof(struct rx_statistics));
      }
  
      fprintf(file, "rx stats: free packets %d, allocs %d, ", (int)freePackets,
***************
*** 6378,6384 ****
--- 6449,6459 ----
      register afs_int32 code;
      struct timeval tv_now, tv_wake, tv_delta;
      struct sockaddr_in taddr, faddr;
+ #ifdef AFS_NT40_ENV
      int faddrLen;
+ #else
+     socklen_t faddrLen;
+ #endif
      fd_set imask;
      register char *tp;
  
***************
*** 6474,6479 ****
--- 6549,6556 ----
  		  afs_uint32 * supportedValues)
  {
      struct rx_debugIn in;
+     afs_int32 *lp = (afs_int32 *) stat;
+     int i;
      afs_int32 rc = 0;
  
      *supportedValues = 0;
***************
*** 6514,6525 ****
  	if (stat->version >= RX_DEBUGI_VERSION_W_WAITED) {
  	    *supportedValues |= RX_SERVER_DEBUG_WAITED_CNT;
  	}
! 
  	stat->nFreePackets = ntohl(stat->nFreePackets);
  	stat->packetReclaims = ntohl(stat->packetReclaims);
  	stat->callsExecuted = ntohl(stat->callsExecuted);
  	stat->nWaiting = ntohl(stat->nWaiting);
  	stat->idleThreads = ntohl(stat->idleThreads);
      }
  
      return rc;
--- 6591,6606 ----
  	if (stat->version >= RX_DEBUGI_VERSION_W_WAITED) {
  	    *supportedValues |= RX_SERVER_DEBUG_WAITED_CNT;
  	}
! 	if (stat->version >= RX_DEBUGI_VERSION_W_PACKETS) {
! 	    *supportedValues |= RX_SERVER_DEBUG_PACKETS_CNT;
! 	}
  	stat->nFreePackets = ntohl(stat->nFreePackets);
  	stat->packetReclaims = ntohl(stat->packetReclaims);
  	stat->callsExecuted = ntohl(stat->callsExecuted);
  	stat->nWaiting = ntohl(stat->nWaiting);
  	stat->idleThreads = ntohl(stat->idleThreads);
+         stat->nWaited = ntohl(stat->nWaited);
+         stat->nPackets = ntohl(stat->nPackets);
      }
  
      return rc;
***************
*** 6527,6533 ****
  
  afs_int32
  rx_GetServerStats(osi_socket socket, afs_uint32 remoteAddr,
! 		  afs_uint16 remotePort, struct rx_stats * stat,
  		  afs_uint32 * supportedValues)
  {
      struct rx_debugIn in;
--- 6608,6614 ----
  
  afs_int32
  rx_GetServerStats(osi_socket socket, afs_uint32 remoteAddr,
! 		  afs_uint16 remotePort, struct rx_statistics * stat,
  		  afs_uint32 * supportedValues)
  {
      struct rx_debugIn in;
Index: openafs/src/rx/rx.h
diff -c openafs/src/rx/rx.h:1.28.4.11 openafs/src/rx/rx.h:1.28.4.13
*** openafs/src/rx/rx.h:1.28.4.11	Tue Jul 22 00:18:28 2008
--- openafs/src/rx/rx.h	Thu Sep 25 15:41:00 2008
***************
*** 789,795 ****
   * Clearly we assume that ntohl will work on these structures so sizeof(int)
   * must equal sizeof(afs_int32). */
  
! struct rx_stats {		/* General rx statistics */
      int packetRequests;		/* Number of packet allocation requests */
      int receivePktAllocFailures;
      int sendPktAllocFailures;
--- 789,795 ----
   * Clearly we assume that ntohl will work on these structures so sizeof(int)
   * must equal sizeof(afs_int32). */
  
! struct rx_statistics {		/* General rx statistics */
      int packetRequests;		/* Number of packet allocation requests */
      int receivePktAllocFailures;
      int sendPktAllocFailures;
***************
*** 845,851 ****
  #define RX_DEBUGI_BADTYPE     (-8)
  
  #define RX_DEBUGI_VERSION_MINIMUM ('L')	/* earliest real version */
! #define RX_DEBUGI_VERSION     ('R')	/* Latest version */
      /* first version w/ secStats */
  #define RX_DEBUGI_VERSION_W_SECSTATS ('L')
      /* version M is first supporting GETALLCONN and RXSTATS type */
--- 845,851 ----
  #define RX_DEBUGI_BADTYPE     (-8)
  
  #define RX_DEBUGI_VERSION_MINIMUM ('L')	/* earliest real version */
! #define RX_DEBUGI_VERSION     ('S')    /* Latest version */
      /* first version w/ secStats */
  #define RX_DEBUGI_VERSION_W_SECSTATS ('L')
      /* version M is first supporting GETALLCONN and RXSTATS type */
***************
*** 858,863 ****
--- 858,864 ----
  #define RX_DEBUGI_VERSION_W_NEWPACKETTYPES ('P')
  #define RX_DEBUGI_VERSION_W_GETPEER ('Q')
  #define RX_DEBUGI_VERSION_W_WAITED ('R')
+ #define RX_DEBUGI_VERSION_W_PACKETS ('S')
  
  #define	RX_DEBUGI_GETSTATS	1	/* get basic rx stats */
  #define	RX_DEBUGI_GETCONN	2	/* get connection info */
***************
*** 876,882 ****
      afs_int32 nWaiting;
      afs_int32 idleThreads;	/* Number of server threads that are idle */
      afs_int32 nWaited;
!     afs_int32 spare2[7];
  };
  
  struct rx_debugConn_vL {
--- 877,884 ----
      afs_int32 nWaiting;
      afs_int32 idleThreads;	/* Number of server threads that are idle */
      afs_int32 nWaited;
!     afs_int32 nPackets;
!     afs_int32 spare2[6];
  };
  
  struct rx_debugConn_vL {
***************
*** 1002,1007 ****
--- 1004,1010 ----
  #define RX_SERVER_DEBUG_NEW_PACKETS		0x40
  #define RX_SERVER_DEBUG_ALL_PEER		0x80
  #define RX_SERVER_DEBUG_WAITED_CNT              0x100
+ #define RX_SERVER_DEBUG_PACKETS_CNT              0x200
  
  #define AFS_RX_STATS_CLEAR_ALL			0xffffffff
  #define AFS_RX_STATS_CLEAR_INVOCATIONS		0x1
Index: openafs/src/rx/rx_event.c
diff -c openafs/src/rx/rx_event.c:1.18.4.1 openafs/src/rx/rx_event.c:1.18.4.3
*** openafs/src/rx/rx_event.c:1.18.4.1	Mon Mar 17 11:38:28 2008
--- openafs/src/rx/rx_event.c	Wed Sep 24 17:36:53 2008
***************
*** 19,25 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_event.c,v 1.18.4.1 2008/03/17 15:38:28 shadow Exp $");
  
  #ifdef KERNEL
  #ifndef UKERNEL
--- 19,25 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_event.c,v 1.18.4.3 2008/09/24 21:36:53 shadow Exp $");
  
  #ifdef KERNEL
  #ifndef UKERNEL
***************
*** 181,191 ****
--- 181,199 ----
  	ep = (struct rxepoch *)rxi_Alloc(sizeof(struct rxepoch));
  	queue_Append(&rxepoch_free, &ep[0]), rxepoch_nFree++;
  #else
+ #if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_FBSD80_ENV)
+ 	ep = (struct rxepoch *)
+ 	    afs_osi_Alloc_NoSleep(sizeof(struct rxepoch) * rxepoch_allocUnit);
+ 	xsp = xfreemallocs;
+ 	xfreemallocs =
+ 	    (struct xfreelist *)afs_osi_Alloc_NoSleep(sizeof(struct xfreelist));
+ #else
  	ep = (struct rxepoch *)
  	    osi_Alloc(sizeof(struct rxepoch) * rxepoch_allocUnit);
  	xsp = xfreemallocs;
  	xfreemallocs =
  	    (struct xfreelist *)osi_Alloc(sizeof(struct xfreelist));
+ #endif
  	xfreemallocs->mem = (void *)ep;
  	xfreemallocs->size = sizeof(struct rxepoch) * rxepoch_allocUnit;
  	xfreemallocs->next = xsp;
***************
*** 206,212 ****
   * units. */
  
  static struct rxevent *
! _rxevent_Post(struct clock *when, struct clock *now, void (*func) (), 
  	      void *arg, void *arg1, int arg2, int newargs)
  {
      register struct rxevent *ev, *evqe, *evqpr;
--- 214,221 ----
   * units. */
  
  static struct rxevent *
! _rxevent_Post(struct clock *when, struct clock *now, 
! 	      void (*func) (struct rxevent *, void *, void *, int), 
  	      void *arg, void *arg1, int arg2, int newargs)
  {
      register struct rxevent *ev, *evqe, *evqpr;
***************
*** 264,274 ****
--- 273,292 ----
  	ev = (struct rxevent *)rxi_Alloc(sizeof(struct rxevent));
  	queue_Append(&rxevent_free, &ev[0]), rxevent_nFree++;
  #else
+ 
+ #if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_FBSD80_ENV)
+ 	ev = (struct rxevent *)afs_osi_Alloc_NoSleep(sizeof(struct rxevent) *
+ 					 rxevent_allocUnit);
+ 	xsp = xfreemallocs;
+ 	xfreemallocs =
+ 	    (struct xfreelist *)afs_osi_Alloc_NoSleep(sizeof(struct xfreelist));
+ #else
  	ev = (struct rxevent *)osi_Alloc(sizeof(struct rxevent) *
  					 rxevent_allocUnit);
  	xsp = xfreemallocs;
  	xfreemallocs =
  	    (struct xfreelist *)osi_Alloc(sizeof(struct xfreelist));
+ #endif
  	xfreemallocs->mem = (void *)ev;
  	xfreemallocs->size = sizeof(struct rxevent) * rxevent_allocUnit;
  	xfreemallocs->next = xsp;
***************
*** 284,290 ****
  
      /* Record user defined event state */
      ev->eventTime = *when;
!     ev->func = func;
      ev->arg = arg;
      ev->arg1 = arg1;
      ev->arg2 = arg2;
--- 302,312 ----
  
      /* Record user defined event state */
      ev->eventTime = *when;
!     if (newargs) {
! 	ev->func.newfunc = func;
!     } else {
! 	ev->func.oldfunc = (void (*)(struct rxevent *, void *, void*))func;
!     }
      ev->arg = arg;
      ev->arg1 = arg1;
      ev->arg2 = arg2;
***************
*** 319,334 ****
  }
  
  struct rxevent *
! rxevent_Post(struct clock *when, void (*func) (), void *arg, void *arg1)
  {
      struct clock now;
      clock_Zero(&now);
!     return _rxevent_Post(when, &now, func, arg, arg1, 0, 0);
  }
  
  struct rxevent *
! rxevent_Post2(struct clock *when, void (*func) (), void *arg, void *arg1,
! 	      int arg2)
  {
      struct clock now;
      clock_Zero(&now);
--- 341,361 ----
  }
  
  struct rxevent *
! rxevent_Post(struct clock *when, 
! 	     void (*func) (struct rxevent *, void *, void *), 
! 	     void *arg, void *arg1)
  {
      struct clock now;
      clock_Zero(&now);
!     return _rxevent_Post(when, &now, 
! 			 (void (*)(struct rxevent *, void *, void *, int))func,
! 			 arg, arg1, 0, 0);
  }
  
  struct rxevent *
! rxevent_Post2(struct clock *when, 
! 	      void (*func) (struct rxevent *, void *, void *, int), 
! 	      void *arg, void *arg1, int arg2)
  {
      struct clock now;
      clock_Zero(&now);
***************
*** 336,349 ****
  }
  
  struct rxevent *
! rxevent_PostNow(struct clock *when, struct clock *now, void (*func) (), 
  		void *arg, void *arg1)
  {
!     return _rxevent_Post(when, now, func, arg, arg1, 0, 0);
  }
  
  struct rxevent *
! rxevent_PostNow2(struct clock *when, struct clock *now, void (*func) (), 
  		 void *arg, void *arg1, int arg2)
  {
      return _rxevent_Post(when, now, func, arg, arg1, arg2, 1);
--- 363,380 ----
  }
  
  struct rxevent *
! rxevent_PostNow(struct clock *when, struct clock *now, 
! 		void (*func) (struct rxevent *, void *, void *), 
  		void *arg, void *arg1)
  {
!     return _rxevent_Post(when, now, 
! 			 (void (*)(struct rxevent *, void *, void *, int))func,
! 			 arg, arg1, 0, 0);
  }
  
  struct rxevent *
! rxevent_PostNow2(struct clock *when, struct clock *now, 
!                  void (*func) (struct rxevent *, void *, void *, int), 
  		 void *arg, void *arg1, int arg2)
  {
      return _rxevent_Post(when, now, func, arg, arg1, arg2, 1);
***************
*** 371,377 ****
  	clock_GetTime(&now);
  	fprintf(rx_Log_event, "%d.%d: rxevent_Cancel_1(%d.%d, %lp, %lp)\n",
  		(int)now.sec, (int)now.usec, (int)ev->eventTime.sec,
! 		(int)ev->eventTime.usec, ev->func,
  		ev->arg);
      }
  #endif
--- 402,408 ----
  	clock_GetTime(&now);
  	fprintf(rx_Log_event, "%d.%d: rxevent_Cancel_1(%d.%d, %lp, %lp)\n",
  		(int)now.sec, (int)now.usec, (int)ev->eventTime.sec,
! 		(int)ev->eventTime.usec, ev->func.newfunc,
  		ev->arg);
      }
  #endif
***************
*** 460,468 ****
  	    rxevent_nPosted--;
  	    MUTEX_EXIT(&rxevent_lock);
  	    if (ev->newargs) {
! 		ev->func(ev, ev->arg, ev->arg1, ev->arg2);
  	    } else {
! 		ev->func(ev, ev->arg, ev->arg1);
  	    }
  	    MUTEX_ENTER(&rxevent_lock);
  	    queue_Append(&rxevent_free, ev);
--- 491,499 ----
  	    rxevent_nPosted--;
  	    MUTEX_EXIT(&rxevent_lock);
  	    if (ev->newargs) {
! 		ev->func.newfunc(ev, ev->arg, ev->arg1, ev->arg2);
  	    } else {
! 		ev->func.oldfunc(ev, ev->arg, ev->arg1);
  	    }
  	    MUTEX_ENTER(&rxevent_lock);
  	    queue_Append(&rxevent_free, ev);
Index: openafs/src/rx/rx_event.h
diff -c openafs/src/rx/rx_event.h:1.6 openafs/src/rx/rx_event.h:1.6.8.1
*** openafs/src/rx/rx_event.h:1.6	Wed Dec  1 18:36:49 2004
--- openafs/src/rx/rx_event.h	Wed Sep 24 17:36:53 2008
***************
*** 20,33 ****
  #include "rx_clock.h"
  #endif /* KERNEL */
  
! /* An event is something that will happen at (or after) a specified clock time, unless cancelled prematurely.  The user routine (*func)() is called with arguments (event, arg, arg1) when the event occurs.  Warnings:  (1) The user supplied routine should NOT cause process preemption.   (2) The event passed to the user is still on the event queue at that time.  The user must not remove (event_Cancel) it explicitly, but the user may remove or schedule any OTHER event at this time. */
  
  struct rxevent {
      struct rx_queue junk;	/* Events are queued */
      struct clock eventTime;	/* When this event times out (in clock.c units) */
!     void (*func) ();		/* Function to call when this expires */
!     char *arg;			/* Argument to the function */
!     char *arg1;			/* Another argument */
      int arg2;			/* An integer argument */
      int newargs;		/* Nonzero if new-form arguments should be used */
  };
--- 20,44 ----
  #include "rx_clock.h"
  #endif /* KERNEL */
  
! /* An event is something that will happen at (or after) a specified clock 
!  * time, unless cancelled prematurely.  The user routine (*func)() is called 
!  * with arguments (event, arg, arg1) when the event occurs.  
!  * Warnings:  
!  *   (1) The user supplied routine should NOT cause process preemption.   
!  *   (2) The event passed to the user is still on the event queue at that 
!  *       time.  The user must not remove (event_Cancel) it explicitly, but 
!  *       the user may remove or schedule any OTHER event at this time. 
!  */
  
  struct rxevent {
      struct rx_queue junk;	/* Events are queued */
      struct clock eventTime;	/* When this event times out (in clock.c units) */
!     union {
! 	void (*oldfunc) (struct rxevent *, void *, void *); 
! 	void (*newfunc) (struct rxevent *, void *, void *, int);
!     } func; 			/* Function to call when this expires */
!     void *arg;			/* Argument to the function */
!     void *arg1;			/* Another argument */
      int arg2;			/* An integer argument */
      int newargs;		/* Nonzero if new-form arguments should be used */
  };
***************
*** 43,56 ****
      struct rx_queue events;	/* list of events for this epoch */
  };
  
! /* Some macros to make macros more reasonable (this allows a block to be used within a macro which does not cause if statements to screw up).   That is, you can use "if (...) macro_name(); else ...;" without having things blow up on the semi-colon. */
  
  #ifndef BEGIN
  #define BEGIN do {
  #define END } while(0)
  #endif
  
! /* This routine must be called to initialize the event package.  nEvents is the number of events to allocate in a batch whenever more are needed.  If this is 0, a default number (10) will be allocated. */
  #if 0
  extern void rxevent_Init( /* nEvents, scheduler */ );
  #endif
--- 54,73 ----
      struct rx_queue events;	/* list of events for this epoch */
  };
  
! /* Some macros to make macros more reasonable (this allows a block to be 
!  * used within a macro which does not cause if statements to screw up).   
!  * That is, you can use "if (...) macro_name(); else ...;" without 
!  * having things blow up on the semi-colon. */
  
  #ifndef BEGIN
  #define BEGIN do {
  #define END } while(0)
  #endif
  
! /* This routine must be called to initialize the event package.  
!  * nEvents is the number of events to allocate in a batch whenever 
!  * more are needed.  If this is 0, a default number (10) will be 
!  * allocated. */
  #if 0
  extern void rxevent_Init( /* nEvents, scheduler */ );
  #endif
***************
*** 60,71 ****
  extern void exevent_NextEvent( /* when */ );
  #endif
  
! /* Arrange for the indicated event at the appointed time.  When is a "struct clock", in the clock.c time base */
  #if 0
  extern struct rxevent *rxevent_Post( /* when, func, arg, arg1 */ );
  #endif
  
! /* Remove the indicated event from the event queue.  The event must be pending.  Also see the warning, above.  The event pointer supplied is zeroed. */
  #ifdef RX_ENABLE_LOCKS
  #ifdef RX_REFCOUNT_CHECK
  #define	rxevent_Cancel(event_ptr, call, type)			    \
--- 77,92 ----
  extern void exevent_NextEvent( /* when */ );
  #endif
  
! /* Arrange for the indicated event at the appointed time.  When is a 
!  * "struct clock", in the clock.c time base */
  #if 0
  extern struct rxevent *rxevent_Post( /* when, func, arg, arg1 */ );
  #endif
  
! /* Remove the indicated event from the event queue.  The event must be 
!  * pending.  Also see the warning, above.  The event pointer supplied 
!  * is zeroed. 
!  */
  #ifdef RX_ENABLE_LOCKS
  #ifdef RX_REFCOUNT_CHECK
  #define	rxevent_Cancel(event_ptr, call, type)			    \
***************
*** 94,100 ****
  	END
  #endif /* RX_ENABLE_LOCKS */
  
! /* The actions specified for each event that has reached the current clock time will be taken.  The current time returned by GetTime is used (warning:  this may be an old time if the user has not called clock_NewTime) */
  #if 0
  extern int rxevent_RaiseEvents();
  #endif
--- 115,125 ----
  	END
  #endif /* RX_ENABLE_LOCKS */
  
! /* The actions specified for each event that has reached the current clock 
!  * time will be taken.  The current time returned by GetTime is used 
!  * (warning:  this may be an old time if the user has not called 
!  * clock_NewTime) 
!  */
  #if 0
  extern int rxevent_RaiseEvents();
  #endif
Index: openafs/src/rx/rx_getaddr.c
diff -c openafs/src/rx/rx_getaddr.c:1.23.4.5 openafs/src/rx/rx_getaddr.c:1.23.4.6
*** openafs/src/rx/rx_getaddr.c:1.23.4.5	Wed Oct 11 07:31:38 2006
--- openafs/src/rx/rx_getaddr.c	Wed Sep 24 17:36:53 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_getaddr.c,v 1.23.4.5 2006/10/11 11:31:38 jaltman Exp $");
  
  #ifndef AFS_DJGPP_ENV
  #ifndef KERNEL
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_getaddr.c,v 1.23.4.6 2008/09/24 21:36:53 shadow Exp $");
  
  #ifndef AFS_DJGPP_ENV
  #ifndef KERNEL
***************
*** 22,27 ****
--- 22,28 ----
  #include <net/if.h>
  #include <netinet/in.h>
  #include <sys/ioctl.h>
+ #include <string.h>
  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
  #include <sys/sysctl.h>
  #include <net/route.h>
***************
*** 48,64 ****
  #ifdef KERNEL
  /* only used for generating random noise */
  
! afs_int32 rxi_tempAddr = 0;	/* default attempt */
  
  /* set the advisory noise */
  void
! rxi_setaddr(afs_int32 x)
  {
      rxi_tempAddr = x;
  }
  
  /* get approx to net addr */
! afs_int32
  rxi_getaddr(void)
  {
      return rxi_tempAddr;
--- 49,65 ----
  #ifdef KERNEL
  /* only used for generating random noise */
  
! afs_uint32 rxi_tempAddr = 0;	/* default attempt */
  
  /* set the advisory noise */
  void
! rxi_setaddr(afs_uint32 x)
  {
      rxi_tempAddr = x;
  }
  
  /* get approx to net addr */
! afs_uint32
  rxi_getaddr(void)
  {
      return rxi_tempAddr;
***************
*** 70,76 ****
  
  /* to satisfy those who call setaddr */
  void
! rxi_setaddr(afs_int32 x)
  {
  }
  
--- 71,77 ----
  
  /* to satisfy those who call setaddr */
  void
! rxi_setaddr(afs_uint32 x)
  {
  }
  
***************
*** 87,96 ****
  /* Return our internet address as a long in network byte order.  Returns zero
   * if it can't find one.
   */
! afs_int32
  rxi_getaddr(void)
  {
!     afs_int32 buffer[1024];
      int count;
  
      count = rx_getAllAddr(buffer, 1024);
--- 88,97 ----
  /* Return our internet address as a long in network byte order.  Returns zero
   * if it can't find one.
   */
! afs_uint32
  rxi_getaddr(void)
  {
!     afs_uint32 buffer[1024];
      int count;
  
      count = rx_getAllAddr(buffer, 1024);
***************
*** 140,146 ****
  */
  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
  int
! rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
  {
      size_t needed;
      int mib[6];
--- 141,147 ----
  */
  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
  int
! rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
  {
      size_t needed;
      int mib[6];
***************
*** 221,228 ****
  }
  
  int
! rxi_getAllAddrMaskMtu(afs_int32 addrBuffer[], afs_int32 maskBuffer[],
! 		      afs_int32 mtuBuffer[], int maxSize)
  {
      int s;
  
--- 222,229 ----
  }
  
  int
! rxi_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
! 		      afs_uint32 mtuBuffer[], int maxSize)
  {
      int s;
  
***************
*** 233,239 ****
      struct sockaddr_dl *sdl;
      struct rt_addrinfo info;
      char *buf, *lim, *next;
!     int count = 0, addrcount = 0, i;
  
      mib[0] = CTL_NET;
      mib[1] = PF_ROUTE;
--- 234,240 ----
      struct sockaddr_dl *sdl;
      struct rt_addrinfo info;
      char *buf, *lim, *next;
!     int count = 0, addrcount = 0;
  
      mib[0] = CTL_NET;
      mib[1] = PF_ROUTE;
***************
*** 321,327 ****
  
  
  int
! rx_getAllAddr(afs_int32 buffer[], int maxSize)
  {
      return rx_getAllAddr_internal(buffer, maxSize, 0);
  }
--- 322,328 ----
  
  
  int
! rx_getAllAddr(afs_uint32 buffer[], int maxSize)
  {
      return rx_getAllAddr_internal(buffer, maxSize, 0);
  }
***************
*** 330,336 ****
  */
  #else
  static int
! rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
  {
      int s;
      int i, len, count = 0;
--- 331,337 ----
  */
  #else
  static int
! rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
  {
      int s;
      int i, len, count = 0;
***************
*** 406,412 ****
  }
  
  int
! rx_getAllAddr(afs_int32 buffer[], int maxSize)
  {
      return rx_getAllAddr_internal(buffer, maxSize, 0);
  }
--- 407,413 ----
  }
  
  int
! rx_getAllAddr(afs_uint32 buffer[], int maxSize)
  {
      return rx_getAllAddr_internal(buffer, maxSize, 0);
  }
***************
*** 418,425 ****
   * by afsi_SetServerIPRank().
   */
  int
! rxi_getAllAddrMaskMtu(afs_int32 addrBuffer[], afs_int32 maskBuffer[],
! 		      afs_int32 mtuBuffer[], int maxSize)
  {
      int s;
      int i, len, count = 0;
--- 419,426 ----
   * by afsi_SetServerIPRank().
   */
  int
! rxi_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
! 		      afs_uint32 mtuBuffer[], int maxSize)
  {
      int s;
      int i, len, count = 0;
Index: openafs/src/rx/rx_globals.h
diff -c openafs/src/rx/rx_globals.h:1.21.2.14 openafs/src/rx/rx_globals.h:1.21.2.20
*** openafs/src/rx/rx_globals.h:1.21.2.14	Wed Aug 13 22:29:02 2008
--- openafs/src/rx/rx_globals.h	Thu Sep 25 16:19:57 2008
***************
*** 177,188 ****
          int gtol_xfer;
          int ltog_ops;
          int ltog_xfer;
!         int alloc_ops;
!         int alloc_xfer;
      } _FPQ;
      struct rx_packet * local_special_packet;
  } rx_ts_info_t;
! EXT struct rx_ts_info_t * rx_ts_info_init();   /* init function for thread-specific data struct */
  #define RX_TS_INFO_GET(ts_info_p) \
      do { \
          ts_info_p = (struct rx_ts_info_t*)pthread_getspecific(rx_ts_info_key); \
--- 177,190 ----
          int gtol_xfer;
          int ltog_ops;
          int ltog_xfer;
!         int lalloc_ops;
!         int lalloc_xfer;
!         int galloc_ops;
!         int galloc_xfer;
      } _FPQ;
      struct rx_packet * local_special_packet;
  } rx_ts_info_t;
! EXT struct rx_ts_info_t * rx_ts_info_init(void);   /* init function for thread-specific data struct */
  #define RX_TS_INFO_GET(ts_info_p) \
      do { \
          ts_info_p = (struct rx_ts_info_t*)pthread_getspecific(rx_ts_info_key); \
***************
*** 203,208 ****
--- 205,211 ----
          if ((p)->flags & RX_PKTFLAG_FREE) \
              osi_Panic("rx packet already free\n"); \
          (p)->flags |= RX_PKTFLAG_FREE; \
+         (p)->flags &= ~(RX_PKTFLAG_TQ|RX_PKTFLAG_IOVQ|RX_PKTFLAG_RQ|RX_PKTFLAG_CP); \
          (p)->length = 0; \
          (p)->niovecs = 0; \
      } while(0)
***************
*** 264,277 ****
          rx_TSFPQLocalMax = newmax; \
          rx_TSFPQGlobSize = newglob; \
      } while(0)
  /* move packets from local (thread-specific) to global free packet queue.
!    rx_freePktQ_lock must be held. default is to move the difference between the current lenght, and the 
!    allowed max plus one extra glob. */
  #define RX_TS_FPQ_LTOG(rx_ts_info_p) \
      do { \
          register int i; \
          register struct rx_packet * p; \
!         register int tsize = (rx_ts_info_p)->_FPQ.len - rx_TSFPQLocalMax + rx_TSFPQGlobSize; \
          for (i=0,p=queue_Last(&((rx_ts_info_p)->_FPQ), rx_packet); \
               i < tsize; i++,p=queue_Prev(p, rx_packet)); \
          queue_SplitAfterPrepend(&((rx_ts_info_p)->_FPQ),&rx_freePacketQueue,p); \
--- 267,294 ----
          rx_TSFPQLocalMax = newmax; \
          rx_TSFPQGlobSize = newglob; \
      } while(0)
+ /* record the number of packets allocated by this thread 
+  * and stored in the thread local queue */
+ #define RX_TS_FPQ_LOCAL_ALLOC(rx_ts_info_p,num_alloc) \
+     do { \
+         (rx_ts_info_p)->_FPQ.lalloc_ops++; \
+         (rx_ts_info_p)->_FPQ.lalloc_xfer += num_alloc; \
+     } while (0)
+ /* record the number of packets allocated by this thread 
+  * and stored in the global queue */
+ #define RX_TS_FPQ_GLOBAL_ALLOC(rx_ts_info_p,num_alloc) \
+     do { \
+         (rx_ts_info_p)->_FPQ.galloc_ops++; \
+         (rx_ts_info_p)->_FPQ.galloc_xfer += num_alloc; \
+     } while (0)
  /* move packets from local (thread-specific) to global free packet queue.
!    rx_freePktQ_lock must be held. default is to reduce the queue size to 40% ofmax */
  #define RX_TS_FPQ_LTOG(rx_ts_info_p) \
      do { \
          register int i; \
          register struct rx_packet * p; \
!         register int tsize = (rx_ts_info_p)->_FPQ.len - rx_TSFPQLocalMax + 3 *  rx_TSFPQGlobSize; \
! 	if (tsize <= 0) break; \
          for (i=0,p=queue_Last(&((rx_ts_info_p)->_FPQ), rx_packet); \
               i < tsize; i++,p=queue_Prev(p, rx_packet)); \
          queue_SplitAfterPrepend(&((rx_ts_info_p)->_FPQ),&rx_freePacketQueue,p); \
***************
*** 280,289 ****
          (rx_ts_info_p)->_FPQ.ltog_ops++; \
          (rx_ts_info_p)->_FPQ.ltog_xfer += tsize; \
          if ((rx_ts_info_p)->_FPQ.delta) { \
-             (rx_ts_info_p)->_FPQ.alloc_ops++; \
-             (rx_ts_info_p)->_FPQ.alloc_xfer += (rx_ts_info_p)->_FPQ.delta; \
              MUTEX_ENTER(&rx_stats_mutex); \
-             rx_nPackets += (rx_ts_info_p)->_FPQ.delta; \
              RX_TS_FPQ_COMPUTE_LIMITS; \
              MUTEX_EXIT(&rx_stats_mutex); \
             (rx_ts_info_p)->_FPQ.delta = 0; \
--- 297,303 ----
***************
*** 294,299 ****
--- 308,314 ----
      do { \
          register int i; \
          register struct rx_packet * p; \
+         if (num_transfer <= 0) break; \
          for (i=0,p=queue_Last(&((rx_ts_info_p)->_FPQ), rx_packet); \
  	     i < (num_transfer); i++,p=queue_Prev(p, rx_packet)); \
          queue_SplitAfterPrepend(&((rx_ts_info_p)->_FPQ),&rx_freePacketQueue,p); \
***************
*** 302,311 ****
          (rx_ts_info_p)->_FPQ.ltog_ops++; \
          (rx_ts_info_p)->_FPQ.ltog_xfer += (num_transfer); \
          if ((rx_ts_info_p)->_FPQ.delta) { \
-             (rx_ts_info_p)->_FPQ.alloc_ops++; \
-             (rx_ts_info_p)->_FPQ.alloc_xfer += (rx_ts_info_p)->_FPQ.delta; \
              MUTEX_ENTER(&rx_stats_mutex); \
-             rx_nPackets += (rx_ts_info_p)->_FPQ.delta; \
              RX_TS_FPQ_COMPUTE_LIMITS; \
              MUTEX_EXIT(&rx_stats_mutex); \
              (rx_ts_info_p)->_FPQ.delta = 0; \
--- 317,323 ----
***************
*** 493,499 ****
  #endif
  EXT char rx_waitingForPackets;	/* Processes set and wait on this variable when waiting for packet buffers */
  
! EXT struct rx_stats rx_stats;
  
  EXT struct rx_peer **rx_peerHashTable;
  EXT struct rx_connection **rx_connHashTable;
--- 505,511 ----
  #endif
  EXT char rx_waitingForPackets;	/* Processes set and wait on this variable when waiting for packet buffers */
  
! EXT struct rx_statistics rx_stats;
  
  EXT struct rx_peer **rx_peerHashTable;
  EXT struct rx_connection **rx_connHashTable;
***************
*** 530,536 ****
  #ifdef AFS_NT40_ENV
  EXT int rxdebug_active;
  #if !defined(_WIN64)
! #define dpf(args) if (rxdebug_active) rxi_DebugPrint args;
  #else
  #define dpf(args)
  #endif
--- 542,548 ----
  #ifdef AFS_NT40_ENV
  EXT int rxdebug_active;
  #if !defined(_WIN64)
! #define dpf(args) do { if (rx_debugFile) rxi_DebugPrint args; } while (0)
  #else
  #define dpf(args)
  #endif
***************
*** 538,544 ****
  #ifdef DPF_FSLOG
  #define dpf(args) FSLog args
  #else
! #define dpf(args) if (rx_debugFile) rxi_DebugPrint args; else
  #endif 
  #endif
  #define rx_Log_event rxevent_debugFile
--- 550,556 ----
  #ifdef DPF_FSLOG
  #define dpf(args) FSLog args
  #else
! #define dpf(args) do { if (rx_debugFile) rxi_DebugPrint args; } while (0)
  #endif 
  #endif
  #define rx_Log_event rxevent_debugFile
Index: openafs/src/rx/rx_kcommon.c
diff -c openafs/src/rx/rx_kcommon.c:1.56.2.8 openafs/src/rx/rx_kcommon.c:1.56.2.9
*** openafs/src/rx/rx_kcommon.c:1.56.2.8	Wed Apr  9 12:40:00 2008
--- openafs/src/rx/rx_kcommon.c	Fri Aug 22 00:31:48 2008
***************
*** 15,21 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.56.2.8 2008/04/09 16:40:00 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
--- 15,21 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.56.2.9 2008/08/22 04:31:48 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  
***************
*** 475,481 ****
      pp->natMTU = MIN(pp->ifMTU, OLD_MAX_PACKET_SIZE);
      pp->ifDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(RX_MAX_FRAGS, pp->ifMTU));
      pp->maxDgramPackets = 1;
  
      /* Initialize slow start parameters */
--- 475,481 ----
      pp->natMTU = MIN(pp->ifMTU, OLD_MAX_PACKET_SIZE);
      pp->ifDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(rxi_nSendFrags, pp->ifMTU));
      pp->maxDgramPackets = 1;
  
      /* Initialize slow start parameters */
Index: openafs/src/rx/rx_lwp.c
diff -c openafs/src/rx/rx_lwp.c:1.19.4.3 openafs/src/rx/rx_lwp.c:1.19.4.4
*** openafs/src/rx/rx_lwp.c:1.19.4.3	Tue May 20 17:59:02 2008
--- openafs/src/rx/rx_lwp.c	Wed Sep 24 17:36:53 2008
***************
*** 22,28 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_lwp.c,v 1.19.4.3 2008/05/20 21:59:02 shadow Exp $");
  
  # include <sys/types.h>		/* fd_set on older platforms */
  # include <errno.h>
--- 22,28 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_lwp.c,v 1.19.4.4 2008/09/24 21:36:53 shadow Exp $");
  
  # include <sys/types.h>		/* fd_set on older platforms */
  # include <errno.h>
***************
*** 50,58 ****
  
  #define MAXTHREADNAMELENGTH 64
  
- extern int (*registerProgram) ();
- extern int (*swapNameProgram) ();
- 
  int debugSelectFailure;		/* # of times select failed */
  
  /*
--- 50,55 ----
***************
*** 138,144 ****
      /* Priority of listener should be high, so it can keep conns alive */
  #define	RX_LIST_STACK	24000
      LWP_CreateProcess(rx_ListenerProc, RX_LIST_STACK, LWP_MAX_PRIORITY,
! 		      (void *)0, "rx_Listener", &rx_listenerPid);
      if (registerProgram)
  	(*registerProgram) (rx_listenerPid, "listener");
  }
--- 135,141 ----
      /* Priority of listener should be high, so it can keep conns alive */
  #define	RX_LIST_STACK	24000
      LWP_CreateProcess(rx_ListenerProc, RX_LIST_STACK, LWP_MAX_PRIORITY,
! 		      NULL, "rx_Listener", &rx_listenerPid);
      if (registerProgram)
  	(*registerProgram) (rx_listenerPid, "listener");
  }
***************
*** 283,289 ****
  			    rxi_FreePacket(p);
  			}
  			if (swapNameProgram) {
! 			    (*swapNameProgram) (rx_listenerPid, &name, 0);
  			    rx_listenerPid = 0;
  			}
  			return;
--- 280,286 ----
  			    rxi_FreePacket(p);
  			}
  			if (swapNameProgram) {
! 			    (*swapNameProgram) (rx_listenerPid, name, 0);
  			    rx_listenerPid = 0;
  			}
  			return;
***************
*** 303,309 ****
  			    rxi_FreePacket(p);
  			}
  			if (swapNameProgram) {
! 			    (*swapNameProgram) (rx_listenerPid, &name, 0);
  			    rx_listenerPid = 0;
  			}
  			return;
--- 300,306 ----
  			    rxi_FreePacket(p);
  			}
  			if (swapNameProgram) {
! 			    (*swapNameProgram) (rx_listenerPid, name, 0);
  			    rx_listenerPid = 0;
  			}
  			return;
Index: openafs/src/rx/rx_lwp.h
diff -c openafs/src/rx/rx_lwp.h:1.4 openafs/src/rx/rx_lwp.h:1.4.6.1
*** openafs/src/rx/rx_lwp.h:1.4	Wed Apr 13 22:25:13 2005
--- openafs/src/rx/rx_lwp.h	Thu Sep 25 08:30:52 2008
***************
*** 25,30 ****
--- 25,31 ----
  #define MUTEX_TRYENTER(a) 1
  #define MUTEX_EXIT(a)
  #define MUTEX_INIT(a,b,c,d)
+ #define MUTEX_ISMINE(a)
  #define CV_INIT(a,b,c,d)
  #define CV_DESTROY(a)
  #define osirx_AssertMine(a, b)
Index: openafs/src/rx/rx_multi.c
diff -c openafs/src/rx/rx_multi.c:1.9.8.1 openafs/src/rx/rx_multi.c:1.9.8.2
*** openafs/src/rx/rx_multi.c:1.9.8.1	Fri Feb  8 16:21:07 2008
--- openafs/src/rx/rx_multi.c	Tue Aug 26 10:01:39 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_multi.c,v 1.9.8.1 2008/02/08 21:21:07 shadow Exp $");
  
  #ifdef	KERNEL
  #include "afs/sysincludes.h"
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_multi.c,v 1.9.8.2 2008/08/26 14:01:39 shadow Exp $");
  
  #ifdef	KERNEL
  #include "afs/sysincludes.h"
***************
*** 48,53 ****
--- 48,54 ----
      mh->nextReady = mh->firstNotReady = mh->ready = ready;
      mh->nReady = 0;
      mh->nConns = nConns;
+ 
  #ifdef RX_ENABLE_LOCKS
      MUTEX_INIT(&mh->lock, "rx_multi_lock", MUTEX_DEFAULT, 0);
      CV_INIT(&mh->cv, "rx_multi_cv", CV_DEFAULT, 0);
Index: openafs/src/rx/rx_packet.c
diff -c openafs/src/rx/rx_packet.c:1.62.2.16 openafs/src/rx/rx_packet.c:1.62.2.18
*** openafs/src/rx/rx_packet.c:1.62.2.16	Wed Aug 13 22:29:02 2008
--- openafs/src/rx/rx_packet.c	Thu Sep 25 15:36:34 2008
***************
*** 15,21 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.62.2.16 2008/08/14 02:29:02 jaltman Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
--- 15,21 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.62.2.18 2008/09/25 19:36:34 shadow Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
***************
*** 101,107 ****
  struct rx_packet *rx_mallocedP = 0;
  
  extern char cml_version_number[];
- extern int (*rx_almostSent) ();
  
  static int AllocPacketBufs(int class, int num_pkts, struct rx_queue *q);
  
--- 101,106 ----
***************
*** 112,120 ****
  static int rxi_FreeDataBufsToQueue(struct rx_packet *p, 
  				   afs_uint32 first, 
  				   struct rx_queue * q);
  static int
  rxi_FreeDataBufsTSFPQ(struct rx_packet *p, afs_uint32 first, int flush_global);
! 
  
  /* some rules about packets:
   * 1.  When a packet is allocated, the final iov_buf contains room for
--- 111,120 ----
  static int rxi_FreeDataBufsToQueue(struct rx_packet *p, 
  				   afs_uint32 first, 
  				   struct rx_queue * q);
+ #ifdef RX_ENABLE_TSFPQ
  static int
  rxi_FreeDataBufsTSFPQ(struct rx_packet *p, afs_uint32 first, int flush_global);
! #endif
  
  /* some rules about packets:
   * 1.  When a packet is allocated, the final iov_buf contains room for
***************
*** 267,273 ****
  AllocPacketBufs(int class, int num_pkts, struct rx_queue * q)
  {
      register struct rx_ts_info_t * rx_ts_info;
!     int transfer, alloc;
      SPLVAR;
  
      RX_TS_INFO_GET(rx_ts_info);
--- 267,273 ----
  AllocPacketBufs(int class, int num_pkts, struct rx_queue * q)
  {
      register struct rx_ts_info_t * rx_ts_info;
!     int transfer;
      SPLVAR;
  
      RX_TS_INFO_GET(rx_ts_info);
***************
*** 276,291 ****
      if (transfer > 0) {
          NETPRI;
          MUTEX_ENTER(&rx_freePktQ_lock);
! 	
! 	if ((transfer + rx_TSFPQGlobSize) <= rx_nFreePackets) {
! 	    transfer += rx_TSFPQGlobSize;
! 	} else if (transfer <= rx_nFreePackets) {
! 	    transfer = rx_nFreePackets;
! 	} else {
  	    /* alloc enough for us, plus a few globs for other threads */
! 	    alloc = transfer + (3 * rx_TSFPQGlobSize) - rx_nFreePackets;
! 	    rxi_MorePacketsNoLock(MAX(alloc, rx_initSendWindow));
! 	    transfer = rx_TSFPQGlobSize;
  	}
  
  	RX_TS_FPQ_GTOL2(rx_ts_info, transfer);
--- 276,285 ----
      if (transfer > 0) {
          NETPRI;
          MUTEX_ENTER(&rx_freePktQ_lock);
! 	transfer = MAX(transfer, rx_TSFPQGlobSize);
! 	if (transfer > rx_nFreePackets) {
  	    /* alloc enough for us, plus a few globs for other threads */
! 	    rxi_MorePacketsNoLock(transfer + 4 * rx_initSendWindow);
  	}
  
  	RX_TS_FPQ_GTOL2(rx_ts_info, transfer);
***************
*** 303,309 ****
  AllocPacketBufs(int class, int num_pkts, struct rx_queue * q)
  {
      struct rx_packet *c;
!     int i, overq = 0;
      SPLVAR;
  
      NETPRI;
--- 297,306 ----
  AllocPacketBufs(int class, int num_pkts, struct rx_queue * q)
  {
      struct rx_packet *c;
!     int i;
! #ifdef KERNEL
!     int overq = 0;
! #endif
      SPLVAR;
  
      NETPRI;
***************
*** 344,350 ****
      }
  #else /* KERNEL */
      if (rx_nFreePackets < num_pkts) {
!         rxi_MorePacketsNoLock(MAX((num_pkts-rx_nFreePackets), rx_initSendWindow));
      }
  #endif /* KERNEL */
  
--- 341,347 ----
      }
  #else /* KERNEL */
      if (rx_nFreePackets < num_pkts) {
! 	rxi_MorePacketsNoLock(MAX((num_pkts-rx_nFreePackets), 4 * rx_initSendWindow));
      }
  #endif /* KERNEL */
  
***************
*** 543,560 ****
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
      osi_Assert(p);
  
      PIN(p, getme);		/* XXXXX */
      memset((char *)p, 0, getme);
      RX_TS_INFO_GET(rx_ts_info);
  
      for (e = p + apackets; p < e; p++) {
          RX_PACKET_IOV_INIT(p);
  	p->niovecs = 2;
  
  	RX_TS_FPQ_CHECKIN(rx_ts_info,p);
      }
      rx_ts_info->_FPQ.delta += apackets;
  
--- 540,570 ----
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = (struct rx_packet *)osi_Alloc(getme);
      osi_Assert(p);
  
      PIN(p, getme);		/* XXXXX */
      memset((char *)p, 0, getme);
      RX_TS_INFO_GET(rx_ts_info);
  
+     RX_TS_FPQ_LOCAL_ALLOC(rx_ts_info,apackets);
+     /* TSFPQ patch also needs to keep track of total packets */
+     MUTEX_ENTER(&rx_stats_mutex);
+     rx_nPackets += apackets;
+     RX_TS_FPQ_COMPUTE_LIMITS;
+     MUTEX_EXIT(&rx_stats_mutex);
+ 
      for (e = p + apackets; p < e; p++) {
          RX_PACKET_IOV_INIT(p);
  	p->niovecs = 2;
  
  	RX_TS_FPQ_CHECKIN(rx_ts_info,p);
+ 
+         NETPRI;
+         MUTEX_ENTER(&rx_freePktQ_lock);
+         rx_mallocedP = p;
+         MUTEX_EXIT(&rx_freePktQ_lock);
+         USERPRI;
      }
      rx_ts_info->_FPQ.delta += apackets;
  
***************
*** 579,585 ****
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
      osi_Assert(p);
  
      PIN(p, getme);		/* XXXXX */
--- 589,595 ----
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = (struct rx_packet *)osi_Alloc(getme);
      osi_Assert(p);
  
      PIN(p, getme);		/* XXXXX */
***************
*** 593,599 ****
--- 603,611 ----
  	p->niovecs = 2;
  
  	queue_Append(&rx_freePacketQueue, p);
+ 	rx_mallocedP = p;
      }
+ 
      rx_nFreePackets += apackets;
      rxi_NeedMorePackets = FALSE;
      rxi_PacketsUnWait();
***************
*** 613,629 ****
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
  
      PIN(p, getme);		/* XXXXX */
      memset((char *)p, 0, getme);
      RX_TS_INFO_GET(rx_ts_info);
  
      for (e = p + apackets; p < e; p++) {
          RX_PACKET_IOV_INIT(p);
  	p->niovecs = 2;
- 
  	RX_TS_FPQ_CHECKIN(rx_ts_info,p);
      }
      rx_ts_info->_FPQ.delta += apackets;
  
--- 625,653 ----
      SPLVAR;
  
      getme = apackets * sizeof(struct rx_packet);
!     p = (struct rx_packet *)osi_Alloc(getme);
  
      PIN(p, getme);		/* XXXXX */
      memset((char *)p, 0, getme);
      RX_TS_INFO_GET(rx_ts_info);
  
+     RX_TS_FPQ_LOCAL_ALLOC(rx_ts_info,apackets);
+     /* TSFPQ patch also needs to keep track of total packets */
+     MUTEX_ENTER(&rx_stats_mutex);
+     rx_nPackets += apackets;
+     RX_TS_FPQ_COMPUTE_LIMITS;
+     MUTEX_EXIT(&rx_stats_mutex);
+ 
      for (e = p + apackets; p < e; p++) {
          RX_PACKET_IOV_INIT(p);
  	p->niovecs = 2;
  	RX_TS_FPQ_CHECKIN(rx_ts_info,p);
+ 	
+         NETPRI;
+         MUTEX_ENTER(&rx_freePktQ_lock);
+         rx_mallocedP = p;
+         MUTEX_EXIT(&rx_freePktQ_lock);
+         USERPRI;
      }
      rx_ts_info->_FPQ.delta += apackets;
  
***************
*** 647,652 ****
--- 671,679 ----
  void
  rxi_MorePacketsNoLock(int apackets)
  {
+ #ifdef RX_ENABLE_TSFPQ
+     register struct rx_ts_info_t * rx_ts_info;
+ #endif /* RX_ENABLE_TSFPQ */
      struct rx_packet *p, *e;
      int getme;
  
***************
*** 656,662 ****
  	* ((rx_maxJumboRecvSize - RX_FIRSTBUFFERSIZE) / RX_CBUFFERSIZE);
      do {
          getme = apackets * sizeof(struct rx_packet);
!         p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
  	if (p == NULL) {
              apackets -= apackets / 4;
              osi_Assert(apackets > 0);
--- 683,689 ----
  	* ((rx_maxJumboRecvSize - RX_FIRSTBUFFERSIZE) / RX_CBUFFERSIZE);
      do {
          getme = apackets * sizeof(struct rx_packet);
!         p = (struct rx_packet *)osi_Alloc(getme);
  	if (p == NULL) {
              apackets -= apackets / 4;
              osi_Assert(apackets > 0);
***************
*** 664,675 ****
--- 691,708 ----
      } while(p == NULL);
      memset((char *)p, 0, getme);
  
+ #ifdef RX_ENABLE_TSFPQ
+     RX_TS_INFO_GET(rx_ts_info);
+     RX_TS_FPQ_GLOBAL_ALLOC(rx_ts_info,apackets);
+ #endif /* RX_ENABLE_TSFPQ */ 
+ 
      for (e = p + apackets; p < e; p++) {
          RX_PACKET_IOV_INIT(p);
  	p->flags |= RX_PKTFLAG_FREE;
  	p->niovecs = 2;
  
  	queue_Append(&rx_freePacketQueue, p);
+ 	rx_mallocedP = p;
      }
  
      rx_nFreePackets += apackets;
***************
*** 717,723 ****
              if ((num_keep_local > rx_TSFPQLocalMax) && !allow_overcommit)
                  xfer = rx_TSFPQLocalMax - rx_ts_info->_FPQ.len;
              if (rx_nFreePackets < xfer) {
!                 rxi_MorePacketsNoLock(xfer - rx_nFreePackets);
              }
              RX_TS_FPQ_GTOL2(rx_ts_info, xfer);
          }
--- 750,756 ----
              if ((num_keep_local > rx_TSFPQLocalMax) && !allow_overcommit)
                  xfer = rx_TSFPQLocalMax - rx_ts_info->_FPQ.len;
              if (rx_nFreePackets < xfer) {
! 		rxi_MorePacketsNoLock(MAX(xfer - rx_nFreePackets, 4 * rx_initSendWindow));
              }
              RX_TS_FPQ_GTOL2(rx_ts_info, xfer);
          }
***************
*** 818,823 ****
--- 851,857 ----
   * returns:
   *   number of continuation buffers freed
   */
+ #ifndef RX_ENABLE_TSFPQ
  static int
  rxi_FreeDataBufsToQueue(struct rx_packet *p, afs_uint32 first, struct rx_queue * q)
  {
***************
*** 838,843 ****
--- 872,878 ----
  
      return count;
  }
+ #endif
  
  /*
   * free packet continuation buffers into the global free packet pool
***************
*** 1097,1103 ****
  	    osi_Panic("rxi_AllocPacket error");
  #else /* KERNEL */
          if (queue_IsEmpty(&rx_freePacketQueue))
! 	    rxi_MorePacketsNoLock(rx_initSendWindow);
  #endif /* KERNEL */
  
  
--- 1132,1138 ----
  	    osi_Panic("rxi_AllocPacket error");
  #else /* KERNEL */
          if (queue_IsEmpty(&rx_freePacketQueue))
! 	    rxi_MorePacketsNoLock(4 * rx_initSendWindow);
  #endif /* KERNEL */
  
  
***************
*** 1153,1159 ****
  	osi_Panic("rxi_AllocPacket error");
  #else /* KERNEL */
      if (queue_IsEmpty(&rx_freePacketQueue))
! 	rxi_MorePacketsNoLock(rx_initSendWindow);
  #endif /* KERNEL */
  
      rx_nFreePackets--;
--- 1188,1194 ----
  	osi_Panic("rxi_AllocPacket error");
  #else /* KERNEL */
      if (queue_IsEmpty(&rx_freePacketQueue))
! 	rxi_MorePacketsNoLock(4 * rx_initSendWindow);
  #endif /* KERNEL */
  
      rx_nFreePackets--;
***************
*** 1187,1193 ****
          MUTEX_ENTER(&rx_freePktQ_lock);
  
          if (queue_IsEmpty(&rx_freePacketQueue))
!             rxi_MorePacketsNoLock(rx_initSendWindow);
  
  	RX_TS_FPQ_GTOL(rx_ts_info);
  
--- 1222,1228 ----
          MUTEX_ENTER(&rx_freePktQ_lock);
  
          if (queue_IsEmpty(&rx_freePacketQueue))
! 	    rxi_MorePacketsNoLock(4 * rx_initSendWindow);
  
  	RX_TS_FPQ_GTOL(rx_ts_info);
  
***************
*** 1746,1751 ****
--- 1781,1787 ----
  #endif
  	    MUTEX_ENTER(&rx_serverPool_lock);
  	    tstat.nFreePackets = htonl(rx_nFreePackets);
+ 	    tstat.nPackets = htonl(rx_nPackets);
  	    tstat.callsExecuted = htonl(rxi_nCalls);
  	    tstat.packetReclaims = htonl(rx_packetReclaims);
  	    tstat.usedFDs = CountFDs(64);
Index: openafs/src/rx/rx_packet.h
diff -c openafs/src/rx/rx_packet.h:1.14.4.1 openafs/src/rx/rx_packet.h:1.14.4.3
*** openafs/src/rx/rx_packet.h:1.14.4.1	Tue May 20 17:59:02 2008
--- openafs/src/rx/rx_packet.h	Thu Sep 25 15:36:34 2008
***************
*** 9,18 ****
  
  #ifndef _RX_PACKET_
  #define _RX_PACKET_
- #ifndef UKERNEL
  #if defined(AFS_NT40_ENV) || defined(AFS_DJGPP_ENV)
  #include "rx_xmit_nt.h"
  #endif
  #ifndef AFS_NT40_ENV
  #include <sys/uio.h>
  #endif /* !AFS_NT40_ENV */
--- 9,18 ----
  
  #ifndef _RX_PACKET_
  #define _RX_PACKET_
  #if defined(AFS_NT40_ENV) || defined(AFS_DJGPP_ENV)
  #include "rx_xmit_nt.h"
  #endif
+ #ifndef UKERNEL
  #ifndef AFS_NT40_ENV
  #include <sys/uio.h>
  #endif /* !AFS_NT40_ENV */
***************
*** 173,179 ****
   */
  #define	RX_PKTFLAG_ACKED	0x01
  #define	RX_PKTFLAG_FREE		0x02
! 
  
  /* The rx part of the header of a packet, in host form */
  struct rx_header {
--- 173,182 ----
   */
  #define	RX_PKTFLAG_ACKED	0x01
  #define	RX_PKTFLAG_FREE		0x02
! #define RX_PKTFLAG_TQ           0x04
! #define RX_PKTFLAG_RQ           0x08
! #define RX_PKTFLAG_IOVQ         0x10
! #define RX_PKTFLAG_CP           0x20
  
  /* The rx part of the header of a packet, in host form */
  struct rx_header {
Index: openafs/src/rx/rx_prototypes.h
diff -c openafs/src/rx/rx_prototypes.h:1.29.4.10 openafs/src/rx/rx_prototypes.h:1.29.4.12
*** openafs/src/rx/rx_prototypes.h:1.29.4.10	Tue May 20 17:59:02 2008
--- openafs/src/rx/rx_prototypes.h	Thu Sep 25 13:15:56 2008
***************
*** 11,16 ****
--- 11,26 ----
  #define _RX_PROTOTYPES_H
  
  /* rx.c */
+ #ifndef KERNEL
+ #ifndef AFS_PTHREAD_ENV
+ extern int (*registerProgram) (PROCESS, char *);
+ extern int (*swapNameProgram) (PROCESS, const char *, char *);
+ #endif
+ #endif
+ extern int (*rx_justReceived) (struct rx_packet *, struct sockaddr_in *);
+ extern int (*rx_almostSent) (struct rx_packet *, struct sockaddr_in *);
+ 
+ 
  extern void rx_SetEpoch(afs_uint32 epoch);
  extern int rx_Init(u_int port);
  extern int rx_InitHost(u_int host, u_int port);
***************
*** 122,128 ****
  extern void rxi_AckAll(struct rxevent *event, register struct rx_call *call,
  		       char *dummy);
  extern void rxi_SendDelayedAck(struct rxevent *event,
! 			       register struct rx_call *call, char *dummy);
  extern void rxi_ClearTransmitQueue(register struct rx_call *call,
  				   register int force);
  extern void rxi_ClearReceiveQueue(register struct rx_call *call);
--- 132,138 ----
  extern void rxi_AckAll(struct rxevent *event, register struct rx_call *call,
  		       char *dummy);
  extern void rxi_SendDelayedAck(struct rxevent *event,
! 			       void *call /* struct rx_call *call */, void *dummy);
  extern void rxi_ClearTransmitQueue(register struct rx_call *call,
  				   register int force);
  extern void rxi_ClearReceiveQueue(register struct rx_call *call);
***************
*** 142,150 ****
  				     *optionalPacket, int serial, int reason,
  				     int istack);
  extern void rxi_StartUnlocked(struct rxevent *event,
! 			      register struct rx_call *call,
  			      void *arg1, int istack);
! extern void rxi_Start(struct rxevent *event, register struct rx_call *call,
  		      void *arg1, int istack);
  extern void rxi_Send(register struct rx_call *call,
  		     register struct rx_packet *p, int istack);
--- 152,161 ----
  				     *optionalPacket, int serial, int reason,
  				     int istack);
  extern void rxi_StartUnlocked(struct rxevent *event,
! 			      void *call, /* register struct rx_call */
  			      void *arg1, int istack);
! extern void rxi_Start(struct rxevent *event, 
! 		      void *call, /* register struct rx_call */
  		      void *arg1, int istack);
  extern void rxi_Send(register struct rx_call *call,
  		     register struct rx_packet *p, int istack);
***************
*** 154,179 ****
  extern int rxi_CheckCall(register struct rx_call *call);
  #endif /* RX_ENABLE_LOCKS */
  extern void rxi_KeepAliveEvent(struct rxevent *event,
! 			       register struct rx_call *call, char *dummy);
  extern void rxi_ScheduleKeepAliveEvent(register struct rx_call *call);
  extern void rxi_KeepAliveOn(register struct rx_call *call);
  extern void rxi_SendDelayedConnAbort(struct rxevent *event,
! 				     register struct rx_connection *conn,
! 				     char *dummy);
  extern void rxi_SendDelayedCallAbort(struct rxevent *event,
! 				     register struct rx_call *call,
! 				     char *dummy);
  extern void rxi_ChallengeEvent(struct rxevent *event,
! 			       register struct rx_connection *conn,
  			       void *arg1, int atries);
  extern void rxi_ChallengeOn(register struct rx_connection *conn);
  extern void rxi_ComputeRoundTripTime(register struct rx_packet *p,
  				     register struct clock *sentp,
  				     register struct rx_peer *peer);
! extern void rxi_ReapConnections(void);
  extern int rxs_Release(struct rx_securityClass *aobj);
  #ifndef KERNEL
! extern void rx_PrintTheseStats(FILE * file, struct rx_stats *s, int size,
  			       afs_int32 freePackets, char version);
  extern void rx_PrintStats(FILE * file);
  extern void rx_PrintPeerStats(FILE * file, struct rx_peer *peer);
--- 165,192 ----
  extern int rxi_CheckCall(register struct rx_call *call);
  #endif /* RX_ENABLE_LOCKS */
  extern void rxi_KeepAliveEvent(struct rxevent *event,
! 			       void *call /* struct rx_call *call */, 
! 			       void *dummy);
  extern void rxi_ScheduleKeepAliveEvent(register struct rx_call *call);
  extern void rxi_KeepAliveOn(register struct rx_call *call);
  extern void rxi_SendDelayedConnAbort(struct rxevent *event,
! 				     void *conn, /* struct rx_connection *conn */
! 				     void *dummy);
  extern void rxi_SendDelayedCallAbort(struct rxevent *event,
! 				     void *call, /* struct rx_call *call */
! 				     void *dummy);
  extern void rxi_ChallengeEvent(struct rxevent *event,
! 			       void *conn, /* struct rx_connection *conn */
  			       void *arg1, int atries);
  extern void rxi_ChallengeOn(register struct rx_connection *conn);
  extern void rxi_ComputeRoundTripTime(register struct rx_packet *p,
  				     register struct clock *sentp,
  				     register struct rx_peer *peer);
! extern void rxi_ReapConnections(struct rxevent *unused, void *unused1, 
! 				void *unused2);
  extern int rxs_Release(struct rx_securityClass *aobj);
  #ifndef KERNEL
! extern void rx_PrintTheseStats(FILE * file, struct rx_statistics *s, int size,
  			       afs_int32 freePackets, char version);
  extern void rx_PrintStats(FILE * file);
  extern void rx_PrintPeerStats(FILE * file, struct rx_peer *peer);
***************
*** 184,190 ****
  				   afs_uint32 * supportedValues);
  extern afs_int32 rx_GetServerStats(osi_socket socket, afs_uint32 remoteAddr,
  				   afs_uint16 remotePort,
! 				   struct rx_stats *stat,
  				   afs_uint32 * supportedValues);
  extern afs_int32 rx_GetServerVersion(osi_socket socket, afs_uint32 remoteAddr,
  				     afs_uint16 remotePort,
--- 197,203 ----
  				   afs_uint32 * supportedValues);
  extern afs_int32 rx_GetServerStats(osi_socket socket, afs_uint32 remoteAddr,
  				   afs_uint16 remotePort,
! 				   struct rx_statistics *stat,
  				   afs_uint32 * supportedValues);
  extern afs_int32 rx_GetServerVersion(osi_socket socket, afs_uint32 remoteAddr,
  				     afs_uint16 remotePort,
***************
*** 247,252 ****
--- 260,268 ----
  extern void rx_clearPeerRPCStats(afs_uint32 clearFlag);
  extern void rx_SetRxStatUserOk(int (*proc) (struct rx_call * call));
  extern int rx_RxStatUserOk(struct rx_call *call);
+ extern afs_int32 rx_SetSecurityConfiguration(struct rx_service *service,
+ 					     rx_securityConfigVariables type,
+ 					     void *value);
  
  
  /* old style till varargs */
***************
*** 302,315 ****
  /* this func seems to be called with tons of different style routines, need to look
  at another time. */
  #else
! extern struct rxevent *rxevent_Post(struct clock *when, void (*func) (),
  				    void *arg, void *arg1);
! extern struct rxevent *rxevent_Post2(struct clock *when, void (*func) (),
  				    void *arg, void *arg1, int arg2);
  extern struct rxevent *rxevent_PostNow(struct clock *when, struct clock *now,
! 				       void (*func) (), void *arg, void *arg1);
  extern struct rxevent *rxevent_PostNow2(struct clock *when, struct clock *now,
! 					void (*func) (), void *arg, 
  					void *arg1, int arg2);
  #endif
  extern void shutdown_rxevent(void);
--- 318,333 ----
  /* this func seems to be called with tons of different style routines, need to look
  at another time. */
  #else
! extern struct rxevent *rxevent_Post(struct clock *when, 
! 				    void (*func) (struct rxevent *, void *, void *),
  				    void *arg, void *arg1);
! extern struct rxevent *rxevent_Post2(struct clock *when, 
! 				    void (*func) (struct rxevent *, void *, void *, int),
  				    void *arg, void *arg1, int arg2);
  extern struct rxevent *rxevent_PostNow(struct clock *when, struct clock *now,
! 				       void (*func) (struct rxevent *, void *, void *), void *arg, void *arg1);
  extern struct rxevent *rxevent_PostNow2(struct clock *when, struct clock *now,
! 					void (*func) (struct rxevent *, void *, void *, int), void *arg, 
  					void *arg1, int arg2);
  #endif
  extern void shutdown_rxevent(void);
***************
*** 324,331 ****
  
  
  /* rx_getaddr.c */
! extern void rxi_setaddr(afs_int32 x);
! extern afs_int32 rxi_getaddr(void);
  
  /* rx_globals.c */
  
--- 342,354 ----
  
  
  /* rx_getaddr.c */
! extern void rxi_setaddr(afs_uint32 x);
! extern afs_uint32 rxi_getaddr(void);
! extern int rx_getAllAddr(afs_uint32 * buffer, int maxSize);
! extern int rxi_getAllAddrMaskMtu(afs_uint32 addrBuffer[], 
! 			  	 afs_uint32 maskBuffer[],
! 				 afs_uint32 mtuBuffer[],
! 				 int maxSize);
  
  /* rx_globals.c */
  
***************
*** 584,590 ****
  #endif
  extern osi_socket rxi_GetUDPSocket(u_short port);
  extern void osi_AssertFailU(const char *expr, const char *file, int line);
- extern int rx_getAllAddr(afs_int32 * buffer, int maxSize);
  extern void rxi_InitPeerParams(struct rx_peer *pp);
  extern int rxi_HandleSocketError(int socket);
  
--- 607,612 ----
***************
*** 595,601 ****
  
  extern void rx_GetIFInfo(void);
  extern void rx_SetNoJumbo(void);
! 
  
  /* rx_xmit_nt.c */
  
--- 617,623 ----
  
  extern void rx_GetIFInfo(void);
  extern void rx_SetNoJumbo(void);
! extern void rx_SetMaxMTU(int mtu);
  
  /* rx_xmit_nt.c */
  
Index: openafs/src/rx/rx_pthread.h
diff -c openafs/src/rx/rx_pthread.h:1.5 openafs/src/rx/rx_pthread.h:1.5.6.1
*** openafs/src/rx/rx_pthread.h:1.5	Wed Apr 13 22:25:13 2005
--- openafs/src/rx/rx_pthread.h	Thu Sep 25 07:50:58 2008
***************
*** 34,40 ****
  
  typedef pthread_mutex_t afs_kmutex_t;
  typedef pthread_cond_t afs_kcondvar_t;
! #define MUTEX_ISMINE
  #define pthread_yield() Sleep(0)
  
  #else /* AFS_NT40_ENV */
--- 34,45 ----
  
  typedef pthread_mutex_t afs_kmutex_t;
  typedef pthread_cond_t afs_kcondvar_t;
! #ifdef	RX_ENABLE_LOCKS
! #define MUTEX_ISMINE(l) (pthread_mutex_trylock(l) == EDEADLK)
! #else
! #define MUTEX_ISMINE(l) (1)
! #endif
! 
  #define pthread_yield() Sleep(0)
  
  #else /* AFS_NT40_ENV */
Index: openafs/src/rx/rx_rdwr.c
diff -c openafs/src/rx/rx_rdwr.c:1.29.2.4 openafs/src/rx/rx_rdwr.c:1.29.2.8
*** openafs/src/rx/rx_rdwr.c:1.29.2.4	Thu May  8 17:25:58 2008
--- openafs/src/rx/rx_rdwr.c	Thu Sep 25 16:17:54 2008
***************
*** 15,21 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_rdwr.c,v 1.29.2.4 2008/05/08 21:25:58 shadow Exp $");
  
  #ifdef KERNEL
  #ifndef UKERNEL
--- 15,21 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_rdwr.c,v 1.29.2.8 2008/09/25 20:17:54 shadow Exp $");
  
  #ifdef KERNEL
  #ifndef UKERNEL
***************
*** 137,142 ****
--- 137,143 ----
  			afs_int32 error;
  			register struct rx_connection *conn = call->conn;
  			queue_Remove(rp);
+ 			rp->flags &= ~RX_PKTFLAG_RQ;
  
  			/* RXS_CheckPacket called to undo RXS_PreparePacket's
  			 * work.  It may reduce the length of the packet by up
***************
*** 161,166 ****
--- 162,168 ----
  			}
  			call->rnext++;
  			cp = call->currentPacket = rp;
+ 			call->currentPacket->flags |= RX_PKTFLAG_CP;
  			call->curvec = 1;	/* 0th vec is always header */
  			/* begin at the beginning [ more or less ], continue 
  			 * on until the end, then stop. */
***************
*** 263,268 ****
--- 265,271 ----
  
  		if (!call->nLeft) {
  		    /* out of packet.  Get another one. */
+ 		    call->currentPacket->flags &= ~RX_PKTFLAG_CP;
  		    rxi_FreePacket(cp);
  		    cp = call->currentPacket = (struct rx_packet *)0;
  		} else if (!call->curlen) {
***************
*** 270,275 ****
--- 273,279 ----
  		    if (++call->curvec >= cp->niovecs) {
  			/* current packet is exhausted, get ready for another */
  			/* don't worry about curvec and stuff, they get set somewhere else */
+ 			call->currentPacket->flags &= ~RX_PKTFLAG_CP;
  			rxi_FreePacket(cp);
  			cp = call->currentPacket = (struct rx_packet *)0;
  			call->nLeft = 0;
***************
*** 325,330 ****
--- 329,344 ----
  	call->curpos = tcurpos + nbytes;
  	call->curlen = tcurlen - nbytes;
  	call->nLeft = tnLeft - nbytes;
+ 
+         if (!call->nLeft) {
+             /* out of packet.  Get another one. */
+             NETPRI;
+             MUTEX_ENTER(&call->lock);
+             rxi_FreePacket(call->currentPacket);
+             call->currentPacket = (struct rx_packet *)0;
+             MUTEX_EXIT(&call->lock);
+             USERPRI;
+         }
  	return nbytes;
      }
  
***************
*** 373,378 ****
--- 387,401 ----
  	call->curpos = tcurpos + sizeof(afs_int32);
  	call->curlen = (u_short)(tcurlen - sizeof(afs_int32));
  	call->nLeft = (u_short)(tnLeft - sizeof(afs_int32));
+         if (!call->nLeft) {
+             /* out of packet.  Get another one. */
+             NETPRI;
+             MUTEX_ENTER(&call->lock);
+             rxi_FreePacket(call->currentPacket);
+             call->currentPacket = (struct rx_packet *)0;
+             MUTEX_EXIT(&call->lock);
+             USERPRI;
+         }
  	return sizeof(afs_int32);
      }
  
***************
*** 417,422 ****
--- 440,446 ----
  		    afs_int32 error;
  		    register struct rx_connection *conn = call->conn;
  		    queue_Remove(rp);
+ 		    rp->flags &= ~RX_PKTFLAG_RQ;
  
  		    /* RXS_CheckPacket called to undo RXS_PreparePacket's
  		     * work.  It may reduce the length of the packet by up
***************
*** 440,445 ****
--- 464,470 ----
  		    }
  		    call->rnext++;
  		    curp = call->currentPacket = rp;
+ 		    call->currentPacket->flags |= RX_PKTFLAG_CP;
  		    call->curvec = 1;	/* 0th vec is always header */
  		    cur_iov = &curp->wirevec[1];
  		    /* begin at the beginning [ more or less ], continue 
***************
*** 494,499 ****
--- 519,526 ----
  
  	    if (!call->nLeft) {
  		/* out of packet.  Get another one. */
+                 curp->flags &= ~RX_PKTFLAG_CP;
+                 curp->flags |= RX_PKTFLAG_IOVQ;
  		queue_Append(&call->iovq, curp);
  		curp = call->currentPacket = (struct rx_packet *)0;
  	    } else if (!call->curlen) {
***************
*** 501,506 ****
--- 528,535 ----
  		if (++call->curvec >= curp->niovecs) {
  		    /* current packet is exhausted, get ready for another */
  		    /* don't worry about curvec and stuff, they get set somewhere else */
+ 		    curp->flags &= ~RX_PKTFLAG_CP;
+ 		    curp->flags |= RX_PKTFLAG_IOVQ;
  		    queue_Append(&call->iovq, curp);
  		    curp = call->currentPacket = (struct rx_packet *)0;
  		    call->nLeft = 0;
***************
*** 553,559 ****
  rxi_ReadvProc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
  	      int nbytes)
  {
-     struct rx_packet *rp;
      int requestCount;
      int nextio;
  
--- 582,587 ----
***************
*** 652,657 ****
--- 680,686 ----
  	    && (call->mode == RX_MODE_RECEIVING)) {
  	    call->mode = RX_MODE_SENDING;
  	    if (cp) {
+ 		cp->flags &= ~RX_PKTFLAG_CP;
  		rxi_FreePacket(cp);
  		cp = call->currentPacket = (struct rx_packet *)0;
  		call->nLeft = 0;
***************
*** 689,702 ****
  		 * conn->securityMaxTrailerSize */
  		hadd32(call->bytesSent, cp->length);
  		rxi_PrepareSendPacket(call, cp, 0);
  		queue_Append(&call->tq, cp);
! 		cp = call->currentPacket = NULL;
  		if (!
  		    (call->
  		     flags & (RX_CALL_FAST_RECOVER |
  			      RX_CALL_FAST_RECOVER_WAIT))) {
  		    rxi_Start(0, call, 0, 0);
  		}
  	    }
  	    /* Wait for transmit window to open up */
  	    while (!call->error
--- 718,737 ----
  		 * conn->securityMaxTrailerSize */
  		hadd32(call->bytesSent, cp->length);
  		rxi_PrepareSendPacket(call, cp, 0);
+ 		cp->flags &= ~RX_PKTFLAG_CP;
+ 		cp->flags |= RX_PKTFLAG_TQ;
  		queue_Append(&call->tq, cp);
! 		cp = call->currentPacket = (struct rx_packet *)0;
  		if (!
  		    (call->
  		     flags & (RX_CALL_FAST_RECOVER |
  			      RX_CALL_FAST_RECOVER_WAIT))) {
  		    rxi_Start(0, call, 0, 0);
  		}
+ 	    } else if (cp) {
+ 		cp->flags &= ~RX_PKTFLAG_CP;
+ 		rxi_FreePacket(cp);
+ 		cp = call->currentPacket = (struct rx_packet *)0;
  	    }
  	    /* Wait for transmit window to open up */
  	    while (!call->error
***************
*** 719,724 ****
--- 754,760 ----
  #endif /* RX_ENABLE_LOCKS */
  	    }
  	    if ((cp = rxi_AllocSendPacket(call, nbytes))) {
+ 		cp->flags |= RX_PKTFLAG_CP;
  		call->currentPacket = cp;
  		call->nFree = cp->length;
  		call->curvec = 1;	/* 0th vec is always header */
***************
*** 732,737 ****
--- 768,774 ----
  	    }
  	    if (call->error) {
  		if (cp) {
+ 		    cp->flags &= ~RX_PKTFLAG_CP;
  		    rxi_FreePacket(cp);
  		    call->currentPacket = NULL;
  		}
***************
*** 926,931 ****
--- 963,969 ----
  	    && (call->mode == RX_MODE_RECEIVING)) {
  	    call->mode = RX_MODE_SENDING;
  	    if (cp) {
+ 		cp->flags &= ~RX_PKTFLAG_CP;
  		rxi_FreePacket(cp);
  		cp = call->currentPacket = (struct rx_packet *)0;
  		call->nLeft = 0;
***************
*** 952,957 ****
--- 990,996 ----
  		*nio = nextio;
  		return requestCount - nbytes;
  	    }
+ 	    cp->flags |= RX_PKTFLAG_IOVQ;
  	    queue_Append(&call->iovq, cp);
  	    tnFree = cp->length;
  	    tcurvec = 1;
***************
*** 1055,1062 ****
  
      if (call->error) {
  	if (cp) {
  	    queue_Prepend(&call->iovq, cp);
! 	    cp = call->currentPacket = NULL;
  	}
  	rxi_FreePackets(0, &call->iovq);
  	return 0;
--- 1094,1103 ----
  
      if (call->error) {
  	if (cp) {
+             cp->flags &= ~RX_PKTFLAG_CP;
+             cp->flags |= RX_PKTFLAG_IOVQ;
  	    queue_Prepend(&call->iovq, cp);
! 	    cp = call->currentPacket = (struct rx_packet *)0;
  	}
  	rxi_FreePackets(0, &call->iovq);
  	return 0;
***************
*** 1078,1095 ****
  	     * conn->securityMaxTrailerSize */
  	    hadd32(call->bytesSent, cp->length);
  	    rxi_PrepareSendPacket(call, cp, 0);
  	    queue_Append(&tmpq, cp);
  
  	    /* The head of the iovq is now the current packet */
  	    if (nbytes) {
  		if (queue_IsEmpty(&call->iovq)) {
  		    call->error = RX_PROTOCOL_ERROR;
- 		    cp = call->currentPacket = NULL;
  		    rxi_FreePackets(0, &tmpq);
  		    return 0;
  		}
  		cp = queue_First(&call->iovq, rx_packet);
  		queue_Remove(cp);
  		call->currentPacket = cp;
  		call->nFree = cp->length;
  		call->curvec = 1;
--- 1119,1138 ----
  	     * conn->securityMaxTrailerSize */
  	    hadd32(call->bytesSent, cp->length);
  	    rxi_PrepareSendPacket(call, cp, 0);
+ 	    cp->flags |= RX_PKTFLAG_TQ;
  	    queue_Append(&tmpq, cp);
  
  	    /* The head of the iovq is now the current packet */
  	    if (nbytes) {
  		if (queue_IsEmpty(&call->iovq)) {
  		    call->error = RX_PROTOCOL_ERROR;
  		    rxi_FreePackets(0, &tmpq);
  		    return 0;
  		}
  		cp = queue_First(&call->iovq, rx_packet);
  		queue_Remove(cp);
+                 cp->flags &= ~RX_PKTFLAG_IOVQ;
+                 cp->flags |= RX_PKTFLAG_CP;
  		call->currentPacket = cp;
  		call->nFree = cp->length;
  		call->curvec = 1;
***************
*** 1107,1114 ****
  		|| iov[nextio].iov_len > (int)call->curlen) {
  		call->error = RX_PROTOCOL_ERROR;
  		if (cp) {
  		    queue_Prepend(&tmpq, cp);
- 		    call->currentPacket = NULL;
  		}
  		rxi_FreePackets(0, &tmpq);
  		return 0;
--- 1150,1157 ----
  		|| iov[nextio].iov_len > (int)call->curlen) {
  		call->error = RX_PROTOCOL_ERROR;
  		if (cp) {
+ 		    cp->flags &= ~RX_PKTFLAG_CP;
  		    queue_Prepend(&tmpq, cp);
  		}
  		rxi_FreePackets(0, &tmpq);
  		return 0;
***************
*** 1152,1159 ****
  
      if (call->error) {
  	if (cp) {
  	    rxi_FreePacket(cp);
- 	    cp = call->currentPacket = NULL;
  	}
  	return 0;
      }
--- 1195,1202 ----
  
      if (call->error) {
  	if (cp) {
+ 	    cp->flags &= ~RX_PKTFLAG_CP;
  	    rxi_FreePacket(cp);
  	}
  	return 0;
      }
***************
*** 1224,1229 ****
--- 1267,1273 ----
  	    /* cp->length is only supposed to be the user's data */
  	    /* cp->length was already set to (then-current) 
  	     * MaxUserDataSize or less. */
+ 	    cp->flags &= ~RX_PKTFLAG_CP;
  	    cp->length -= call->nFree;
  	    call->currentPacket = (struct rx_packet *)0;
  	    call->nFree = 0;
***************
*** 1241,1246 ****
--- 1285,1291 ----
  	/* The 1 specifies that this is the last packet */
  	hadd32(call->bytesSent, cp->length);
  	rxi_PrepareSendPacket(call, cp, 1);
+ 	cp->flags |= RX_PKTFLAG_TQ;
  	queue_Append(&call->tq, cp);
  	if (!
  	    (call->
Index: openafs/src/rx/rx_trace.c
diff -c openafs/src/rx/rx_trace.c:1.11.14.2 openafs/src/rx/rx_trace.c:1.11.14.3
*** openafs/src/rx/rx_trace.c:1.11.14.2	Mon Nov 26 16:08:43 2007
--- openafs/src/rx/rx_trace.c	Wed Sep 24 17:36:53 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_trace.c,v 1.11.14.2 2007/11/26 21:08:43 shadow Exp $");
  
  #ifdef RXDEBUG
  #include <string.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_trace.c,v 1.11.14.3 2008/09/24 21:36:53 shadow Exp $");
  
  #ifdef RXDEBUG
  #include <string.h>
***************
*** 47,53 ****
  };
  
  void
! rxi_flushtrace()
  {
      if (rxi_logfd >= 0)
  	write(rxi_logfd, rxi_tracebuf, rxi_tracepos);
--- 47,53 ----
  };
  
  void
! rxi_flushtrace(void)
  {
      if (rxi_logfd >= 0)
  	write(rxi_logfd, rxi_tracebuf, rxi_tracepos);
***************
*** 55,63 ****
  }
  
  void
! rxi_calltrace(event, call)
!      unsigned int event;
!      struct rx_call *call;
  {
      struct clock now;
      struct rx_trace rxtinfo;
--- 55,61 ----
  }
  
  void
! rxi_calltrace(unsigned int event, struct rx_call *call)
  {
      struct clock now;
      struct rx_trace rxtinfo;
***************
*** 130,137 ****
  #endif
  
  int
! main(argc, argv)
!      char **argv;
  {
      struct rx_trace ip;
      int err = 0;
--- 128,134 ----
  #endif
  
  int
! main(int argc, char **argv)
  {
      struct rx_trace ip;
      int err = 0;
Index: openafs/src/rx/rx_trace.h
diff -c openafs/src/rx/rx_trace.h:1.3 openafs/src/rx/rx_trace.h:1.3.14.1
*** openafs/src/rx/rx_trace.h:1.3	Tue Jul 15 19:16:10 2003
--- openafs/src/rx/rx_trace.h	Wed Sep 24 17:36:53 2008
***************
*** 14,20 ****
  #define rxi_calltrace(a,b)
  #define rxi_flushtrace()
  #else
! extern void rxi_calltrace(), rxi_flushtrace();
  
  #define RX_CALL_ARRIVAL 0
  #define RX_CALL_START 1
--- 14,21 ----
  #define rxi_calltrace(a,b)
  #define rxi_flushtrace()
  #else
! extern void rxi_calltrace(unsigned int event, struct rx_call *call);
! extern void rxi_flushtrace(void);
  
  #define RX_CALL_ARRIVAL 0
  #define RX_CALL_START 1
Index: openafs/src/rx/rx_user.c
diff -c openafs/src/rx/rx_user.c:1.24.4.4 openafs/src/rx/rx_user.c:1.24.4.6
*** openafs/src/rx/rx_user.c:1.24.4.4	Thu May 29 09:33:29 2008
--- openafs/src/rx/rx_user.c	Thu Sep 25 08:07:49 2008
***************
*** 13,19 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_user.c,v 1.24.4.4 2008/05/29 13:33:29 jaltman Exp $");
  
  # include <sys/types.h>
  # include <errno.h>
--- 13,19 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_user.c,v 1.24.4.6 2008/09/25 12:07:49 jaltman Exp $");
  
  # include <sys/types.h>
  # include <errno.h>
***************
*** 300,306 ****
  ** maxSize - max number of interfaces to return.
  */
  int
! rx_getAllAddr(afs_int32 * buffer, int maxSize)
  {
      int count = 0, offset = 0;
  
--- 300,306 ----
  ** maxSize - max number of interfaces to return.
  */
  int
! rx_getAllAddr(afs_uint32 * buffer, int maxSize)
  {
      int count = 0, offset = 0;
  
***************
*** 729,738 ****
      pp->natMTU = MIN((int)pp->ifMTU, OLD_MAX_PACKET_SIZE);
      pp->maxDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(RX_MAX_FRAGS, pp->ifMTU));
      pp->ifDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(RX_MAX_FRAGS, pp->ifMTU));
      pp->maxDgramPackets = 1;
      /* Initialize slow start parameters */
      pp->MTU = MIN(pp->natMTU, pp->maxMTU);
--- 729,738 ----
      pp->natMTU = MIN((int)pp->ifMTU, OLD_MAX_PACKET_SIZE);
      pp->maxDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(rxi_nSendFrags, pp->ifMTU));
      pp->ifDgramPackets =
  	MIN(rxi_nDgramPackets,
! 	    rxi_AdjustDgramPackets(rxi_nSendFrags, pp->ifMTU));
      pp->maxDgramPackets = 1;
      /* Initialize slow start parameters */
      pp->MTU = MIN(pp->natMTU, pp->maxMTU);
Index: openafs/src/rx/xdr_prototypes.h
diff -c openafs/src/rx/xdr_prototypes.h:1.8 openafs/src/rx/xdr_prototypes.h:1.8.4.1
*** openafs/src/rx/xdr_prototypes.h:1.8	Sat Nov  5 01:48:18 2005
--- openafs/src/rx/xdr_prototypes.h	Wed Sep 24 17:36:53 2008
***************
*** 83,88 ****
--- 83,90 ----
  
  /* xdr_refernce.c */
  
+ extern bool_t xdr_reference(XDR *xdrs, caddr_t *pp, u_int size, 
+ 			    xdrproc_t proc);
  
  /* xdr_stdio.c */
  
Index: openafs/src/rx/xdr_refernce.c
diff -c openafs/src/rx/xdr_refernce.c:1.7.4.1 openafs/src/rx/xdr_refernce.c:1.7.4.2
*** openafs/src/rx/xdr_refernce.c:1.7.4.1	Tue Oct 30 11:16:45 2007
--- openafs/src/rx/xdr_refernce.c	Wed Sep 24 17:36:53 2008
***************
*** 31,37 ****
  #include "rx.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/xdr_refernce.c,v 1.7.4.1 2007/10/30 15:16:45 shadow Exp $");
  
  #ifndef	NeXT
  
--- 31,37 ----
  #include "rx.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/xdr_refernce.c,v 1.7.4.2 2008/09/24 21:36:53 shadow Exp $");
  
  #ifndef	NeXT
  
***************
*** 59,69 ****
   * proc is the routine to handle the referenced structure.
   */
  bool_t
! xdr_reference(xdrs, pp, size, proc)
!      register XDR *xdrs;
!      caddr_t *pp;		/* the pointer to work on */
!      u_int size;		/* size of the object pointed to */
!      xdrproc_t proc;		/* xdr routine to handle the object */
  {
      register caddr_t loc = *pp;
      register bool_t stat;
--- 59,68 ----
   * proc is the routine to handle the referenced structure.
   */
  bool_t
! xdr_reference(register XDR *xdrs, 
! 	      caddr_t *pp, /* the pointer to work on */
! 	      u_int size, /* size of the object pointed to */
! 	      xdrproc_t proc)  /* xdr routine to handle the object */
  {
      register caddr_t loc = *pp;
      register bool_t stat;
***************
*** 80,85 ****
--- 79,86 ----
  	    }
  	    memset(loc, 0, (int)size);
  	    break;
+ 	case XDR_ENCODE:
+ 	    break;
  	}
  
      stat = (*proc) (xdrs, loc, LASTUNSIGNED);
***************
*** 90,93 ****
      }
      return (stat);
  }
! #endif /* NeXT */
--- 91,94 ----
      }
      return (stat);
  }
! #endif /* !NeXT */
Index: openafs/src/rx/FBSD/rx_kmutex.h
diff -c openafs/src/rx/FBSD/rx_kmutex.h:1.6 openafs/src/rx/FBSD/rx_kmutex.h:1.6.14.1
*** openafs/src/rx/FBSD/rx_kmutex.h:1.6	Tue Jul 15 19:16:18 2003
--- openafs/src/rx/FBSD/rx_kmutex.h	Tue Aug 26 10:01:39 2008
***************
*** 18,24 ****
  
  #include <sys/systm.h>
  #include <sys/proc.h>
! #ifdef AFS_FBSD50_ENV
  #include <sys/lockmgr.h>
  #else
  #include <sys/lock.h>
--- 18,25 ----
  
  #include <sys/systm.h>
  #include <sys/proc.h>
! #ifdef AFS_FBSD70_ENV
! #include <sys/lock.h>
  #include <sys/lockmgr.h>
  #else
  #include <sys/lock.h>
***************
*** 27,62 ****
  #define RX_ENABLE_LOCKS         1
  #define AFS_GLOBAL_RXLOCK_KERNEL
  
- /*
-  * Condition variables
-  *
-  * In Digital Unix (OSF/1), we use something akin to the ancient sleep/wakeup
-  * mechanism.  The condition variable itself plays no role; we just use its
-  * address as a convenient unique number.
-  */
- #define CV_INIT(cv,a,b,c)
- #define CV_DESTROY(cv)
- #define CV_WAIT(cv, lck)    { \
- 	                        int isGlockOwner = ISAFS_GLOCK(); \
- 	                        if (isGlockOwner) AFS_GUNLOCK();  \
- 	                        MUTEX_EXIT(lck);        \
- 	                        tsleep(cv, PSOCK, "afs_rx_cv_wait", 0);  \
- 	                        if (isGlockOwner) AFS_GLOCK();  \
- 	                        MUTEX_ENTER(lck); \
- 	                    }
- 
- #define CV_TIMEDWAIT(cv,lck,t)  { \
- 	                        int isGlockOwner = ISAFS_GLOCK(); \
- 	                        if (isGlockOwner) AFS_GUNLOCK();  \
- 	                        MUTEX_EXIT(lck);        \
- 	                        tsleep(cv, PSOCK, "afs_rx_cv_timedwait", t); \
- 	                        if (isGlockOwner) AFS_GLOCK();  \
- 	                        MUTEX_ENTER(lck);       \
- 
- #define CV_SIGNAL(cv)           wakeup_one(cv)
- #define CV_BROADCAST(cv)        wakeup(cv)
- 
- /* #define osi_rxWakeup(cv)        wakeup(cv) */
  typedef int afs_kcondvar_t;
  
  #define HEAVY_LOCKS
--- 28,33 ----
***************
*** 89,95 ****
--- 60,106 ----
  #undef MUTEX_ISMINE
  #define MUTEX_ISMINE(a) (((afs_kmutex_t *)(a))->owner == curproc)
  
+ #elif defined(AFS_FBSD70_ENV) /* dunno about 6.x */
+ 
+ typedef struct mtx afs_kmutex_t;
+ 
+ #if defined(AFS_FBSD80_ENV) && defined(WITNESS)
+ #define WITCLEAR_MTX(a)					\
+     do { memset((a), 0, sizeof(struct mtx)); } while(0);
+ #else
+ #define WITCLEAR_MTX(a) {}
+ #endif
+ 
+ #define MUTEX_INIT(a,b,c,d)					     \
+   do {								     \
+       WITCLEAR_MTX(a);						     \
+       mtx_init((a), (b), 0 /* type defaults to name */, MTX_DEF | MTX_DUPOK);    \
+   } while(0);
+ 
+ #define MUTEX_DESTROY(a)			\
+     do {					\
+ 	mtx_destroy((a));			\
+     } while(0);
+ 
+ #define MUTEX_ENTER(a) \
+     do {	       \
+ 	mtx_lock((a)); \
+     } while(0);
+ 
+ #define MUTEX_TRYENTER(a)			\
+     ( mtx_trylock((a)) )
+ 
+ #define MUTEX_EXIT(a)	 \
+     do {		 \
+ 	mtx_unlock((a)); \
+     } while(0);
+ 
+ #undef MUTEX_ISMINE
+ #define MUTEX_ISMINE(a)				\
+     ( mtx_owned((a)) )
+ 
  #elif defined(AFS_FBSD50_ENV)
+ 
  typedef struct {
      struct lock lock;
      struct thread *owner;
***************
*** 133,139 ****
  
  #define MUTEX_INIT(a,b,c,d) \
      do { \
! 	lockinit(&(a)->lock,PSOCK, "afs rx mutex", 0, 0); \
  	(a)->owner = 0; \
      } while(0);
  #define MUTEX_DESTROY(a) \
--- 144,150 ----
  
  #define MUTEX_INIT(a,b,c,d) \
      do { \
! 	lockinit(&(a)->lock, PSOCK, "afs rx mutex", 0, 0); \
  	(a)->owner = 0; \
      } while(0);
  #define MUTEX_DESTROY(a) \
***************
*** 198,201 ****
--- 209,264 ----
  #undef osirx_AssertMine
  extern void osirx_AssertMine(afs_kmutex_t * lockaddr, char *msg);
  
+ 
+ /*
+  * Condition variables
+  *
+  * In Digital Unix (OSF/1), we use something akin to the ancient sleep/wakeup
+  * mechanism.  The condition variable itself plays no role; we just use its
+  * address as a convenient unique number.
+  */
+ #define CV_INIT(cv,a,b,c)
+ #define CV_DESTROY(cv)
+ 
+ #if defined(AFS_FBSD70_ENV)
+ 
+ #define CV_WAIT(cv, lck)    { \
+     int isGlockOwner = ISAFS_GLOCK();					\
+     if (isGlockOwner) AFS_GUNLOCK();					\
+     msleep(cv, lck, PSOCK, "afs_rx_cv_wait", 0);			\
+     if (isGlockOwner) AFS_GLOCK();					\
+   }
+ 
+ #define CV_TIMEDWAIT(cv,lck,t)  { \
+ 	                        int isGlockOwner = ISAFS_GLOCK(); \
+ 	                        if (isGlockOwner) AFS_GUNLOCK();  \
+ 	                        msleep(cv, lck, PSOCK, "afs_rx_cv_timedwait", t); \
+ 	                        if (isGlockOwner) AFS_GLOCK();  \
+ 				}
+ #else /* !AFS_FBSD70_ENV */
+ #define CV_WAIT(cv, lck)    { \
+ 	                        int isGlockOwner = ISAFS_GLOCK(); \
+ 	                        if (isGlockOwner) AFS_GUNLOCK();  \
+ 	                        MUTEX_EXIT(lck);        \
+ 	                        tsleep(cv, PSOCK, "afs_rx_cv_wait", 0);  \
+ 	                        if (isGlockOwner) AFS_GLOCK();  \
+ 	                        MUTEX_ENTER(lck); \
+ 	                    }
+ 
+ #define CV_TIMEDWAIT(cv,lck,t)  { \
+ 	                        int isGlockOwner = ISAFS_GLOCK(); \
+ 	                        if (isGlockOwner) AFS_GUNLOCK();  \
+ 	                        MUTEX_EXIT(lck);        \
+ 	                        tsleep(cv, PSOCK, "afs_rx_cv_timedwait", t); \
+ 	                        if (isGlockOwner) AFS_GLOCK();  \
+ 	                        MUTEX_ENTER(lck);       \
+ 				}
+ #endif /* AFS_FBSD80_ENV */
+ 
+ #define CV_SIGNAL(cv)           wakeup_one(cv)
+ #define CV_BROADCAST(cv)        wakeup(cv)
+ 
+ /* #define osi_rxWakeup(cv)        wakeup(cv) */
+ 
+ 
  #endif /* _RX_KMUTEX_H_ */
Index: openafs/src/rx/FBSD/rx_knet.c
diff -c openafs/src/rx/FBSD/rx_knet.c:1.15 openafs/src/rx/FBSD/rx_knet.c:1.15.6.1
*** openafs/src/rx/FBSD/rx_knet.c:1.15	Wed Apr 13 22:25:16 2005
--- openafs/src/rx/FBSD/rx_knet.c	Tue Aug 26 10:01:39 2008
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/FBSD/rx_knet.c,v 1.15 2005/04/14 02:25:16 shadow Exp $");
  
  #ifdef AFS_FBSD40_ENV
  #include <sys/malloc.h>
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/FBSD/rx_knet.c,v 1.15.6.1 2008/08/26 14:01:39 shadow Exp $");
  
  #ifdef AFS_FBSD40_ENV
  #include <sys/malloc.h>
***************
*** 77,82 ****
--- 77,84 ----
      return code;
  }
  
+ #define so_is_disconn(so) ((so)->so_state & SS_ISDISCONNECTED)
+ 
  extern int rxk_ListenerPid;
  void
  osi_StopListener(void)
***************
*** 88,102 ****
       * soclose() is currently protected by Giant,
       * but pfind and psignal are MPSAFE.
       */
!     AFS_GUNLOCK();
      soclose(rx_socket);
      p = pfind(rxk_ListenerPid);
      if (p)
  	psignal(p, SIGUSR1);
  #ifdef AFS_FBSD50_ENV
      PROC_UNLOCK(p);
  #endif
!     AFS_GLOCK();
  }
  
  int
--- 90,132 ----
       * soclose() is currently protected by Giant,
       * but pfind and psignal are MPSAFE.
       */
!     int haveGlock = ISAFS_GLOCK();
!     if (haveGlock)
! 	AFS_GUNLOCK();
!     soshutdown(rx_socket, 2);
! #ifndef AFS_FBSD70_ENV
      soclose(rx_socket);
+ #endif
      p = pfind(rxk_ListenerPid);
+     afs_warn("osi_StopListener: rxk_ListenerPid %lx\n", p);
      if (p)
  	psignal(p, SIGUSR1);
  #ifdef AFS_FBSD50_ENV
      PROC_UNLOCK(p);
  #endif
! #ifdef AFS_FBSD70_ENV
!     {
!       /* Avoid destroying socket until osi_NetReceive has
!        * had a chance to clean up */
!       int tries;
!       struct mtx s_mtx;
! 
!       MUTEX_INIT(&s_mtx, "rx_shutdown_mutex", MUTEX_DEFAULT, 0);
!       MUTEX_ENTER(&s_mtx);
!       tries = 3;
!       while ((tries > 0) && (!so_is_disconn(rx_socket))) {
! 	msleep(&osi_StopListener, &s_mtx, PSOCK | PCATCH,
! 	       "rx_shutdown_timedwait", 1 * hz);
! 	--tries;
!       }
!       if (so_is_disconn(rx_socket))
! 	soclose(rx_socket);
!       MUTEX_EXIT(&s_mtx);
!       MUTEX_DESTROY(&s_mtx);
!     }
! #endif
!     if (haveGlock)
! 	AFS_GLOCK();
  }
  
  int
Index: openafs/src/rxdebug/rxdebug.c
diff -c openafs/src/rxdebug/rxdebug.c:1.6.8.3 openafs/src/rxdebug/rxdebug.c:1.6.8.5
*** openafs/src/rxdebug/rxdebug.c:1.6.8.3	Wed Oct 31 00:09:34 2007
--- openafs/src/rxdebug/rxdebug.c	Thu Sep 25 15:55:16 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rxdebug/rxdebug.c,v 1.6.8.3 2007/10/31 04:09:34 shadow Exp $");
  
  #include <sys/types.h>
  #include <errno.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rxdebug/rxdebug.c,v 1.6.8.5 2008/09/25 19:55:16 shadow Exp $");
  
  #include <sys/types.h>
  #include <errno.h>
***************
*** 106,111 ****
--- 106,112 ----
      int withIdleThreads;
      int withWaited;
      int withPeers;
+     int withPackets;
      struct rx_debugStats tstats;
      char *portName, *hostName;
      char hoststr[20];
***************
*** 255,264 ****
      withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
      withWaited = (supportedDebugValues & RX_SERVER_DEBUG_WAITED_CNT);
      withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
  
!     printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
! 	   tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
! 	   tstats.usedFDs);
      if (!tstats.waitingForPackets)
  	printf("not ");
      printf("waiting for packets.\n");
--- 256,271 ----
      withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
      withWaited = (supportedDebugValues & RX_SERVER_DEBUG_WAITED_CNT);
      withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
+     withPackets = (supportedDebugValues & RX_SERVER_DEBUG_PACKETS_CNT);
  
!     if (withPackets)
!         printf("Free packets: %d/%d, packet reclaims: %d, calls: %d, used FDs: %d\n",
!                tstats.nFreePackets, tstats.nPackets, tstats.packetReclaims, 
!                tstats.callsExecuted, tstats.usedFDs);
!     else
!         printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
!                tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
!                tstats.usedFDs);
      if (!tstats.waitingForPackets)
  	printf("not ");
      printf("waiting for packets.\n");
***************
*** 276,282 ****
  	    fprintf(stderr,
  		    "WARNING: Server doesn't support retrieval of Rx statistics\n");
  	} else {
! 	    struct rx_stats rxstats;
  
  	    /* should gracefully handle the case where rx_stats grows */
  	    code =
--- 283,289 ----
  	    fprintf(stderr,
  		    "WARNING: Server doesn't support retrieval of Rx statistics\n");
  	} else {
! 	    struct rx_statistics rxstats;
  
  	    /* should gracefully handle the case where rx_stats grows */
  	    code =
Index: openafs/src/sys/Makefile.in
diff -c openafs/src/sys/Makefile.in:1.36.2.9 openafs/src/sys/Makefile.in:1.36.2.10
*** openafs/src/sys/Makefile.in:1.36.2.9	Mon Jun 30 19:37:34 2008
--- openafs/src/sys/Makefile.in	Wed Sep  3 14:27:24 2008
***************
*** 215,221 ****
  
  afs.exp: ${srcdir}/afs4.exp ${srcdir}/afs5.exp
  	@set -x; case ${SYS_NAME} in \
! 		rs_aix5* ) \
  			cp -p ${srcdir}/afs5.exp afs.exp ;; \
  		rs_aix* ) \
  			cp -p ${srcdir}/afs4.exp afs.exp ;; \
--- 215,221 ----
  
  afs.exp: ${srcdir}/afs4.exp ${srcdir}/afs5.exp
  	@set -x; case ${SYS_NAME} in \
! 		rs_aix[56]* ) \
  			cp -p ${srcdir}/afs5.exp afs.exp ;; \
  		rs_aix* ) \
  			cp -p ${srcdir}/afs4.exp afs.exp ;; \
***************
*** 225,231 ****
  
  afsl.exp: ${srcdir}/afsl4.exp ${srcdir}/afsl5.exp
  	@set -x; case ${SYS_NAME} in \
! 		rs_aix5* ) \
  			cp -p ${srcdir}/afsl5.exp afsl.exp ;; \
  		rs_aix* ) \
  			cp -p ${srcdir}/afsl4.exp afsl.exp ;; \
--- 225,231 ----
  
  afsl.exp: ${srcdir}/afsl4.exp ${srcdir}/afsl5.exp
  	@set -x; case ${SYS_NAME} in \
! 		rs_aix[56]* ) \
  			cp -p ${srcdir}/afsl5.exp afsl.exp ;; \
  		rs_aix* ) \
  			cp -p ${srcdir}/afsl4.exp afsl.exp ;; \
Index: openafs/src/tvolser/Makefile.in
diff -c openafs/src/tvolser/Makefile.in:1.4.2.3 openafs/src/tvolser/Makefile.in:1.4.2.4
*** openafs/src/tvolser/Makefile.in:1.4.2.3	Thu Jul 17 20:24:13 2008
--- openafs/src/tvolser/Makefile.in	Thu Sep 25 17:40:49 2008
***************
*** 57,67 ****
  	${TOP_LIBDIR}/libafsauthent.a   \
  	${TOP_LIBDIR}/libafsrpc.a       \
  	${TOP_LIBDIR}/libafsutil.a      \
- 	${TOP_LIBDIR}/libubik_pthread.a \
  	${TOP_LIBDIR}/libusd.a
  
! all: volserver vos
  
  COMPILE=${CC} ${CFLAGS} -c $?
  
  rx_pthread.o: ${RX}/rx_pthread.c
--- 57,68 ----
  	${TOP_LIBDIR}/libafsauthent.a   \
  	${TOP_LIBDIR}/libafsrpc.a       \
  	${TOP_LIBDIR}/libafsutil.a      \
  	${TOP_LIBDIR}/libusd.a
  
! all: volserver 
  
+ all_vos: vos
+ 	
  COMPILE=${CC} ${CFLAGS} -c $?
  
  rx_pthread.o: ${RX}/rx_pthread.c
***************
*** 221,228 ****
  	${COMPILE}
  
  
! vos: vos.o  ${VOSOBJS} ${VLSERVEROBJS} ${LIBS}
! 	${CC} ${LDFLAGS} -o vos vos.o ${VOSOBJS} ${VLSERVEROBJS} ${LIBS} ${MT_LIBS} ${XLIBS}
  
  volserver: ${objects} ${LIBS}
  	${CC} ${LDFLAGS} -o volserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS}
--- 222,229 ----
  	${COMPILE}
  
  
! vos: vos.o  ${VOSOBJS} ${VLSERVEROBJS} ${LIBS} ${TOP_LIBDIR}/libubik_pthread.a
! 	${CC} ${LDFLAGS} -o vos vos.o ${VOSOBJS} ${VLSERVEROBJS} ${LIBS} ${TOP_LIBDIR}/libubik_pthread.a ${MT_LIBS} ${XLIBS}
  
  volserver: ${objects} ${LIBS}
  	${CC} ${LDFLAGS} -o volserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS}
***************
*** 233,239 ****
  ${DEST}/root.server/usr/afs/bin/vos: vos
  	${INSTALL} -ns $? $@
  
! install: ${DESTDIR}${afssrvlibexecdir}/volserver ${DESTDIR}${afssrvsbindir}/vos
  clean:
  	$(RM) -f *.o volserver vos core AFS_component_version_number.c
  
--- 234,242 ----
  ${DEST}/root.server/usr/afs/bin/vos: vos
  	${INSTALL} -ns $? $@
  
! install: ${DESTDIR}${afssrvlibexecdir}/volserver 
! install_vos: ${DESTDIR}${afssrvsbindir}/vos
! 
  clean:
  	$(RM) -f *.o volserver vos core AFS_component_version_number.c
  
***************
*** 245,249 ****
  ${DESTDIR}${afssrvsbindir}/vos: vos
  	${INSTALL} -ns $? $@
  
! dest: ${DEST}/root.server/usr/afs/bin/volserver ${DEST}/root.server/usr/afs/bin/vos
  
--- 248,253 ----
  ${DESTDIR}${afssrvsbindir}/vos: vos
  	${INSTALL} -ns $? $@
  
! dest: ${DEST}/root.server/usr/afs/bin/volserver 
! dest_vos: ${DEST}/root.server/usr/afs/bin/vos
  
Index: openafs/src/util/afsutil.h
diff -c openafs/src/util/afsutil.h:1.21.2.2 openafs/src/util/afsutil.h:1.21.2.3
*** openafs/src/util/afsutil.h:1.21.2.2	Wed Oct 31 00:26:18 2007
--- openafs/src/util/afsutil.h	Tue Aug 26 10:11:47 2008
***************
*** 70,76 ****
  
  /* Need a thead safe ctime for pthread builds. Use std ctime for LWP */
  #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
! #ifdef AFS_SUN5_ENV
  #define afs_ctime(C, B, L) ctime_r(C, B, L)
  #else
  /* Cast is for platforms which do not prototype ctime_r */
--- 70,76 ----
  
  /* Need a thead safe ctime for pthread builds. Use std ctime for LWP */
  #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
! #if defined(AFS_SUN5_ENV) && !defined(_POSIX_PTHREAD_SEMANTICS) && (_POSIX_C_SOURCE - 0 < 199506L)
  #define afs_ctime(C, B, L) ctime_r(C, B, L)
  #else
  /* Cast is for platforms which do not prototype ctime_r */
Index: openafs/src/venus/fs.c
diff -c openafs/src/venus/fs.c:1.30.2.16 openafs/src/venus/fs.c:1.30.2.18
*** openafs/src/venus/fs.c:1.30.2.16	Fri May 23 10:25:12 2008
--- openafs/src/venus/fs.c	Mon Sep 22 15:35:29 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/fs.c,v 1.30.2.16 2008/05/23 14:25:12 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.30.2.18 2008/09/22 19:35:29 shadow Exp $");
  
  #include <afs/afs_args.h>
  #include <rx/xdr.h>
***************
*** 1275,1280 ****
--- 1275,1344 ----
      return 0;
  }
  
+ #if defined(AFS_CACHE_BYPASS)
+ /*
+  * Set cache-bypass threshold.  Files larger than this size will not be cached.
+  * With a threshold of 0, the cache is always bypassed.  With a threshold of -1,
+  * cache bypass is disabled.
+  */
+  
+ static int
+ BypassThresholdCmd(struct cmd_syndesc *as, char *arock)
+ {
+     afs_int32 code;
+     afs_int32 size;
+     struct ViceIoctl blob;
+     afs_int32 threshold_i, threshold_o;
+     char *tp;	
+     
+     /* if new threshold supplied, then set and confirm, else,
+      * get current threshold and print
+      */
+ 	 
+     if(as->parms[0].items) {
+ 	int digit, ix, len;
+ 				
+ 	tp = as->parms[0].items->data;
+ 	len = strlen(tp);
+ 	digit = 1; 
+ 	for(ix = 0; ix < len; ++ix) {
+ 	    if(!isdigit(tp[0])) {
+ 		digit = 0;
+ 		break;
+ 	    }
+ 	}
+ 	if (digit == 0) {
+ 	    fprintf(stderr, "fs bypassthreshold -size: %s must be an undecorated digit string.\n", tp);
+ 	    return EINVAL;
+ 	}
+ 	threshold_i = atoi(tp);
+ 	if(ix > 9 && threshold_i < 2147483647) 
+ 	    threshold_i = 2147483647;
+ 	blob.in = (char *) &threshold_i;
+ 	blob.in_size = sizeof(threshold_i);
+     } else {
+ 	blob.in = NULL;
+ 	blob.in_size = 0;
+     }
+ 
+     blob.out = (char *) &threshold_o;
+     blob.out_size = sizeof(threshold_o);
+     code = pioctl(0, VIOC_SETBYPASS_THRESH, &blob, 1);
+     if (code) {
+ 	Die(errno, NULL);
+ 	return 1;
+     } else {		
+ 	printf("Cache bypass threshold %d", threshold_o);
+ 	if(threshold_o ==  -1)
+ 	    printf(" (disabled)");
+ 	printf("\n");
+     }
+ 
+     return 0;
+ }
+ 
+ #endif
+ 
  static int
  FlushCmd(struct cmd_syndesc *as, void *arock)
  {
***************
*** 3305,3315 ****
  
  #ifdef AFS_DISCON_ENV
  static char *modenames[] = {
!     "readonly",
      "fetchonly", /* Not currently supported */
      "partial",   /* Not currently supported */
!     "nat",
!     "full",
      NULL
  };
  
--- 3369,3387 ----
  
  #ifdef AFS_DISCON_ENV
  static char *modenames[] = {
!     "offline",
!     "online",
!     "readonly",  /* Not currently supported */
      "fetchonly", /* Not currently supported */
      "partial",   /* Not currently supported */
!     NULL
! };
! 
! static char *policynames[] = {
!     "client",
!     "server",
!     "closer",  /* Not currently supported. */
!     "manual",  /* Not currently supported. */
      NULL
  };
  
***************
*** 3318,3330 ****
  {
      struct cmd_item *ti;
      char *modename;
!     int modelen;
!     afs_int32 mode, code;
      struct ViceIoctl blob;
  
      blob.in = NULL;
      blob.in_size = 0;
  
      ti = as->parms[0].items;
      if (ti) {
  	modename = ti->data;
--- 3390,3405 ----
  {
      struct cmd_item *ti;
      char *modename;
!     char *policyname;
!     int modelen, policylen;
!     afs_int32 mode, policy, code;
      struct ViceIoctl blob;
  
      blob.in = NULL;
      blob.in_size = 0;
  
+     space[0] = space[1] = space[2] = 0;
+ 
      ti = as->parms[0].items;
      if (ti) {
  	modename = ti->data;
***************
*** 3335,3346 ****
  	if (modenames[mode] == NULL)
  	    printf("Unknown discon mode \"%s\"\n", modename);
  	else {
! 	    memcpy(space, &mode, sizeof mode);
! 	    blob.in = space;
! 	    blob.in_size = sizeof mode;
  	}
      }
  
      blob.out_size = sizeof(mode);
      blob.out = space;
      code = pioctl(0, VIOC_DISCON, &blob, 1);
--- 3410,3440 ----
  	if (modenames[mode] == NULL)
  	    printf("Unknown discon mode \"%s\"\n", modename);
  	else {
! 	    space[0] = mode + 1;
! 	}
!     }
!     ti = as->parms[1].items;
!     if (ti) {
! 	policyname = ti->data;
! 	policylen = strlen(policyname);
! 	for (policy = 0; policynames[policy] != NULL; policy++)
! 	    if (!strncasecmp(policyname, policynames[policy], policylen))
! 		break;
! 	if (policynames[policy] == NULL)
! 	    printf("Unknown discon mode \"%s\"\n", policyname);
! 	else {
! 	    space[1] = policy + 1;
  	}
      }
  
+     if (as->parms[2].items) {
+     	space[2] = 1;
+     	printf("force on\n");
+     }
+ 
+     blob.in = space;
+     blob.in_size = 3 * sizeof(afs_int32);
+ 
      blob.out_size = sizeof(mode);
      blob.out = space;
      code = pioctl(0, VIOC_DISCON, &blob, 1);
***************
*** 3508,3513 ****
--- 3602,3613 ----
      cmd_AddParm(ts, "-fast", CMD_FLAG, CMD_OPTIONAL,
  		"don't check name with VLDB");
  
+ #if defined(AFS_CACHE_BYPASS)
+ 	ts = cmd_CreateSyntax("bypassthreshold", BypassThresholdCmd, 0,
+ 		"get/set cache bypass file size threshold");
+ 	cmd_AddParm(ts, "-size", CMD_SINGLE, CMD_OPTIONAL, "file size");
+ #endif
+ 
  /*
  
  defect 3069
***************
*** 3678,3684 ****
  #ifdef AFS_DISCON_ENV
      ts = cmd_CreateSyntax("discon", DisconCmd, NULL,
  			  "disconnection mode");
!     cmd_AddParm(ts, "-mode", CMD_SINGLE, CMD_OPTIONAL, "readonly | nat | full");
  #endif
  
      ts = cmd_CreateSyntax("nukenfscreds", NukeNFSCredsCmd, NULL, "nuke credentials for NFS client");
--- 3778,3786 ----
  #ifdef AFS_DISCON_ENV
      ts = cmd_CreateSyntax("discon", DisconCmd, NULL,
  			  "disconnection mode");
!     cmd_AddParm(ts, "-mode", CMD_SINGLE, CMD_REQUIRED, "offline | online");
!     cmd_AddParm(ts, "-policy", CMD_SINGLE, CMD_OPTIONAL, "client | server");
!     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "Force reconnection, despite any synchronization issues.");
  #endif
  
      ts = cmd_CreateSyntax("nukenfscreds", NukeNFSCredsCmd, NULL, "nuke credentials for NFS client");
Index: openafs/src/viced/afsfileprocs.c
diff -c openafs/src/viced/afsfileprocs.c:1.113.2.26 openafs/src/viced/afsfileprocs.c:1.113.2.28
*** openafs/src/viced/afsfileprocs.c:1.113.2.26	Wed Jul 30 16:01:58 2008
--- openafs/src/viced/afsfileprocs.c	Fri Sep  5 12:57:55 2008
***************
*** 29,35 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/afsfileprocs.c,v 1.113.2.26 2008/07/30 20:01:58 jaltman Exp $");
  
  #include <stdio.h>
  #include <stdlib.h>
--- 29,35 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/afsfileprocs.c,v 1.113.2.28 2008/09/05 16:57:55 shadow Exp $");
  
  #include <stdio.h>
  #include <stdlib.h>
Index: openafs/src/viced/viced.c
diff -c openafs/src/viced/viced.c:1.75.2.23 openafs/src/viced/viced.c:1.75.2.25
*** openafs/src/viced/viced.c:1.75.2.23	Fri May  9 14:50:57 2008
--- openafs/src/viced/viced.c	Wed Sep 24 17:36:49 2008
***************
*** 22,28 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/viced.c,v 1.75.2.23 2008/05/09 18:50:57 shadow Exp $");
  
  #include <stdio.h>
  #include <stdlib.h>
--- 22,28 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/viced/viced.c,v 1.75.2.25 2008/09/24 21:36:49 shadow Exp $");
  
  #include <stdio.h>
  #include <stdlib.h>
***************
*** 162,168 ****
  int SawPctSpare;
  int debuglevel = 0;
  int printBanner = 0;
! int rxJumbograms = 1;		/* default is to send and receive jumbograms. */
  int rxBind = 0;		/* don't bind */
  int rxkadDisableDotCheck = 0;      /* disable check for dot in principal name */ 
  int rxMaxMTU = -1;
--- 162,168 ----
  int SawPctSpare;
  int debuglevel = 0;
  int printBanner = 0;
! int rxJumbograms = 0;		/* default is to not send and receive jumbograms. */
  int rxBind = 0;		/* don't bind */
  int rxkadDisableDotCheck = 0;      /* disable check for dot in principal name */ 
  int rxMaxMTU = -1;
***************
*** 256,262 ****
      for (i = 0; i < tsize; i++) {
  	if (afs_fstat(i, &status) != -1) {
  	    printf("%d: dev %x, inode %u, length %u, type/mode %x\n", i,
! 		   status.st_dev, status.st_ino, status.st_size,
  		   status.st_mode);
  	}
      }
--- 256,263 ----
      for (i = 0; i < tsize; i++) {
  	if (afs_fstat(i, &status) != -1) {
  	    printf("%d: dev %x, inode %u, length %u, type/mode %x\n", i,
! 		   status.st_dev, status.st_ino, 
! 		   (unsigned int) status.st_size,
  		   status.st_mode);
  	}
      }
***************
*** 921,926 ****
--- 922,929 ----
      strcat(buffer, "[-udpsize <size of socket buffer in bytes>] ");
      strcat(buffer, "[-sendsize <size of send buffer in bytes>] ");
      strcat(buffer, "[-abortthreshold <abort threshold>] ");
+     strcat(buffer, "[-nojumbo (disable jumbogram network packets - deprecated)] ");
+     strcat(buffer, "[-jumbo (enable jumbogram network packets)] ");
  /*   strcat(buffer, "[-enable_peer_stats] "); */
  /*   strcat(buffer, "[-enable_process_stats] "); */
      strcat(buffer, "[-help]\n");
***************
*** 1272,1277 ****
--- 1275,1282 ----
  #endif
  	else if (!strcmp(argv[i], "-nojumbo")) {
  	    rxJumbograms = 0;
+ 	} else if (!strcmp(argv[i], "-jumbo")) {
+ 	    rxJumbograms = 1;
  	} else if (!strcmp(argv[i], "-rxbind")) {
  	    rxBind = 1;
  	} else if (!strcmp(argv[i], "-allow-dotted-principals")) {
***************
*** 2091,2098 ****
      }
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK,
!                                     NULL);
      }
      rx_SetMinProcs(tservice, 3);
      rx_SetMaxProcs(tservice, lwps);
--- 2096,2102 ----
      }
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
      }
      rx_SetMinProcs(tservice, 3);
      rx_SetMaxProcs(tservice, lwps);
Index: openafs/src/vlserver/vlserver.c
diff -c openafs/src/vlserver/vlserver.c:1.22.2.9 openafs/src/vlserver/vlserver.c:1.22.2.11
*** openafs/src/vlserver/vlserver.c:1.22.2.9	Wed Apr  2 15:51:57 2008
--- openafs/src/vlserver/vlserver.c	Wed Sep 24 17:36:52 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vlserver/vlserver.c,v 1.22.2.9 2008/04/02 19:51:57 shadow Exp $");
  
  #include <afs/stds.h>
  #include <sys/types.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vlserver/vlserver.c,v 1.22.2.11 2008/09/24 21:36:52 shadow Exp $");
  
  #include <afs/stds.h>
  #include <sys/types.h>
***************
*** 63,72 ****
  static void *CheckSignal(void*);
  int LogLevel = 0;
  int smallMem = 0;
! int rxJumbograms = 1;		/* default is to send and receive jumbo grams */
  int rxMaxMTU = -1;
  afs_int32 rxBind = 0;
  int rxkadDisableDotCheck = 0;
  
  #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
  afs_uint32 SHostAddrs[ADDRSPERSITE];
--- 63,73 ----
  static void *CheckSignal(void*);
  int LogLevel = 0;
  int smallMem = 0;
! int rxJumbograms = 0;		/* default is to not send and receive jumbo grams */
  int rxMaxMTU = -1;
  afs_int32 rxBind = 0;
  int rxkadDisableDotCheck = 0;
+ int debuglevel = 0;
  
  #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
  afs_uint32 SHostAddrs[ADDRSPERSITE];
***************
*** 170,176 ****
      for (index = 1; index < argc; index++) {
  	if (strcmp(argv[index], "-noauth") == 0) {
  	    noAuth = 1;
- 
  	} else if (strcmp(argv[index], "-p") == 0) {
  	    lwps = atoi(argv[++index]);
  	    if (lwps > MAXLWP) {
--- 171,176 ----
***************
*** 178,187 ****
  		       lwps, MAXLWP);
  		lwps = MAXLWP;
  	    }
! 
  	} else if (strcmp(argv[index], "-nojumbo") == 0) {
  	    rxJumbograms = 0;
! 
  	} else if (strcmp(argv[index], "-rxbind") == 0) {
  	    rxBind = 1;
  	} else if (strcmp(argv[index], "-allow-dotted-principals") == 0) {
--- 178,194 ----
  		       lwps, MAXLWP);
  		lwps = MAXLWP;
  	    }
! 	} else if (strcmp(argv[index], "-d") == 0) {
! 	    if ((index + 1) >= argc) {
! 		fprintf(stderr, "missing argument for -d\n"); 
! 		return -1; 
! 	    }
! 	    debuglevel = atoi(argv[++index]);
! 	    LogLevel = debuglevel;
  	} else if (strcmp(argv[index], "-nojumbo") == 0) {
  	    rxJumbograms = 0;
! 	} else if (strcmp(argv[index], "-jumbo") == 0) {
! 	    rxJumbograms = 1;
  	} else if (strcmp(argv[index], "-rxbind") == 0) {
  	    rxBind = 1;
  	} else if (strcmp(argv[index], "-allow-dotted-principals") == 0) {
***************
*** 253,266 ****
  #ifndef AFS_NT40_ENV
  	    printf("Usage: vlserver [-p <number of processes>] [-nojumbo] "
  		   "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
! 		   "[-auditlog <log path>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #else
  	    printf("Usage: vlserver [-p <number of processes>] [-nojumbo] "
  		   "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
! 		   "[-auditlog <log path>] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #endif
--- 260,273 ----
  #ifndef AFS_NT40_ENV
  	    printf("Usage: vlserver [-p <number of processes>] [-nojumbo] "
  		   "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
! 		   "[-auditlog <log path>] [-jumbo] [-d <debug level>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #else
  	    printf("Usage: vlserver [-p <number of processes>] [-nojumbo] "
  		   "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
! 		   "[-auditlog <log path>] [-jumbo] [-d <debug level>] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #endif
***************
*** 394,401 ****
  
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK,
!                                     NULL);
      }
  
      tservice =
--- 401,407 ----
  
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
      }
  
      tservice =
Index: openafs/src/vol/vnode_inline.h
diff -c openafs/src/vol/vnode_inline.h:1.1.2.5 openafs/src/vol/vnode_inline.h:1.1.2.6
*** openafs/src/vol/vnode_inline.h:1.1.2.5	Mon Apr 21 14:55:48 2008
--- openafs/src/vol/vnode_inline.h	Wed Sep 24 17:34:33 2008
***************
*** 12,25 ****
  
  #include "vnode.h"
  
- #ifdef AFS_HPUX_ENV
- #define static_inline static __inline
- #elif defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
- #define static_inline static
- #else
- #define static_inline static inline
- #endif
- 
  /***************************************************/
  /* demand attach vnode state machine routines      */
  /***************************************************/
--- 12,17 ----
Index: openafs/src/vol/vol-salvage.c
diff -c openafs/src/vol/vol-salvage.c:1.51.2.17 openafs/src/vol/vol-salvage.c:1.51.2.18
*** openafs/src/vol/vol-salvage.c:1.51.2.17	Tue Aug 12 15:14:58 2008
--- openafs/src/vol/vol-salvage.c	Mon Sep 22 15:29:56 2008
***************
*** 87,93 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vol/vol-salvage.c,v 1.51.2.17 2008/08/12 19:14:58 shadow Exp $");
  
  #ifndef AFS_NT40_ENV
  #include <sys/param.h>
--- 87,93 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vol/vol-salvage.c,v 1.51.2.18 2008/09/22 19:29:56 shadow Exp $");
  
  #ifndef AFS_NT40_ENV
  #include <sys/param.h>
***************
*** 2403,2409 ****
      dir->dirHandle = newdir;
  }
  
! void
  JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
  	   Unique unique)
  {
--- 2403,2409 ----
      dir->dirHandle = newdir;
  }
  
! int
  JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
  	   Unique unique)
  {
***************
*** 2421,2427 ****
  	    CopyOnWrite(dir);
  	    assert(Delete(&dir->dirHandle, name) == 0);
  	}
! 	return;
      }
  #ifdef AFS_AIX_ENV
  #ifndef AFS_NAMEI_ENV
--- 2421,2427 ----
  	    CopyOnWrite(dir);
  	    assert(Delete(&dir->dirHandle, name) == 0);
  	}
! 	return 0;
      }
  #ifdef AFS_AIX_ENV
  #ifndef AFS_NAMEI_ENV
***************
*** 2435,2441 ****
  	    CopyOnWrite(dir);
  	    assert(Delete(&dir->dirHandle, name) == 0);
  	}
! 	return;
      }
  #endif
  #endif
--- 2435,2441 ----
  	    CopyOnWrite(dir);
  	    assert(Delete(&dir->dirHandle, name) == 0);
  	}
! 	return 0;
      }
  #endif
  #endif
***************
*** 2453,2459 ****
  		CopyOnWrite(dir);
  		assert(Delete(&dir->dirHandle, name) == 0);
  	    }
! 	    return;
  	}
      }
  
--- 2453,2459 ----
  		CopyOnWrite(dir);
  		assert(Delete(&dir->dirHandle, name) == 0);
  	    }
! 	    return 0;
  	}
      }
  
***************
*** 2468,2474 ****
  	     * entry. Otherwise, it will get created in the next 
  	     * salvage and deleted again here. So Just skip it.
  	     */
! 	    return;
  	}
  
  	todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
--- 2468,2474 ----
  	     * entry. Otherwise, it will get created in the next 
  	     * salvage and deleted again here. So Just skip it.
  	     */
! 	    return 0;
  	}
  
  	todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
***************
*** 2486,2492 ****
  		assert(Create(&dir->dirHandle, name, &fid) == 0);
  	}
  	if (todelete)
! 	    return;		/* no need to continue */
      }
  
      if (strcmp(name, ".") == 0) {
--- 2486,2492 ----
  		assert(Create(&dir->dirHandle, name, &fid) == 0);
  	}
  	if (todelete)
! 	    return 0;		/* no need to continue */
      }
  
      if (strcmp(name, ".") == 0) {
***************
*** 2543,2549 ****
  	}
  	vnodeEssence->claimed = 0;	/* Not claimed: Orphaned */
  	vnodeEssence->todelete = 1;	/* Will later delete vnode and decr inode */
! 	return;
      } else {
  	if (ShowSuid && (vnodeEssence->modeBits & 06000))
  	    Log("FOUND suid/sgid file: %s/%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
--- 2543,2549 ----
  	}
  	vnodeEssence->claimed = 0;	/* Not claimed: Orphaned */
  	vnodeEssence->todelete = 1;	/* Will later delete vnode and decr inode */
! 	return 0;
      } else {
  	if (ShowSuid && (vnodeEssence->modeBits & 06000))
  	    Log("FOUND suid/sgid file: %s/%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
***************
*** 2560,2573 ****
  	    if (fdP == NULL) {
  		Log("ERROR %s could not open mount point vnode %u\n", dir->vname, vnodeNumber);
  		IH_RELEASE(ihP);
! 		return;
  	    }
  	    size = FDH_SIZE(fdP);
  	    if (size < 0) {
  		Log("ERROR %s mount point has invalid size %d, vnode %u\n", dir->vname, size, vnodeNumber);
  		FDH_REALLYCLOSE(fdP);
  		IH_RELEASE(ihP);
! 		return;
  	    }
  	
  	    if (size > 1024)
--- 2560,2573 ----
  	    if (fdP == NULL) {
  		Log("ERROR %s could not open mount point vnode %u\n", dir->vname, vnodeNumber);
  		IH_RELEASE(ihP);
! 		return 0;
  	    }
  	    size = FDH_SIZE(fdP);
  	    if (size < 0) {
  		Log("ERROR %s mount point has invalid size %d, vnode %u\n", dir->vname, size, vnodeNumber);
  		FDH_REALLYCLOSE(fdP);
  		IH_RELEASE(ihP);
! 		return 0;
  	    }
  	
  	    if (size > 1024)
***************
*** 2634,2646 ****
  		    CopyOnWrite(dir);
  		    assert(Delete(&dir->dirHandle, name) == 0);
  		}
! 		return;
  	    }
  	}
  	/* This directory claims the vnode */
  	vnodeEssence->claimed = 1;
      }
      vnodeEssence->count--;
  }
  
  void
--- 2634,2647 ----
  		    CopyOnWrite(dir);
  		    assert(Delete(&dir->dirHandle, name) == 0);
  		}
! 		return 0;
  	    }
  	}
  	/* This directory claims the vnode */
  	vnodeEssence->claimed = 1;
      }
      vnodeEssence->count--;
+     return 0;
  }
  
  void
Index: openafs/src/vol/vol-salvage.h
diff -c openafs/src/vol/vol-salvage.h:1.1.4.4 openafs/src/vol/vol-salvage.h:1.1.4.5
*** openafs/src/vol/vol-salvage.h:1.1.4.4	Thu Jun 12 15:18:50 2008
--- openafs/src/vol/vol-salvage.h	Wed Sep 24 18:46:17 2008
***************
*** 238,244 ****
  			       Unique * maxu);
  extern int GetInodeSummary(char *path, VolumeId singleVolumeNumber);
  extern void GetVolumeSummary(VolumeId singleVolumeNumber);
! extern void JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
  		       Unique unique);
  extern void MaybeZapVolume(register struct InodeSummary *isp, char *message,
  			   int deleteMe, int check);
--- 238,244 ----
  			       Unique * maxu);
  extern int GetInodeSummary(char *path, VolumeId singleVolumeNumber);
  extern void GetVolumeSummary(VolumeId singleVolumeNumber);
! extern int JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
  		       Unique unique);
  extern void MaybeZapVolume(register struct InodeSummary *isp, char *message,
  			   int deleteMe, int check);
Index: openafs/src/vol/volume.c
diff -c openafs/src/vol/volume.c:1.43.2.22 openafs/src/vol/volume.c:1.43.2.23
*** openafs/src/vol/volume.c:1.43.2.22	Mon Jul 28 08:58:42 2008
--- openafs/src/vol/volume.c	Thu Sep 25 03:50:16 2008
***************
*** 22,28 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vol/volume.c,v 1.43.2.22 2008/07/28 12:58:42 shadow Exp $");
  
  #include <rx/xdr.h>
  #include <afs/afsint.h>
--- 22,28 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vol/volume.c,v 1.43.2.23 2008/09/25 07:50:16 shadow Exp $");
  
  #include <rx/xdr.h>
  #include <afs/afsint.h>
***************
*** 2920,2926 ****
  	       }
  	       *ec = VOFFLINE;
  	   }
! 	   ReleaseVolumeHeader(vp->header);
  	   vp = NULL;
  	   break;
  	}
--- 2920,2927 ----
  	       }
  	       *ec = VOFFLINE;
  	   }
! 	   VChangeState_r(vp, VOL_STATE_UNATTACHED);
! 	   FreeVolumeHeader(vp);
  	   vp = NULL;
  	   break;
  	}
***************
*** 3928,3935 ****
  	vp->salvage.reason = reason;
  	vp->stats.last_salvage = FT_ApproxTime();
  	if (flags & VOL_SALVAGE_INVALIDATE_HEADER) {
! 	    /* XXX this should likely be changed to FreeVolumeHeader() */
! 	    ReleaseVolumeHeader(vp->header);
  	}
  	if (vp->stats.salvages < SALVAGE_COUNT_MAX) {
  	    VChangeState_r(vp, VOL_STATE_SALVAGING);
--- 3929,3941 ----
  	vp->salvage.reason = reason;
  	vp->stats.last_salvage = FT_ApproxTime();
  	if (flags & VOL_SALVAGE_INVALIDATE_HEADER) {
! 	    /* Instead of ReleaseVolumeHeader, we do FreeVolumeHeader() 
!                so that the the next VAttachVolumeByVp_r() invocation 
!                of attach2() will pull in a cached header 
!                entry and fail, then load a fresh one from disk and attach 
!                it to the volume.             
! 	    */
! 	    FreeVolumeHeader(vp);
  	}
  	if (vp->stats.salvages < SALVAGE_COUNT_MAX) {
  	    VChangeState_r(vp, VOL_STATE_SALVAGING);
***************
*** 6186,6192 ****
--- 6192,6203 ----
      volume_hdr_LRU.stats.used = howMany;
      volume_hdr_LRU.stats.attached = 0;
      hp = (struct volHeader *)(calloc(howMany, sizeof(struct volHeader)));
+     assert(hp != NULL);
+ 
      while (howMany--)
+ 	/* We are using ReleaseVolumeHeader to initialize the values on the header list
+  	 * to ensure they have the right values
+  	 */
  	ReleaseVolumeHeader(hp++);
  }
  
***************
*** 6383,6389 ****
  #endif /* AFS_DEMAND_ATTACH_FS */
      if (*ec) {
  	/* maintain (nUsers==0) => header in LRU invariant */
! 	ReleaseVolumeHeader(vp->header);
      }
  }
  
--- 6394,6400 ----
  #endif /* AFS_DEMAND_ATTACH_FS */
      if (*ec) {
  	/* maintain (nUsers==0) => header in LRU invariant */
! 	FreeVolumeHeader(vp);
      }
  }
  
Index: openafs/src/vol/volume_inline.h
diff -c openafs/src/vol/volume_inline.h:1.1.2.6 openafs/src/vol/volume_inline.h:1.1.2.7
*** openafs/src/vol/volume_inline.h:1.1.2.6	Thu Jul 10 14:14:54 2008
--- openafs/src/vol/volume_inline.h	Wed Sep 24 17:34:33 2008
***************
*** 12,26 ****
  
  #include "volume.h"
  
- #ifdef AFS_HPUX_ENV
- #define static_inline static __inline
- #elif defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
- #define static_inline static
- #else
- #define static_inline static inline
- #endif
- 
- 
  /***************************************************/
  /* demand attach fs state machine routines         */
  /***************************************************/
--- 12,17 ----
Index: openafs/src/volser/volmain.c
diff -c openafs/src/volser/volmain.c:1.22.2.11 openafs/src/volser/volmain.c:1.22.2.13
*** openafs/src/volser/volmain.c:1.22.2.11	Thu Mar 27 12:20:39 2008
--- openafs/src/volser/volmain.c	Wed Sep 24 17:36:52 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volmain.c,v 1.22.2.11 2008/03/27 16:20:39 shadow Exp $");
  
  #include <sys/types.h>
  #include <string.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volmain.c,v 1.22.2.13 2008/09/24 21:36:52 shadow Exp $");
  
  #include <sys/types.h>
  #include <string.h>
***************
*** 84,89 ****
--- 84,90 ----
  struct afsconf_dir *tdir;
  static afs_int32 runningCalls = 0;
  int DoLogging = 0;
+ int debuglevel = 0; 
  #define MAXLWP 128
  int lwps = 9;
  int udpBufSize = 0;		/* UDP buffer size for receive */
***************
*** 242,248 ****
      int rxpackets = 100;
      char commandLine[150];
      int i;
!     int rxJumbograms = 1;	/* default is to send and receive jumbograms. */
      int rxMaxMTU = -1;
      int bufSize = 0;		/* temp variable to read in udp socket buf size */
      afs_uint32 host = ntohl(INADDR_ANY);
--- 243,249 ----
      int rxpackets = 100;
      char commandLine[150];
      int i;
!     int rxJumbograms = 0;	/* default is to send and receive jumbograms. */
      int rxMaxMTU = -1;
      int bufSize = 0;		/* temp variable to read in udp socket buf size */
      afs_uint32 host = ntohl(INADDR_ANY);
***************
*** 294,299 ****
--- 295,307 ----
  	    rxBind = 1;
  	} else if (strcmp(argv[code], "-allow-dotted-principals") == 0) {
  	    rxkadDisableDotCheck = 1;
+ 	} else if (strcmp(argv[code], "-d") == 0) {
+ 	    if ((code + 1) >= argc) {
+ 		fprintf(stderr, "missing argument for -d\n"); 
+ 		return -1; 
+ 	    }
+ 	    debuglevel = atoi(argv[++code]);
+ 	    LogLevel = debuglevel;
  	} else if (strcmp(argv[code], "-p") == 0) {
  	    lwps = atoi(argv[++code]);
  	    if (lwps > MAXLWP) {
***************
*** 333,338 ****
--- 341,348 ----
  		printf("Warning: auditlog %s not writable, ignored.\n", fileName);
  	} else if (strcmp(argv[code], "-nojumbo") == 0) {
  	    rxJumbograms = 0;
+ 	} else if (strcmp(argv[code], "-jumbo") == 0) {
+ 	    rxJumbograms = 1;
  	} else if (!strcmp(argv[code], "-rxmaxmtu")) {
  	    if ((code + 1) >= argc) {
  		fprintf(stderr, "missing argument for -rxmaxmtu\n"); 
***************
*** 384,399 ****
  	  usage:
  #ifndef AFS_NT40_ENV
  	    printf("Usage: volserver [-log] [-p <number of processes>] "
! 		   "[-auditlog <log path>] "
! 		   "[-nojumbo] [-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
  		   "[-udpsize <size of socket buffer in bytes>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #else
  	    printf("Usage: volserver [-log] [-p <number of processes>] "
! 		   "[-auditlog <log path>] "
! 		   "[-nojumbo] [-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
  		   "[-udpsize <size of socket buffer in bytes>] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
--- 394,409 ----
  	  usage:
  #ifndef AFS_NT40_ENV
  	    printf("Usage: volserver [-log] [-p <number of processes>] "
! 		   "[-auditlog <log path>] [-d <debug level>] "
! 		   "[-nojumbo] [-jumbo] [-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
  		   "[-udpsize <size of socket buffer in bytes>] "
  		   "[-syslog[=FACILITY]] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
  #else
  	    printf("Usage: volserver [-log] [-p <number of processes>] "
! 		   "[-auditlog <log path>] [-d <debug level>] "
! 		   "[-nojumbo] [-jumbo] [-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals] "
  		   "[-udpsize <size of socket buffer in bytes>] "
  		   "[-enable_peer_stats] [-enable_process_stats] "
  		   "[-help]\n");
***************
*** 525,532 ****
  
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(service, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK,
!                                     NULL);
      }
  
      service =
--- 535,541 ----
  
      if (rxkadDisableDotCheck) {
          rx_SetSecurityConfiguration(service, RXS_CONFIG_FLAGS,
!                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
      }
  
      service =
Index: openafs/src/volser/volprocs.c
diff -c openafs/src/volser/volprocs.c:1.42.2.17 openafs/src/volser/volprocs.c:1.42.2.18
*** openafs/src/volser/volprocs.c:1.42.2.17	Sat Aug 16 16:07:45 2008
--- openafs/src/volser/volprocs.c	Thu Sep 25 04:58:22 2008
***************
*** 13,19 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volprocs.c,v 1.42.2.17 2008/08/16 20:07:45 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
--- 13,19 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/volser/volprocs.c,v 1.42.2.18 2008/09/25 08:58:22 shadow Exp $");
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 230,238 ****
      did.Vnode = (VnodeId) 1;
      did.Unique = 1;
  
!     assert(!(MakeDir(&dir, &did, &did)));
      DFlush();			/* flush all modified dir buffers out */
!     DZap(&dir);			/* Remove all buffers for this dir */
      length = Length(&dir);	/* Remember size of this directory */
  
      FidZap(&dir);		/* Done with the dir handle obtained via SetSalvageDirHandle() */
--- 230,238 ----
      did.Vnode = (VnodeId) 1;
      did.Unique = 1;
  
!     assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
      DFlush();			/* flush all modified dir buffers out */
!     DZap((afs_int32 *)&dir);			/* Remove all buffers for this dir */
      length = Length(&dir);	/* Remember size of this directory */
  
      FidZap(&dir);		/* Done with the dir handle obtained via SetSalvageDirHandle() */
***************
*** 1831,1839 ****
   * fill in appropriate type of on-wire volume metadata structure.
   *
   * @param vp      pointer to volume object
-  * @param hdr     pointer to volume disk data object
   * @param handle  pointer to wire format handle object
   *
   * @pre handle object must have a valid pointer and enumeration value
   *
   * @note passing a NULL value for vp means that the fileserver doesn't
--- 1831,1839 ----
   * fill in appropriate type of on-wire volume metadata structure.
   *
   * @param vp      pointer to volume object
   * @param handle  pointer to wire format handle object
   *
+  * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
   * @pre handle object must have a valid pointer and enumeration value
   *
   * @note passing a NULL value for vp means that the fileserver doesn't
***************
*** 1844,1855 ****
   *   @retval 1 failure
   */
  static int
! FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
  {
      unsigned int numStatBytes, now;
  
      /*read in the relevant info */
!     strcpy(VOLINT_INFO_PTR(handle, name), hdr->name);
      VOLINT_INFO_STORE(handle, status, VOK);	/*its ok */
      VOLINT_INFO_STORE(handle, volid, hdr->id);
      VOLINT_INFO_STORE(handle, type, hdr->type);	/*if ro volume */
--- 1844,1856 ----
   *   @retval 1 failure
   */
  static int
! FillVolInfo(Volume * vp, volint_info_handle_t * handle)
  {
      unsigned int numStatBytes, now;
+     register struct VolumeDiskData *hdr = &vp->header->diskstuff;
  
      /*read in the relevant info */
!     strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
      VOLINT_INFO_STORE(handle, status, VOK);	/*its ok */
      VOLINT_INFO_STORE(handle, volid, hdr->id);
      VOLINT_INFO_STORE(handle, type, hdr->type);	/*if ro volume */
***************
*** 1880,1895 ****
       * along with the blessed and inService flags from the header.
       *   -- tkeiser 11/27/2007
       */
      if (!vp ||
  	(V_attachState(vp) == VOL_STATE_UNATTACHED) ||
  	VIsErrorState(V_attachState(vp)) ||
  	!hdr->inService ||
! 	!hdr->blessed) {
  	VOLINT_INFO_STORE(handle, inUse, 0);
      } else {
  	VOLINT_INFO_STORE(handle, inUse, 1);
      }
  #else
      if (hdr->inUse == fileServer) {
  	VOLINT_INFO_STORE(handle, inUse, 1);
      } else {
--- 1881,1915 ----
       * along with the blessed and inService flags from the header.
       *   -- tkeiser 11/27/2007
       */
+ 
+     /* Conditions that offline status is based on: 
+ 		volume is unattached state
+ 		volume state is in (one of several error states)
+ 		volume not in service
+ 		volume is not marked as blessed (not on hold)
+ 		volume in salvage req. state
+ 		volume needsSalvaged 
+ 		next op would set volume offline
+ 		next op would not leave volume online (based on several conditions)
+     */
      if (!vp ||
  	(V_attachState(vp) == VOL_STATE_UNATTACHED) ||
  	VIsErrorState(V_attachState(vp)) ||
  	!hdr->inService ||
! 	!hdr->blessed || 
! 	(V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
! 	hdr->needsSalvaged ||
! 	(vp->pending_vol_op && 
! 		(vp->pending_vol_op->com.command == FSYNC_VOL_OFF || 
! 		!VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
! 	)
! 	) {
  	VOLINT_INFO_STORE(handle, inUse, 0);
      } else {
  	VOLINT_INFO_STORE(handle, inUse, 1);
      }
  #else
+     /* offline status based on program type, where != fileServer enum (1) is offline */
      if (hdr->inUse == fileServer) {
  	VOLINT_INFO_STORE(handle, inUse, 1);
      } else {
***************
*** 1899,1904 ****
--- 1919,1925 ----
  
  
      switch(handle->volinfo_type) {
+ 	/* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
      case VOLINT_INFO_TYPE_BASE:
  
  #ifdef AFS_DEMAND_ATTACH_FS
***************
*** 2031,2037 ****
      int reason;
      afs_int32 error;
      struct volser_trans *ttc = NULL;
!     struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf, *tv = NULL;
  
      ttc = NewTrans(volumeId, partId);
      if (!ttc) {
--- 2052,2069 ----
      int reason;
      afs_int32 error;
      struct volser_trans *ttc = NULL;
!     struct Volume *fill_tv, *tv = NULL;
! #ifdef AFS_DEMAND_ATTACH_FS
!     struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
!     SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
!     SYNC_response fs_res; /* Response handle for the pending_vol_op */
!     FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
! 
!     /* Set up response handle for pending_vol_op */
!     fs_res.hdr.response_len = sizeof(fs_res.hdr);
!     fs_res.payload.buf = fs_res_buf;
!     fs_res.payload.len = SYNC_PROTO_MAX_LEN;
! #endif
  
      ttc = NewTrans(volumeId, partId);
      if (!ttc) {
***************
*** 2041,2046 ****
--- 2073,2079 ----
  	goto drop;
      }
  
+     /* Get volume from volserver */
      tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
      if (error) {
  	Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n", 
***************
*** 2074,2096 ****
  	/*this volume will be salvaged */
  	Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
  	    volumeId, pname, volname);
- 	goto drop;
      }
  
  #ifdef AFS_DEMAND_ATTACH_FS
      if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
  	goto drop;
      }
  #endif
  
      /* ok, we have all the data we need; fill in the on-wire struct */
!     code = FillVolInfo(fs_tv, &tv->header->diskstuff, handle);
! 
  
   drop:
      if (code == -1) {
  	VOLINT_INFO_STORE(handle, status, 0);
! 	strcpy(VOLINT_INFO_PTR(handle, name), volname);
  	VOLINT_INFO_STORE(handle, volid, volumeId);
      }
      if (tv) {
--- 2107,2146 ----
  	/*this volume will be salvaged */
  	Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
  	    volumeId, pname, volname);
      }
  
  #ifdef AFS_DEMAND_ATTACH_FS
+     /* If using DAFS, get volume from fsserver */
      if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
  	goto drop;
      }
+ 
+     /* fs_tv is a shallow copy, must populate certain structures before passing along */
+     if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) { 
+ 	/* If we if the pending vol op */
+ 	memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
+ 	fs_tv->pending_vol_op=&pending_vol_op_res;
+     } else {
+ 	fs_tv->pending_vol_op=NULL;
+     }
+ 
+     /* populate the header from the volserver copy */
+     fs_tv->header=tv->header;
+ 
+     /* When using DAFS, use the fs volume info, populated with required structures */
+     fill_tv = fs_tv;
+ #else 
+     /* When not using DAFS, just use the local volume info */
+     fill_tv = tv;
  #endif
  
      /* ok, we have all the data we need; fill in the on-wire struct */
!     code = FillVolInfo(fill_tv, handle);
  
   drop:
      if (code == -1) {
  	VOLINT_INFO_STORE(handle, status, 0);
! 	strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
  	VOLINT_INFO_STORE(handle, volid, volumeId);
      }
      if (tv) {
***************
*** 2098,2104 ****
  	tv = NULL;
  	if (error) {
  	    VOLINT_INFO_STORE(handle, status, 0);
! 	    strcpy(VOLINT_INFO_PTR(handle, name), volname);
  	    Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
  		volumeId, pname, volname);
  	}
--- 2148,2154 ----
  	tv = NULL;
  	if (error) {
  	    VOLINT_INFO_STORE(handle, status, 0);
! 	    strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
  	    Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
  		volumeId, pname, volname);
  	}
***************
*** 2141,2146 ****
--- 2191,2198 ----
      volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
      if (!volumeInfo->volEntries_val)
  	return ENOMEM;
+     memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
+ 
      pntr = volumeInfo->volEntries_val;
      volumeInfo->volEntries_len = 1;
      if (GetPartName(partid, pname))
***************
*** 2246,2251 ****
--- 2298,2305 ----
  	(volintXInfo *) malloc(sizeof(volintXInfo));
      if (!a_volumeXInfoP->volXEntries_val)
  	return ENOMEM;
+     memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+ 
      xInfoP = a_volumeXInfoP->volXEntries_val;
      a_volumeXInfoP->volXEntries_len = 1;
      code = ENODEV;
***************
*** 2353,2358 ****
--- 2407,2414 ----
  	(volintInfo *) malloc(allocSize * sizeof(volintInfo));
      if (!volumeInfo->volEntries_val)
  	return ENOMEM;
+     memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
+ 
      pntr = volumeInfo->volEntries_val;
      volumeInfo->volEntries_len = 0;
      if (GetPartName(partid, pname))
***************
*** 2484,2489 ****
--- 2540,2547 ----
  	(volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
      if (!a_volumeXInfoP->volXEntries_val)
  	return ENOMEM;
+     memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+ 
      xInfoP = a_volumeXInfoP->volXEntries_val;
      a_volumeXInfoP->volXEntries_len = 0;
  
