diff --git a/NEWS b/NEWS
index ee059b7c01..9da1b00f8c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,22 @@
                        User-Visible OpenAFS Changes
 
+OpenAFS 1.8.12 (pre-release)
+
+  All client platforms
+
+    * Avoid panics when writing to the cache fails while creating
+      or extending directories. (15742..15744, 15758)
+
+  Linux clients
+
+    * Add support for Linux 6.9 (15739)
+
+    * Add support for Linux 6.8 (15679..15706, 15727)
+
+    * Resolve a kernel module loading issue on the AArch64 architecture,
+      which occurs due to an unsupported RELA relocation (15728)
+
+
 OpenAFS 1.8.11
 
   All platforms
diff --git a/configure-libafs.ac b/configure-libafs.ac
index 644376c551..41fd10cdfa 100644
--- a/configure-libafs.ac
+++ b/configure-libafs.ac
@@ -4,7 +4,7 @@ AC_CONFIG_AUX_DIR([build-tools])
 AC_CONFIG_SRCDIR([src/libafs/Makefile.common.in])
 
 AC_CONFIG_HEADERS([src/config/afsconfig.h])
-MACOS_VERSION=1.8.11
+MACOS_VERSION=1.8.12fc1
 
 AC_SUBST([MACOS_VERSION])
 
diff --git a/configure.ac b/configure.ac
index c23514e940..ff6a588c15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ AC_CONFIG_MACRO_DIR([src/cf])
 AC_CONFIG_SRCDIR([src/config/stds.h])
 
 AC_CONFIG_HEADERS([src/config/afsconfig.h])
-MACOS_VERSION=1.8.11
+MACOS_VERSION=1.8.12fc1
 
 AC_SUBST([MACOS_VERSION])
 
diff --git a/src/afs/FBSD/osi_vfsops.c b/src/afs/FBSD/osi_vfsops.c
index 6044bbed17..8a979db6d7 100644
--- a/src/afs/FBSD/osi_vfsops.c
+++ b/src/afs/FBSD/osi_vfsops.c
@@ -18,7 +18,6 @@ struct mount *afs_globalVFS = NULL;
 int afs_pbuf_freecnt = -1;
 
 extern int Afs_xsetgroups();
-extern int afs_xioctl();
 
 static struct syscall_helper_data afs_syscalls[] = {
     {
diff --git a/src/afs/HPUX/osi_vfsops.c b/src/afs/HPUX/osi_vfsops.c
index 0ddc227c78..46faca7433 100644
--- a/src/afs/HPUX/osi_vfsops.c
+++ b/src/afs/HPUX/osi_vfsops.c
@@ -290,7 +290,7 @@ int afs_vfs_slot = -1;
 
 afsc_link()
 {
-    extern int Afs_syscall(), afs_xioctl(), Afs_xsetgroups();
+    extern int Afs_syscall(), Afs_xsetgroups();
 
     /* For now nothing special is required during AFS initialization. */
     AFS_STATCNT(afsc_link);
diff --git a/src/afs/LINUX/osi_crypto.c b/src/afs/LINUX/osi_crypto.c
index ead19161ca..7f8435c656 100644
--- a/src/afs/LINUX/osi_crypto.c
+++ b/src/afs/LINUX/osi_crypto.c
@@ -25,6 +25,9 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
+#include "afs/sysincludes.h"
+#include "afsincludes.h"
+
 #include <linux/random.h>
 
 int
diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c
index e8c2980681..cb91ecb0ac 100644
--- a/src/afs/LINUX/osi_file.c
+++ b/src/afs/LINUX/osi_file.c
@@ -47,7 +47,7 @@ extern struct cred *cache_creds;
 #endif
 
 /* Old export ops: decode_fh will call back here. Accept any dentry it suggests */
-int
+static int
 afs_fh_acceptable(void *context, struct dentry *dp)
 {
     return 1;
diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c
index 87d149f56b..901312d2a5 100644
--- a/src/afs/LINUX/osi_groups.c
+++ b/src/afs/LINUX/osi_groups.c
@@ -166,8 +166,11 @@ __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
 }
 
 #ifdef LINUX_KEYRING_SUPPORT
-extern struct key_type key_type_keyring __attribute__((weak));
+# if defined(EXPORTED_KEY_TYPE_KEYRING)
 static struct key_type *__key_type_keyring = &key_type_keyring;
+# else
+static struct key_type *__key_type_keyring;
+# endif
 
 /* install_session_keyring returns negative error values */
 static int
diff --git a/src/afs/LINUX/osi_ioctl.c b/src/afs/LINUX/osi_ioctl.c
index fbdee29cb8..3e797745cc 100644
--- a/src/afs/LINUX/osi_ioctl.c
+++ b/src/afs/LINUX/osi_ioctl.c
@@ -34,9 +34,6 @@
 
 extern struct proc_dir_entry *openafs_procfs;
 
-extern asmlinkage long
-afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
-
 static int
 afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h
index 916a1dfeda..263c8633c1 100644
--- a/src/afs/LINUX/osi_machdep.h
+++ b/src/afs/LINUX/osi_machdep.h
@@ -77,6 +77,7 @@
 #endif
 
 #include "afs/sysincludes.h"
+#include "roken.h"
 
 #if !defined(HAVE_LINUX_TIME_T)
 typedef time64_t time_t;
diff --git a/src/afs/LINUX/osi_misc.c b/src/afs/LINUX/osi_misc.c
index aa5d5fc936..27f73cd1f1 100644
--- a/src/afs/LINUX/osi_misc.c
+++ b/src/afs/LINUX/osi_misc.c
@@ -155,7 +155,8 @@ int osi_abspath(char *aname, char *buf, int buflen,
 
 
 /* This could use some work, and support on more platforms. */
-int afs_thread_wrapper(void *rock)
+static int
+afs_thread_wrapper(void *rock)
 {
     void (*proc)(void) = rock;
     __module_get(THIS_MODULE);
diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c
index fdc347d2c5..30ac048d32 100644
--- a/src/afs/LINUX/osi_module.c
+++ b/src/afs/LINUX/osi_module.c
@@ -64,7 +64,7 @@ afs_init_idmap(void)
 }
 #endif
 
-int __init
+static int __init
 afs_init(void)
 {
     int err;
@@ -114,7 +114,7 @@ afs_init(void)
     return 0;
 }
 
-void __exit
+static void __exit
 afs_cleanup(void)
 {
     afs_shutdown_pagecopy();
diff --git a/src/afs/LINUX/osi_pag_module.c b/src/afs/LINUX/osi_pag_module.c
index e832c5abd8..24b938f0ee 100644
--- a/src/afs/LINUX/osi_pag_module.c
+++ b/src/afs/LINUX/osi_pag_module.c
@@ -58,7 +58,7 @@ int afs_global_owner = 0;
 struct user_namespace *afs_ns;
 #endif
 
-int __init
+static int __init
 afspag_init(void)
 {
 #if !defined(EXPORTED_PROC_ROOT_FS)
@@ -90,7 +90,7 @@ afspag_init(void)
     return 0;
 }
 
-void __exit
+static void __exit
 afspag_cleanup(void)
 {
 #if !defined(EXPORTED_PROC_ROOT_FS)
diff --git a/src/afs/LINUX/osi_pagecopy.c b/src/afs/LINUX/osi_pagecopy.c
index 7142a1b06d..42f5e38e03 100644
--- a/src/afs/LINUX/osi_pagecopy.c
+++ b/src/afs/LINUX/osi_pagecopy.c
@@ -61,6 +61,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include "osi_pagecopy.h"
 
 static DECLARE_WAIT_QUEUE_HEAD (afs_pagecopy_wq);
 static spinlock_t afs_pagecopy_lock;
diff --git a/src/afs/LINUX/osi_probe.c b/src/afs/LINUX/osi_probe.c
index 9b06fa7b1a..be42ecf85e 100644
--- a/src/afs/LINUX/osi_probe.c
+++ b/src/afs/LINUX/osi_probe.c
@@ -48,9 +48,13 @@
 #ifdef OSI_PROBE_STANDALONE
 # define OSI_PROBE_DEBUG
 #endif
+
 #ifndef OSI_PROBE_STANDALONE
 # include <afsconfig.h>
 # include "afs/param.h"
+
+# include "afs/sysincludes.h"
+# include "afsincludes.h"
 #endif
 
 #include <linux/version.h>
@@ -61,10 +65,6 @@
 /* Slightly kludgy, but too bad */
 #define scsi_command_size scsi_command_size_tbl
 #endif
-#ifndef OSI_PROBE_STANDALONE
-# include "afs/sysincludes.h"
-# include "afsincludes.h"
-#endif
 #include <linux/sched.h>
 #ifdef HAVE_LINUX_CONFIG_H
 # include <linux/config.h>
diff --git a/src/afs/LINUX/osi_syscall.c b/src/afs/LINUX/osi_syscall.c
index 836491c29c..dc78da8746 100644
--- a/src/afs/LINUX/osi_syscall.c
+++ b/src/afs/LINUX/osi_syscall.c
@@ -14,6 +14,10 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
+#include <linux/module.h> /* early to avoid printf->printk mapping */
+#include "afs/sysincludes.h"
+#include "afsincludes.h"
+
 #ifdef LINUX_KEYRING_SUPPORT
 /* The syscall probing stuff is unnecessary (and is never called) if we have
  * keyrings support; we rely on keyrings instead of group ids to track PAGs.
@@ -31,9 +35,6 @@ osi_syscall_clean(void)
 
 #else /* LINUX_KEYRING_SUPPORT */
 
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
 #include <linux/unistd.h>		/* For syscall numbers. */
 #include <linux/mm.h>
 
@@ -90,9 +91,6 @@ osi_syscall_clean(void)
 
 
 /***** ALL PLATFORMS *****/
-extern asmlinkage long
-afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
-
 static SYSCALLTYPE *afs_sys_call_table;
 static SYSCALLTYPE afs_ni_syscall = 0;
 
diff --git a/src/afs/LINUX/osi_sysctl.c b/src/afs/LINUX/osi_sysctl.c
index a0a0398923..c1116fc79e 100644
--- a/src/afs/LINUX/osi_sysctl.c
+++ b/src/afs/LINUX/osi_sysctl.c
@@ -54,6 +54,14 @@ extern afs_int32 afs_pct2;
 # define AFS_SYSCTL_INT(num, perms, var) \
 	AFS_SYSCTL_INT2(num, perms, #var, var)
 
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
+/* end of list sentinel not needed */
+#  define AFS_SYSCTL_SENTINEL
+# else
+/* NULL entry to mark the end of the list */
+#  define AFS_SYSCTL_SENTINEL { .procname = NULL }
+# endif
+
 static struct ctl_table_header *afs_sysctl = NULL;
 
 static struct ctl_table afs_sysctl_table[] = {
@@ -75,9 +83,7 @@ static struct ctl_table afs_sysctl_table[] = {
     AFS_SYSCTL_INT( 13, 0644, afs_cacheBlocks),
     AFS_SYSCTL_INT2(14, 0644, "md5inum", afs_md5inum),
 
-    {
-	.procname	= 0
-    }
+    AFS_SYSCTL_SENTINEL
 };
 # if !defined(HAVE_LINUX_REGISTER_SYSCTL)
 static struct ctl_table fs_sysctl_table[] = {
@@ -87,9 +93,7 @@ static struct ctl_table fs_sysctl_table[] = {
 	.mode		= 0555,
 	.child		= afs_sysctl_table
     },
-    {
-	.procname	= 0
-    }
+    AFS_SYSCTL_SENTINEL
 };
 # endif
 int
diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c
index 897fd37abd..43644f44b5 100644
--- a/src/afs/LINUX/osi_vcache.c
+++ b/src/afs/LINUX/osi_vcache.c
@@ -15,6 +15,14 @@
 
 #include "osi_compat.h"
 
+#if defined(STRUCT_DENTRY_HAS_D_CHILDREN)
+# define afs_for_each_child(child, parent) \
+	 hlist_for_each_entry((child), &(parent)->d_children, d_sib)
+#else
+# define afs_for_each_child(child, parent) \
+	 list_for_each_entry((child), &(parent)->d_subdirs, d_child)
+#endif
+
 static void
 TryEvictDirDentries(struct inode *inode)
 {
@@ -312,7 +320,7 @@ osi_ResetVCache(struct vcache *avc)
 	     * because 'dp' is an ancestor of 'child'.
 	     */
 	    struct dentry *child;
-	    list_for_each_entry(child, &dp->d_subdirs, d_child) {
+	    afs_for_each_child(child, dp) {
 		spin_lock(&child->d_lock);
 		child->d_time = 0;
 		spin_unlock(&child->d_lock);
diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c
index b85ab3fdfb..bb49a5ce21 100644
--- a/src/afs/LINUX/osi_vfsops.c
+++ b/src/afs/LINUX/osi_vfsops.c
@@ -40,7 +40,7 @@ extern struct dentry_operations afs_dentry_operations;
 
 /* Forward declarations */
 static int afs_root(struct super_block *afsp);
-int afs_fill_super(struct super_block *sb, void *data, int silent);
+static int afs_fill_super(struct super_block *sb, void *data, int silent);
 
 
 /*
@@ -52,19 +52,22 @@ int afs_fill_super(struct super_block *sb, void *data, int silent);
 #if defined(STRUCT_FILE_SYSTEM_TYPE_HAS_MOUNT)
 static struct dentry *
 afs_mount(struct file_system_type *fs_type, int flags,
-           const char *dev_name, void *data) {
+	  const char *dev_name, void *data)
+{
     return mount_nodev(fs_type, flags, data, afs_fill_super);
 }
 #elif defined(GET_SB_HAS_STRUCT_VFSMOUNT)
 static int
 afs_get_sb(struct file_system_type *fs_type, int flags,
-	   const char *dev_name, void *data, struct vfsmount *mnt) {
+	   const char *dev_name, void *data, struct vfsmount *mnt)
+{
     return get_sb_nodev(fs_type, flags, data, afs_fill_super, mnt);
 }
 #else
 static struct super_block *
 afs_get_sb(struct file_system_type *fs_type, int flags,
-	   const char *dev_name, void *data) {
+	   const char *dev_name, void *data)
+{
     return get_sb_nodev(fs_type, flags, data, afs_fill_super);
 }
 #endif
@@ -83,7 +86,7 @@ struct file_system_type afs_fs_type = {
 
 struct backing_dev_info *afs_backing_dev_info;
 
-int
+static int
 afs_fill_super(struct super_block *sb, void *data, int silent)
 {
     int code = 0;
@@ -372,7 +375,7 @@ afs_put_super(struct super_block *sbp)
  * statp is in user space, so we need to cobble together a statfs, then
  * copy it.
  */
-int
+static int
 #if defined(STATFS_TAKES_DENTRY)
 afs_statfs(struct dentry *dentry, struct kstatfs *statp)
 #else
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 7e85aa5528..b709ad1a5e 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -407,8 +407,6 @@ afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
 }
 #endif
 
-extern int BlobScan(struct dcache * afile, afs_int32 ablob, afs_int32 *ablobOut);
-
 /* This is a complete rewrite of afs_readdir, since we can make use of
  * filldir instead of afs_readdir_move. Note that changes to vcache/dcache
  * handling and use of bulkstats will need to be reflected here as well.
@@ -615,10 +613,6 @@ out1:
 }
 
 
-/* in afs_pioctl.c */
-extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
-		      unsigned long arg);
-
 static long afs_unlocked_xioctl(struct file *fp, unsigned int com,
                                unsigned long arg) {
     return afs_xioctl(FILE_INODE(fp), fp, com, arg);
@@ -718,6 +712,61 @@ afs_linux_fsync(struct file *fp, int datasync)
 
 }
 
+/* Handle getting/setting file_lock type */
+
+static inline unsigned char
+afs_get_flock_type(struct file_lock *flp)
+{
+#if defined(HAVE_FILE_LOCK_CORE)
+    return flp->c.flc_type;
+#else
+    return flp->fl_type;
+#endif
+}
+
+static inline void
+afs_set_flock_type(struct file_lock *flp, unsigned char type)
+{
+#if defined(HAVE_FILE_LOCK_CORE)
+    flp->c.flc_type = type;
+#else
+    flp->fl_type = type;
+#endif
+}
+
+/* Handle getting/setting file_lock pid */
+
+static inline pid_t
+afs_get_flock_pid(struct file_lock *flp)
+{
+#if defined(HAVE_FILE_LOCK_CORE)
+    return flp->c.flc_pid;
+#else
+    return flp->fl_pid;
+#endif
+}
+
+static inline void
+afs_set_flock_pid(struct file_lock *flp, pid_t pid)
+{
+#if defined(HAVE_FILE_LOCK_CORE)
+    flp->c.flc_pid = pid;
+#else
+    flp->fl_pid = pid;
+#endif
+}
+
+/* Handle clearing file_lock sleep */
+
+static inline void
+afs_clear_flock_sleep(struct file_lock *flp)
+{
+#if defined(HAVE_FILE_LOCK_CORE)
+	flp->c.flc_flags &= ~FL_SLEEP;
+#else
+	flp->fl_flags &= ~FL_SLEEP;
+#endif
+}
 
 static int
 afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
@@ -729,8 +778,8 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 
     /* Convert to a lock format afs_lockctl understands. */
     memset(&flock, 0, sizeof(flock));
-    flock.l_type = flp->fl_type;
-    flock.l_pid = flp->fl_pid;
+    flock.l_type = afs_get_flock_type(flp);
+    flock.l_pid = afs_get_flock_pid(flp);
     flock.l_whence = 0;
     flock.l_start = flp->fl_start;
     if (flp->fl_end == OFFSET_MAX)
@@ -752,10 +801,10 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
     AFS_GUNLOCK();
 
-    if ((code == 0 || flp->fl_type == F_UNLCK) &&
-        (cmd == F_SETLK || cmd == F_SETLKW)) {
+    if ((code == 0 || afs_get_flock_type(flp) == F_UNLCK) &&
+	(cmd == F_SETLK || cmd == F_SETLKW)) {
 	code = afs_posix_lock_file(fp, flp);
-	if (code && flp->fl_type != F_UNLCK) {
+	if (code && afs_get_flock_type(flp) != F_UNLCK) {
 	    struct AFS_FLOCK flock2;
 	    flock2 = flock;
 	    flock2.l_type = F_UNLCK;
@@ -768,17 +817,17 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
      * kernel, as lockctl knows nothing about byte range locks
      */
     if (code == 0 && cmd == F_GETLK && flock.l_type == F_UNLCK) {
-        afs_posix_test_lock(fp, flp);
-        /* If we found a lock in the kernel's structure, return it */
-        if (flp->fl_type != F_UNLCK) {
-            crfree(credp);
-            return 0;
-        }
+	afs_posix_test_lock(fp, flp);
+	/* If we found a lock in the kernel's structure, return it */
+	if (afs_get_flock_type(flp) != F_UNLCK) {
+	    crfree(credp);
+	    return 0;
+	}
     }
 
     /* Convert flock back to Linux's file_lock */
-    flp->fl_type = flock.l_type;
-    flp->fl_pid = flock.l_pid;
+    afs_set_flock_type(flp, flock.l_type);
+    afs_set_flock_pid(flp, flock.l_pid);
     flp->fl_start = flock.l_start;
     if (flock.l_len == 0)
 	flp->fl_end = OFFSET_MAX; /* Lock to end of file */
@@ -798,8 +847,8 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
     struct AFS_FLOCK flock;
     /* Convert to a lock format afs_lockctl understands. */
     memset(&flock, 0, sizeof(flock));
-    flock.l_type = flp->fl_type;
-    flock.l_pid = flp->fl_pid;
+    flock.l_type = afs_get_flock_type(flp);
+    flock.l_pid = afs_get_flock_pid(flp);
     flock.l_whence = 0;
     flock.l_start = 0;
     flock.l_len = 0;
@@ -818,11 +867,11 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
     code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
     AFS_GUNLOCK();
 
-    if ((code == 0 || flp->fl_type == F_UNLCK) &&
-        (cmd == F_SETLK || cmd == F_SETLKW)) {
-	flp->fl_flags &=~ FL_SLEEP;
+    if ((code == 0 || afs_get_flock_type(flp) == F_UNLCK) &&
+	(cmd == F_SETLK || cmd == F_SETLKW)) {
+	afs_clear_flock_sleep(flp);
 	code = flock_lock_file_wait(fp, flp);
-	if (code && flp->fl_type != F_UNLCK) {
+	if (code && afs_get_flock_type(flp) != F_UNLCK) {
 	    struct AFS_FLOCK flock2;
 	    flock2 = flock;
 	    flock2.l_type = F_UNLCK;
@@ -832,8 +881,8 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
 	}
     }
     /* Convert flock back to Linux's file_lock */
-    flp->fl_type = flock.l_type;
-    flp->fl_pid = flock.l_pid;
+    afs_set_flock_type(flp, flock.l_type);
+    afs_set_flock_pid(flp, flock.l_pid);
 
     crfree(credp);
     return code;
diff --git a/src/afs/NBSD/osi_kmod.c b/src/afs/NBSD/osi_kmod.c
index f6585651e2..eefaf5617c 100644
--- a/src/afs/NBSD/osi_kmod.c
+++ b/src/afs/NBSD/osi_kmod.c
@@ -44,7 +44,6 @@
 #include "afs/afsincludes.h"    /* Afs-based standard headers */
 
 extern int afs3_syscall(struct lwp *, const void *, register_t *);
-extern int afs_xioctl(struct lwp *, const void *, register_t *);
 extern int Afs_xsetgroups(struct lwp *, const void *, register_t *);
 
 #if !defined(AFS_NBSD60_ENV)
diff --git a/src/afs/NBSD/osi_vfsops.c b/src/afs/NBSD/osi_vfsops.c
index 7679ff1695..5032a1dd9e 100644
--- a/src/afs/NBSD/osi_vfsops.c
+++ b/src/afs/NBSD/osi_vfsops.c
@@ -110,7 +110,6 @@ VFS_PROTOS(afs);
 #ifndef AFS_NBSD60_ENV
 extern int sys_lkmnosys(struct lwp *, const void *, register_t *);
 extern int afs3_syscall(struct lwp *, const void *, register_t *);
-extern int afs_xioctl(struct lwp *, const void *, register_t *);
 extern int Afs_xsetgroups(struct lwp *, const void *, register_t *);
 static int afs_badcall(struct lwp *, const void *, register_t *);
 
diff --git a/src/afs/OBSD/osi_vfsops.c b/src/afs/OBSD/osi_vfsops.c
index 830906cc38..e7729261ea 100644
--- a/src/afs/OBSD/osi_vfsops.c
+++ b/src/afs/OBSD/osi_vfsops.c
@@ -108,7 +108,7 @@ NONINFRINGEMENT.
 /* from /usr/src/sys/kern/vfs_subr.c */
 extern void insmntque(struct vnode *, struct mount *);
 
-extern int sys_lkmnosys(), afs_xioctl(), Afs_xsetgroups();
+extern int sys_lkmnosys(), Afs_xsetgroups();
 
 static int lkmid = -1;
 static int afs_badcall(struct proc *p, void *xx, register_t * yy);
diff --git a/src/afs/SOLARIS/osi_vfsops.c b/src/afs/SOLARIS/osi_vfsops.c
index c6c9ddf565..f3f9bd33c9 100644
--- a/src/afs/SOLARIS/osi_vfsops.c
+++ b/src/afs/SOLARIS/osi_vfsops.c
@@ -389,7 +389,6 @@ afsinit(int fstype, char *dummy)
 afsinit(struct vfssw *vfsswp, int fstype)
 #endif
 {
-    extern int afs_xioctl();
     extern int afs_xsetgroups();
 
     AFS_STATCNT(afsinit);
diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c
index e1796c54f2..0fbe4e8f95 100644
--- a/src/afs/VNOPS/afs_vnop_lookup.c
+++ b/src/afs/VNOPS/afs_vnop_lookup.c
@@ -667,8 +667,6 @@ afs_CheckBulkStatus(struct afs_conn *tc, int nFids, AFSBulkStats *statParm,
     return 0;
 }
 
-extern int BlobScan(struct dcache * afile, afs_int32 ablob, afs_int32 *ablobOut);
-
 /* called with an unlocked directory and directory cookie.  Areqp
  * describes who is making the call.
  * Scans the next N (about 30, typically) directory entries, and does
diff --git a/src/afs/afs_buffer.c b/src/afs/afs_buffer.c
index 5552d1c21e..4cf6d51408 100644
--- a/src/afs/afs_buffer.c
+++ b/src/afs/afs_buffer.c
@@ -525,7 +525,7 @@ DFlushDCache(struct dcache *adc)
     ObtainReadLock(&afs_bufferLock);
 
     for (i = 0; i <= PHPAGEMASK; i++)
-        for (tb = phTable[pHash(adc->index, i)]; tb; tb = tb->hashNext)
+	for (tb = phTable[pHash(adc->index, i)]; tb != NULL; tb = tb->hashNext)
 	    if (tb->fid == adc->index) {
 		ObtainWriteLock(&tb->lock, 701);
 		tb->lockers++;
@@ -580,12 +580,24 @@ DFlush(void)
     return 0;
 }
 
+/*!
+ * Prepare a new directory page buffer
+ *
+ * \param adc	    pointer to the directory object dcache
+ * \param page	    page we want
+ * \param entry	    buffer to return requested page
+ *
+ * \retval 0	    success; entry is updated
+ * \retval non-zero internal error or IO error writing to disk
+ */
 int
 DNew(struct dcache *adc, int page, struct DirBuffer *entry)
 {
     /* Same as read, only do *not* even try to read the page, since it
      * probably doesn't exist. */
     struct buffer *tb;
+    int code;
+
     AFS_STATCNT(DNew);
 
     ObtainWriteLock(&afs_bufferLock, 264);
@@ -600,7 +612,11 @@ DNew(struct dcache *adc, int page, struct DirBuffer *entry)
      * DFlush due to lock hierarchy issues */
     if ((page + 1) * AFS_BUFFER_PAGESIZE > adc->f.chunkBytes) {
 	afs_AdjustSize(adc, (page + 1) * AFS_BUFFER_PAGESIZE);
-	osi_Assert(afs_WriteDCache(adc, 1) == 0);
+	code = afs_WriteDCache(adc, 1);
+	if (code) {
+	    ReleaseWriteLock(&afs_bufferLock);
+	    return code;
+	}
     }
     ObtainWriteLock(&tb->lock, 265);
     tb->lockers++;
diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c
index ba78bce6e3..4ac63b1872 100644
--- a/src/afs/afs_call.c
+++ b/src/afs/afs_call.c
@@ -267,7 +267,7 @@ afsd_thread(int *rock)
     }
 }
 
-void
+static void
 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
 	     long parm6)
 {
@@ -436,7 +436,7 @@ afsd_thread(void *rock)
     return 0;
 }
 
-void
+static void
 # if defined(AFS_LINUX_ENV) && !defined(INIT_WORK_HAS_DATA)
 afsd_launcher(struct work_struct *work)
 # else
@@ -457,7 +457,7 @@ afsd_launcher(void *rock)
 # endif /* !HAVE_LINUX_KTHREAD_RUN */
 }
 
-void
+static void
 afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
 	     long parm6)
 {
diff --git a/src/afs/afs_callback.c b/src/afs/afs_callback.c
index e7d8ab5d44..1fe990edf8 100644
--- a/src/afs/afs_callback.c
+++ b/src/afs/afs_callback.c
@@ -19,6 +19,8 @@
 
 #include "afs/sysincludes.h"	/*Standard vendor system headers */
 #include "afsincludes.h"	/*AFS-based standard headers */
+#define FSINT_COMMON_XG
+#include "afs/afscbint.h"
 #include "afs/afs_stats.h"	/*Cache Manager stats */
 #include "afs/opr.h"
 #include "afs/afs_args.h"
@@ -1472,71 +1474,6 @@ SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
     return 0;
 }
 
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_FetchData
- *
- * Description:
- *      Routine to do third party move from a remioserver to the original
- *      issuer of an ArchiveData request. Presently supported only by the
- *      "fs" command, not by the AFS client.
- *
- * Arguments:
- *      rxcall:        Ptr to Rx call on which this request came in.
- *      Fid:           pointer to AFSFid structure.
- *      Fd:            File descriptor inside fs command.
- *      Position:      Offset in the file.
- *      Length:        Data length to transfer.
- *      TotalLength:   Pointer to total file length field
- *
- * Returns:
- *      0 on success
- *
- * Environment:
- *      Nothing interesting.
- *
- * Side Effects:
- *------------------------------------------------------------------------*/
-int
-SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
-		   afs_int64 Position, afs_int64 Length,
-		   afs_int64 * TotalLength)
-{
-    return ENOSYS;
-}
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_StoreData
- *
- * Description:
- *      Routine to do third party move from a remioserver to the original
- *      issuer of a RetrieveData request. Presently supported only by the
- *      "fs" command, not by the AFS client.
- *
- * Arguments:
- *      rxcall:        Ptr to Rx call on which this request came in.
- *      Fid:           pointer to AFSFid structure.
- *      Fd:            File descriptor inside fs command.
- *      Position:      Offset in the file.
- *      Length:        Data length to transfer.
- *      TotalLength:   Pointer to total file length field
- *
- * Returns:
- *      0 on success
- *
- * Environment:
- *      Nothing interesting.
- *
- * Side Effects:
- *      As advertised.
- *------------------------------------------------------------------------*/
-int
-SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
-		   afs_int64 Position, afs_int64 Length,
-		   afs_int64 * TotalLength)
-{
-    return ENOSYS;
-}
-
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_GetCellByNum
  *
@@ -1636,14 +1573,3 @@ SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
 
     return code;
 }
-
-
-int
-SRXAFSCB_GetDE(struct rx_call *a_call, afs_int32 a_index, afs_int32 *addr,
-	       afs_int32 *inode, afs_int32 *flags, afs_int32 *time,
-	       char ** fileName)
-{ /*SRXAFSCB_GetDE*/
-    int code = 0;				/*Return code*/
-    return(code);
-
-} /*SRXAFSCB_GetDE*/
diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c
index 3572f2f231..35fd594732 100644
--- a/src/afs/afs_dcache.c
+++ b/src/afs/afs_dcache.c
@@ -1674,7 +1674,7 @@ afs_AllocDiscardDSlot(afs_int32 lock)
  *
  * \return The new dcache.
  */
-struct dcache *
+static struct dcache *
 afs_AllocDCache(struct vcache *avc, afs_int32 chunk, afs_int32 lock,
 		struct VenusFid *ashFid)
 {
@@ -3842,6 +3842,9 @@ afs_MakeShadowDir(struct vcache *avc, struct dcache *adc)
 
     ReleaseWriteLock(&afs_xdcache);
 
+    /* Make sure and flush dir buffers back into the disk cache */
+    DFlushDCache(adc);
+
     /* Alloc a 4k block. */
     data = afs_osi_Alloc(4096);
     if (!data) {
diff --git a/src/afs/afs_disconnected.c b/src/afs/afs_disconnected.c
index 3b88585393..03ff90f7ea 100644
--- a/src/afs/afs_disconnected.c
+++ b/src/afs/afs_disconnected.c
@@ -102,7 +102,7 @@ afs_FindDCacheByFid(struct VenusFid *afid)
  *
  * \return Mask of operations.
  */
-int
+static int
 afs_GenStoreStatus(struct vcache *avc, struct AFSStoreStatus *astat)
 {
     if (!avc || !astat || !avc->f.ddirty_flags)
@@ -157,7 +157,7 @@ get_parent_dir_fid_hook(void *hdata, char *aname, afs_int32 vnode,
  *
  * \return 0 on success, -1 on failure
  */
-int
+static int
 afs_GetParentDirFid(struct vcache *avc, struct VenusFid *afid)
 {
     struct dcache *tdc;
@@ -234,7 +234,7 @@ get_vnode_name_hook(void *hdata, char *aname, afs_int32 vnode,
  * \param deleted Has this file been deleted? If yes, use the shadow
  * dir for looking up the name.
  */
-int
+static int
 afs_GetVnodeName(struct vcache *avc, struct VenusFid *afid, char *aname,
 		 int deleted)
 {
@@ -358,7 +358,7 @@ chk_del_children_hook(void *hdata, char *aname, afs_int32 vnode,
  *
  * \note afs_DDirtyVCListLock must be write locked.
  */
-int
+static int
 afs_CheckDeletedChildren(struct vcache *avc)
 {
     struct dcache *tdc;
@@ -452,7 +452,7 @@ fix_children_fids_hook(void *hdata, char *aname, afs_int32 vnode,
  * \param old_fid The current dir's fid.
  * \param new_fid The new dir's fid.
  */
-void
+static void
 afs_FixChildrenFids(struct VenusFid *old_fid, struct VenusFid *new_fid)
 {
     struct dcache *tdc;
@@ -499,7 +499,7 @@ afs_DbgListDirEntries(struct VenusFid *afid)
  * 	   be deferred to later in the resync process
  */
 
-int
+static int
 afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
 		    char *aname, struct vcache **adp)
 {
@@ -548,7 +548,7 @@ end:
  * - Get the new name from the current dir.
  * - Old dir fid and new dir fid are collected along the way.
  * */
-int
+static int
 afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
 {
     struct VenusFid old_pdir_fid, new_pdir_fid;
@@ -651,7 +651,7 @@ done:
  * - Handle errors.
  * - Reorder vhash and dcaches in their hashes, using the newly acquired fid.
  */
-int
+static int
 afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
 		    afs_ucred_t *acred)
 {
@@ -921,7 +921,7 @@ end:
  *
  * \note avc must be write locked.
  */
-int
+static int
 afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
 {
     char *tname = NULL;
@@ -1022,7 +1022,7 @@ end:
  *
  * \return 0 for success. On failure, other error codes.
  */
-int
+static int
 afs_SendChanges(struct vcache *avc, struct vrequest *areq)
 {
     struct afs_conn *tc;
@@ -1334,37 +1334,6 @@ afs_DisconDiscardAll(afs_ucred_t *acred)
     ReleaseWriteLock(&afs_disconDirtyLock);
 }
 
-/*!
- * Print list of disconnected files.
- *
- * \note Call with afs_DDirtyVCListLock read locked.
- */
-void
-afs_DbgDisconFiles(void)
-{
-    struct vcache *tvc;
-    struct afs_q *q;
-    int i = 0;
-
-    afs_warn("List of dirty files: \n");
-
-    ObtainReadLock(&afs_disconDirtyLock);
-    for (q = QPrev(&afs_disconDirty); q != &afs_disconDirty; q = QPrev(q)) {
-        tvc = QEntry(q, struct vcache, dirtyq);
-
-	afs_warn("Cell=%u Volume=%u VNode=%u Unique=%u\n",
-		tvc->f.fid.Cell,
-		tvc->f.fid.Fid.Volume,
-		tvc->f.fid.Fid.Vnode,
-		tvc->f.fid.Fid.Unique);
-
-	i++;
-	if (i >= 30)
-	    osi_Panic("afs_DbgDisconFiles: loop in dirty list\n");
-    }
-    ReleaseReadLock(&afs_disconDirtyLock);
-}
-
 /*!
  * Generate a fake fid for a disconnected shadow dir.
  * Similar to afs_GenFakeFid, only that it uses the dhash
diff --git a/src/afs/afs_fetchstore.c b/src/afs/afs_fetchstore.c
index 7b35b8f7f8..97d0671811 100644
--- a/src/afs/afs_fetchstore.c
+++ b/src/afs/afs_fetchstore.c
@@ -77,14 +77,14 @@ FillStoreStats(int code, int idx, osi_timeval32_t xferStartTime,
 
 
 
-afs_int32
+static afs_int32
 rxfs_storeUfsPrepare(void *r, afs_uint32 size, afs_uint32 *tlen)
 {
     *tlen = (size > AFS_LRALLOCSIZ ?  AFS_LRALLOCSIZ : size);
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeMemPrepare(void *r, afs_uint32 size, afs_uint32 *tlen)
 {
     afs_int32 code;
@@ -105,7 +105,7 @@ rxfs_storeMemPrepare(void *r, afs_uint32 size, afs_uint32 *tlen)
     return code;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeUfsRead(void *r, struct osi_file *tfile, afs_uint32 offset,
 		  afs_uint32 tlen, afs_uint32 *bytesread)
 {
@@ -126,7 +126,7 @@ rxfs_storeUfsRead(void *r, struct osi_file *tfile, afs_uint32 offset,
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeMemRead(void *r, struct osi_file *tfile, afs_uint32 offset,
 		  afs_uint32 tlen, afs_uint32 *bytesread)
 {
@@ -142,7 +142,7 @@ rxfs_storeMemRead(void *r, struct osi_file *tfile, afs_uint32 offset,
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeMemWrite(void *r, afs_uint32 l, afs_uint32 *byteswritten)
 {
     afs_int32 code;
@@ -159,7 +159,7 @@ rxfs_storeMemWrite(void *r, afs_uint32 l, afs_uint32 *byteswritten)
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeUfsWrite(void *r, afs_uint32 l, afs_uint32 *byteswritten)
 {
     afs_int32 code;
@@ -179,7 +179,7 @@ rxfs_storeUfsWrite(void *r, afs_uint32 l, afs_uint32 *byteswritten)
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storePadd(void *rock, afs_uint32 size)
 {
     afs_int32 code = 0;
@@ -203,7 +203,7 @@ rxfs_storePadd(void *rock, afs_uint32 size)
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeStatus(void *rock)
 {
     struct rxfs_storeVariables *v = (struct rxfs_storeVariables *)rock;
@@ -213,7 +213,7 @@ rxfs_storeStatus(void *rock)
     return 1;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeClose(void *r, struct AFSFetchStatus *OutStatus, int *doProcessFS)
 {
     afs_int32 code;
@@ -236,7 +236,7 @@ rxfs_storeClose(void *r, struct AFSFetchStatus *OutStatus, int *doProcessFS)
     return code;
 }
 
-afs_int32
+static afs_int32
 rxfs_storeDestroy(void **r, afs_int32 code)
 {
     struct rxfs_storeVariables *v = (struct rxfs_storeVariables *)*r;
@@ -255,7 +255,7 @@ rxfs_storeDestroy(void **r, afs_int32 code)
     return code;
 }
 
-afs_int32
+static afs_int32
 afs_GenericStoreProc(struct storeOps *ops, void *rock,
 		     struct dcache *tdc, int *shouldwake,
 		     afs_size_t *bytesXferred)
@@ -353,7 +353,7 @@ struct storeOps rxfs_storeMemOps = {
 #endif
 };
 
-afs_int32
+static afs_int32
 rxfs_storeInit(struct vcache *avc, struct afs_conn *tc,
                 struct rx_connection *rxconn, afs_size_t base,
 		afs_size_t bytes, afs_size_t length,
@@ -437,7 +437,7 @@ unsigned int storeallmissing = 0;
  * \param ops pointer to the block of storeOps to be used for this operation
  * \param rock pointer to the opaque protocol-specific data of this operation
  */
-afs_int32
+static afs_int32
 afs_CacheStoreDCaches(struct vcache *avc, struct dcache **dclist,
 		      afs_size_t bytes, afs_hyper_t *anewDV, int *doProcessFS,
 		      struct AFSFetchStatus *OutStatus, afs_uint32 nchunks,
@@ -564,7 +564,6 @@ afs_CacheStoreVCache(struct dcache **dcList, struct vcache *avc,
 		     afs_hyper_t *anewDV, afs_size_t *amaxStoredLength)
 {
     afs_int32 code = 0;
-    struct storeOps *ops;
     void * rock = NULL;
     unsigned int i, j;
 
@@ -619,7 +618,8 @@ afs_CacheStoreVCache(struct dcache **dcList, struct vcache *avc,
 		       ICL_HANDLE_OFFSET(length));
 
 	    do {
-	        tc = afs_Conn(&avc->f.fid, areq, 0, &rxconn);
+		struct storeOps *ops = NULL;
+		tc = afs_Conn(&avc->f.fid, areq, 0, &rxconn);
 
 #ifdef AFS_64BIT_CLIENT
 	      restart:
@@ -720,7 +720,7 @@ struct rxfs_fetchVariables {
     afs_int32 iovmax;
 };
 
-afs_int32
+static afs_int32
 rxfs_fetchUfsRead(void *r, afs_uint32 size, afs_uint32 *bytesread)
 {
     afs_int32 code;
@@ -738,7 +738,7 @@ rxfs_fetchUfsRead(void *r, afs_uint32 size, afs_uint32 *bytesread)
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_fetchMemRead(void *r, afs_uint32 tlen, afs_uint32 *bytesread)
 {
     afs_int32 code;
@@ -755,7 +755,7 @@ rxfs_fetchMemRead(void *r, afs_uint32 tlen, afs_uint32 *bytesread)
 }
 
 
-afs_int32
+static afs_int32
 rxfs_fetchMemWrite(void *r, struct osi_file *fP, afs_uint32 offset,
 		   afs_uint32 tlen, afs_uint32 *byteswritten)
 {
@@ -771,7 +771,7 @@ rxfs_fetchMemWrite(void *r, struct osi_file *fP, afs_uint32 offset,
     return 0;
 }
 
-afs_int32
+static afs_int32
 rxfs_fetchUfsWrite(void *r, struct osi_file *fP, afs_uint32 offset,
 		   afs_uint32 tlen, afs_uint32 *byteswritten)
 {
@@ -787,7 +787,7 @@ rxfs_fetchUfsWrite(void *r, struct osi_file *fP, afs_uint32 offset,
 }
 
 
-afs_int32
+static afs_int32
 rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
 		struct afs_FetchOutput *o)
 {
@@ -814,7 +814,7 @@ rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
     return code;
 }
 
-afs_int32
+static afs_int32
 rxfs_fetchDestroy(void **r, afs_int32 code)
 {
     struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)*r;
@@ -833,7 +833,7 @@ rxfs_fetchDestroy(void **r, afs_int32 code)
     return code;
 }
 
-afs_int32
+static afs_int32
 rxfs_fetchMore(void *r, afs_int32 *length, afs_uint32 *moredata)
 {
     afs_int32 code;
@@ -882,7 +882,7 @@ struct fetchOps rxfs_fetchMemOps = {
     rxfs_fetchDestroy
 };
 
-afs_int32
+static afs_int32
 rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
                struct vcache *avc, afs_offs_t base,
 	       afs_uint32 size, afs_int32 *alength, struct dcache *adc,
diff --git a/src/afs/afs_icl.c b/src/afs/afs_icl.c
index 8d09113dcb..08a1660206 100644
--- a/src/afs/afs_icl.c
+++ b/src/afs/afs_icl.c
@@ -34,7 +34,7 @@ int afs_icl_sizeofLong = ICL_LONG;
 int afs_icl_inited = 0;
 
 /* init function, called once, under afs_icl_lock */
-int
+static int
 afs_icl_Init(void)
 {
     afs_icl_inited = 1;
@@ -538,20 +538,8 @@ afs_icl_AppendString(struct afs_icl_log *logp, char *astr)
 #define ICL_APPENDLONG(lp, x) ICL_APPENDINT32((lp), (x))
 #endif
 
-/* routine to tell whether we're dealing with the address or the
- * object itself
- */
-int
-afs_icl_UseAddr(int type)
-{
-    if (type == ICL_TYPE_HYPER || type == ICL_TYPE_STRING
-	|| type == ICL_TYPE_FID || type == ICL_TYPE_INT64)
-	return 1;
-    else
-	return 0;
-}
 
-void
+static void
 afs_icl_AppendOne(struct afs_icl_log *logp, int type, long parm)
 {
     if (type) {
@@ -884,19 +872,6 @@ afs_icl_CopyOut(struct afs_icl_log *logp, afs_int32 * bufferp,
     return code;
 }
 
-/* return basic parameter information about a log */
-int
-afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
-		    afs_int32 * curSizep)
-{
-    ObtainReadLock(&logp->lock);
-    *maxSizep = logp->logSize;
-    *curSizep = logp->logElements;
-    ReleaseReadLock(&logp->lock);
-    return 0;
-}
-
-
 /* hold and release logs */
 int
 afs_icl_LogHold(struct afs_icl_log *logp)
@@ -907,14 +882,6 @@ afs_icl_LogHold(struct afs_icl_log *logp)
     return 0;
 }
 
-/* hold and release logs, called with lock already held */
-int
-afs_icl_LogHoldNL(struct afs_icl_log *logp)
-{
-    logp->refCount++;
-    return 0;
-}
-
 /* keep track of how many sets believe the log itself is allocated */
 int
 afs_icl_LogUse(struct afs_icl_log *logp)
@@ -1070,32 +1037,6 @@ afs_icl_FindLog(char *name)
     return tp;
 }
 
-int
-afs_icl_EnumerateLogs(int (*aproc)
-		        (char *name, char *arock, struct afs_icl_log * tp),
-		      char *arock)
-{
-    struct afs_icl_log *tp;
-    afs_int32 code;
-
-    code = 0;
-    ObtainWriteLock(&afs_icl_lock, 195);
-    for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
-	tp->refCount++;		/* hold this guy */
-	ReleaseWriteLock(&afs_icl_lock);
-	ObtainReadLock(&tp->lock);
-	code = (*aproc) (tp->name, arock, tp);
-	ReleaseReadLock(&tp->lock);
-	ObtainWriteLock(&afs_icl_lock, 196);
-	if (--tp->refCount == 0)
-	    afs_icl_ZapLog(tp);
-	if (code)
-	    break;
-    }
-    ReleaseWriteLock(&afs_icl_lock);
-    return code;
-}
-
 struct afs_icl_set *afs_icl_allSets = 0;
 
 int
@@ -1198,46 +1139,6 @@ afs_icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
     return 0;
 }
 
-/* function to change event enabling information for a particular set */
-int
-afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
-{
-    char *tp;
-
-    ObtainWriteLock(&setp->lock, 200);
-    if (!ICL_EVENTOK(setp, eventID)) {
-	ReleaseWriteLock(&setp->lock);
-	return -1;
-    }
-    tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
-    if (setValue)
-	*tp |= ICL_EVENTMASK(eventID);
-    else
-	*tp &= ~(ICL_EVENTMASK(eventID));
-    ReleaseWriteLock(&setp->lock);
-    return 0;
-}
-
-/* return indication of whether a particular event ID is enabled
- * for tracing.  If *getValuep is set to 0, the event is disabled,
- * otherwise it is enabled.  All events start out enabled by default.
- */
-int
-afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
-{
-    ObtainReadLock(&setp->lock);
-    if (!ICL_EVENTOK(setp, eventID)) {
-	ReleaseWriteLock(&setp->lock);
-	return -1;
-    }
-    if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
-	*getValuep = 1;
-    else
-	*getValuep = 0;
-    ReleaseReadLock(&setp->lock);
-    return 0;
-}
-
 /* hold and release event sets */
 int
 afs_icl_SetHold(struct afs_icl_set *setp)
@@ -1340,54 +1241,6 @@ afs_icl_ZeroSet(struct afs_icl_set *setp)
     return code;
 }
 
-int
-afs_icl_EnumerateSets(int (*aproc)
-		        (char *name, char *arock, struct afs_icl_log * tp),
-		      char *arock)
-{
-    struct afs_icl_set *tp, *np;
-    afs_int32 code;
-
-    code = 0;
-    ObtainWriteLock(&afs_icl_lock, 205);
-    for (tp = afs_icl_allSets; tp; tp = np) {
-	tp->refCount++;		/* hold this guy */
-	ReleaseWriteLock(&afs_icl_lock);
-	code = (*aproc) (tp->name, arock, (struct afs_icl_log *)tp);
-	ObtainWriteLock(&afs_icl_lock, 206);
-	np = tp->nextp;		/* tp may disappear next, but not np */
-	if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
-	    afs_icl_ZapSet(tp);
-	if (code)
-	    break;
-    }
-    ReleaseWriteLock(&afs_icl_lock);
-    return code;
-}
-
-int
-afs_icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
-{
-    int i;
-    int code = -1;
-
-    ObtainWriteLock(&setp->lock, 207);
-    for (i = 0; i < ICL_LOGSPERSET; i++) {
-	if (!setp->logs[i]) {
-	    setp->logs[i] = newlogp;
-	    code = i;
-	    afs_icl_LogHold(newlogp);
-	    if (!(setp->states & ICL_SETF_FREED)) {
-		/* bump up the number of sets using the log */
-		afs_icl_LogUse(newlogp);
-	    }
-	    break;
-	}
-    }
-    ReleaseWriteLock(&setp->lock);
-    return code;
-}
-
 int
 afs_icl_SetSetStat(struct afs_icl_set *setp, int op)
 {
diff --git a/src/afs/afs_memcache.c b/src/afs/afs_memcache.c
index 936cbe927e..419083da27 100644
--- a/src/afs/afs_memcache.c
+++ b/src/afs/afs_memcache.c
@@ -302,16 +302,6 @@ afs_MemCacheTruncate(struct osi_file *fP, int size)
     return 0;
 }
 
-int
-afs_MemExtendEntry(struct memCacheEntry *mceP, afs_uint32 size)
-{
-    int code = 0;
-    ObtainWriteLock(&mceP->afs_memLock, 560);
-    code = _afs_MemExtendEntry(mceP, size);
-    ReleaseWriteLock(&mceP->afs_memLock);
-    return code;
-}
-
 void
 shutdown_memcache(void)
 {
diff --git a/src/afs/afs_nfsclnt.c b/src/afs/afs_nfsclnt.c
index fbb5006cea..4c7806d244 100644
--- a/src/afs/afs_nfsclnt.c
+++ b/src/afs/afs_nfsclnt.c
@@ -160,7 +160,6 @@ afs_nfsclient_init(void)
     osi_Assert(ISAFS_GLOCK());
 #endif
     if (!init_nfsexporter) {
-	extern struct afs_exporter *exporter_add();
 
 	init_nfsexporter = 1;
 	LOCK_INIT(&afs_xnfspag, "afs_xnfspag");
diff --git a/src/afs/afs_osi.c b/src/afs/afs_osi.c
index 18732d1a35..e8f852e2e4 100644
--- a/src/afs/afs_osi.c
+++ b/src/afs/afs_osi.c
@@ -25,11 +25,6 @@
  *     -- On HP called from afsc_link.
  *     -- On SGI called from afs_init. */
 
-/* No hckernel-specific header for this prototype. */
-#ifndef UKERNEL
-extern void init_hckernel_mutex(void);
-#endif
-
 afs_lock_t afs_ftf;		/* flush text lock */
 
 #ifdef AFS_SGI_ENV
@@ -152,14 +147,6 @@ afs_osi_MaskUserLoop(void)
 #endif
 }
 
-void
-afs_osi_UnmaskUserLoop(void)
-{
-#ifdef AFS_DARWIN_ENV
-    afs_osi_fullSigRestore();
-#endif
-}
-
 /* register rxk listener proc info */
 void
 afs_osi_RxkRegister(void)
diff --git a/src/afs/afs_osi.h b/src/afs/afs_osi.h
index 79c44a985e..e3f0e0ccb2 100644
--- a/src/afs/afs_osi.h
+++ b/src/afs/afs_osi.h
@@ -458,4 +458,9 @@ extern int osi_ShouldDeferRemunlink(struct vcache *avc);
 # define osi_ShouldDeferRemunlink(avc) 0
 #endif
 
+/* No hckernel-specific header for this prototype. */
+#ifndef UKERNEL
+extern void init_hckernel_mutex(void);
+#endif
+
 #endif /* _AFS_OSI_ */
diff --git a/src/afs/afs_pag_cred.c b/src/afs/afs_pag_cred.c
index 3dce8543be..e77cf8ae36 100644
--- a/src/afs/afs_pag_cred.c
+++ b/src/afs/afs_pag_cred.c
@@ -32,7 +32,7 @@ static struct afspag_cell *cells = 0;
 static struct afspag_cell *primary_cell = 0;
 
 
-struct afspag_cell *
+static struct afspag_cell *
 afspag_GetCell(char *acell)
 {
     struct afspag_cell *tcell;
@@ -66,7 +66,7 @@ out:
 }
 
 
-struct afspag_cell *
+static struct afspag_cell *
 afspag_GetPrimaryCell(void)
 {
     struct afspag_cell *tcell;
diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c
index 9182a4b52f..7ddb5add29 100644
--- a/src/afs/afs_pioctl.c
+++ b/src/afs/afs_pioctl.c
@@ -1426,12 +1426,6 @@ DECL_PIOCTL(PGetFID)
  *
  * \post Changed ACL, via direct writing to the wire
  */
-int
-dummy_PSetAcl(char *ain, char *aout)
-{
-    return 0;
-}
-
 DECL_PIOCTL(PSetAcl)
 {
     afs_int32 code;
diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
index e9a655e65d..2ca80a563c 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -26,6 +26,7 @@ extern void afs_FreeAllAxs(struct axscache **headp);
 extern void shutdown_xscache(void);
 
 /* afs_buffer.c */
+extern void DFlushDCache(struct dcache *);
 extern void shutdown_bufferpackage(void);
 
 /* afs_call.c */
@@ -64,52 +65,8 @@ extern unsigned int lastCallBack_dv;
 extern osi_timeval32_t lastCallBack_time;
 extern struct interfaceAddr afs_cb_interface;
 
-extern int afs_RXCallBackServer(void);
-extern int SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
-			  struct AFSDBCacheEntry *a_result);
-extern int SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
-			    struct AFSDBCacheEntry64 *a_result);
-extern int SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
-			    struct AFSDBLock *a_result);
-extern int SRXAFSCB_CallBack(struct rx_call *a_call,
-			     struct AFSCBFids *a_fids,
-			     struct AFSCBs *a_callbacks);
-extern int SRXAFSCB_Probe(struct rx_call *a_call);
-extern int SRXAFSCB_InitCallBackState(struct rx_call *a_call);
-extern int SRXAFSCB_XStatsVersion(struct rx_call *a_call,
-				  afs_int32 * a_versionP);
-extern int SRXAFSCB_GetXStats(struct rx_call *a_call,
-			      afs_int32 a_clientVersionNum,
-			      afs_int32 a_collectionNumber,
-			      afs_int32 * a_srvVersionNumP,
-			      afs_int32 * a_timeP, AFSCB_CollData * a_dataP);
 extern int afs_RXCallBackServer(void);
 extern int shutdown_CB(void);
-extern int SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
-				       struct interfaceAddr *addr);
-extern int SRXAFSCB_WhoAreYou(struct rx_call *a_call,
-			      struct interfaceAddr *addr);
-extern int SRXAFSCB_InitCallBackState3(struct rx_call *a_call,
-				       afsUUID * a_uuid);
-extern int SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid);
-extern int SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
-				   afs_int32 * a_srvr_addr,
-				   afs_int32 * a_srvr_rank);
-extern int SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
-				  char **a_name, serverList * a_hosts);
-extern int SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name);
-extern int SRXAFSCB_GetCacheConfig(struct rx_call *a_call,
-				   afs_uint32 callerVersion,
-				   afs_uint32 * serverVersion,
-				   afs_uint32 * configCount,
-				   cacheConfig * config);
-extern int SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid,
-			      afs_int32 Fd, afs_int64 Position,
-			      afs_int64 Length, afs_int64 * TotalLength);
-extern int SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid,
-			      afs_int32 Fd, afs_int64 Position,
-			      afs_int64 Length, afs_int64 * TotalLength);
-
 
 /* afs_cbqueue.c */
 extern afs_rwlock_t afs_xcbhash;
@@ -338,6 +295,8 @@ extern void init_sys_error_to_et(void);
 
 /* afs_exporter.c */
 extern struct afs_exporter *root_exported;
+extern struct afs_exporter * exporter_add(afs_int32 size, struct exporterops *ops,
+					  afs_int32 state, afs_int32 type, char *data);
 extern struct afs_exporter *exporter_find(int type);
 extern void shutdown_exporter(void);
 
@@ -364,10 +323,7 @@ extern int afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize,
 extern int afs_icl_CopyOut(struct afs_icl_log *logp,
 			   afs_int32 * bufferp, afs_int32 * bufSizep,
 			   afs_uint32 * cookiep, afs_int32 * flagsp);
-extern int afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
-			       afs_int32 * curSizep);
 extern int afs_icl_LogHold(struct afs_icl_log *logp);
-extern int afs_icl_LogHoldNL(struct afs_icl_log *logp);
 extern int afs_icl_LogUse(struct afs_icl_log *logp);
 extern int afs_icl_LogFreeUse(struct afs_icl_log *logp);
 extern int afs_icl_LogSetSize(struct afs_icl_log *logp,
@@ -378,11 +334,6 @@ extern int afs_icl_LogReleNL(struct afs_icl_log *logp);
 extern int afs_icl_ZeroLog(struct afs_icl_log *logp);
 extern int afs_icl_LogFree(struct afs_icl_log *logp);
 extern struct afs_icl_log *afs_icl_FindLog(char *name);
-extern int
-  afs_icl_EnumerateLogs(int (*aproc)
-
-			  (char *name, char *arock, struct afs_icl_log * tp),
-			char *arock);
 extern int afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
 			     struct afs_icl_log *fatalLogp,
 			     struct afs_icl_set **outSetpp);
@@ -391,18 +342,7 @@ extern int afs_icl_CreateSetWithFlags(char *name,
 				      struct afs_icl_log *fatalLogp,
 				      afs_uint32 flags,
 				      struct afs_icl_set **outSetpp);
-extern int afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID,
-			     int setValue);
-extern int afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID,
-			     int *getValuep);
 extern int afs_icl_ZeroSet(struct afs_icl_set *setp);
-extern int
-  afs_icl_EnumerateSets(int (*aproc)
-
-			  (char *name, char *arock, struct afs_icl_log * tp),
-			char *arock);
-extern int afs_icl_AddLogToSet(struct afs_icl_set *setp,
-			       struct afs_icl_log *newlogp);
 extern int afs_icl_SetSetStat(struct afs_icl_set *setp, int op);
 extern int afs_icl_SetHold(struct afs_icl_set *setp);
 extern int afs_icl_ZapSet(struct afs_icl_set *setp);
@@ -836,6 +776,23 @@ extern int afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg,
 extern int HandleIoctl(struct vcache *avc, afs_int32 acom,
 		       struct afs_ioctl *adata);
 
+#if defined(AFS_SUN5_ENV)
+struct afs_ioctl_sys;
+extern int afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp);
+#elif defined(AFS_LINUX_ENV)
+extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com, unsigned long arg);
+#elif defined(AFS_DAWRIN_ENV) & !defined(AFS_DARWIN80)
+extern int afs_xioctl(afs_proc_t *p, struct ioctl_args *uap, register_t *retval);
+#elif defined(AFS_FBSD_ENV)
+extern int afs_xioctl(struct thread *td, struct ioctl_args *uap, register_t *retval);
+#elif defined(AFS_NBSD_ENV)
+extern int afs_xioctl(afs_proc_t *p, const struct sys_ioctl_args *uap, register_t *retval);
+#elif defined(AFS_XBSD_ENV)
+extern int afs_xioctl(afs_proc_t *p, const struct ioctl_args *uap, register_t *retval);
+#elif defined(UKERNEL)
+extern int afs_xioctl(void);
+#endif
+
 
 /* afs_segments.c */
 extern int afs_StoreAllSegments(struct vcache *avc,
@@ -949,6 +906,10 @@ extern int afs3_syscall(afs_proc_t *p, void *args, long *retval);
 extern int Afs_syscall(void);
 #endif
 
+#if defined(AFS_LINUX_ENV)
+extern asmlinkage long afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
+#endif
+
 /* afs_tokens.c */
 struct ktc_tokenUnion;
 struct ktc_setTokenData;
@@ -1318,6 +1279,7 @@ extern void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
 
 /* VNOPS/afs_vnop_readdir.c */
 extern int afs_rd_stash_i;
+extern int BlobScan(struct dcache * afile, afs_int32 ablob, int *ablobOut);
 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 extern int afs_readdir(OSI_VC_DECL(avc), struct uio *auio,
 		       afs_ucred_t *acred, int *eofp);
diff --git a/src/afs/afs_server.c b/src/afs/afs_server.c
index 3674eff438..9d2d93cde0 100644
--- a/src/afs/afs_server.c
+++ b/src/afs/afs_server.c
@@ -556,7 +556,7 @@ CkSrv_MarkUpDown(struct afs_conn **conns, struct rx_connection **rxconns,
     }
 }
 
-void
+static void
 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
 	      struct afs_conn **conns)
 {
diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c
index e72b45ea42..f500b65a3d 100644
--- a/src/afs/afs_vcache.c
+++ b/src/afs/afs_vcache.c
@@ -727,7 +727,7 @@ afs_FlushReclaimedVcaches(void)
 #endif
 }
 
-void
+static void
 afs_PostPopulateVCache(struct vcache *avc, struct VenusFid *afid, int seq)
 {
     /*
diff --git a/src/cf/linux-kernel-assorted.m4 b/src/cf/linux-kernel-assorted.m4
index 49827d5be9..aea7b2bd73 100644
--- a/src/cf/linux-kernel-assorted.m4
+++ b/src/cf/linux-kernel-assorted.m4
@@ -59,6 +59,7 @@ LINUX_D_INVALIDATE_IS_VOID
 LINUX_KERNEL_READ_OFFSET_IS_LAST
 LINUX_KEYRING_SEARCH_TAKES_RECURSE
 LINUX_GENERIC_FILLATTR_TAKES_REQUEST_MASK
+LINUX_FILE_LOCK_CORE
 ])
 
 
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 7f3000fc16..6f9d350227 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -252,6 +252,17 @@ AC_CHECK_LINUX_FUNC([inode_atime_mtime_accessors],
 		    [inode_set_atime(NULL, 0, 0);
 		     inode_set_mtime(NULL, 0, 0);])
 
+dnl Linux 6.8 removed the strlcpy() function.  We test to see if we can redefine
+dnl a strlcpy() function.  We use a totally different function signature to
+dnl to ensure that this fails when the kernel does provide strlcpy().
+AC_CHECK_LINUX_FUNC([no_strlcpy],
+		    [[#include <linux/string.h>
+		     size_t strlcpy(char *d);
+		     size_t strlcpy(char *d) { return strlen(d); }]],
+		    [[static char buff[10];
+		     size_t s;
+		     s = strlcpy(buff);]])
+
 dnl Consequences - things which get set as a result of the
 dnl                above tests
 AS_IF([test "x$ac_cv_linux_func_d_alloc_anon" = "xno"],
diff --git a/src/cf/linux-kernel-struct.m4 b/src/cf/linux-kernel-struct.m4
index 2824ec1986..5cd346fb52 100644
--- a/src/cf/linux-kernel-struct.m4
+++ b/src/cf/linux-kernel-struct.m4
@@ -17,6 +17,9 @@ AC_CHECK_LINUX_STRUCT([dentry], [d_u.d_alias], [dcache.h])
 dnl linux 2.6.16 moved dentry->d_child to dentry->d_u.d_child
 dnl linux 3.19 moved it back to dentry->d_child
 AC_CHECK_LINUX_STRUCT([dentry], [d_u.d_child], [dcache.h])
+dnl linux 6.8 uses hlist for dentry children and renamed
+dnl d_subdirs/d_child to d_childern/d_sib
+AC_CHECK_LINUX_STRUCT([dentry], [d_children], [dcache.h])
 AC_CHECK_LINUX_STRUCT([dentry_operations], [d_automount], [dcache.h])
 AC_CHECK_LINUX_STRUCT([group_info], [gid], [cred.h])
 AC_CHECK_LINUX_STRUCT([inode], [i_alloc_sem], [fs.h])
diff --git a/src/cf/linux-test1.m4 b/src/cf/linux-test1.m4
index 7bb5a677c2..010a4464f2 100644
--- a/src/cf/linux-test1.m4
+++ b/src/cf/linux-test1.m4
@@ -16,7 +16,7 @@ _ACEOF
 /* end confdefs.h */
 #include <linux/module.h>
 $1
-
+void conftest(void);
 void conftest(void)
 { 
 $2
@@ -201,7 +201,7 @@ AC_DEFUN([AC_CHECK_LINUX_OPERATION],
      CPPFLAGS="$CPPFLAGS -Werror"
      AC_TRY_KBUILD(
       [$4
-       $5 op($6) { return ($5)0; };],
+       static $5 op($6) { return ($5)0; };],
       [static struct $1 ops;  ops.$2 = op;],
 		   AS_VAR_SET([ac_linux_operation], [yes]),
 		   AS_VAR_SET([ac_linux_operation], [no]))
diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4
index 3596b6aad0..b22930690e 100644
--- a/src/cf/linux-test4.m4
+++ b/src/cf/linux-test4.m4
@@ -400,9 +400,9 @@ AC_DEFUN([LINUX_INIT_WORK_HAS_DATA], [
   AC_CHECK_LINUX_BUILD([whether INIT_WORK has a _data argument],
 		       [ac_cv_linux_init_work_has_data],
 [#include <linux/kernel.h>
-#include <linux/workqueue.h>],
-[ 
-void f(struct work_struct *w) {}
+#include <linux/workqueue.h>
+static void f(struct work_struct *w) {}],
+[
 struct work_struct *w;
 int *i;
 INIT_WORK(w,f,i);],
@@ -493,7 +493,7 @@ AC_DEFUN([LINUX_KMEM_CACHE_CREATE_CTOR_TAKES_VOID],[
   AC_CHECK_LINUX_BUILD([whether kmem_cache_create constructor takes a void pointer],
 			[ac_cv_linux_kmem_cache_create_ctor_takes_void],
 			[#include <linux/slab.h>
-			 void _ctor(void *v) { };],
+			 static void _ctor(void *v) { };],
 			[kmem_cache_create(NULL, 0, 0, 0, _ctor);],
 			[KMEM_CACHE_CTOR_TAKES_VOID],
 			[define if kmem_cache_create constructor takes a single void ptr],
@@ -667,7 +667,7 @@ AC_DEFUN([LINUX_IOP_GETATTR_TAKES_PATH_STRUCT], [
   AC_CHECK_LINUX_BUILD([whether 4.11+ inode.i_op->getattr takes a struct path argument],
                         [ac_cv_linux_iop_getattr_takes_path_struct],
                         [#include <linux/fs.h>
-                        int _getattr(const struct path *path, struct kstat *stat, u32 request_mask,
+                        static int _getattr(const struct path *path, struct kstat *stat, u32 request_mask,
                           unsigned int sync_mode) {return 0;};
                         struct inode_operations _i_ops;],
                         [_i_ops.getattr = _getattr;],
@@ -692,10 +692,10 @@ AC_DEFUN([LINUX_IOP_MKDIR_TAKES_UMODE_T], [
 AC_DEFUN([LINUX_IOP_CREATE_TAKES_UMODE_T], [
   AC_CHECK_LINUX_BUILD([whether inode.i_op->create takes a umode_t argument],
 			[ac_cv_linux_iop_create_takes_umode_t],
-			[#include <linux/fs.h>],
+			[#include <linux/fs.h>
+			 static int _create(struct inode *i, struct dentry *d, umode_t m, struct nameidata *n)
+			 {return 0;};],
 			[static struct inode_operations _i_ops;
-			int _create(struct inode *i, struct dentry *d, umode_t m, struct nameidata *n)
-				{return 0;};
 			_i_ops.create = _create;],
 			[IOP_CREATE_TAKES_UMODE_T],
 			[define if inode.i_op->create takes a umode_t argument],
@@ -867,3 +867,21 @@ AC_DEFUN([LINUX_GENERIC_FILLATTR_TAKES_REQUEST_MASK], [
                        [define if your generic_fillattr has the request_mask_parameter],
                        [])
 ])
+
+dnl linux 6.9 moved and renamed fl_type, fl_pid  and fl_flags
+dnl from file_lock into a new structure file_lock_core.  Check for these as a
+dnl single test
+AC_DEFUN([LINUX_FILE_LOCK_CORE], [
+  AC_CHECK_LINUX_BUILD([whether fl_type fl_pid and fl_flags are in structure file_lock_core],
+                       [ac_cv_linux_file_lock_core],
+                       [#include <linux/filelock.h>],
+                       [
+                       static struct file_lock flock;
+                       flock.c.flc_type = 0;
+                       flock.c.flc_pid = 0;
+                       flock.c.flc_flags = 0;
+                       ],
+                       [HAVE_FILE_LOCK_CORE],
+                       [define if file_lock_core exists],
+                       [])
+])
diff --git a/src/config/NTMakefile.amd64_w2k b/src/config/NTMakefile.amd64_w2k
index d732ecc3a9..161ef011e8 100644
--- a/src/config/NTMakefile.amd64_w2k
+++ b/src/config/NTMakefile.amd64_w2k
@@ -88,7 +88,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1101
+AFSPRODUCT_VER_PATCH=1200
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/config/NTMakefile.i386_nt40 b/src/config/NTMakefile.i386_nt40
index 81e0968b93..54f9341e6b 100644
--- a/src/config/NTMakefile.i386_nt40
+++ b/src/config/NTMakefile.i386_nt40
@@ -88,7 +88,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1101
+AFSPRODUCT_VER_PATCH=1200
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/config/NTMakefile.i386_w2k b/src/config/NTMakefile.i386_w2k
index c7232094b9..d2632a10dc 100644
--- a/src/config/NTMakefile.i386_w2k
+++ b/src/config/NTMakefile.i386_w2k
@@ -92,7 +92,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1101
+AFSPRODUCT_VER_PATCH=1200
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/crypto/hcrypto/kernel/roken.h b/src/crypto/hcrypto/kernel/roken.h
index e69de29bb2..6cb0601313 100644
--- a/src/crypto/hcrypto/kernel/roken.h
+++ b/src/crypto/hcrypto/kernel/roken.h
@@ -0,0 +1,46 @@
+#ifndef OPENAFS_HCRYPTO_KERNEL_ROKEN_H
+#define OPENAFS_HCRYPTO_KERNEL_ROKEN_H
+
+/*
+ * This is a stub roken.h used for building roken code (or roken-using code) in
+ * the kernel. For userspace code, use a real roken.h. This just contains a few
+ * prototypes of roken functions we actually use in kernel code.
+ */
+
+#ifndef KERNEL
+# error "This header is for kernel code only"
+#endif
+
+/*
+ * The following function annotations are not needed when building for kernel
+ * space
+ */
+#define ROKEN_LIB_FUNCTION
+#define ROKEN_LIB_CALL
+#define ROKEN_LIB_VARIABLE
+
+/*
+ * Our HAVE_STRLCPY from autoconf refers to whether strlcpy() is available in
+ * userspace. Whether it's available in the kernel is another question, so
+ * override HAVE_STRLCPY here. Usually it is available (only a few cases lack
+ * it), so turn it on by default, and turn it off for a few cases below.
+ */
+#undef HAVE_STRLCPY
+#define HAVE_STRLCPY 1
+
+#ifdef AFS_AIX_ENV
+# undef HAVE_STRLCPY
+#elif defined(AFS_LINUX_ENV) && defined(HAVE_LINUX_NO_STRLCPY)
+# undef HAVE_STRLCPY
+#endif
+
+/* strlcpy.c */
+#if defined (AFS_LINUX_ENV) && !defined(HAVE_STRLCPY)
+# define strlcpy rk_strlcpy
+ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL strlcpy (char *, const char *, size_t);
+#endif
+
+/* ct.c */
+int ct_memcmp(const void *p1, const void *p2, size_t len);
+
+#endif /* OPENAFS_HCRYPTO_KERNEL_ROKEN_H */
diff --git a/src/crypto/rfc3961/krb5_locl.h b/src/crypto/rfc3961/krb5_locl.h
index eb279a95ff..04292eefaf 100644
--- a/src/crypto/rfc3961/krb5_locl.h
+++ b/src/crypto/rfc3961/krb5_locl.h
@@ -5,6 +5,7 @@
 #ifdef KERNEL
 
 #include "config.h"
+#include <roken.h>
 
 #else
 #include <afsconfig.h>
@@ -285,11 +286,138 @@ int copy_EncryptionKey(const krb5_keyblock *, krb5_keyblock *);
 krb5_error_code krb5_enctype_to_string(krb5_context context,
 				       krb5_enctype etype,
 				       char **string);
-#ifdef KERNEL
-/* Roken provides this in userspace, but we're on our own in the kernel. */
-int ct_memcmp(const void *p1, const void *p2, size_t len);
-#endif
 
+/*
+ * Unused prototypes from heimdal/krb5.  These are functions that are not used
+ * outside of their compilation unit at all, but we may need to declare them to
+ * avoid compiler warnings.
+ */
+struct _krb5_key_data;
+struct _krb5_encryption_type;
+/* heimdal/krb5/crypto.c */
+KRB5_LIB_FUNCTION krb5_error_code _krb5_derive_key(krb5_context context,
+						   struct _krb5_encryption_type *et,
+						   struct _krb5_key_data *key,
+						   const void *constant,
+						   size_t len);
+KRB5_LIB_FUNCTION krb5_error_code krb5_allow_weak_crypto(krb5_context context,
+							 krb5_boolean enable);
+KRB5_LIB_FUNCTION krb5_error_code krb5_checksum_disable(krb5_context context,
+							krb5_cksumtype type);
+KRB5_LIB_FUNCTION krb5_boolean krb5_checksum_is_keyed(krb5_context context,
+						      krb5_cksumtype type);
+KRB5_LIB_FUNCTION krb5_error_code krb5_cksumtype_valid(krb5_context context,
+						       krb5_cksumtype ctype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_create_checksum_iov(krb5_context context,
+							   krb5_crypto crypto,
+							   unsigned usage,
+							   krb5_crypto_iov *data,
+							   unsigned int num_data,
+							   krb5_cksumtype *type);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_getblocksize(krb5_context context,
+							   krb5_crypto crypto,
+							   size_t *blocksize);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_getenctype(krb5_context context,
+							 krb5_crypto crypto,
+							 krb5_enctype *enctype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_getpadsize(krb5_context context,
+							 krb5_crypto crypto,
+							 size_t *padsize);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_length(krb5_context context,
+						     krb5_crypto crypto,
+						     int type,
+						     size_t *len);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_length_iov(krb5_context context,
+							 krb5_crypto crypto,
+							 krb5_crypto_iov *data,
+							 unsigned int num_data);
+KRB5_LIB_FUNCTION krb5_error_code krb5_decrypt_iov_ivec(krb5_context context,
+							krb5_crypto crypto,
+							unsigned usage,
+							krb5_crypto_iov *data,
+							unsigned int num_data,
+							void *ivec);
+KRB5_LIB_FUNCTION krb5_error_code krb5_decrypt_ivec(krb5_context context,
+						    krb5_crypto crypto,
+						    unsigned usage,
+						    void *data,
+						    size_t len,
+						    krb5_data *result,
+						    void *ivec);
+KRB5_LIB_FUNCTION krb5_error_code krb5_encrypt_iov_ivec(krb5_context context,
+							krb5_crypto crypto,
+							unsigned usage,
+							krb5_crypto_iov *data,
+							int num_data,
+							void *ivec);
+KRB5_LIB_FUNCTION krb5_error_code krb5_encrypt_ivec(krb5_context context,
+						    krb5_crypto crypto,
+						    unsigned usage,
+						    const void *data,
+						    size_t len,
+						    krb5_data *result,
+						    void *ivec);
+KRB5_LIB_FUNCTION krb5_error_code krb5_enctype_disable(krb5_context context,
+						       krb5_enctype enctype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_enctype_enable(krb5_context context,
+						      krb5_enctype enctype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_enctype_to_keytype(krb5_context context,
+							  krb5_enctype etype,
+							  krb5_keytype *keytype);
+KRB5_LIB_FUNCTION size_t krb5_get_wrapped_length (krb5_context context,
+						  krb5_crypto  crypto,
+						  size_t       data_len);
+KRB5_LIB_FUNCTION krb5_error_code krb5_hmac(krb5_context context,
+					    krb5_cksumtype cktype,
+					    const void *data,
+					    size_t len,
+					    unsigned usage,
+					    krb5_keyblock *key,
+					    Checksum *result);
+KRB5_LIB_FUNCTION krb5_boolean krb5_is_enctype_weak(krb5_context context,
+						    krb5_enctype enctype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_string_to_enctype(krb5_context context,
+							 const char *string,
+							 krb5_enctype *etype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_verify_checksum_iov(krb5_context context,
+							   krb5_crypto crypto,
+							   unsigned usage,
+							   krb5_crypto_iov *data,
+							   unsigned int num_data,
+							   krb5_cksumtype *type);
+KRB5_LIB_FUNCTION krb5_error_code krb5_generate_random_keyblock(krb5_context context,
+								krb5_enctype type,
+								krb5_keyblock *key);
+KRB5_LIB_FUNCTION krb5_boolean krb5_checksum_is_collision_proof(krb5_context context,
+								krb5_cksumtype type);
+
+KRB5_LIB_FUNCTION krb5_error_code krb5_cksumtype_to_enctype(krb5_context context,
+							    krb5_cksumtype ctype,
+							    krb5_enctype *etype);
+KRB5_LIB_FUNCTION krb5_error_code krb5_encrypt_EncryptedData(krb5_context context,
+							     krb5_crypto crypto,
+							     unsigned usage,
+							     void *data,
+							     size_t len,
+							     int kvno,
+							     EncryptedData *result);
+KRB5_LIB_FUNCTION krb5_error_code krb5_crypto_getconfoundersize(krb5_context context,
+								krb5_crypto crypto,
+								size_t *confoundersize);
+
+KRB5_LIB_FUNCTION krb5_error_code krb5_decrypt_EncryptedData(krb5_context context,
+							     krb5_crypto crypto,
+							     unsigned usage,
+							     const EncryptedData *e,
+							     krb5_data *result);
+/* heimdal/krb5/data.c */
+KRB5_LIB_FUNCTION krb5_error_code krb5_data_realloc(krb5_data *p, int len);
+KRB5_LIB_FUNCTION krb5_error_code krb5_copy_data(krb5_context context,
+						 const krb5_data *indata,
+						 krb5_data **outdata);
+KRB5_LIB_FUNCTION int krb5_data_cmp(const krb5_data *data1, const krb5_data *data2);
+/* heimdal/krb5/store-int.c */
+KRB5_LIB_FUNCTION krb5_ssize_t _krb5_get_int(void *buffer, unsigned long *value, size_t size);
 
 #include "crypto.h"
 
diff --git a/src/dir/dir.c b/src/dir/dir.c
index 364117fceb..1fb64a2e92 100644
--- a/src/dir/dir.c
+++ b/src/dir/dir.c
@@ -74,7 +74,7 @@ extern int DNew(struct dcache *adc, int page, struct DirBuffer *);
 
 /* Local static prototypes */
 static int FindBlobs(dir_file_t, int);
-static void AddPage(dir_file_t, int);
+static int AddPage(dir_file_t, int);
 static void FreeBlobs(dir_file_t, int, int);
 static int FindItem(dir_file_t, char *, struct DirBuffer *,
 		    struct DirBuffer *);
@@ -211,7 +211,15 @@ afs_dir_Delete(dir_file_t dir, char *entry)
     return 0;
 }
 
-/* Find a bunch of contiguous entries; at least nblobs in a row. */
+/*!
+ * Find a bunch of contiguous entries; at least nblobs in a row.
+ *
+ * \param dir	    pointer to the directory object
+ * \param nblobs    number of contiguous entries we need
+ *
+ * \return element number (directory entry) of the requested space
+ * \retval -1		failed to find 'nblobs' contiguous entries
+ */
 static int
 FindBlobs(dir_file_t dir, int nblobs)
 {
@@ -221,6 +229,7 @@ FindBlobs(dir_file_t dir, int nblobs)
     struct DirHeader *dhp;
     struct PageHeader *pp;
     int pgcount;
+    int code;
 
     /* read the dir header in first. */
     if (DRead(dir, 0, &headerbuf) != 0)
@@ -240,12 +249,16 @@ FindBlobs(dir_file_t dir, int nblobs)
 		}
 		if (i > pgcount - 1) {
 		    /* this page is bigger than last allocated page */
-		    AddPage(dir, i);
+		    code = AddPage(dir, i);
+		    if (code)
+			break;
 		    dhp->header.pgcount = htons(i + 1);
 		}
 	    } else if (dhp->alloMap[i] == EPP) {
 		/* Add the page to the directory. */
-		AddPage(dir, i);
+		code = AddPage(dir, i);
+		if (code)
+		    break;
 		dhp->alloMap[i] = EPP - 1;
 		dhp->header.pgcount = htons(i + 1);
 	    }
@@ -280,20 +293,32 @@ FindBlobs(dir_file_t dir, int nblobs)
 	    DRelease(&pagebuf, 0);	/* This dir page is unchanged. */
 	}
     }
-    /* If we make it here, the directory is full. */
+    /* If we make it here, the directory is full, or we encountered an I/O error. */
     DRelease(&headerbuf, 1);
     return -1;
 }
 
-static void
+/*!
+ * Add a page to a directory object.
+ *
+ * \param dir	    pointer to the directory object
+ * \param pageno    page number to add
+ *
+ * \retval 0	    succcess
+ * \retval non-zero return error from DNew
+ */
+static int
 AddPage(dir_file_t dir, int pageno)
 {				/* Add a page to a directory. */
     int i;
     struct PageHeader *pp;
     struct DirBuffer pagebuf;
+    int code;
 
     /* Get a new buffer labelled dir,pageno */
-    DNew(dir, pageno, &pagebuf);
+    code = DNew(dir, pageno, &pagebuf);
+    if (code)
+	return code;
     pp = (struct PageHeader *)pagebuf.data;
 
     pp->tag = htons(1234);
@@ -304,6 +329,7 @@ AddPage(dir_file_t dir, int pageno)
     for (i = 1; i < EPP / 8; i++)	/* It's a constant */
 	pp->freebitmap[i] = 0;
     DRelease(&pagebuf, 1);
+    return 0;
 }
 
 /* Free a whole bunch of directory entries. */
@@ -338,10 +364,17 @@ FreeBlobs(dir_file_t dir, int firstblob, int nblobs)
     DRelease(&pagehdbuf, 1);
 }
 
-/*
+/*!
  * Format an empty directory properly.  Note that the first 13 entries in a
  * directory header page are allocated, 1 to the page header, 4 to the
  * allocation map and 8 to the hash table.
+ *
+ * \param dir	    pointer to the directory object
+ * \param me	    fid (vnode+uniq) for new dir
+ * \param parent    fid (vnode+uniq) for parent dir
+ *
+ * \retval 0	    success
+ * \retval nonzero  error code
  */
 int
 afs_dir_MakeDir(dir_file_t dir, afs_int32 * me, afs_int32 * parent)
@@ -349,8 +382,11 @@ afs_dir_MakeDir(dir_file_t dir, afs_int32 * me, afs_int32 * parent)
     int i;
     struct DirBuffer buffer;
     struct DirHeader *dhp;
+    int code;
 
-    DNew(dir, 0, &buffer);
+    code = DNew(dir, 0, &buffer);
+    if (code)
+	return code;
     dhp = (struct DirHeader *)buffer.data;
 
     dhp->header.pgcount = htons(1);
@@ -366,8 +402,12 @@ afs_dir_MakeDir(dir_file_t dir, afs_int32 * me, afs_int32 * parent)
     for (i = 0; i < NHASHENT; i++)
 	dhp->hashTable[i] = 0;
     DRelease(&buffer, 1);
-    afs_dir_Create(dir, ".", me);
-    afs_dir_Create(dir, "..", parent);	/* Virtue is its own .. */
+    code = afs_dir_Create(dir, ".", me);
+    if (code)
+	return code;
+    code = afs_dir_Create(dir, "..", parent);
+    if (code)
+	return code;
     return 0;
 }
 
diff --git a/src/external/libafsdep b/src/external/libafsdep
index fb365df2da..9d36a30c09 100644
--- a/src/external/libafsdep
+++ b/src/external/libafsdep
@@ -24,3 +24,4 @@ heimdal/krb5/crypto-evp.c
 heimdal/krb5/keyblock.c
 heimdal/krb5/store-int.c
 heimdal/roken/ct.c
+heimdal/roken/strlcpy.c
\ No newline at end of file
diff --git a/src/fsint/afsint.xg b/src/fsint/afsint.xg
index 9fe4980c6c..cdcd07a293 100644
--- a/src/fsint/afsint.xg
+++ b/src/fsint/afsint.xg
@@ -664,6 +664,7 @@ FsCmd(
 ) = 220;
 
 #ifdef RPC_CLIENT
+%int RXAFS_ResidencyCmd(struct rx_connection *z_conn, AFSFid *Fid, struct FsCmdInputs *Inputs, struct FsCmdOutputs *Outputs);
 %int RXAFS_ResidencyCmd(struct rx_connection *z_conn, AFSFid *Fid, struct FsCmdInputs *Inputs, struct FsCmdOutputs *Outputs)
 %{
 %  return RXAFS_FsCmd(z_conn, Fid, Inputs, Outputs);
diff --git a/src/libafs/MakefileProto.LINUX.in b/src/libafs/MakefileProto.LINUX.in
index 8744ab8b61..6e62c8c97f 100644
--- a/src/libafs/MakefileProto.LINUX.in
+++ b/src/libafs/MakefileProto.LINUX.in
@@ -42,7 +42,8 @@ AFS_OS_OBJS = \
 	osi_ioctl.o \
 	osi_proc.o \
 	osi_vnodeops.o \
-	osi_pagecopy.o
+	osi_pagecopy.o \
+	strlcpy-kernel.o
 
 AFS_OS_PAGOBJS = \
 	osi_alloc.o \
@@ -59,7 +60,8 @@ AFS_OS_PAGOBJS = \
 	osi_flush.o \
 <all>
 	osi_ioctl.o \
-	osi_pag_module.o 
+	osi_pag_module.o \
+	strlcpy-kernel.o
 
 AFS_OS_NFSOBJS =
 
diff --git a/src/rx/rx.c b/src/rx/rx.c
index aaec609075..d6c52c369b 100644
--- a/src/rx/rx.c
+++ b/src/rx/rx.c
@@ -6513,7 +6513,7 @@ mtuout:
     return -1;
 }
 
-void
+static void
 rxi_NatKeepAliveEvent(struct rxevent *event, void *arg1,
 		      void *dummy, int dummy2)
 {
@@ -6615,7 +6615,7 @@ rx_SetConnSecondsUntilNatPing(struct rx_connection *conn, afs_int32 seconds)
  * declared dead; if nothing has been sent for a while, we send a
  * keep-alive packet (if we're actually trying to keep the call alive)
  */
-void
+static void
 rxi_KeepAliveEvent(struct rxevent *event, void *arg1, void *dummy,
 		   int dummy2)
 {
@@ -6656,7 +6656,7 @@ rxi_KeepAliveEvent(struct rxevent *event, void *arg1, void *dummy,
 }
 
 /* Does what's on the nameplate. */
-void
+static void
 rxi_GrowMTUEvent(struct rxevent *event, void *arg1, void *dummy, int dummy2)
 {
     struct rx_call *call = arg1;
@@ -8266,7 +8266,7 @@ static int rxi_monitor_processStats = 0;
 static int rxi_monitor_peerStats = 0;
 
 
-void
+static void
 rxi_ClearRPCOpStat(rx_function_entry_v1_p rpc_stat)
 {
     rpc_stat->invocations = 0;
diff --git a/src/rx/rx_kcommon.c b/src/rx/rx_kcommon.c
index b6a069c1d2..c90df3d365 100644
--- a/src/rx/rx_kcommon.c
+++ b/src/rx/rx_kcommon.c
@@ -33,7 +33,6 @@ int (*rxk_PacketArrivalProc) (struct rx_packet * ahandle, struct sockaddr_in * a
 int (*rxk_GetPacketProc) (struct rx_packet **ahandle, int asize);
 #endif
 
-osi_socket *rxk_NewSocketHost(afs_uint32 ahost, short aport);
 extern struct interfaceAddr afs_cb_interface;
 
 rxk_ports_t rxk_ports;
diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h
index 87a1049f7d..6e1ae566c0 100644
--- a/src/rx/rx_prototypes.h
+++ b/src/rx/rx_prototypes.h
@@ -24,9 +24,10 @@ extern void rx_rto_setPeerTimeoutSecs(struct rx_peer *, int secs);
 
 extern int rx_Init(u_int port);
 extern int rx_InitHost(u_int host, u_int port);
-#ifdef AFS_NT40_ENV
+
 extern void rx_DebugOnOff(int on);
 extern void rx_StatsOnOff(int on);
+#ifdef AFS_NT40_ENV
 extern void rx_StartClientThread(void);
 #endif
 extern void rx_StartServer(int donateMe);
@@ -332,6 +333,8 @@ extern void rxi_ListenerProc(osi_socket usockp, int *tnop,
 extern void rxk_init(void);
 # endif
 
+extern osi_socket *rxk_NewSocketHost(afs_uint32 ahost, short aport);
+
 /* UKERNEL/rx_knet.c */
 # ifdef UKERNEL
 extern void afs_rxevent_daemon(void);
diff --git a/src/rxgen/rpc_parse.c b/src/rxgen/rpc_parse.c
index 768e42f3ba..e648a66001 100644
--- a/src/rxgen/rpc_parse.c
+++ b/src/rxgen/rpc_parse.c
@@ -2148,8 +2148,14 @@ er_TailofOldStyleProc_setup(void)
 static void
 h_ProcMainBody_setup(void)
 {
+    char *pprefix = PackagePrefix[PackageIndex];
     f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n",
-	    prefix, PackagePrefix[PackageIndex]);
+	    prefix, pprefix);
+    f_print(fout,"extern char * %s%sTranslateOpCode(int op);\n", prefix,
+	    pprefix);
+    f_print(fout,"extern struct %s%sstats *%s%sOpCodeStats(int op);\n",
+	    prefix, pprefix,
+	    prefix, pprefix);
 }
 
 static void
@@ -2161,6 +2167,10 @@ h_HeadofOldStyleProc_setup(void)
     f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n",
 	    prefix, pprefix);
     f_print(fout,"\nextern int %sOpCodeIndex(int op);\n", PackagePrefix[PackageIndex]);
+    f_print(fout, "extern char * %s%sTranslateOpCode(int op);\n",
+	    prefix, pprefix);
+    f_print(fout, "extern struct %s%sstats *%s%sOpCodeStats(int op);\n",
+	    prefix, pprefix, prefix, pprefix);
 }
 
 void
diff --git a/src/tools/rxperf/rxperf.c b/src/tools/rxperf/rxperf.c
index 6a9dbc3b2a..62c18d5539 100644
--- a/src/tools/rxperf/rxperf.c
+++ b/src/tools/rxperf/rxperf.c
@@ -118,7 +118,7 @@ start_timer(void)
  */
 
 static void
-end_and_print_timer(char *str, long long bytes)
+end_and_print_timer(FILE *output, char *str, long long bytes)
 {
     long long start_l, stop_l;
     double kbps;
@@ -128,15 +128,15 @@ end_and_print_timer(char *str, long long bytes)
     gettimeofday(&timer_stop, NULL);
     start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec;
     stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec;
-    printf("%s:\t%8llu msec", str, (stop_l - start_l) / 1000);
+    fprintf(output, "%s:\t%8llu msec", str, (stop_l - start_l) / 1000);
 
     kbps = bytes * 8000.0 / (stop_l - start_l);
     if (kbps > 1000000.0)
-        printf("\t[%.4g Gbit/s]\n", kbps/1000000.0);
+        fprintf(output, "\t[%.4g Gbit/s]\n", kbps/1000000.0);
     else if (kbps > 1000.0)
-        printf("\t[%.4g Mbit/s]\n", kbps/1000.0);
+        fprintf(output, "\t[%.4g Mbit/s]\n", kbps/1000.0);
     else
-        printf("\t[%.4g kbit/s]\n", kbps);
+        fprintf(output, "\t[%.4g kbit/s]\n", kbps);
 }
 
 /*
@@ -684,7 +684,7 @@ static void
 do_client(const char *server, short port, char *filename, afs_int32 command,
 	  afs_int32 times, afs_int32 bytes, afs_int32 sendbytes, afs_int32 readbytes,
           int dumpstats, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout,
-          int udpbufsz, int nostats, int hotthread, int threads)
+          int udpbufsz, int nostats, int hotthread, int threads, FILE *output)
 {
     struct rx_connection *conn;
     afs_uint32 addr;
@@ -803,20 +803,21 @@ do_client(const char *server, short port, char *filename, afs_int32 command,
 
     switch (command) {
     case RX_PERF_RPC:
-        end_and_print_timer(stamp, (long long)threads*times*(sendbytes+readbytes));
+        end_and_print_timer(output, stamp, (long long)threads*times*(sendbytes+readbytes));
         break;
     case RX_PERF_RECV:
     case RX_PERF_SEND:
     case RX_PERF_FILE:
-        end_and_print_timer(stamp, (long long)threads*times*bytes);
+        end_and_print_timer(output, stamp, (long long)threads*times*bytes);
         break;
     }
 
     DBFPRINT(("done for good\n"));
 
+
     if (dumpstats) {
-	rx_PrintStats(stdout);
-	rx_PrintPeerStats(stdout, rx_PeerOf(conn));
+	rx_PrintStats(output);
+	rx_PrintPeerStats(output, rx_PeerOf(conn));
     }
     rx_Finalize();
 
@@ -986,10 +987,11 @@ rxperf_client(int argc, char **argv)
     int minpeertimeout = 0;
     char *ptr;
     int ch;
+    FILE *output = NULL;
 
     cmd = RX_PERF_UNKNOWN;
 
-    while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:P:r:s:w:W:f:HDNjm:u:4:t:V")) != -1) {
+    while ((ch = getopt(argc, argv, "T:S:R:b:c:d:o:p:P:r:s:w:W:f:HDNjm:u:4:t:V")) != -1) {
 	switch (ch) {
 	case 'b':
 	    bytes = strtol(optarg, &ptr, 0);
@@ -1017,6 +1019,16 @@ rxperf_client(int argc, char **argv)
 	    errx(1, "compiled without RXDEBUG");
 #endif
 	    break;
+	case 'o':
+	    if (output == NULL) {
+		output = fopen(optarg, "w");
+		if (output == NULL) {
+		    err(1, "can't open %s", optarg);
+		}
+	    } else {
+		warnx("-o option given more than once, ignoring -o %s", optarg);
+	    }
+	    break;
 	case 'P':
 	    minpeertimeout = strtol(optarg, &ptr, 0);
 	    if (ptr != 0 && ptr[0] != '\0')
@@ -1129,7 +1141,14 @@ rxperf_client(int argc, char **argv)
 
     do_client(host, port, filename, cmd, times, bytes, sendbytes,
 	      readbytes, dumpstats, nojumbo, maxmtu, maxwsize, minpeertimeout,
-              udpbufsz, nostats, hotthreads, threads);
+	      udpbufsz, nostats, hotthreads, threads,
+	      (output == NULL ? stdout : output));
+
+    if (output != NULL) {
+	if (fclose(output) < 0) {
+	    err(1, "fclose");
+	}
+    }
 
     return 0;
 }
diff --git a/tests/rx/perf-t b/tests/rx/perf-t
index 530630aed9..11ade3a38f 100755
--- a/tests/rx/perf-t
+++ b/tests/rx/perf-t
@@ -11,21 +11,45 @@ my $build = $ENV{C_TAP_BUILD};
 $build = ".." if (!defined($build));
 my $rxperf = $build."/../src/tools/rxperf/rxperf";
 
+
+# Wait for the server to finish initializing.
+sub
+wait_for_server {
+    my $pid = shift;
+    for (my $i = 0; $i < 10; $i++) {
+        if ($i > 0) {
+            sleep(1);
+        }
+        my $rc = system($rxperf, "client", "-c", "rpc", "-p", $port, "-S",
+                        "128", "-R", "128", "-T", "1", "-H", "-N",
+                        "-o", "/dev/null");
+        if ($rc == 0) {
+            return;
+        }
+    }
+    kill("TERM", $pid);
+    waitpid($pid, 0);
+    die("Unable to contact rxperf server.");
+}
+
 # Start up an rxperf server
 
 my $pid = fork();
 if ($pid == -1) {
     fail("Failed to fork rxperf server");
     exit(1);
-} elsif ($pid == 0) { 
+} elsif ($pid == 0) {
     exec({$rxperf}
 	 "rxperf", "server", "-p", $port, "-u", "1024", "-H", "-N");
     die("Kabooom ?");
 }
+# Give the server some time to initialize
+wait_for_server($pid);
+
 pass("Started rxperf server");
 
 # Start up an rxperf client, and run a test
-is(0, 
+is(0,
    system("$rxperf client -c rpc -p $port -S 1048576 -R 1048576 -T 30 -u 1024 -H -N"),
    "single threaded client ran successfully");
 
@@ -44,5 +68,3 @@ if (WIFSIGNALED($?) && WTERMSIG($?) != SIGTERM) {
 } else {
     pass("Server exited succesfully");
 }
-
-
