Index: openafs/src/WINNT/afsd/cm_ioctl.c
diff -c openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.13 openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.15
*** openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.13	Thu Aug  4 12:06:37 2005
--- openafs/src/WINNT/afsd/cm_ioctl.c	Fri Sep  9 08:53:17 2005
***************
*** 78,83 ****
--- 78,84 ----
      lock_ReleaseMutex(&scp->mx);
  
      lock_ReleaseWrite(&scp->bufCreateLock);
+     afsi_log("cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
      return code;
  }
  
***************
*** 145,150 ****
--- 146,153 ----
      cm_scache_t *substRootp;
      char * relativePath = ioctlp->inDatap;
  
+     osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
+ 
      /* This is usually the file name, but for StatMountPoint it is the path. */
      /* ioctlp->inDatap can be either of the form:
       *    \path\.
***************
*** 530,535 ****
--- 533,565 ----
      return code;
  }
  
+ long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
+ {
+     long code;
+     cm_scache_t *scp;
+     unsigned long volume;
+     int i;
+     cm_req_t req;
+ 
+     cm_InitReq(&req);
+ 
+     lock_ObtainWrite(&cm_scacheLock);
+     for (i=0; i<cm_data.hashTableSize; i++) {
+         for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+ 	    cm_HoldSCacheNoLock(scp);
+ 	    lock_ReleaseWrite(&cm_scacheLock);
+ 
+ 	    /* now flush the file */
+ 	    code = cm_FlushFile(scp, userp, &req);
+ 	    lock_ObtainWrite(&cm_scacheLock);
+ 	    cm_ReleaseSCacheNoLock(scp);
+         }
+     }
+     lock_ReleaseWrite(&cm_scacheLock);
+ 
+     return code;
+ }
+ 
  long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
  {
      long code;
***************
*** 555,562 ****
  
                  /* now flush the file */
                  code = cm_FlushFile(scp, userp, &req);
-                 if ( code )
-                     afsi_log("cm_FlushFile returns error: [%x]",code);
                  lock_ObtainWrite(&cm_scacheLock);
                  cm_ReleaseSCacheNoLock(scp);
              }
--- 585,590 ----
Index: openafs/src/WINNT/afsd/cm_ioctl.h
diff -c openafs/src/WINNT/afsd/cm_ioctl.h:1.8.2.1 openafs/src/WINNT/afsd/cm_ioctl.h:1.8.2.2
*** openafs/src/WINNT/afsd/cm_ioctl.h:1.8.2.1	Sun Oct 10 19:52:05 2004
--- openafs/src/WINNT/afsd/cm_ioctl.h	Wed Sep  7 12:31:14 2005
***************
*** 59,64 ****
--- 59,66 ----
  
  extern long cm_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp);
  
+ extern long cm_IoctlFlushAllVolumes(smb_ioctl_t *ioctlp, cm_user_t *userp);
+ 
  extern long cm_IoctlFlushVolume(smb_ioctl_t *ioctlp, cm_user_t *userp);
  
  extern long cm_IoctlFlushFile(smb_ioctl_t *ioctlp, cm_user_t *userp);
Index: openafs/src/WINNT/afsd/cm_memmap.c
diff -c openafs/src/WINNT/afsd/cm_memmap.c:1.1.2.3 openafs/src/WINNT/afsd/cm_memmap.c:1.1.2.4
*** openafs/src/WINNT/afsd/cm_memmap.c:1.1.2.3	Wed May 18 18:57:08 2005
--- openafs/src/WINNT/afsd/cm_memmap.c	Fri Sep  9 15:49:30 2005
***************
*** 1,4 ****
--- 1,5 ----
  #include <windows.h>
+ #include <tchar.h>
  #include "afsd.h"
  #include "cm_memmap.h"
  
***************
*** 408,413 ****
--- 409,587 ----
      return 0;
  }
  
+ DWORD 
+ GetVolSerialNumber(char * cachePath)
+ {
+     char rootpath[128];
+     int  i = 0;
+     DWORD serial = 0;
+ 
+     if ( cachePath[0] == '\\' && cachePath[1] == '\\' ||
+ 	 cachePath[0] == '/' && cachePath[1] == '/' ) 
+     {
+ 	rootpath[0]=rootpath[1]='\\';
+ 	for ( i=2; cachePath[i]; i++ ) {
+ 	    rootpath[i] = cachePath[i];
+ 	    if ( cachePath[i] == '\\' || cachePath[i] == '/' ) {
+ 		i++;
+ 		break;
+ 	    }
+ 	}
+     } else if ( cachePath[1] == ':' ) {
+ 	rootpath[0] = cachePath[0];
+ 	rootpath[1] = ':';
+ 	i = 2;
+     }
+ 
+     for ( ; cachePath[i]; i++ ) {
+ 	rootpath[i] = cachePath[i];
+ 	if ( cachePath[i] == '\\' || cachePath[i] == '/' ) {
+ 	    i++;
+ 	    break;
+ 	}
+     }
+     rootpath[i] = '\0';
+ 
+     GetVolumeInformation(rootpath, NULL, 0, &serial, NULL, NULL, NULL, 0);
+     return serial;
+ }
+ 
+ BOOL GetTextualSid( PSID pSid, PBYTE TextualSid, LPDWORD lpdwBufferLen )
+ {
+     PSID_IDENTIFIER_AUTHORITY psia;
+     DWORD dwSubAuthorities;
+     DWORD dwSidRev=SID_REVISION;
+     DWORD dwCounter;
+     DWORD dwSidSize;
+ 
+     // Validate the binary SID.
+     if(!IsValidSid(pSid)) 
+ 	return FALSE;
+ 
+     // Get the identifier authority value from the SID.
+ 
+     psia = GetSidIdentifierAuthority(pSid);
+ 
+     // Get the number of subauthorities in the SID.
+ 
+     dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
+ 
+     // Compute the buffer length.
+     // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
+ 
+     dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1);
+ 
+     // Check input buffer length.
+     // If too small, indicate the proper size and set the last error.
+ 
+     if (*lpdwBufferLen < dwSidSize)
+     {
+         *lpdwBufferLen = dwSidSize;
+         SetLastError(ERROR_INSUFFICIENT_BUFFER);
+         return FALSE;
+     }
+ 
+     // Add 'S' prefix and revision number to the string.
+     dwSidSize=sprintf(TextualSid, "S-%lu-", dwSidRev );
+ 
+     // Add a SID identifier authority to the string.
+     if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
+     {
+         dwSidSize+=sprintf(TextualSid + strlen(TextualSid),
+                     "0x%02hx%02hx%02hx%02hx%02hx%02hx",
+                     (USHORT)psia->Value[0],
+                     (USHORT)psia->Value[1],
+                     (USHORT)psia->Value[2],
+                     (USHORT)psia->Value[3],
+                     (USHORT)psia->Value[4],
+                     (USHORT)psia->Value[5]);
+     }
+     else
+     {
+         dwSidSize+=sprintf(TextualSid + strlen(TextualSid),
+                     "%lu",
+                     (ULONG)(psia->Value[5]      )   +
+                     (ULONG)(psia->Value[4] <<  8)   +
+                     (ULONG)(psia->Value[3] << 16)   +
+                     (ULONG)(psia->Value[2] << 24)   );
+     }
+ 
+     // Add SID subauthorities to the string.
+     //
+     for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
+     {
+         dwSidSize+=sprintf(TextualSid + dwSidSize, "-%lu",
+                     *GetSidSubAuthority(pSid, dwCounter) );
+     }
+ 
+     return TRUE;
+ }
+ 
+ PBYTE 
+ IsSubAuthValid( PBYTE SidData, DWORD SidLength )
+ {
+     PBYTE	sidPtr;
+ 
+     sidPtr = NULL;
+     if ( SidLength % sizeof(DWORD) == 0 )  {
+ 	for ( sidPtr = SidData + SidLength - 5*sizeof(DWORD); 
+ 	      sidPtr >= SidData; 
+ 	      sidPtr -= sizeof(DWORD) )
+ 	    if ( ((PDWORD)sidPtr)[1] == 0x05000000 &&  
+ 		 ((PDWORD)sidPtr)[2] == 0x00000015 )
+ 		break;
+ 	if ( sidPtr < SidData )
+ 	    sidPtr = NULL;
+     }
+     return sidPtr;
+ }
+ 
+ BOOL
+ GetMachineSid(PBYTE SidBuffer, DWORD SidSize)
+ {
+     HKEY  	hKey;
+     PBYTE 	vData;
+     DWORD 	dwType;
+     DWORD 	dwLen;
+     PBYTE 	pSid;
+     DWORD 	dwStatus;
+ 
+     if (!SidBuffer)
+ 	return FALSE;
+ 
+     //
+     // Read the last subauthority of the current computer SID
+     //
+     if( RegOpenKey( HKEY_LOCAL_MACHINE, "SECURITY\\SAM\\Domains\\Account", 
+ 		    &hKey) != ERROR_SUCCESS ) {
+ 	return FALSE;
+     }
+     dwLen = 0;
+     vData = NULL;
+     RegQueryValueEx( hKey, "V", NULL, &dwType, vData, &dwLen );
+     vData = (PBYTE) malloc( dwLen );
+     dwStatus = RegQueryValueEx( hKey, "V", NULL, &dwType, vData, &dwLen );
+     RegCloseKey( hKey );
+     if( dwStatus != ERROR_SUCCESS ) {
+ 	return FALSE;
+     }
+ 
+     //
+     // Make sure that we're dealing with a SID we understand
+     //
+     pSid = IsSubAuthValid( vData, dwLen );
+ 
+     if( !pSid || SidSize < dwLen - (pSid - vData)) {
+ 	free(vData);
+ 	return FALSE;
+     }
+ 
+     memset(SidBuffer, 0, SidSize);
+     memcpy(SidBuffer, pSid, dwLen - (pSid - vData) );
+     free(vData);
+     return TRUE;
+ }
+ 
  int
  cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chunkSize, DWORD cacheBlocks)
  {
***************
*** 417,426 ****
--- 591,607 ----
      DWORD mappingSize;
      DWORD maxVols = stats/2;
      DWORD maxCells = stats/4;
+     DWORD volumeSerialNumber = 0;
+     DWORD sidStringSize = 0;
+     DWORD rc;
+     CHAR  machineSid[6 * sizeof(DWORD)]="";
      char * baseAddress = NULL;
      cm_config_data_t * config_data_p;
      char * p;
  
+     volumeSerialNumber = GetVolSerialNumber(cachePath);
+     GetMachineSid(machineSid, sizeof(machineSid));
+ 
      mappingSize = ComputeSizeOfMappingFile(stats, maxVols, maxCells, chunkSize, cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE);
  
      if ( !virtualCache ) {
***************
*** 644,653 ****
          cm_data.bufDataBaseAddress = (char *) baseAddress;
          baseAddress += ComputeSizeOfDataBuffers(cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE);
          cm_data.bufEndOfData = (char *) baseAddress;
- 
          cm_data.fakeDirVersion = 0x8;
- 
          UuidCreate((UUID *)&cm_data.Uuid);
      }
  
      UuidToString((UUID *)&cm_data.Uuid, &p);
--- 825,876 ----
          cm_data.bufDataBaseAddress = (char *) baseAddress;
          baseAddress += ComputeSizeOfDataBuffers(cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE);
          cm_data.bufEndOfData = (char *) baseAddress;
          cm_data.fakeDirVersion = 0x8;
          UuidCreate((UUID *)&cm_data.Uuid);
+ 	cm_data.volSerialNumber = volumeSerialNumber;
+ 	memcpy(cm_data.Sid, machineSid, sizeof(machineSid));
+     } else {
+ 	int gennew = 0;
+ 
+ 	if ( volumeSerialNumber == 0 || volumeSerialNumber != cm_data.volSerialNumber ) {
+ 	    gennew = 1;
+ 	    afsi_log("Volume serial number change, generating new UUID");
+ 	    afsi_log("Old volume Serial Number: 0x%x", cm_data.volSerialNumber);
+ 	} else if ( machineSid[0] && memcmp(machineSid, cm_data.Sid, sizeof(machineSid))) {
+ 	    gennew = 1;
+ 	    afsi_log("Machine Sid changed, generating new UUID");
+ 	    GetTextualSid( (PSID)cm_data.Sid, NULL, &sidStringSize );
+ 	    if (sidStringSize) {
+ 		p = malloc(sidStringSize * sizeof(TCHAR));
+ 		if (p) {
+ 		    rc = GetTextualSid( (PSID)cm_data.Sid, p, &sidStringSize );
+ 		    afsi_log("Old Machine SID: %s", rc ? p : "unknown");
+ 		    free(p);
+ 		}
+ 	    } else {
+ 		afsi_log("Old Machine SID: unknown");
+ 	    }
+ 	}
+ 
+ 	if (gennew) {
+ 	    UuidCreate((UUID *)&cm_data.Uuid);
+ 	    cm_data.volSerialNumber = volumeSerialNumber;
+ 	    memcpy(cm_data.Sid, machineSid, sizeof(machineSid));
+ 	}
+     }
+ 
+     afsi_log("Volume Serial Number: 0x%x", cm_data.volSerialNumber);
+ 
+     GetTextualSid( (PSID)cm_data.Sid, NULL, &sidStringSize );
+     if (sidStringSize) {
+ 	p = malloc(sidStringSize * sizeof(TCHAR));
+ 	if (p) {
+ 	    rc = GetTextualSid( (PSID)cm_data.Sid, p, &sidStringSize );
+ 	    afsi_log("Machine SID: %s", rc ? p : "unknown");
+ 	    free(p);
+ 	}
+     } else {
+ 	afsi_log("Machine SID: unknown");
      }
  
      UuidToString((UUID *)&cm_data.Uuid, &p);
Index: openafs/src/WINNT/afsd/cm_memmap.h
diff -c openafs/src/WINNT/afsd/cm_memmap.h:1.1.2.1 openafs/src/WINNT/afsd/cm_memmap.h:1.1.2.2
*** openafs/src/WINNT/afsd/cm_memmap.h:1.1.2.1	Fri Mar 11 02:22:40 2005
--- openafs/src/WINNT/afsd/cm_memmap.h	Fri Sep  9 15:49:30 2005
***************
*** 78,83 ****
--- 78,85 ----
  
      time_t              mountRootGen;
      afsUUID             Uuid;
+     DWORD 		volSerialNumber;
+     CHAR 		Sid[6 * sizeof(DWORD)];
  } cm_config_data_t;
  
  extern cm_config_data_t cm_data;
***************
*** 93,99 ****
  DWORD ComputeSizeOfDataBuffers(DWORD cacheBlocks, DWORD blockSize);
  DWORD ComputeSizeOfDataHT(void);
  DWORD ComputeSizeOfDataHeaders(DWORD cacheBlocks);
! DWORD ComputeSizeOfMappingFile(DWORD stats, DWORD chunkSize, DWORD cacheBlocks, DWORD blockSize);
  PSECURITY_ATTRIBUTES CreateCacheFileSA();
  VOID  FreeCacheFileSA(PSECURITY_ATTRIBUTES psa);
  int   cm_ShutdownMappedMemory(void);
--- 95,101 ----
  DWORD ComputeSizeOfDataBuffers(DWORD cacheBlocks, DWORD blockSize);
  DWORD ComputeSizeOfDataHT(void);
  DWORD ComputeSizeOfDataHeaders(DWORD cacheBlocks);
! DWORD ComputeSizeOfMappingFile(DWORD stats, DWORD maxVols, DWORD maxCells, DWORD chunkSize, DWORD cacheBlocks, DWORD blockSize);
  PSECURITY_ATTRIBUTES CreateCacheFileSA();
  VOID  FreeCacheFileSA(PSECURITY_ATTRIBUTES psa);
  int   cm_ShutdownMappedMemory(void);
Index: openafs/src/WINNT/afsd/fs.c
diff -c openafs/src/WINNT/afsd/fs.c:1.16.2.10 openafs/src/WINNT/afsd/fs.c:1.16.2.15
*** openafs/src/WINNT/afsd/fs.c:1.16.2.10	Wed Aug 31 07:00:31 2005
--- openafs/src/WINNT/afsd/fs.c	Fri Sep  9 15:44:57 2005
***************
*** 1344,1349 ****
--- 1344,1364 ----
  }
  
  static int
+ FlushAllCmd(struct cmd_syndesc *as, char *arock)
+ {
+     afs_int32 code;
+     struct ViceIoctl blob;
+ 
+     blob.in_size = blob.out_size = 0;
+     code = pioctl(NULL, VIOC_FLUSHALL, &blob, 0);
+     if (code) {
+ 	fprintf(stderr, "Error flushing all ");
+ 	return 1;
+     }
+     return 0;
+ }
+ 
+ static int
  FlushVolumeCmd(struct cmd_syndesc *as, char *arock)
  {
      afs_int32 code;
***************
*** 1817,1823 ****
--- 1832,1840 ----
  #endif
      char path[1024] = "";
      struct afsconf_cell info;
+ #ifndef WIN32
      struct vldbentry vldbEntry;
+ #endif
      struct ViceIoctl blob;
      char * parent;
  
***************
*** 4456,4462 ****
      cmd_AddParm(ts, "-cell", CMD_LIST, 0, "cell name");
      cmd_AddParm(ts, "-suid", CMD_FLAG, CMD_OPTIONAL, "allow setuid programs");
      cmd_AddParm(ts, "-nosuid", CMD_FLAG, CMD_OPTIONAL, "disallow setuid programs");
!     
      ts = cmd_CreateSyntax("flushvolume", FlushVolumeCmd, 0, "flush all data in volume");
      cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
  
--- 4473,4481 ----
      cmd_AddParm(ts, "-cell", CMD_LIST, 0, "cell name");
      cmd_AddParm(ts, "-suid", CMD_FLAG, CMD_OPTIONAL, "allow setuid programs");
      cmd_AddParm(ts, "-nosuid", CMD_FLAG, CMD_OPTIONAL, "disallow setuid programs");
! 
!     ts = cmd_CreateSyntax("flushall", FlushAllCmd, 0, "flush all data");
! 
      ts = cmd_CreateSyntax("flushvolume", FlushVolumeCmd, 0, "flush all data in volume");
      cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
  
Index: openafs/src/WINNT/afsd/smb_iocons.h
diff -c openafs/src/WINNT/afsd/smb_iocons.h:1.6.2.1 openafs/src/WINNT/afsd/smb_iocons.h:1.6.2.2
*** openafs/src/WINNT/afsd/smb_iocons.h:1.6.2.1	Fri Mar 11 01:58:52 2005
--- openafs/src/WINNT/afsd/smb_iocons.h	Wed Sep  7 12:31:14 2005
***************
*** 91,94 ****
--- 91,95 ----
  #define VIOC_SETRXKCRYPT		0x28
  #define VIOC_TRACEMEMDUMP               0x29
  #define VIOC_SHUTDOWN                   0x2a
+ #define VIOC_FLUSHALL                   0x2b
  #endif /*  __SMB_IOCONS_H_ENV_ */
Index: openafs/src/WINNT/afsd/smb_ioctl.c
diff -c openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.1 openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.3
*** openafs/src/WINNT/afsd/smb_ioctl.c:1.14.2.1	Fri Mar 11 01:58:52 2005
--- openafs/src/WINNT/afsd/smb_ioctl.c	Wed Sep  7 15:24:39 2005
***************
*** 31,36 ****
--- 31,40 ----
  
  void smb_InitIoctl(void)
  {
+         int i;
+         for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
+ 	    smb_ioctlProcsp[i] = NULL;
+ 
  	smb_ioctlProcsp[VIOCGETAL] = cm_IoctlGetACL;
          smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = cm_IoctlGetFileCellName;
          smb_ioctlProcsp[VIOCSETAL] = cm_IoctlSetACL;
***************
*** 74,79 ****
--- 78,84 ----
  #endif
  	smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = cm_IoctlMemoryDump;
  	smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
+         smb_ioctlProcsp[VIOC_FLUSHALL] = cm_IoctlFlushAllVolumes;
  }
  
  /* called to make a fid structure into an IOCTL fid structure */
Index: openafs/src/afs/afs_daemons.c
diff -c openafs/src/afs/afs_daemons.c:1.28.2.5 openafs/src/afs/afs_daemons.c:1.28.2.7
*** openafs/src/afs/afs_daemons.c:1.28.2.5	Sun Apr  3 14:18:54 2005
--- openafs/src/afs/afs_daemons.c	Wed Sep  7 13:43:25 2005
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.28.2.5 2005/04/03 18:18:54 shadow Exp $");
  
  #ifdef AFS_AIX51_ENV
  #define __FULL_PROTO
--- 11,17 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.28.2.7 2005/09/07 17:43:25 shadow Exp $");
  
  #ifdef AFS_AIX51_ENV
  #define __FULL_PROTO
***************
*** 309,316 ****
--- 309,363 ----
  		 * count to zero and fs checkv is executed when the current
  		 * directory is /afs.
  		 */
+ #ifdef AFS_LINUX20_ENV
+ 		{
+ 		    struct vrequest treq;
+ 		    struct vattr vattr;
+ 		    cred_t *credp;
+ 		    struct dentry *dp;
+ 		    struct vcache *vcp;
+ 		    
+ 		    afs_rootFid.Fid.Volume = volid;
+ 		    afs_rootFid.Fid.Vnode = 1;
+ 		    afs_rootFid.Fid.Unique = 1;
+ 		    
+ 		    credp = crref();
+ 		    if (afs_InitReq(&treq, credp))
+ 			goto out;
+ 		    vcp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+ 		    if (!vcp)
+ 			goto out;
+ 		    afs_getattr(vcp, &vattr, credp);
+ 		    afs_fill_inode(AFSTOV(vcp), &vattr);
+ 		    
+ 		    dp = d_find_alias(AFSTOV(afs_globalVp));
+ 		    
+ #if defined(AFS_LINUX24_ENV)
+ 		    spin_lock(&dcache_lock);
+ #if defined(AFS_LINUX26_ENV)
+ 		    spin_lock(&dp->d_lock);
+ #endif
+ #endif
+ 		    list_del_init(&dp->d_alias);
+ 		    list_add(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
+ 		    dp->d_inode = AFSTOV(vcp);
+ #if defined(AFS_LINUX24_ENV)
+ #if defined(AFS_LINUX26_ENV)
+ 		    spin_unlock(&dp->d_lock);
+ #endif
+ 		    spin_unlock(&dcache_lock);
+ #endif
+ 		    dput(dp);
+ 		    
+ 		    AFS_FAST_RELE(afs_globalVp);
+ 		    afs_globalVp = vcp;
+ 		out:
+ 		    crfree(credp);
+ 		}
+ #else
  		AFS_FAST_RELE(afs_globalVp);
  		afs_globalVp = 0;
+ #endif
  	    }
  	    afs_rootFid.Fid.Volume = volid;
  	    afs_rootFid.Fid.Vnode = 1;
Index: openafs/src/afs/LINUX/osi_sleep.c
diff -c openafs/src/afs/LINUX/osi_sleep.c:1.22.2.6 openafs/src/afs/LINUX/osi_sleep.c:1.22.2.7
*** openafs/src/afs/LINUX/osi_sleep.c:1.22.2.6	Wed Aug 10 15:23:19 2005
--- openafs/src/afs/LINUX/osi_sleep.c	Thu Sep  8 14:53:45 2005
***************
*** 11,17 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_sleep.c,v 1.22.2.6 2005/08/10 19:23:19 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/LINUX/osi_sleep.c,v 1.22.2.7 2005/09/08 18:53:45 shadow Exp $");
  
  #include "afs/sysincludes.h"	/* Standard vendor system headers */
  #include "afsincludes.h"	/* Afs-based standard headers */
***************
*** 194,200 ****
  	schedule();
  #ifdef AFS_LINUX26_ENV
  #ifdef CONFIG_PM
! 	if (current->flags & PF_FREEZE)
  #ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
  	    refrigerator(PF_FREEZE);
  #else
--- 194,206 ----
  	schedule();
  #ifdef AFS_LINUX26_ENV
  #ifdef CONFIG_PM
! 	if (
! #ifdef PF_FREEZE
! 	    current->flags & PF_FREEZE
! #else
! 	    !current->todo
! #endif
! 	    )
  #ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
  	    refrigerator(PF_FREEZE);
  #else
Index: openafs/src/config/NTMakefile.amd64_w2k
diff -c openafs/src/config/NTMakefile.amd64_w2k:1.1.2.16 openafs/src/config/NTMakefile.amd64_w2k:1.1.2.17
*** openafs/src/config/NTMakefile.amd64_w2k:1.1.2.16	Wed Aug 31 20:15:20 2005
--- openafs/src/config/NTMakefile.amd64_w2k	Wed Sep 14 00:34:49 2005
***************
*** 80,86 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0002
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
--- 80,86 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0003
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
Index: openafs/src/config/NTMakefile.i386_nt40
diff -c openafs/src/config/NTMakefile.i386_nt40:1.46.2.31 openafs/src/config/NTMakefile.i386_nt40:1.46.2.32
*** openafs/src/config/NTMakefile.i386_nt40:1.46.2.31	Wed Aug 31 20:15:20 2005
--- openafs/src/config/NTMakefile.i386_nt40	Wed Sep 14 00:34:49 2005
***************
*** 80,86 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0002
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
--- 80,86 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0003
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
Index: openafs/src/config/NTMakefile.i386_w2k
diff -c openafs/src/config/NTMakefile.i386_w2k:1.1.2.17 openafs/src/config/NTMakefile.i386_w2k:1.1.2.18
*** openafs/src/config/NTMakefile.i386_w2k:1.1.2.17	Fri Sep  2 13:37:08 2005
--- openafs/src/config/NTMakefile.i386_w2k	Wed Sep 14 00:34:49 2005
***************
*** 79,85 ****
  
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0002
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
--- 79,85 ----
  
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MINOR=4
! AFSPRODUCT_VER_PATCH=0003
  AFSPRODUCT_VER_BUILD=0
  
  # For MSI installer, each major release should have a different GUID
Index: openafs/src/packaging/MacOS/OpenAFS.info
diff -c openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.17 openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.18
*** openafs/src/packaging/MacOS/OpenAFS.info:1.1.4.17	Mon Sep  5 01:04:19 2005
--- openafs/src/packaging/MacOS/OpenAFS.info	Wed Sep 14 14:27:19 2005
***************
*** 1,5 ****
  Title OpenAFS
! Version 1.4.0-rc3
  Description The OpenAFS distributed filesystem. This package installs an almost-ready-to-run client for OpenAFS. see http://www.openafs.org for more information.
  DefaultLocation /
  Diskname (null)
--- 1,5 ----
  Title OpenAFS
! Version 1.4.0-rc4
  Description The OpenAFS distributed filesystem. This package installs an almost-ready-to-run client for OpenAFS. see http://www.openafs.org for more information.
  DefaultLocation /
  Diskname (null)
Index: openafs/src/rx/rx.c
diff -c openafs/src/rx/rx.c:1.58.2.22 openafs/src/rx/rx.c:1.58.2.26
*** openafs/src/rx/rx.c:1.58.2.22	Fri Sep  2 18:50:59 2005
--- openafs/src/rx/rx.c	Wed Sep 14 04:53:12 2005
***************
*** 17,23 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx.c,v 1.58.2.22 2005/09/02 22:50:59 shadow Exp $");
  
  #ifdef KERNEL
  #include "afs/sysincludes.h"
--- 17,23 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx.c,v 1.58.2.26 2005/09/14 08:53:12 jaltman Exp $");
  
  #ifdef KERNEL
  #include "afs/sysincludes.h"
***************
*** 1170,1180 ****
--- 1170,1186 ----
      MUTEX_ENTER(&call->lock);
      while (call->flags & RX_CALL_TQ_BUSY) {
  	call->flags |= RX_CALL_TQ_WAIT;
+ 	call->tqWaiters++;
  #ifdef RX_ENABLE_LOCKS
+ 	osirx_AssertMine(&call->lock, "rxi_Start lock4");
  	CV_WAIT(&call->cv_tq, &call->lock);
  #else /* RX_ENABLE_LOCKS */
  	osi_rxSleep(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
+ 	call->tqWaiters--;
+ 	if (call->tqWaiters == 0) {
+ 	    call->flags &= ~RX_CALL_TQ_WAIT;
+ 	}
      }
      if (call->flags & RX_CALL_TQ_CLEARME) {
  	rxi_ClearTransmitQueue(call, 0);
***************
*** 2602,2607 ****
--- 2608,2616 ----
  	    call = rxi_NewCall(conn, channel);
  	    MUTEX_EXIT(&conn->conn_call_lock);
  	    *call->callNumber = np->header.callNumber;
+ 	    if (np->header.callNumber == 0) 
+ 		dpf(("RecPacket call 0 %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %lx resend %d.%0.3d len %d", np->header.serial, rx_packetTypes[np->header.type - 1], conn->peer->host, conn->peer->port, np->header.serial, np->header.epoch, np->header.cid, np->header.callNumber, np->header.seq, np->header.flags, (unsigned long)np, np->retryTime.sec, np->retryTime.usec / 1000, np->length));
+ 
  	    call->state = RX_STATE_PRECALL;
  	    clock_GetTime(&call->queueTime);
  	    hzero(call->bytesSent);
***************
*** 2635,2645 ****
--- 2644,2659 ----
  	    while ((call->state == RX_STATE_ACTIVE)
  		   && (call->flags & RX_CALL_TQ_BUSY)) {
  		call->flags |= RX_CALL_TQ_WAIT;
+ 		call->tqWaiters++;
  #ifdef RX_ENABLE_LOCKS
+ 		osirx_AssertMine(&call->lock, "rxi_Start lock3");
  		CV_WAIT(&call->cv_tq, &call->lock);
  #else /* RX_ENABLE_LOCKS */
  		osi_rxSleep(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
+ 		call->tqWaiters--;
+ 		if (call->tqWaiters == 0)
+ 		    call->flags &= ~RX_CALL_TQ_WAIT;
  	    }
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
  	    /* If the new call cannot be taken right now send a busy and set
***************
*** 2659,2664 ****
--- 2673,2681 ----
  	    }
  	    rxi_ResetCall(call, 0);
  	    *call->callNumber = np->header.callNumber;
+ 	    if (np->header.callNumber == 0) 
+ 		dpf(("RecPacket call 0 %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %lx resend %d.%0.3d len %d", np->header.serial, rx_packetTypes[np->header.type - 1], conn->peer->host, conn->peer->port, np->header.serial, np->header.epoch, np->header.cid, np->header.callNumber, np->header.seq, np->header.flags, (unsigned long)np, np->retryTime.sec, np->retryTime.usec / 1000, np->length));
+ 
  	    call->state = RX_STATE_PRECALL;
  	    clock_GetTime(&call->queueTime);
  	    hzero(call->bytesSent);
***************
*** 3796,3806 ****
--- 3813,3828 ----
  	call->flags |= RX_CALL_FAST_RECOVER_WAIT;
  	while (call->flags & RX_CALL_TQ_BUSY) {
  	    call->flags |= RX_CALL_TQ_WAIT;
+ 	    call->tqWaiters++;
  #ifdef RX_ENABLE_LOCKS
+ 	    osirx_AssertMine(&call->lock, "rxi_Start lock2");
  	    CV_WAIT(&call->cv_tq, &call->lock);
  #else /* RX_ENABLE_LOCKS */
  	    osi_rxSleep(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
+ 	    call->tqWaiters--;
+ 	    if (call->tqWaiters == 0)
+ 		call->flags &= ~RX_CALL_TQ_WAIT;
  	}
  	MUTEX_ENTER(&peer->peer_lock);
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
***************
*** 4334,4340 ****
      if (call->error)
  	error = call->error;
  #ifdef RX_GLOBAL_RXLOCK_KERNEL
!     if (!(call->flags & RX_CALL_TQ_BUSY)) {
  	rxi_ResetCall(call, 0);
      }
  #else
--- 4356,4362 ----
      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);
      }
  #else
***************
*** 4410,4416 ****
      flags = call->flags;
      rxi_ClearReceiveQueue(call);
  #ifdef	AFS_GLOBAL_RXLOCK_KERNEL
!     if (call->flags & RX_CALL_TQ_BUSY) {
  	call->flags = RX_CALL_TQ_CLEARME | RX_CALL_TQ_BUSY;
  	call->flags |= (flags & RX_CALL_TQ_WAIT);
      } else
--- 4432,4438 ----
      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;
  	call->flags |= (flags & RX_CALL_TQ_WAIT);
      } else
***************
*** 4418,4424 ****
--- 4440,4457 ----
      {
  	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));
+ 	}
  	call->flags = 0;
+ 	while (call->tqWaiters) {
+ #ifdef RX_ENABLE_LOCKS
+ 	    CV_BROADCAST(&call->cv_tq);
+ #else /* RX_ENABLE_LOCKS */
+ 	    osi_rxWakeup(&call->tq);
+ #endif /* RX_ENABLE_LOCKS */
+ 	    call->tqWaiters--;
+ 	}
      }
      queue_Init(&call->rq);
      call->error = 0;
***************
*** 4971,4981 ****
--- 5004,5019 ----
  	call->flags |= RX_CALL_FAST_RECOVER_WAIT;
  	while (call->flags & RX_CALL_TQ_BUSY) {
  	    call->flags |= RX_CALL_TQ_WAIT;
+ 	    call->tqWaiters++;
  #ifdef RX_ENABLE_LOCKS
+ 	    osirx_AssertMine(&call->lock, "rxi_Start lock1");
  	    CV_WAIT(&call->cv_tq, &call->lock);
  #else /* RX_ENABLE_LOCKS */
  	    osi_rxSleep(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
+ 	    call->tqWaiters--;
+ 	    if (call->tqWaiters == 0)
+ 		call->flags &= ~RX_CALL_TQ_WAIT;
  	}
  #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
  	call->flags &= ~RX_CALL_FAST_RECOVER_WAIT;
***************
*** 5131,5144 ****
  		 */
  		if (call->flags & RX_CALL_FAST_RECOVER_WAIT) {
  		    call->flags &= ~RX_CALL_TQ_BUSY;
! 		    if (call->flags & RX_CALL_TQ_WAIT) {
! 			call->flags &= ~RX_CALL_TQ_WAIT;
  #ifdef RX_ENABLE_LOCKS
! 			CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 			osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
- 		    }
  		    return;
  		}
  		if (call->error) {
--- 5169,5183 ----
  		 */
  		if (call->flags & RX_CALL_FAST_RECOVER_WAIT) {
  		    call->flags &= ~RX_CALL_TQ_BUSY;
! 		    if (call->tqWaiters || (call->flags & RX_CALL_TQ_WAIT)) {
! 			dpf(("call %x has %d waiters and flags %d\n", call, call->tqWaiters, call->flags));
! 		    }
  #ifdef RX_ENABLE_LOCKS
! 		    osirx_AssertMine(&call->lock, "rxi_Start start");
! 		    CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 		    osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
  		    return;
  		}
  		if (call->error) {
***************
*** 5150,5163 ****
  		    rx_tq_debug.rxi_start_aborted++;
  		    MUTEX_EXIT(&rx_stats_mutex);
  		    call->flags &= ~RX_CALL_TQ_BUSY;
! 		    if (call->flags & RX_CALL_TQ_WAIT) {
! 			call->flags &= ~RX_CALL_TQ_WAIT;
  #ifdef RX_ENABLE_LOCKS
! 			CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 			osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
- 		    }
  		    rxi_CallError(call, call->error);
  		    return;
  		}
--- 5189,5203 ----
  		    rx_tq_debug.rxi_start_aborted++;
  		    MUTEX_EXIT(&rx_stats_mutex);
  		    call->flags &= ~RX_CALL_TQ_BUSY;
! 		    if (call->tqWaiters || (call->flags & RX_CALL_TQ_WAIT)) {
! 			dpf(("call %x has %d waiters and flags %d\n", call, call->tqWaiters, call->flags));
! 		    }
  #ifdef RX_ENABLE_LOCKS
! 		    osirx_AssertMine(&call->lock, "rxi_Start middle");
! 		    CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 		    osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
  		    rxi_CallError(call, call->error);
  		    return;
  		}
***************
*** 5237,5250 ****
  	     * protected by the global lock.
  	     */
  	    call->flags &= ~RX_CALL_TQ_BUSY;
! 	    if (call->flags & RX_CALL_TQ_WAIT) {
! 		call->flags &= ~RX_CALL_TQ_WAIT;
  #ifdef RX_ENABLE_LOCKS
! 		CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 		osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
- 	    }
  	} else {
  	    call->flags |= RX_CALL_NEED_START;
  	}
--- 5277,5291 ----
  	     * protected by the global lock.
  	     */
  	    call->flags &= ~RX_CALL_TQ_BUSY;
! 	    if (call->tqWaiters || (call->flags & RX_CALL_TQ_WAIT)) {
! 		dpf(("call %x has %d waiters and flags %d\n", call, call->tqWaiters, call->flags));
! 	    }
  #ifdef RX_ENABLE_LOCKS
! 	    osirx_AssertMine(&call->lock, "rxi_Start end");
! 	    CV_BROADCAST(&call->cv_tq);
  #else /* RX_ENABLE_LOCKS */
! 	    osi_rxWakeup(&call->tq);
  #endif /* RX_ENABLE_LOCKS */
  	} else {
  	    call->flags |= RX_CALL_NEED_START;
  	}
Index: openafs/src/rx/rx.h
diff -c openafs/src/rx/rx.h:1.22.2.3 openafs/src/rx/rx.h:1.22.2.4
*** openafs/src/rx/rx.h:1.22.2.3	Sun Jan 30 23:14:46 2005
--- openafs/src/rx/rx.h	Wed Sep 14 01:12:45 2005
***************
*** 540,545 ****
--- 540,546 ----
      struct clock startTime;	/* time call was started */
      afs_hyper_t bytesSent;	/* Number bytes sent */
      afs_hyper_t bytesRcvd;	/* Number bytes received */
+     u_short tqWaiters;
  };
  
  #ifndef KDUMP_RX_LOCK
Index: openafs/src/rx/rx_packet.c
diff -c openafs/src/rx/rx_packet.c:1.35.2.15 openafs/src/rx/rx_packet.c:1.35.2.16
*** openafs/src/rx/rx_packet.c:1.35.2.15	Sun May 29 23:41:45 2005
--- openafs/src/rx/rx_packet.c	Tue Sep 13 23:58:28 2005
***************
*** 15,21 ****
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.35.2.15 2005/05/30 03:41:45 jaltman Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
--- 15,21 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_packet.c,v 1.35.2.16 2005/09/14 03:58:28 shadow Exp $");
  
  #ifdef KERNEL
  #if defined(UKERNEL)
***************
*** 2500,2505 ****
--- 2500,2510 ----
      p->header.cid = (conn->cid | call->channel);
      p->header.serviceId = conn->serviceId;
      p->header.securityIndex = conn->securityIndex;
+ 
+     /* No data packets on call 0. Where do these come from? */
+     if (*call->callNumber == 0)
+ 	*call->callNumber = 1;
+ 
      p->header.callNumber = *call->callNumber;
      p->header.seq = call->tnext++;
      p->header.epoch = conn->epoch;
Index: openafs/src/rx/LINUX/rx_kmutex.c
diff -c openafs/src/rx/LINUX/rx_kmutex.c:1.7.2.2 openafs/src/rx/LINUX/rx_kmutex.c:1.7.2.3
*** openafs/src/rx/LINUX/rx_kmutex.c:1.7.2.2	Mon Apr 25 13:20:00 2005
--- openafs/src/rx/LINUX/rx_kmutex.c	Wed Sep 14 01:12:46 2005
***************
*** 17,23 ****
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/LINUX/rx_kmutex.c,v 1.7.2.2 2005/04/25 17:20:00 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  #include "rx_kmutex.h"
--- 17,23 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/LINUX/rx_kmutex.c,v 1.7.2.3 2005/09/14 05:12:46 shadow Exp $");
  
  #include "rx/rx_kcommon.h"
  #include "rx_kmutex.h"
***************
*** 72,78 ****
  int
  afs_cv_wait(afs_kcondvar_t * cv, afs_kmutex_t * l, int sigok)
  {
!     int isAFSGlocked = ISAFS_GLOCK();
      sigset_t saved_set;
  #ifdef DECLARE_WAITQUEUE
      DECLARE_WAITQUEUE(wait, current);
--- 72,78 ----
  int
  afs_cv_wait(afs_kcondvar_t * cv, afs_kmutex_t * l, int sigok)
  {
!     int seq, isAFSGlocked = ISAFS_GLOCK();
      sigset_t saved_set;
  #ifdef DECLARE_WAITQUEUE
      DECLARE_WAITQUEUE(wait, current);
***************
*** 80,87 ****
      struct wait_queue wait = { current, NULL };
  #endif
  
!     add_wait_queue(cv, &wait);
      set_current_state(TASK_INTERRUPTIBLE);
  
      if (isAFSGlocked)
  	AFS_GUNLOCK();
--- 80,89 ----
      struct wait_queue wait = { current, NULL };
  #endif
  
!     seq = cv->seq;
!     
      set_current_state(TASK_INTERRUPTIBLE);
+     add_wait_queue(&cv->waitq, &wait);
  
      if (isAFSGlocked)
  	AFS_GUNLOCK();
***************
*** 95,102 ****
  	SIG_UNLOCK(current);
      }
  
!     schedule();
!     remove_wait_queue(cv, &wait);
  
      if (!sigok) {
  	SIG_LOCK(current);
--- 97,109 ----
  	SIG_UNLOCK(current);
      }
  
!     while(seq == cv->seq) {
! 	schedule();
! 	/* should we refrigerate? */
!     }
! 
!     remove_wait_queue(&cv->waitq, &wait);
!     set_current_state(TASK_RUNNING);
  
      if (!sigok) {
  	SIG_LOCK(current);
***************
*** 115,137 ****
  void
  afs_cv_timedwait(afs_kcondvar_t * cv, afs_kmutex_t * l, int waittime)
  {
!     int isAFSGlocked = ISAFS_GLOCK();
      long t = waittime * HZ / 1000;
  #ifdef DECLARE_WAITQUEUE
      DECLARE_WAITQUEUE(wait, current);
  #else
      struct wait_queue wait = { current, NULL };
  #endif
  
-     add_wait_queue(cv, &wait);
      set_current_state(TASK_INTERRUPTIBLE);
  
      if (isAFSGlocked)
  	AFS_GUNLOCK();
      MUTEX_EXIT(l);
  
!     t = schedule_timeout(t);
!     remove_wait_queue(cv, &wait);
  
      if (isAFSGlocked)
  	AFS_GLOCK();
--- 122,151 ----
  void
  afs_cv_timedwait(afs_kcondvar_t * cv, afs_kmutex_t * l, int waittime)
  {
!     int seq, isAFSGlocked = ISAFS_GLOCK();
      long t = waittime * HZ / 1000;
  #ifdef DECLARE_WAITQUEUE
      DECLARE_WAITQUEUE(wait, current);
  #else
      struct wait_queue wait = { current, NULL };
  #endif
+     seq = cv->seq;
  
      set_current_state(TASK_INTERRUPTIBLE);
+     add_wait_queue(&cv->waitq, &wait);
  
      if (isAFSGlocked)
  	AFS_GUNLOCK();
      MUTEX_EXIT(l);
  
!     while(seq == cv->seq) {
! 	t = schedule_timeout(t);
! 	if (!t)         /* timeout */
! 	    break;
!     }
!     
!     remove_wait_queue(&cv->waitq, &wait);
!     set_current_state(TASK_RUNNING);
  
      if (isAFSGlocked)
  	AFS_GLOCK();
Index: openafs/src/rx/LINUX/rx_kmutex.h
diff -c openafs/src/rx/LINUX/rx_kmutex.h:1.11.2.3 openafs/src/rx/LINUX/rx_kmutex.h:1.11.2.4
*** openafs/src/rx/LINUX/rx_kmutex.h:1.11.2.3	Mon Apr 25 13:23:19 2005
--- openafs/src/rx/LINUX/rx_kmutex.h	Wed Sep 14 01:12:46 2005
***************
*** 43,53 ****
  #define set_current_state(X) current->state=X
  #endif
  
  #if defined(AFS_LINUX24_ENV)
! typedef wait_queue_head_t afs_kcondvar_t;
  #else
! typedef struct wait_queue *afs_kcondvar_t;
  #endif
  
  static inline int
  MUTEX_ISMINE(afs_kmutex_t * l)
--- 43,56 ----
  #define set_current_state(X) current->state=X
  #endif
  
+ typedef struct afs_kcondvar {
+     int seq;
  #if defined(AFS_LINUX24_ENV)
!     wait_queue_head_t waitq;
  #else
!     struct wait_queue *waitq;
  #endif
+ } afs_kcondvar_t;
  
  static inline int
  MUTEX_ISMINE(afs_kmutex_t * l)
***************
*** 62,68 ****
  #define MUTEX_EXIT		afs_mutex_exit
  
  #if defined(AFS_LINUX24_ENV)
! #define CV_INIT(cv,b,c,d)	init_waitqueue_head((wait_queue_head_t *)(cv))
  #else
  #define CV_INIT(cv,b,c,d)	init_waitqueue((struct wait_queue**)(cv))
  #endif
--- 65,71 ----
  #define MUTEX_EXIT		afs_mutex_exit
  
  #if defined(AFS_LINUX24_ENV)
! #define CV_INIT(cv,b,c,d)      do { (cv)->seq = 0; init_waitqueue_head(&(cv)->waitq); } while (0)
  #else
  #define CV_INIT(cv,b,c,d)	init_waitqueue((struct wait_queue**)(cv))
  #endif
***************
*** 71,82 ****
  #define CV_WAIT(cv, m)		afs_cv_wait(cv, m, 0)
  #define CV_TIMEDWAIT		afs_cv_timedwait
  
  #if defined(AFS_LINUX24_ENV)
! #define CV_SIGNAL(cv)		wake_up((wait_queue_head_t *)cv)
! #define CV_BROADCAST(cv)	wake_up((wait_queue_head_t *)cv)
  #else
! #define CV_SIGNAL(cv)		wake_up((struct wait_queue**)cv)
! #define CV_BROADCAST(cv)	wake_up((struct wait_queue**)cv)
  #endif
  
  #endif /* RX_KMUTEX_H_ */
--- 74,84 ----
  #define CV_WAIT(cv, m)		afs_cv_wait(cv, m, 0)
  #define CV_TIMEDWAIT		afs_cv_timedwait
  
+ #define CV_SIGNAL(cv)          do { ++(cv)->seq; wake_up(&(cv)->waitq); } while (0)
  #if defined(AFS_LINUX24_ENV)
! #define CV_BROADCAST(cv)       do { ++(cv)->seq; wake_up_all(&(cv)->waitq); } while (0)
  #else
! #define CV_BROADCAST(cv)       do { ++(cv)->seq; wake_up(&(cv)->waitq); } while (0)
  #endif
  
  #endif /* RX_KMUTEX_H_ */
