Index: openafs/src/WINNT/afsd/cm.h
diff -c openafs/src/WINNT/afsd/cm.h:1.17.2.17 openafs/src/WINNT/afsd/cm.h:1.17.2.18
*** openafs/src/WINNT/afsd/cm.h:1.17.2.17	Tue Sep 16 07:47:47 2008
--- openafs/src/WINNT/afsd/cm.h	Thu Oct  2 08:14:02 2008
***************
*** 109,123 ****
  
  #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
--- 109,123 ----
  
  #define LOCK_HIERARCHY_IGNORE                    0
  
! #define LOCK_HIERARCHY_SMB_STARTED              20
! #define LOCK_HIERARCHY_SMB_LISTENER             30
! #define LOCK_HIERARCHY_SMB_DIRWATCH             40
! #define LOCK_HIERARCHY_SMB_GLOBAL               50
! #define LOCK_HIERARCHY_SMB_DIRSEARCH            60
! #define LOCK_HIERARCHY_SMB_FID                  70
! #define LOCK_HIERARCHY_SMB_TID                  80
! #define LOCK_HIERARCHY_SMB_UID                  90
  #define LOCK_HIERARCHY_SMB_RAWBUF              100
  #define LOCK_HIERARCHY_SMB_RCT_GLOBAL          110
  #define LOCK_HIERARCHY_SMB_USERNAME            115
  #define LOCK_HIERARCHY_SMB_VC                  120
Index: openafs/src/WINNT/afsd/smb3.c
diff -c openafs/src/WINNT/afsd/smb3.c:1.95.2.79 openafs/src/WINNT/afsd/smb3.c:1.95.2.80
*** openafs/src/WINNT/afsd/smb3.c:1.95.2.79	Sat Sep 13 09:51:50 2008
--- openafs/src/WINNT/afsd/smb3.c	Thu Oct  2 08:14:04 2008
***************
*** 8548,8556 ****
              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;
          }
  
--- 8548,8554 ----
***************
*** 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)
--- 8587,8592 ----
***************
*** 8694,8700 ****
          smb_FreePacket(watch);
  
          smb_ReleaseFID(fidp);
-         lock_ObtainMutex(&smb_Dir_Watch_Lock);
          watch = nextWatch;
      }
      lock_ReleaseMutex(&smb_Dir_Watch_Lock);
--- 8689,8694 ----
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.37 openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.39
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.37	Wed Aug 13 23:18:07 2008
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm	Tue Oct  7 18:09:54 2008
***************
*** 57,63 ****
  
  <h1>OpenAFS for Windows</h1>
  
! <h2>Version 1.5.52</h2>
  
  <p class=MsoNormal>&nbsp; </p>
  
--- 57,63 ----
  
  <h1>OpenAFS for Windows</h1>
  
! <h2>Version 1.5.54</h2>
  
  <p class=MsoNormal>&nbsp; </p>
  
***************
*** 78,84 ****
  <span
  style='font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  </span></span><a
! href="ReleaseNotes/relnotes-frames.htm">OpenAFS for Windows 1.5.52
  Release Notes</a></p>
  
  <p style='margin-left:36.0pt;text-indent:-18.0pt;'>
--- 78,84 ----
  <span
  style='font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  </span></span><a
! href="ReleaseNotes/relnotes-frames.htm">OpenAFS for Windows 1.5.54
  Release Notes</a></p>
  
  <p style='margin-left:36.0pt;text-indent:-18.0pt;'>
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.35 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.37
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.35	Wed Aug 13 23:18:13 2008
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm	Tue Oct  7 18:10:00 2008
***************
*** 18,24 ****
  .shape {behavior:url(#default#VML);}
  </style>
  <![endif]-->
! <title>OpenAFS for Windows 1.5.52 Release Notes</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:Revision>1</o:Revision>
--- 18,24 ----
  .shape {behavior:url(#default#VML);}
  </style>
  <![endif]-->
! <title>OpenAFS for Windows 1.5.54 Release Notes</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:Revision>1</o:Revision>
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes-frames.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes-frames.htm:1.1.4.37 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes-frames.htm:1.1.4.39
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes-frames.htm:1.1.4.37	Wed Aug 13 23:18:13 2008
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes-frames.htm	Tue Oct  7 18:10:00 2008
***************
*** 10,16 ****
  <meta name=Originator content="Microsoft Word 12">
  <link rel=File-List href="relnotes-frames_files/filelist.xml">
  <link rel=Preview href="relnotes-frames_files/preview.wmf">
! <title>OpenAFS for Windows 1.5.52 Release Notes</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:LastAuthor>Jeffrey Eric Altman</o:LastAuthor>
--- 10,16 ----
  <meta name=Originator content="Microsoft Word 12">
  <link rel=File-List href="relnotes-frames_files/filelist.xml">
  <link rel=Preview href="relnotes-frames_files/preview.wmf">
! <title>OpenAFS for Windows 1.5.54 Release Notes</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:LastAuthor>Jeffrey Eric Altman</o:LastAuthor>
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes.htm:1.6.4.43 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes.htm:1.6.4.45
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes.htm:1.6.4.43	Wed Aug 13 23:18:13 2008
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/relnotes.htm	Tue Oct  7 18:10:00 2008
***************
*** 22,28 ****
  .shape {behavior:url(#default#VML);}
  </style>
  <![endif]-->
! <title>OpenAFS for Windows 1.5.52 Release Notes</title>
  <o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
   name="PostalCode"/>
  <o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
--- 22,28 ----
  .shape {behavior:url(#default#VML);}
  </style>
  <![endif]-->
! <title>OpenAFS for Windows 1.5.54 Release Notes</title>
  <o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
   name="PostalCode"/>
  <o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
***************
*** 1209,1215 ****
  
  <div class=Section1>
  
! <p class=MsoTitle>OpenAFS for Windows 1.5.52 (with Unicode Support)<br>
  Release Notes</p>
  
  <p class=MsoBodyText>The Andrew File System (AFS) is a location-independent
--- 1209,1215 ----
  
  <div class=Section1>
  
! <p class=MsoTitle>OpenAFS for Windows 1.5.54 (with Unicode Support)<br>
  Release Notes</p>
  
  <p class=MsoBodyText>The Andrew File System (AFS) is a location-independent
***************
*** 2746,2757 ****
  
  <p class=MsoNormal>OpenAFS for Windows implements an SMB server which is used
  as a gateway to the AFS filesystem.&nbsp; Because of limitations of the SMB
! implementation, Windows stores all files into AFS using OEM code pages such as
  CP437 (United States) or CP850 (Western Europe).&nbsp; These code pages are
! incompatible with the ISO Latin-1 character set typically used as the default
  on UNIX systems in both the <st1:country-region w:st="on">United States</st1:country-region>
  and <st1:place w:st="on">Western Europe</st1:place>.&nbsp; Filenames stored by
! OpenAFS for Windows are therefore unreadable on UNIX systems if they include
  any of the following characters:</p>
  
  <table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0
--- 2746,2757 ----
  
  <p class=MsoNormal>OpenAFS for Windows implements an SMB server which is used
  as a gateway to the AFS filesystem.&nbsp; Because of limitations of the SMB
! implementation in pre-1.5.50 releases, Windows stored all files into AFS using OEM code pages such as
  CP437 (United States) or CP850 (Western Europe).&nbsp; These code pages are
! incompatible with the ISO Latin-1 or Unicode (UTF-8) character sets typically used as the default
  on UNIX systems in both the <st1:country-region w:st="on">United States</st1:country-region>
  and <st1:place w:st="on">Western Europe</st1:place>.&nbsp; Filenames stored by
! OpenAFS for Windows were therefore unreadable on UNIX systems if they include
  any of the following characters:</p>
  
  <table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0
***************
*** 2835,2850 ****
  
  <p class=preformattedtext>&nbsp;</p>
  
! <p class=MsoNormal>The OpenAFS Client provides an optional registry value, <i><a
  href="#_Value___:_StoreAnsiFilenames"><span class=Heading1Char><span
  style='font-size:14.0pt;mso-fareast-font-family:"MS Mincho";text-decoration:
! none;text-underline:none'>StoreAnsiFilenames</span></span></a></i>, that can be
  set to instruct OpenAFS to store filenames using the ANSI Code Page instead of
  the OEM Code Page.&nbsp; The ANSI Code Page is a compatible superset of
  Latin-1.&nbsp; This setting is not the default setting because making this
  change would prevent OpenAFS for Windows from being able to access filenames
  containing the above characters which were created without this setting.</p>
  
  <h2><a name="_Toc206421277"></a><a name="_Toc193871667"></a><a
  name="_Toc193871422"></a><a name="_Toc191662100"></a><a name="_Toc152605068"></a><a
  name="_Toc115416133"></a><a name="_Toc139993117"></a><a name="_Toc126872198"></a><a
--- 2835,2860 ----
  
  <p class=preformattedtext>&nbsp;</p>
  
! <p class=MsoNormal>The pre-1.5.50 OpenAFS Client provided an optional registry value, <i><a
  href="#_Value___:_StoreAnsiFilenames"><span class=Heading1Char><span
  style='font-size:14.0pt;mso-fareast-font-family:"MS Mincho";text-decoration:
! none;text-underline:none'>StoreAnsiFilenames</span></span></a></i>, that could be
  set to instruct OpenAFS to store filenames using the ANSI Code Page instead of
  the OEM Code Page.&nbsp; The ANSI Code Page is a compatible superset of
  Latin-1.&nbsp; This setting is not the default setting because making this
  change would prevent OpenAFS for Windows from being able to access filenames
  containing the above characters which were created without this setting.</p>
  
+ <p class=MsoNormal>
+ All versions of OpenAFS for Windows 1.5.50 and above exchange file names with 
+ Microsoft Windows using the Unicode character set.  All file names are read from 
+ and stored to AFS file servers using the UTF-8 encoding of Unicode.  As a result 
+ the <i><a href="#_Value___:_StoreAnsiFilenames"><span class=Heading1Char><span
+ style='font-size:14.0pt;mso-fareast-font-family:"MS Mincho";text-decoration:
+ none;text-underline:none'>StoreAnsiFilenames</span></span></a></i> option is no 
+ longer supported.
+ </p>
+ 
  <h2><a name="_Toc206421277"></a><a name="_Toc193871667"></a><a
  name="_Toc193871422"></a><a name="_Toc191662100"></a><a name="_Toc152605068"></a><a
  name="_Toc115416133"></a><a name="_Toc139993117"></a><a name="_Toc126872198"></a><a
***************
*** 4583,4588 ****
--- 4593,4600 ----
    class=Heading1Char><span style='font-size:14.0pt;mso-fareast-font-family:
    "MS Mincho";text-decoration:none;text-underline:none'>StoreAnsiFilenames</span></span></a></p>
    <p class=MsoList>Valid values&nbsp;&nbsp;&nbsp; : '0' or '1'</p>
+   <p class=MsoNormal>This option is no longer supported as of 1.5.50 now that all file names 
+   are stored to AFS file servers using the UTF-8 encoding of Unicode.</p>
    </td>
   </tr>
   <tr style='mso-yfti-irow:13;mso-yfti-lastrow:yes'>
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.36 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.38
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.36	Wed Aug 13 23:18:15 2008
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm	Tue Oct  7 18:10:01 2008
***************
*** 11,17 ****
  <meta name=Originator content="Microsoft Word 11">
  <base target=body>
  <link rel=File-List href="toc_files/filelist.xml">
! <title>OpenAFS for Windows 1.5.52 Table of Contents</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:Author>Jeffrey Altman</o:Author>
--- 11,17 ----
  <meta name=Originator content="Microsoft Word 11">
  <base target=body>
  <link rel=File-List href="toc_files/filelist.xml">
! <title>OpenAFS for Windows 1.5.54 Table of Contents</title>
  <!--[if gte mso 9]><xml>
   <o:DocumentProperties>
    <o:Author>Jeffrey Altman</o:Author>
Index: openafs/src/afs/DARWIN/osi_vfsops.c
diff -c openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.2 openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.3
*** openafs/src/afs/DARWIN/osi_vfsops.c:1.17.4.2	Fri Aug 22 15:26:48 2008
--- openafs/src/afs/DARWIN/osi_vfsops.c	Tue Oct  7 17:30:33 2008
***************
*** 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 */
--- 5,11 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v 1.17.4.3 2008/10/07 21:30:33 shadow Exp $");
  
  #include <afs/sysincludes.h>	/* Standard vendor system headers */
  #include <afsincludes.h>	/* Afs-based standard headers */
***************
*** 118,124 ****
      afs_globalVFS = mp;
  #ifdef AFS_DARWIN80_ENV
      vfs_ioattr(mp, &ioattr);
!     ioattr.io_devblocksize = 8192;
      vfs_setioattr(mp, &ioattr);
      /* f_iosize is handled in VFS_GETATTR */
  #else
--- 118,124 ----
      afs_globalVFS = mp;
  #ifdef AFS_DARWIN80_ENV
      vfs_ioattr(mp, &ioattr);
!     ioattr.io_devblocksize = (16 * 32768);
      vfs_setioattr(mp, &ioattr);
      /* f_iosize is handled in VFS_GETATTR */
  #else
***************
*** 366,393 ****
      AFS_GLOCK();
      AFS_STATCNT(afs_statfs);
  
- #if 0
-     abp->f_type = MOUNT_AFS;
- #endif
  #ifdef AFS_DARWIN80_ENV
!     abp->f_bsize = abp->f_iosize = vfs_devblocksize(mp);
  #else
      abp->f_bsize = mp->vfs_bsize;
      abp->f_iosize = mp->vfs_bsize;
  #endif
  
      /* Fake a high number below to satisfy programs that use the statfs call
       * to make sure that there's enough space in the device partition before
       * storing something there.
       */
      abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
! 	abp->f_ffree = 
! #ifdef AFS_DARWIN80_ENV
!         0xffffffffffffffff
! #else
! 	2000000
! #endif
! 	;
  
      if (abp != sysstat) {
          abp->f_fsid.val[0] = sysstat->f_fsid.val[0];
--- 366,388 ----
      AFS_GLOCK();
      AFS_STATCNT(afs_statfs);
  
  #ifdef AFS_DARWIN80_ENV
!     abp->f_iosize = (256 * 1024);
!     abp->f_bsize = vfs_devblocksize(mp);
  #else
      abp->f_bsize = mp->vfs_bsize;
      abp->f_iosize = mp->vfs_bsize;
  #endif
+ #if 0
+     abp->f_type = MOUNT_AFS;
+ #endif
  
      /* Fake a high number below to satisfy programs that use the statfs call
       * to make sure that there's enough space in the device partition before
       * storing something there.
       */
      abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
!       abp->f_ffree = 0x7fffffff;
  
      if (abp != sysstat) {
          abp->f_fsid.val[0] = sysstat->f_fsid.val[0];
Index: openafs/src/afs/LINUX/osi_vnodeops.c
diff -c openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.31 openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.33
*** openafs/src/afs/LINUX/osi_vnodeops.c:1.126.2.31	Thu Sep 25 07:42:43 2008
--- openafs/src/afs/LINUX/osi_vnodeops.c	Tue Oct  7 15:00:42 2008
***************
*** 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"
--- 22,28 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.126.2.33 2008/10/07 19:00:42 shadow Exp $");
  
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
***************
*** 831,837 ****
      credp = crref();
      code = afs_getattr(vcp, &vattr, credp);
      if (!code)
!         vattr2inode(AFSTOV(vcp), &vattr);
  
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
--- 831,837 ----
      credp = crref();
      code = afs_getattr(vcp, &vattr, credp);
      if (!code)
!         afs_fill_inode(AFSTOV(vcp), &vattr);
  
      AFS_GUNLOCK();
  #ifdef AFS_LINUX24_ENV
***************
*** 876,886 ****
--- 876,888 ----
      cred_t *credp = NULL;
      struct vcache *vcp, *pvcp, *tvc = NULL;
      int valid;
+     struct afs_fakestat_state fakestate;
  
  #ifdef AFS_LINUX24_ENV
      maybe_lock_kernel();
  #endif
      AFS_GLOCK();
+     afs_InitFakeStat(&fakestate);
  
      if (dp->d_inode) {
  
***************
*** 892,899 ****
  
  	if (vcp->mvstat == 1) {         /* mount point */
  	    if (vcp->mvid && (vcp->states & CMValid)) {
! 		/* a mount point, not yet replaced by its directory */
! 		goto bad_dentry;
  	    }
  	} else
  	    if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
--- 894,921 ----
  
  	if (vcp->mvstat == 1) {         /* mount point */
  	    if (vcp->mvid && (vcp->states & CMValid)) {
! 		int tryEvalOnly = 0;
! 		int code = 0;
! 		struct vrequest treq;
! 
! 		credp = crref();
! 		code = afs_InitReq(&treq, credp);
! 		if (
! #ifdef AFS_DARWIN_ENV
! 		    (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
! 		    (strcmp(dp->d_name.name, "Contents") == 0) ||
! #endif
! 		    (strcmp(dp->d_name.name, ".directory") == 0)) {
! 		    tryEvalOnly = 1;
! 		}
! 		if (tryEvalOnly)
! 		    code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
! 		else
! 		    code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
! 		if ((tryEvalOnly && vcp->mvstat == 1) || code) {
! 		    /* a mount point, not yet replaced by its directory */
! 		    goto bad_dentry;
! 		}
  	    }
  	} else
  	    if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
***************
*** 957,962 ****
--- 979,985 ----
      /* Clean up */
      if (tvc)
  	afs_PutVCache(tvc);
+     afs_PutFakeStat(&fakestate);
      AFS_GUNLOCK();
      if (credp)
  	crfree(credp);
***************
*** 971,977 ****
      return valid;
  
    bad_dentry:
!     valid = 0;
      goto done;
  }
  
--- 994,1003 ----
      return valid;
  
    bad_dentry:
!     if (have_submounts(dp))
! 	valid = 1;
!     else 
! 	valid = 0;
      goto done;
  }
  
Index: openafs/src/config/NTMakefile.amd64_w2k
diff -c openafs/src/config/NTMakefile.amd64_w2k:1.24.2.47 openafs/src/config/NTMakefile.amd64_w2k:1.24.2.49
*** openafs/src/config/NTMakefile.amd64_w2k:1.24.2.47	Sat Aug 16 13:15:51 2008
--- openafs/src/config/NTMakefile.amd64_w2k	Tue Oct  7 17:56:55 2008
***************
*** 84,90 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5200
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 84,90 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5400
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/config/NTMakefile.i386_nt40
diff -c openafs/src/config/NTMakefile.i386_nt40:1.84.2.45 openafs/src/config/NTMakefile.i386_nt40:1.84.2.47
*** openafs/src/config/NTMakefile.i386_nt40:1.84.2.45	Sat Aug 16 13:15:52 2008
--- openafs/src/config/NTMakefile.i386_nt40	Tue Oct  7 17:56:55 2008
***************
*** 84,90 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5200
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 84,90 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5400
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/config/NTMakefile.i386_w2k
diff -c openafs/src/config/NTMakefile.i386_w2k:1.23.2.49 openafs/src/config/NTMakefile.i386_w2k:1.23.2.51
*** openafs/src/config/NTMakefile.i386_w2k:1.23.2.49	Sat Aug 16 13:15:52 2008
--- openafs/src/config/NTMakefile.i386_w2k	Tue Oct  7 17:56:55 2008
***************
*** 88,94 ****
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5200
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
--- 88,94 ----
  #define used in WinNT/2000 installation and program version display
  AFSPRODUCT_VER_MAJOR=1
  AFSPRODUCT_VER_MINOR=5
! AFSPRODUCT_VER_PATCH=5400
  AFSPRODUCT_VER_BUILD=0
  
  AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
Index: openafs/src/libafsrpc/afsrpc.def
diff -c openafs/src/libafsrpc/afsrpc.def:1.11.4.7 openafs/src/libafsrpc/afsrpc.def:1.11.4.8
*** openafs/src/libafsrpc/afsrpc.def:1.11.4.7	Tue Feb  5 12:26:47 2008
--- openafs/src/libafsrpc/afsrpc.def	Tue Oct  7 18:28:49 2008
***************
*** 68,81 ****
  	xdrrx_create				@72
  	hton_syserr_conv			@73
  	rxkad_global_stats			@74 DATA
! 	afs_com_err					@75
! 	afs_error_message				@76
  	rx_socket				@77 DATA
  ;	AssertionFailed				@79
  	afs_winsockInit				@80
  	rxevent_debugFile			@81 DATA
  	rx_debugFile				@82 DATA
! 	rx_connDeadTime				@83 DATA
  	rx_maxReceiveSize			@84 DATA
  	rx_UdpBufSize				@85 DATA
  	rx_extraQuota				@86 DATA
--- 68,81 ----
  	xdrrx_create				@72
  	hton_syserr_conv			@73
  	rxkad_global_stats			@74 DATA
! 	afs_com_err				@75
! 	afs_error_message			@76
  	rx_socket				@77 DATA
  ;	AssertionFailed				@79
  	afs_winsockInit				@80
  	rxevent_debugFile			@81 DATA
  	rx_debugFile				@82 DATA
!         rx_connDeadTime                         @83 DATA
  	rx_maxReceiveSize			@84 DATA
  	rx_UdpBufSize				@85 DATA
  	rx_extraQuota				@86 DATA
***************
*** 226,228 ****
--- 226,245 ----
          StartRXAFS_GetTime                      @231
          EndRXAFS_GetCapabilities                @232
          StartRXAFS_GetCapabilities              @233
+         xdr_afs_uint32                          @234
+         xdr_afs_int32                           @235
+         xdr_afs_uint64                          @236
+         xdr_afs_int64                           @237
+         clock_now                               @238
+         clock_UpdateTime                        @239
+         clock_haveCurrentTime                   @240
+ 
+ ; for performance testing
+         rx_TSFPQGlobSize                        @2001 DATA
+         rx_TSFPQLocalMax                        @2002 DATA
+         rx_TSFPQMaxProcs                        @2003 DATA
+         rx_ReadvProc                            @2004
+         rx_WritevProc                           @2005
+         rx_WritevAlloc                          @2006
+         rxi_MorePackets                         @2007
+ 
Index: openafs/src/rx/rx.c
diff -c openafs/src/rx/rx.c:1.97.2.37 openafs/src/rx/rx.c:1.97.2.40
*** openafs/src/rx/rx.c:1.97.2.37	Thu Sep 25 16:17:54 2008
--- openafs/src/rx/rx.c	Sat Oct  4 01:05:20 2008
***************
*** 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"
--- 17,23 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx.c,v 1.97.2.40 2008/10/04 05:05:20 jaltman Exp $");
  
  #ifdef KERNEL
  #include "afs/sysincludes.h"
***************
*** 6275,6295 ****
  
  /* Don't call this debugging routine directly; use dpf */
  void
! rxi_DebugPrint(char *format, int a1, int a2, int a3, int a4, int a5, int a6,
! 	       int a7, int a8, int a9, int a10, int a11, int a12, int a13,
! 	       int a14, int a15)
  {
  #ifdef AFS_NT40_ENV
      char msg[512];
      char tformat[256];
      size_t len;
  
      len = _snprintf(tformat, sizeof(tformat), "tid[%d] %s", GetCurrentThreadId(), format);
  
      if (len > 0) {
! 	len = _snprintf(msg, sizeof(msg)-2, 
! 			tformat, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 
! 			a11, a12, a13, a14, a15);
  	if (len > 0) {
  	    if (msg[len-1] != '\n') {
  		msg[len] = '\n';
--- 6275,6294 ----
  
  /* Don't call this debugging routine directly; use dpf */
  void
! rxi_DebugPrint(char *format, ...)
  {
+     va_list ap;
  #ifdef AFS_NT40_ENV
      char msg[512];
      char tformat[256];
      size_t len;
  
+     va_start(ap, format);
+ 
      len = _snprintf(tformat, sizeof(tformat), "tid[%d] %s", GetCurrentThreadId(), format);
  
      if (len > 0) {
! 	len = _vsnprintf(msg, sizeof(msg)-2, tformat, ap);
  	if (len > 0) {
  	    if (msg[len-1] != '\n') {
  		msg[len] = '\n';
***************
*** 6298,6311 ****
  	    OutputDebugString(msg);
  	}
      }
  #else
      struct clock now;
      clock_GetTime(&now);
      fprintf(rx_Log, " %u.%.3u:", (unsigned int)now.sec,
  	    (unsigned int)now.usec / 1000);
!     fprintf(rx_Log, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
! 	    a13, a14, a15);
      putc('\n', rx_Log);
  #endif
  }
  
--- 6297,6314 ----
  	    OutputDebugString(msg);
  	}
      }
+     va_end(ap);
  #else
      struct clock now;
+     
+     va_start(ap, format);
+ 
      clock_GetTime(&now);
      fprintf(rx_Log, " %u.%.3u:", (unsigned int)now.sec,
  	    (unsigned int)now.usec / 1000);
!     vfprintf(rx_Log, format, ap);
      putc('\n', rx_Log);
+     va_end(ap);
  #endif
  }
  
Index: openafs/src/rx/rx_globals.h
diff -c openafs/src/rx/rx_globals.h:1.21.2.20 openafs/src/rx/rx_globals.h:1.21.2.21
*** openafs/src/rx/rx_globals.h:1.21.2.20	Thu Sep 25 16:19:57 2008
--- openafs/src/rx/rx_globals.h	Fri Oct  3 10:57:19 2008
***************
*** 541,551 ****
  #define rx_Log rx_debugFile
  #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
  #else
  #ifdef DPF_FSLOG
  #define dpf(args) FSLog args
--- 541,547 ----
  #define rx_Log rx_debugFile
  #ifdef AFS_NT40_ENV
  EXT int rxdebug_active;
! #define dpf(args) do { if (rxdebug_active) rxi_DebugPrint args; } while (0)
  #else
  #ifdef DPF_FSLOG
  #define dpf(args) FSLog args
Index: openafs/src/rx/rx_kcommon.c
diff -c openafs/src/rx/rx_kcommon.c:1.56.2.9 openafs/src/rx/rx_kcommon.c:1.56.2.10
*** openafs/src/rx/rx_kcommon.c:1.56.2.9	Fri Aug 22 00:31:48 2008
--- openafs/src/rx/rx_kcommon.c	Fri Oct  3 10:55:12 2008
***************
*** 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"
  
--- 15,21 ----
  #include "afs/param.h"
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.56.2.10 2008/10/03 14:55:12 jaltman Exp $");
  
  #include "rx/rx_kcommon.h"
  
***************
*** 126,138 ****
  
  #if !defined(AFS_LINUX26_ENV)
  void
! osi_Panic(msg, a1, a2, a3)
!      char *msg;
  {
      if (!msg)
  	msg = "Unknown AFS panic";
  
!     printf(msg, a1, a2, a3);
  #ifdef AFS_LINUX20_ENV
      * ((char *) 0) = 0; 
  #else
--- 126,139 ----
  
  #if !defined(AFS_LINUX26_ENV)
  void
! osi_Panic(char *msg, ...)
  {
+     va_list ap;
      if (!msg)
  	msg = "Unknown AFS panic";
  
!     va_start(ap, msg);
!     vprintf(msg, ap);
  #ifdef AFS_LINUX20_ENV
      * ((char *) 0) = 0; 
  #else
Index: openafs/src/rx/rx_kcommon.h
diff -c openafs/src/rx/rx_kcommon.h:1.32.4.3 openafs/src/rx/rx_kcommon.h:1.32.4.4
*** openafs/src/rx/rx_kcommon.h:1.32.4.3	Fri Oct  5 18:18:36 2007
--- openafs/src/rx/rx_kcommon.h	Fri Oct  3 10:55:12 2008
***************
*** 139,144 ****
--- 139,145 ----
  #include "afs/longc_procs.h"
  #include "afs/afs_stats.h"
  #include "h/errno.h"
+ #include "stdarg.h"
  #ifdef KERNEL
  #include "afs/sysincludes.h"
  #include "afsincludes.h"
Index: openafs/src/rx/rx_kernel.h
diff -c openafs/src/rx/rx_kernel.h:1.16 openafs/src/rx/rx_kernel.h:1.16.2.1
*** openafs/src/rx/rx_kernel.h:1.16	Wed Feb 15 11:32:42 2006
--- openafs/src/rx/rx_kernel.h	Fri Oct  3 10:55:12 2008
***************
*** 37,42 ****
--- 37,43 ----
  #define osi_Assert(e) (void)((e) || (osi_AssertFailK(#e, __FILE__, __LINE__), 0))
  
  #define	osi_Msg printf)(
+ #define osi_VMsg vprintf)(
  
  #define	osi_YieldIfPossible()
  #define	osi_WakeupAndYieldIfPossible(x)	    rx_Wakeup(x)
Index: openafs/src/rx/rx_prototypes.h
diff -c openafs/src/rx/rx_prototypes.h:1.29.4.12 openafs/src/rx/rx_prototypes.h:1.29.4.13
*** openafs/src/rx/rx_prototypes.h:1.29.4.12	Thu Sep 25 13:15:56 2008
--- openafs/src/rx/rx_prototypes.h	Fri Oct  3 10:55:12 2008
***************
*** 264,282 ****
  					     rx_securityConfigVariables type,
  					     void *value);
  
! 
! /* old style till varargs */
! #if 0
! void
! rxi_DebugPrint(char *format, int a1, int a2, int a3, int a4, int a5, int a6,
!                int a7, int a8, int a9, int a10, int a11, int a12, int a13,
! 	       int a14, int a15);
! void
! rxi_DebugInit(void);
! #else
! void rxi_DebugInit();
! void rxi_DebugPrint();
! #endif
  
  /* rx_clock.c */
  #if !defined(clock_Init)
--- 264,271 ----
  					     rx_securityConfigVariables type,
  					     void *value);
  
! void rxi_DebugInit(void);
! void rxi_DebugPrint(char *format, ...);
  
  /* rx_clock.c */
  #if !defined(clock_Init)
***************
*** 373,379 ****
  #define osi_Assert(expr) \
      do { if (!(expr)) { osi_AssertFailK(#expr, __FILE__, __LINE__); BUG(); } } while (0)
  #else
! extern void osi_Panic();       /* leave without args till stdarg rewrite */
  #endif
  extern int osi_utoa(char *buf, size_t len, unsigned long val);
  extern void rxi_InitPeerParams(register struct rx_peer *pp);
--- 362,368 ----
  #define osi_Assert(expr) \
      do { if (!(expr)) { osi_AssertFailK(#expr, __FILE__, __LINE__); BUG(); } } while (0)
  #else
! extern void osi_Panic(char *fmt, ...);
  #endif
  extern int osi_utoa(char *buf, size_t len, unsigned long val);
  extern void rxi_InitPeerParams(register struct rx_peer *pp);
Index: openafs/src/rx/rx_rdwr.c
diff -c openafs/src/rx/rx_rdwr.c:1.29.2.8 openafs/src/rx/rx_rdwr.c:1.29.2.9
*** openafs/src/rx/rx_rdwr.c:1.29.2.8	Thu Sep 25 16:17:54 2008
--- openafs/src/rx/rx_rdwr.c	Thu Oct  2 07:53:18 2008
***************
*** 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
--- 15,21 ----
  #endif
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_rdwr.c,v 1.29.2.9 2008/10/02 11:53:18 jaltman Exp $");
  
  #ifdef KERNEL
  #ifndef UKERNEL
***************
*** 1121,1126 ****
--- 1121,1127 ----
  	    rxi_PrepareSendPacket(call, cp, 0);
  	    cp->flags |= RX_PKTFLAG_TQ;
  	    queue_Append(&tmpq, cp);
+             cp = call->currentPacket = (struct rx_packet *)0;
  
  	    /* The head of the iovq is now the current packet */
  	    if (nbytes) {
***************
*** 1152,1157 ****
--- 1153,1159 ----
  		if (cp) {
  		    cp->flags &= ~RX_PKTFLAG_CP;
  		    queue_Prepend(&tmpq, cp);
+                     cp = call->currentPacket = (struct rx_packet *)0;
  		}
  		rxi_FreePackets(0, &tmpq);
  		return 0;
***************
*** 1197,1202 ****
--- 1199,1205 ----
  	if (cp) {
  	    cp->flags &= ~RX_PKTFLAG_CP;
  	    rxi_FreePacket(cp);
+             cp = call->currentPacket = (struct rx_packet *)0;
  	}
  	return 0;
      }
Index: openafs/src/rx/rx_user.c
diff -c openafs/src/rx/rx_user.c:1.24.4.6 openafs/src/rx/rx_user.c:1.24.4.7
*** openafs/src/rx/rx_user.c:1.24.4.6	Thu Sep 25 08:07:49 2008
--- openafs/src/rx/rx_user.c	Fri Oct  3 10:55:12 2008
***************
*** 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>
--- 13,19 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/rx/rx_user.c,v 1.24.4.7 2008/10/03 14:55:12 jaltman Exp $");
  
  # include <sys/types.h>
  # include <errno.h>
***************
*** 221,231 ****
  }
  
  void
! osi_Panic(msg, a1, a2, a3) 
!      char *msg; 
  {
      (osi_Msg "Fatal Rx error: ");
!     (osi_Msg msg, a1, a2, a3);
      fflush(stderr);
      fflush(stdout);
      afs_abort();
--- 221,233 ----
  }
  
  void
! osi_Panic(char *msg, ...)
  {
+     va_list ap;
+     va_start(ap, msg);
      (osi_Msg "Fatal Rx error: ");
!     (osi_VMsg msg, ap);
!     va_end(ap);
      fflush(stderr);
      fflush(stdout);
      afs_abort();
Index: openafs/src/rx/rx_user.h
diff -c openafs/src/rx/rx_user.h:1.9 openafs/src/rx/rx_user.h:1.9.4.1
*** openafs/src/rx/rx_user.h:1.9	Sat Nov  5 01:48:18 2005
--- openafs/src/rx/rx_user.h	Fri Oct  3 10:55:12 2008
***************
*** 66,70 ****
--- 66,71 ----
  #define osi_Assert(e) (void)((e) || (osi_AssertFailU(#e, __FILE__, __LINE__), 0))
  
  #define	osi_Msg			    fprintf)(stderr,
+ #define osi_VMsg		    vfprintf)(stderr,
  
  #endif /* RX_USER_INCLUDE */
Index: openafs/src/sys/libafsdep
diff -c /dev/null openafs/src/sys/libafsdep:1.1.2.2
*** /dev/null	Tue Oct  7 22:42:44 2008
--- openafs/src/sys/libafsdep	Fri Sep 26 06:17:17 2008
***************
*** 0 ****
--- 1 ----
+ Krmtsys.*
Index: openafs/src/tbutc/NTMakefile
diff -c openafs/src/tbutc/NTMakefile:1.16.4.4 openafs/src/tbutc/NTMakefile:1.16.4.5
*** openafs/src/tbutc/NTMakefile:1.16.4.4	Wed Jul  2 08:49:26 2008
--- openafs/src/tbutc/NTMakefile	Tue Oct  7 18:26:44 2008
***************
*** 80,86 ****
  	     $(DESTDIR)\lib\afs\afsauth.lib \
  	     $(DESTDIR)\lib\afsrpc.lib \
               $(DESTDIR)\lib\afsrxkad.lib \
- 	     $(DESTDIR)\lib\afsrx.lib \
               $(DESTDIR)\lib\afslwp.lib \
               $(DESTDIR)\lib\afs\afsutil.lib \
               $(DESTDIR)\lib\afs\afsusd.lib \
--- 80,85 ----
Index: openafs/src/ubik/phys.c
diff -c openafs/src/ubik/phys.c:1.9.2.5 openafs/src/ubik/phys.c:1.9.2.6
*** openafs/src/ubik/phys.c:1.9.2.5	Sat Jul 19 02:15:02 2008
--- openafs/src/ubik/phys.c	Tue Oct  7 13:44:13 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/ubik/phys.c,v 1.9.2.5 2008/07/19 06:15:02 rra Exp $");
  
  #include <sys/types.h>
  #ifdef AFS_NT40_ENV
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/ubik/phys.c,v 1.9.2.6 2008/10/07 17:44:13 shadow Exp $");
  
  #include <sys/types.h>
  #ifdef AFS_NT40_ENV
***************
*** 115,121 ****
      }
      if (bestfd) {		/* found a usable slot */
  	tfd = bestfd;
! 	if (tfd->fd >= 0)
  	    close(tfd->fd);
  	tfd->fd = fd;
  	tfd->refCount = 1;	/* us */
--- 115,121 ----
      }
      if (bestfd) {		/* found a usable slot */
  	tfd = bestfd;
! 	if (tfd->fd >= 0) 
  	    close(tfd->fd);
  	tfd->fd = fd;
  	tfd->refCount = 1;	/* us */
***************
*** 137,146 ****
  	return EBADF;
      tfd = fdcache;
      for (i = 0; i < MAXFDCACHE; i++, tfd++) {
! 	if (tfd->fd == afd && tfd->fileID != -10000) {
! 	    tfd->refCount--;
! 	    return 0;
! 	}
      }
      return close(afd);
  }
--- 137,158 ----
  	return EBADF;
      tfd = fdcache;
      for (i = 0; i < MAXFDCACHE; i++, tfd++) {
! 	if (tfd->fd == afd) 
! 	    if (tfd->fileID != -10000) {
! 		tfd->refCount--;
! 		return 0;
! 	    } else {
! 		if (tfd->refCount > 0) {
! 		    tfd->refCount--;
! 		    if (tfd->refCount == 0) {
! 			close(tfd->fd);
! 			tfd->fd = -1;
! 		    }
! 		    return 0;
! 		}
! 		tfd->fd = -1;
! 		break;
! 	    }
      }
      return close(afd);
  }
***************
*** 300,307 ****
      for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
  	if (afid == tfd->fileID) {
  	    tfd->fileID = -10000;
! 	    if (tfd->fd >= 0 && tfd->refCount == 0)
  		close(tfd->fd);
  	    return;
  	}
      }
--- 312,321 ----
      for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
  	if (afid == tfd->fileID) {
  	    tfd->fileID = -10000;
! 	    if (tfd->fd >= 0 && tfd->refCount == 0) {
  		close(tfd->fd);
+ 		tfd->fd = -1;
+ 	    }
  	    return;
  	}
      }
Index: openafs/src/venus/kdump.c
diff -c openafs/src/venus/kdump.c:1.38.4.3 openafs/src/venus/kdump.c:1.38.4.4
*** openafs/src/venus/kdump.c:1.38.4.3	Wed Oct 31 00:09:41 2007
--- openafs/src/venus/kdump.c	Fri Oct  3 16:39:56 2008
***************
*** 11,17 ****
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/kdump.c,v 1.38.4.3 2007/10/31 04:09:41 shadow Exp $");
  
  #include <stdio.h>
  #include <errno.h>
--- 11,17 ----
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/venus/kdump.c,v 1.38.4.4 2008/10/03 20:39:56 shadow Exp $");
  
  #include <stdio.h>
  #include <errno.h>
***************
*** 3408,3414 ****
      off_t symoff;
      char sysname[100];
      afs_int32 count, i;
!     struct rx_stats rx_stats;
  
      printf("\n\nPrinting some general RX stats...\n\n");
      findsym("rx_stats", &symoff);
--- 3408,3414 ----
      off_t symoff;
      char sysname[100];
      afs_int32 count, i;
!     struct rx_statistics rx_stats;
  
      printf("\n\nPrinting some general RX stats...\n\n");
      findsym("rx_stats", &symoff);
***************
*** 3473,3479 ****
      char sysname[100], c;
      afs_int32 count, i, ar[100];
      short sm;
!     struct rx_stats rx_stats;
  
      printf("\n\nPrinting some RX globals...\n\n");
      findsym("rx_extraQuota", &symoff);
--- 3473,3479 ----
      char sysname[100], c;
      afs_int32 count, i, ar[100];
      short sm;
!     struct rx_statistics rx_stats;
  
      printf("\n\nPrinting some RX globals...\n\n");
      findsym("rx_extraQuota", &symoff);
Index: openafs/src/vlserver/vldb_check.c
diff -c openafs/src/vlserver/vldb_check.c:1.11.14.4 openafs/src/vlserver/vldb_check.c:1.11.14.5
*** openafs/src/vlserver/vldb_check.c:1.11.14.4	Tue Dec 11 15:43:50 2007
--- openafs/src/vlserver/vldb_check.c	Tue Oct  7 11:38:29 2008
***************
*** 21,31 ****
  #define MHC 0x100		/* on multihomed chain */
  #define FRC 0x200		/* on free chain */
  
  #include <afsconfig.h>
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vlserver/vldb_check.c,v 1.11.14.4 2007/12/11 20:43:50 shadow Exp $");
  
  #include <sys/types.h>
  #include <sys/stat.h>
--- 21,49 ----
  #define MHC 0x100		/* on multihomed chain */
  #define FRC 0x200		/* on free chain */
  
+ #define REFRW 0x1000            /* linked from something (RW) */
+ #define REFRO 0x2000            /* linked from something (RO) */
+ #define REFBK 0x4000            /* linked from something (BK) */
+ #define REFN  0x8000            /* linked from something (name) */
+ 
+ #define MULTRW 0x10000         /* multiply-chained (RW) */
+ #define MULTRO 0x20000         /* multiply-chained (RO) */
+ #define MULTBK 0x40000         /* multiply-chained (BK) */
+ #define MULTN  0x80000         /* multiply-chained (name) */
+ 
+ #define MISRWH 0x100000          /* mischained (RW) */
+ #define MISROH 0x200000          /* mischained (RO) */
+ #define MISBKH 0x400000          /* mischained (BK) */
+ #define MISNH  0x800000          /* mischained (name) */
+ 
+ #define vldbread(x,y,z) vldbio(x,y,z,0)
+ #define vldbwrite(x,y,z) vldbio(x,y,z,1)
+ 
  #include <afsconfig.h>
  #include <afs/param.h>
  
  RCSID
!     ("$Header: /cvs/openafs/src/vlserver/vldb_check.c,v 1.11.14.5 2008/10/07 15:38:29 shadow Exp $");
  
  #include <sys/types.h>
  #include <sys/stat.h>
***************
*** 48,62 ****
--- 66,93 ----
  #include <afs/afsutil.h>
  #include <afs/cmd.h>
  
+ #define ADDR(x) (x/sizeof(struct nvlentry))
+ 
  int fd;
  int listentries, listservers, listheader, listuheader, verbose;
  
+ int fix = 0;
+ int fixed = 0;
+ int passes = 0;
+ 
  struct er {
      long addr;
      int type;
  } *record;
  int serveraddrs[MAXSERVERID + 2];
  
+ #if 0
+ int
+ writeUbikHeader()
+ {
+     /* Bump the version number?? We could cheat and push a new db... */
+ }
+ #endif
  
  #define HDRSIZE 64
  int
***************
*** 103,112 ****
  }
  
  int
! vldbread(position, buffer, size)
!      int position;
!      char *buffer;
!      int size;
  {
      int offset, r, p;
  
--- 134,140 ----
  }
  
  int
! vldbio(int position, char *buffer, int size, int rdwr)
  {
      int offset, r, p;
  
***************
*** 118,135 ****
  	return (-1);
      }
  
!     /* now read the info */
!     r = read(fd, buffer, size);
      if (r != size) {
! 	printf("error: read of %d bytes failed: %d %d\n", size, r, errno);
  	return (-1);
      }
      return (0);
  }
  
  char *
! vtype(type)
!      int type;
  {
      static char Type[3];
  
--- 146,166 ----
  	return (-1);
      }
  
!     if (rdwr == 1) 
! 	r = write(fd, buffer, size);
!     else 
! 	r = read(fd, buffer, size);
! 
      if (r != size) {
! 	printf("error: %s of %d bytes failed: %d %d\n", rdwr==1?"write":"read",
! 	       size, r, errno);
  	return (-1);
      }
      return (0);
  }
  
  char *
! vtype(int type)
  {
      static char Type[3];
  
***************
*** 145,152 ****
  }
  
  afs_int32
! NameHash(volname)
!      char *volname;
  {
      unsigned int hash;
      char *vchar;
--- 176,182 ----
  }
  
  afs_int32
! NameHash(char *volname)
  {
      unsigned int hash;
      char *vchar;
***************
*** 158,173 ****
  }
  
  afs_int32
! IdHash(volid)
!      afs_int32 volid;
  {
      return ((abs(volid)) % HASHSIZE);
  }
  
  #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
  int
! InvalidVolname(volname)
!      char *volname;
  {
      char *map;
      size_t slen;
--- 188,201 ----
  }
  
  afs_int32
! IdHash(afs_int32 volid)
  {
      return ((abs(volid)) % HASHSIZE);
  }
  
  #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
  int
! InvalidVolname(char *volname)
  {
      char *map;
      size_t slen;
***************
*** 179,186 ****
      return (slen != strspn(volname, map));
  }
  
! readheader(headerp)
!      struct vlheader *headerp;
  {
      int i, j;
  
--- 207,214 ----
      return (slen != strspn(volname, map));
  }
  
! void
! readheader(struct vlheader *headerp)
  {
      int i, j;
  
***************
*** 245,253 ****
      return;
  }
  
! readMH(addr, mhblockP)
!      afs_int32 addr;
!      struct extentaddr *mhblockP;
  {
      int i, j;
      struct extentaddr *e;
--- 273,313 ----
      return;
  }
  
! void
! writeheader(struct vlheader *headerp)
! {
!     int i, j;
! 
!     headerp->vital_header.vldbversion =
! 	htonl(headerp->vital_header.vldbversion);
!     headerp->vital_header.headersize =
! 	htonl(headerp->vital_header.headersize);
!     headerp->vital_header.freePtr = htonl(headerp->vital_header.freePtr);
!     headerp->vital_header.eofPtr = htonl(headerp->vital_header.eofPtr);
!     headerp->vital_header.allocs = htonl(headerp->vital_header.allocs);
!     headerp->vital_header.frees = htonl(headerp->vital_header.frees);
!     headerp->vital_header.MaxVolumeId =
! 	htonl(headerp->vital_header.MaxVolumeId);
!     headerp->vital_header.totalEntries[0] =
! 	htonl(headerp->vital_header.totalEntries[0]);
!     for (i = 0; i < MAXTYPES; i++)
! 	headerp->vital_header.totalEntries[i] =
! 	    htonl(headerp->vital_header.totalEntries[1]);
! 
!     headerp->SIT = htonl(headerp->SIT);
!     for (i = 0; i < MAXSERVERID; i++)
! 	headerp->IpMappedAddr[i] = htonl(headerp->IpMappedAddr[i]);
!     for (i = 0; i < HASHSIZE; i++)
! 	headerp->VolnameHash[i] = htonl(headerp->VolnameHash[i]);
!     for (i = 0; i < MAXTYPES; i++)
! 	for (j = 0; j < HASHSIZE; j++)
! 	    headerp->VolidHash[i][j] = htonl(headerp->VolidHash[i][j]);
! 
!     vldbwrite(0, headerp, sizeof(*headerp));
! }
! 
! void
! readMH(afs_int32 addr, struct extentaddr *mhblockP)
  {
      int i, j;
      struct extentaddr *e;
***************
*** 270,279 ****
      return;
  }
  
! readentry(addr, vlentryp, type)
!      afs_int32 addr;
!      struct nvlentry *vlentryp;
!      afs_int32 *type;
  {
      int i;
  
--- 330,337 ----
      return;
  }
  
! void
! readentry(afs_int32 addr, struct nvlentry *vlentryp, afs_int32 *type)
  {
      int i;
  
***************
*** 352,360 ****
  }
  
  void
! readSIT(base, addr)
!      int base;
!      int addr;
  {
      int i, j, a;
      char sitbuf[VL_ADDREXTBLK_SIZE];
--- 410,441 ----
  }
  
  void
! writeentry(afs_int32 addr, struct nvlentry *vlentryp)
! {
!     int i;
! 
!     if (verbose)
! 	printf("Writing back entry at addr %u\n", addr);
!     fixed++;
!     for (i = 0; i < MAXTYPES; i++)
! 	vlentryp->volumeId[i] = htonl(vlentryp->volumeId[i]);
!     vlentryp->flags = htonl(vlentryp->flags);
!     vlentryp->LockAfsId = htonl(vlentryp->LockAfsId);
!     vlentryp->LockTimestamp = htonl(vlentryp->LockTimestamp);
!     vlentryp->cloneId = htonl(vlentryp->cloneId);
!     for (i = 0; i < MAXTYPES; i++)
! 	vlentryp->nextIdHash[i] = htonl(vlentryp->nextIdHash[i]);
!     vlentryp->nextNameHash = htonl(vlentryp->nextNameHash);
!     for (i = 0; i < NMAXNSERVERS; i++) {
! 	vlentryp->serverNumber[i] = htonl(vlentryp->serverNumber[i]);
! 	vlentryp->serverPartition[i] = htonl(vlentryp->serverPartition[i]);
! 	vlentryp->serverFlags[i] = htonl(vlentryp->serverFlags[i]);
!     }
!     vldbwrite(addr, vlentryp, sizeof(*vlentryp));
! }
! 
! void
! readSIT(int base, int addr)
  {
      int i, j, a;
      char sitbuf[VL_ADDREXTBLK_SIZE];
***************
*** 414,421 ****
   * Remember what the maximum volume id we found is and check against the header.
   */
  void
! ReadAllEntries(header)
!      struct vlheader *header;
  {
      afs_int32 type, rindex, i, j, e;
      int freecount = 0, mhcount = 0, vlcount = 0;
--- 495,501 ----
   * Remember what the maximum volume id we found is and check against the header.
   */
  void
! ReadAllEntries(struct vlheader *header)
  {
      afs_int32 type, rindex, i, j, e;
      int freecount = 0, mhcount = 0, vlcount = 0;
***************
*** 453,458 ****
--- 533,542 ----
  			bkcount++;
  		    continue;
  		}
+ 		if (!vlentry.serverFlags[j]) {
+ 		    /*e = 0;*/
+ 		    continue;
+  		}
  		if (e) {
  		    printf
  			("VLDB entry '%s' contains an unknown RW/RO index serverFlag\n",
***************
*** 504,516 ****
  }
  
  
  /*
   * Follow each Name hash bucket marking it as read in the record array.
   * Record we found it in the name hash within the record array.
   * Check that the name is hashed correctly.
   */
! FollowNameHash(header)
!      struct vlheader *header;
  {
      int count = 0, longest = 0, shortest = -1, chainlength;
      struct nvlentry vlentry;
--- 588,650 ----
  }
  
  
+ void
+ SetHashEnd(long addr, int type, long new)
+ {
+     struct nvlentry vlentry;
+     afs_int32 i, rindex, type2, next = -1;
+ 
+     for (; addr; addr = next) {
+ 	readentry(addr, &vlentry, &type2);
+ 	switch(type & 0xf0) {
+ 	case RWH:
+ 	    next = vlentry.nextIdHash[0];
+ 	    break;
+ 	case ROH:
+ 	    next = vlentry.nextIdHash[1];
+ 	    break;
+ 	case BKH:
+ 	    next = vlentry.nextIdHash[2];
+ 	    break;
+ 	case NH:
+ 	    next = vlentry.nextNameHash;
+ 	    break;
+ 	default:
+ 	    next = -1;
+ 	}
+ 
+ 	if (next < 1) {
+ 	    switch(type & 0xf0) {
+ 	    case RWH:
+ 	      if (vlentry.nextIdHash[0] != 0) {printf("bwoop\n");}
+ 		vlentry.nextIdHash[0] = new;
+ 		break;
+ 	    case ROH:
+ 	      if (vlentry.nextIdHash[1] != 0) {printf("bwoop\n");}
+ 		vlentry.nextIdHash[1] = new;
+ 		break;
+ 	    case BKH:
+ 	      if (vlentry.nextIdHash[2] != 0) {printf("bwoop\n");}
+ 		vlentry.nextIdHash[2] = new;
+ 		break;
+ 	    case NH:
+ 	      if (vlentry.nextNameHash != 0) {printf("bwoop\n");}
+ 		vlentry.nextNameHash = new;
+ 		break;
+ 	    }
+ 	    writeentry(addr, &vlentry);
+ 	    return;
+ 	}
+     }
+ }
+ 
  /*
   * Follow each Name hash bucket marking it as read in the record array.
   * Record we found it in the name hash within the record array.
   * Check that the name is hashed correctly.
   */
! void
! FollowNameHash(struct vlheader *header)
  {
      int count = 0, longest = 0, shortest = -1, chainlength;
      struct nvlentry vlentry;
***************
*** 541,549 ****
--- 675,685 ----
  		printf
  		    ("Name Hash %d: Bad entry '%s': Already in the name hash\n",
  		     i, vlentry.name);
+ 		record[rindex].type |= MULTN;
  		break;
  	    }
  	    record[rindex].type |= NH;
+ 	    record[rindex].type |= REFN;
  
  	    chainlength++;
  	    count++;
***************
*** 553,558 ****
--- 689,695 ----
  		printf
  		    ("Name Hash %d: Bad entry '%s': Incorrect name hash chain (should be in %d)\n",
  		     i, vlentry.name, NameHash(vlentry.name));
+ 		record[rindex].type |= MULTN;
  	    }
  	}
  	if (chainlength > longest)
***************
*** 573,591 ****
   * Record we found it in the id hash within the record array.
   * Check that the ID is hashed correctly.
   */
! FollowIdHash(header)
!      struct vlheader *header;
  {
      int count = 0, longest = 0, shortest = -1, chainlength;
      struct nvlentry vlentry;
      afs_uint32 addr;
!     afs_int32 i, j, hash, type, rindex;
  
      /* Now follow the RW, RO, and BK Hash Tables */
      if (verbose)
  	printf("Check RW, RO, and BK id Hashes\n");
      for (i = 0; i < MAXTYPES; i++) {
  	hash = ((i == 0) ? RWH : ((i == 1) ? ROH : BKH));
  	count = longest = 0;
  	shortest = -1;
  
--- 710,731 ----
   * Record we found it in the id hash within the record array.
   * Check that the ID is hashed correctly.
   */
! void
! FollowIdHash(struct vlheader *header)
  {
      int count = 0, longest = 0, shortest = -1, chainlength;
      struct nvlentry vlentry;
      afs_uint32 addr;
!     afs_int32 i, j, hash, type, rindex, ref, badref, badhash;
  
      /* Now follow the RW, RO, and BK Hash Tables */
      if (verbose)
  	printf("Check RW, RO, and BK id Hashes\n");
      for (i = 0; i < MAXTYPES; i++) {
  	hash = ((i == 0) ? RWH : ((i == 1) ? ROH : BKH));
+ 	ref = ((i == 0) ? REFRW : ((i == 1) ? REFRO : REFBK));
+ 	badref = ((i == 0) ? MULTRW : ((i == 1) ? MULTRO : MULTBK));
+ 	badhash = ((i == 0) ? MULTRW : ((i == 1) ? MULTRO : MULTBK));
  	count = longest = 0;
  	shortest = -1;
  
***************
*** 609,619 ****
  		}
  		if (record[rindex].type & hash) {
  		    printf
! 			("%s Id Hash %d: Bad entry '%s': Already in the the hash table\n",
  			 vtype(i), j, vlentry.name);
  		    break;
  		}
  		record[rindex].type |= hash;
  
  		chainlength++;
  		count++;
--- 749,761 ----
  		}
  		if (record[rindex].type & hash) {
  		    printf
! 			("%s Id Hash %d: Bad entry '%s': Already in the hash table\n",
  			 vtype(i), j, vlentry.name);
+ 		    record[rindex].type |= badref;
  		    break;
  		}
  		record[rindex].type |= hash;
+ 		record[rindex].type |= ref;
  
  		chainlength++;
  		count++;
***************
*** 624,629 ****
--- 766,773 ----
  			("%s Id Hash %d: Bad entry '%s': Incorrect Id hash chain (should be in %d)\n",
  			 vtype(i), j, vlentry.name,
  			 IdHash(vlentry.volumeId[i]));
+ 		    record[rindex].type |= badhash;
+ 		    printf("%d: %x\n", rindex, record[rindex].type);
  		}
  	    }
  
***************
*** 646,653 ****
   * Follow the free chain.
   * Record we found it in the free chain within the record array.
   */
! FollowFreeChain(header)
!      struct vlheader *header;
  {
      afs_int32 count = 0;
      struct nvlentry vlentry;
--- 790,797 ----
   * Follow the free chain.
   * Record we found it in the free chain within the record array.
   */
! void
! FollowFreeChain(struct vlheader *header)
  {
      afs_int32 count = 0;
      struct nvlentry vlentry;
***************
*** 703,710 ****
   * The code does not verify if there are duplicate IP addresses in the 
   * list. The vlserver does this when a fileserver registeres itself.
   */
! CheckIpAddrs(header)
!      struct vlheader *header;
  {
      int mhblocks = 0;
      afs_int32 i, j, m, rindex;
--- 847,854 ----
   * The code does not verify if there are duplicate IP addresses in the 
   * list. The vlserver does this when a fileserver registeres itself.
   */
! void
! CheckIpAddrs(struct vlheader *header)
  {
      int mhblocks = 0;
      afs_int32 i, j, m, rindex;
***************
*** 898,912 ****
      return;
  }
  
  int
! WorkerBee(as, arock)
!      struct cmd_syndesc *as;
!      void *arock;
  {
      char *dbfile;
!     afs_int32 maxentries, type;
      struct vlheader header;
!     struct nvlentry vlentry;
      int i, j, help = 0;
  
      dbfile = as->parms[0].items->data;	/* -database */
--- 1042,1062 ----
      return;
  }
  
+ void 
+ FixBad(afs_uint32 idx, afs_uint32 addr, afs_uint32 type, afs_uint32 tmp, 
+        struct nvlentry *vlentry, afs_uint32 hash) {
+     SetHashEnd(addr, type, tmp);
+     printf("linked unlinked chain %u (index %d) to end of chain %d for %s hash\n", 
+ 	   tmp, ADDR(tmp), hash, type==NH?"Name":(type==RWH?"RW":(type==ROH?"RO":"BK")));
+ }
+ 
  int
! WorkerBee(struct cmd_syndesc *as, void *arock)
  {
      char *dbfile;
!     afs_int32 maxentries, type, tmp;
      struct vlheader header;
!     struct nvlentry vlentry, vlentry2;
      int i, j, help = 0;
  
      dbfile = as->parms[0].items->data;	/* -database */
***************
*** 915,923 ****
      listservers = (as->parms[3].items ? 1 : 0);	/* -servers  */
      listentries = (as->parms[4].items ? 1 : 0);	/* -entries  */
      verbose = (as->parms[5].items ? 1 : 0);	/* -verbose  */
  
      /* open the vldb database file */
!     fd = open(dbfile, O_RDONLY, 0);
      if (fd < 0) {
  	printf("can't open file '%s'. error = %d\n", dbfile, errno);
  	return 0;
--- 1065,1075 ----
      listservers = (as->parms[3].items ? 1 : 0);	/* -servers  */
      listentries = (as->parms[4].items ? 1 : 0);	/* -entries  */
      verbose = (as->parms[5].items ? 1 : 0);	/* -verbose  */
+     fix = (as->parms[6].items ? 1 : 0);	/* -fix  */
  
+  restart:
      /* open the vldb database file */
!     fd = open(dbfile, (fix > 0)?O_RDWR:O_RDONLY, 0);
      if (fd < 0) {
  	printf("can't open file '%s'. error = %d\n", dbfile, errno);
  	return 0;
***************
*** 952,964 ****
      /* Follow the chain of free entries */
      FollowFreeChain(&header);
  
!     /* Now check the record we have been keeping for inconsistancies
       * For valid vlentries, also check that the server we point to is 
       * valid (the serveraddrs array).
       */
      if (verbose)
  	printf("Verify each volume entry\n");
      for (i = 0; i < maxentries; i++) {
  	if (record[i].type == 0)
  	    continue;
  
--- 1104,1122 ----
      /* Follow the chain of free entries */
      FollowFreeChain(&header);
  
!     /* Now check the record we have been keeping for inconsistencies
       * For valid vlentries, also check that the server we point to is 
       * valid (the serveraddrs array).
       */
      if (verbose)
  	printf("Verify each volume entry\n");
      for (i = 0; i < maxentries; i++) {
+ 	int nextp;
+ 	int reft;
+ 	int hash, nexthash = 0;
+ 	int *nextpp;
+ 	char *which;
+ 
  	if (record[i].type == 0)
  	    continue;
  
***************
*** 966,992 ****
  	 * on the hash chains, and its server numbers are good.
  	 */
  	if (record[i].type & VL) {
  	    readentry(record[i].addr, &vlentry, &type);
  
  	    if (InvalidVolname(vlentry.name))
  		printf("Volume '%s' at addr %u has an invalid name\n",
  		       vlentry.name, record[i].addr);
  
! 	    if (!(record[i].type & NH))
! 		printf("Volume '%s' not found in name hash\n", vlentry.name);
  
! 	    if (vlentry.volumeId[0] && !(record[i].type & RWH))
! 		printf("Volume '%s' id %u not found in RW hash chain\n",
! 		       vlentry.name, vlentry.volumeId[0]);
! 
! 	    if (vlentry.volumeId[1] && !(record[i].type & ROH))
! 		printf("Volume '%s' id %u not found in RO hash chain\n",
! 		       vlentry.name, vlentry.volumeId[1]);
! 
! 	    if (vlentry.volumeId[2] && !(record[i].type & BKH))
! 		printf("Volume '%s' id %u not found in BK hash chain\n",
! 		       vlentry.name, vlentry.volumeId[2]);
  
  	    for (j = 0; j < NMAXNSERVERS; j++) {
  		if ((vlentry.serverNumber[j] != 255)
  		    && (serveraddrs[vlentry.serverNumber[j]] == 0)) {
--- 1124,1251 ----
  	 * on the hash chains, and its server numbers are good.
  	 */
  	if (record[i].type & VL) {
+ 	    int foundbad = 0;
+ 	    char volidbuf[256];
+ 
  	    readentry(record[i].addr, &vlentry, &type);
  
  	    if (InvalidVolname(vlentry.name))
  		printf("Volume '%s' at addr %u has an invalid name\n",
  		       vlentry.name, record[i].addr);
  
! 	    if (!(record[i].type & NH)) {
! 		nextp = ADDR(vlentry.nextNameHash);
! 		reft = REFN;
! 		hash = NameHash(vlentry.name);
! 		nextpp = &vlentry.nextNameHash;
! 		which = "name";
! 		sprintf(volidbuf, "");
! 		foundbad = 1;
! 	    }
! 
! 	    if (vlentry.volumeId[0] && !(record[i].type & RWH)) {
! 		nextp = ADDR(vlentry.nextIdHash[0]);
! 		reft = REFRW;
! 		hash = IdHash(vlentry.volumeId[0]);
! 		nextpp = &(vlentry.nextIdHash[0]);
! 		which = "RW";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[0]);
! 		foundbad = 1;
! 	    }
! 
! 	    if (vlentry.volumeId[1] && !(record[i].type & ROH)) {
! 		nextp = ADDR(vlentry.nextIdHash[1]);
! 		reft = REFRO;
! 		hash = IdHash(vlentry.volumeId[1]);
! 		nextpp = &(vlentry.nextIdHash[1]);
! 		which = "RO";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[1]);
! 		foundbad = 1;
! 	    }
! 
! 	    if (vlentry.volumeId[2] && !(record[i].type & BKH)) {
! 		nextp = ADDR(vlentry.nextIdHash[2]);
! 		reft = REFBK;
! 		hash = IdHash(vlentry.volumeId[2]);
! 		nextpp = &(vlentry.nextIdHash[2]);
! 		which = "BK";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[2]);
! 		foundbad = 1;
! 	    }
! 
! 	    if (record[ADDR(vlentry.nextNameHash)].type & MULTN) {
! 		nextp = ADDR(vlentry.nextNameHash);
! 		reft = REFN;
! 		hash = NameHash(vlentry.name);
! 		nextpp = &vlentry.nextNameHash;
! 		which = "name";
! 		sprintf(volidbuf, "");
! 		readentry(nextp, &vlentry2, &type);
! 		nexthash = NameHash(vlentry2.name);
! 		if (hash != nexthash)
! 		    foundbad = 1;
! 	    }
! 
! 	    if ((record[ADDR(vlentry.nextIdHash[0])].type & MULTRW)) {
! 		nextp = ADDR(vlentry.nextIdHash[0]);
! 		reft = REFRW;
! 		hash = IdHash(vlentry.volumeId[0]);
! 		nextpp = &(vlentry.nextIdHash[0]);
! 		which = "RW";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[0]);
! 		readentry(nextp, &vlentry2, &type);
! 		nexthash = IdHash(vlentry2.volumeId[0]);
! 		if (hash != nexthash)
! 		    foundbad = 1;
! 	    }
! 
! 	    if ((record[ADDR(vlentry.nextIdHash[1])].type & MULTRO)) {
! 		nextp = ADDR(vlentry.nextIdHash[1]);
! 		reft = REFRO;
! 		hash = IdHash(vlentry.volumeId[1]);
! 		nextpp = &(vlentry.nextIdHash[1]);
! 		which = "RO";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[1]);
! 		readentry(nextp, &vlentry2, &type);
! 		nexthash = IdHash(vlentry2.volumeId[1]);
! 		if (hash != nexthash)
! 		    foundbad = 1;
! 	    }
  
! 	    if ((record[ADDR(vlentry.nextIdHash[2])].type & MULTBK)) {
! 		nextp = ADDR(vlentry.nextIdHash[2]);
! 		reft = REFBK;
! 		hash = IdHash(vlentry.volumeId[2]);
! 		nextpp = &(vlentry.nextIdHash[2]);
! 		which = "BK";
! 		sprintf(volidbuf, "id %u ", vlentry.volumeId[2]);
! 		readentry(nextp, &vlentry2, &type);
! 		nexthash = IdHash(vlentry2.volumeId[2]);
! 		if (hash != nexthash)
! 		    foundbad = 1;
! 	    }
  
+ 	    if (foundbad) {
+ 		printf("%d: Volume '%s' %snot found in %s hash %d", i, 
+ 		       vlentry.name, volidbuf, which, hash);
+ 		if (nextp) {
+ 		    printf(" (next %d", nextp);
+ 		    if (!(record[nextp].type & reft)) {
+ 			printf(" not in chain ");
+ 			record[nextp].type |= reft;
+ 		    } else if (nextp != 0) {
+ 			printf(" next in chain");
+ 			if (fix) {
+ 			    printf(", unchaining");
+ 			    *nextpp = 0;
+ 			    writeentry(record[i].addr, &vlentry);
+ 			}
+ 		    }
+ 		    printf(")");
+ 		}
+ 		printf("\n");
+ 	    }
+ 	
  	    for (j = 0; j < NMAXNSERVERS; j++) {
  		if ((vlentry.serverNumber[j] != 255)
  		    && (serveraddrs[vlentry.serverNumber[j]] == 0)) {
***************
*** 995,1039 ****
  			 vlentry.name, j, vlentry.serverNumber[j]);
  		}
  	    }
! 
! 	    if (record[i].type & 0xffffff00)
  		printf
  		    ("Volume '%s' id %u also found on other chains (0x%x)\n",
  		     vlentry.name, vlentry.volumeId[0], record[i].type);
! 
  	    /* A free entry */
  	} else if (record[i].type & FR) {
  	    if (!(record[i].type & FRC))
  		printf("Free vlentry at %u not on free chain\n",
  		       record[i].addr);
! 
  	    if (record[i].type & 0xfffffdf0)
  		printf
  		    ("Free vlentry at %u also found on other chains (0x%x)\n",
  		     record[i].addr, record[i].type);
! 
  	    /* A multihomed entry */
  	} else if (record[i].type & MH) {
  	    if (!(record[i].type & MHC))
  		printf("Multihomed block at %u is orphaned\n",
  		       record[i].addr);
! 
  	    if (record[i].type & 0xfffffef0)
  		printf
  		    ("Multihomed block at %u also found on other chains (0x%x)\n",
  		     record[i].addr, record[i].type);
! 
  	} else {
  	    printf("Unknown entry type at %u (0x%x)\n", record[i].addr,
  		   record[i].type);
  	}
      }
      return 0;
  }
  
! main(argc, argv)
!      int argc;
!      char **argv;
  {
      struct cmd_syndesc *ts;
  
--- 1254,1424 ----
  			 vlentry.name, j, vlentry.serverNumber[j]);
  		}
  	    }
! 	
! 	    if (record[i].type & 0xffff0f00)
  		printf
  		    ("Volume '%s' id %u also found on other chains (0x%x)\n",
  		     vlentry.name, vlentry.volumeId[0], record[i].type);
! 	    
  	    /* A free entry */
  	} else if (record[i].type & FR) {
  	    if (!(record[i].type & FRC))
  		printf("Free vlentry at %u not on free chain\n",
  		       record[i].addr);
! 	    
  	    if (record[i].type & 0xfffffdf0)
  		printf
  		    ("Free vlentry at %u also found on other chains (0x%x)\n",
  		     record[i].addr, record[i].type);
! 	    
  	    /* A multihomed entry */
  	} else if (record[i].type & MH) {
  	    if (!(record[i].type & MHC))
  		printf("Multihomed block at %u is orphaned\n",
  		       record[i].addr);
! 	    
  	    if (record[i].type & 0xfffffef0)
  		printf
  		    ("Multihomed block at %u also found on other chains (0x%x)\n",
  		     record[i].addr, record[i].type);
! 	    
  	} else {
  	    printf("Unknown entry type at %u (0x%x)\n", record[i].addr,
  		   record[i].type);
  	}
      }
+ 
+     if (verbose)
+ 	printf("Verify each chain head\n");
+ 
+     {
+ 	afs_uint32 addr;
+ 	int hash;
+ 
+ 	for (j = 0; j < HASHSIZE; j++) {
+ 	    for (addr = header.VolnameHash[j]; j < HASHSIZE; j++) {
+ 		if (record[ADDR(addr)].type & MULTN) {
+ 		    hash = NameHash(vlentry.name);
+ 		    if (hash != j) {
+ 			header.VolnameHash[j] = vlentry.nextNameHash;
+ 			vlentry.nextNameHash = 0;
+ 			if (fix)
+ 			    writeentry(record[i].addr, &vlentry);
+ 		    }
+ 		}
+ 	    }
+ 	}
+ 	for (i = 0; i <= 2; i++) {
+ 	    for (j = 0; j < HASHSIZE; j++) {
+ 		addr = header.VolidHash[i][j]; 
+ 		if (i == 0 && (record[ADDR(addr)].type & MULTRW)) {
+ 		    hash = IdHash(vlentry.volumeId[i]);
+ 		    if (hash != j) {
+ 			header.VolidHash[i][j] = vlentry.nextIdHash[i];
+ 			vlentry.nextIdHash[i] = 0;
+ 			if (fix)
+ 			    writeentry(record[i].addr, &vlentry);
+ 		    }
+ 		}
+ 
+ 		if (i == 1 && (record[ADDR(addr)].type & MULTRO)) {
+ 		    hash = IdHash(vlentry.volumeId[i]);
+ 		    if (hash != j) {
+ 			header.VolidHash[i][j] = vlentry.nextIdHash[i];
+ 			vlentry.nextIdHash[i] = 0;
+ 			if (fix)
+ 			    writeentry(record[i].addr, &vlentry);
+ 		    }
+ 		}
+ 
+ 		if (i == 2 && (record[ADDR(addr)].type & MULTBK)) {
+ 		    hash = IdHash(vlentry.volumeId[i]);
+ 		    if (hash != j) {
+ 			header.VolidHash[i][j] = vlentry.nextIdHash[i];
+ 			vlentry.nextIdHash[i] = 0;
+ 			if (fix)
+ 			    writeentry(record[i].addr, &vlentry);
+ 		    }
+ 		}
+ 	    }
+ 	}
+     }
+     /* By the time we get here, unchained entries are really unchained */
+     printf("Scanning %u entries for possible repairs\n", maxentries);
+     for (i = 0; i < maxentries; i++) {
+ 	int *nextpp;
+ 	if (record[i].type & VL) {
+ 	    readentry(record[i].addr, &vlentry, &type);
+ 	    if (!(record[i].type & REFN)) {
+ 		printf("%d: Record %u (type 0x%x) not in a name chain\n", i, 
+ 		       record[i].addr, record[i].type);
+ 		if (strlen(vlentry.name)>0) {
+ 		    if (fix) {
+ 			if (header.VolnameHash[NameHash(vlentry.name)] == 0)
+ 			    header.VolnameHash[NameHash(vlentry.name)] = record[i].addr;
+ 			else
+ 			    FixBad(i, header.VolnameHash[NameHash(vlentry.name)], NH, record[i].addr, &vlentry, NameHash(vlentry.name));
+ 		    }
+ 		} else {
+ 		    nextpp = &vlentry.nextNameHash;
+ 		    if (fix && *nextpp) {
+ 			printf(", unchaining");
+ 			*nextpp = 0;
+ 			writeentry(record[i].addr, &vlentry);
+ 		    }
+ 		}
+ 	    }
+ 	    if (vlentry.volumeId[0] && !(record[i].type & REFRW)) {
+ 		printf("%d: Record %u (type 0x%x) not in a RW chain\n", i,
+ 		       record[i].addr, record[i].type);
+ 		if (fix) {
+ 		    if (header.VolidHash[0][IdHash(vlentry.volumeId[0])] == 0)
+ 			header.VolidHash[0][IdHash(vlentry.volumeId[0])] = record[i].addr;
+ 		    else
+ 			FixBad(i, header.VolidHash[0][IdHash(vlentry.volumeId[0])], RWH, record[i].addr, &vlentry, IdHash(vlentry.volumeId[0]));
+ 		}
+ 	    }
+ 	    if (vlentry.volumeId[1] && !(record[i].type & REFRO)) {
+ 		printf("%d: Record %u (type 0x%x) not in a RO chain\n", i, 
+ 		       record[i].addr, record[i].type);
+ 		if (fix) {
+ 		    if (header.VolidHash[1][IdHash(vlentry.volumeId[1])] == 0)
+ 			header.VolidHash[1][IdHash(vlentry.volumeId[1])] = record[i].addr;
+ 		    else
+ 			FixBad(i, header.VolidHash[1][IdHash(vlentry.volumeId[1])], ROH, record[i].addr, &vlentry, IdHash(vlentry.volumeId[1]));
+ 		}
+ 	    }
+ 	    if (vlentry.volumeId[2] && !(record[i].type & REFBK)) {
+ 		printf("%d: Record %u (type 0x%x) not in a BK chain\n", i, 
+ 		       record[i].addr, record[i].type);
+ 		if (fix) {
+ 		    if (header.VolidHash[2][IdHash(vlentry.volumeId[2])] == 0)
+ 			header.VolidHash[2][IdHash(vlentry.volumeId[2])] = record[i].addr;
+ 		    else
+ 			FixBad(i, header.VolidHash[2][IdHash(vlentry.volumeId[2])], BKH, record[i].addr, &vlentry, IdHash(vlentry.volumeId[2]));
+ 		}
+ 
+ 	    }
+ 	}
+     }
+     if (fix) 
+ 	writeheader(&header);
+ 
+     close(fd);
+ 
+     if (fixed) {
+       fixed=0;
+       passes++;
+       if (passes < 20)
+ 	goto restart;
+       else
+ 	return 1;
+     }
      return 0;
  }
  
! int
! main(int argc, char **argv)
  {
      struct cmd_syndesc *ts;
  
***************
*** 1049,1054 ****
--- 1434,1440 ----
  		"Display server list");
      cmd_AddParm(ts, "-entries", CMD_FLAG, CMD_OPTIONAL, "Display entries");
      cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose");
+     cmd_AddParm(ts, "-fix", CMD_FLAG, CMD_OPTIONAL, "attempt to patch the database (potentially dangerous)");
  
      return cmd_Dispatch(argc, argv);
  }
