diff --git a/CODING b/CODING
index e89b691eba..53fa2fd385 100644
--- a/CODING
+++ b/CODING
@@ -332,7 +332,6 @@ afs/afs_syscall.c    : old-style
 		     : all (ukernel) : syscall pointer issues
 afsd/afsd_kernel.c   : deprecated    : daemon() marked as deprecated on Darwin
 bozo/bosserver.c     : deprecated    : daemon() marked as deprecated on Darwin
-bucoord/ubik_db_if.c : strict-proto  : ubik_Call_SingleServer
 bucoord/commands.c   : all	     : signed vs unsigned for dates
 external/heimdal/hcrypto/validate.c: all: statement with empty body
 external/heimdal/hcrypto/evp.c:      cast-function-type
@@ -341,13 +340,9 @@ external/heimdal/hcrypto/evp-algs.c: cast-function-type
              : Linux kernel build uses -Wcast-function-type
 external/heimdal/krb5/crypto.c: use-after-free : False postive on certain GCC
                                                  compilers
-kauth/admin_tools.c  : strict-proto  : ubik_Call
-kauth/authclient.c   : strict-proto  : ubik_Call nonsense
-libadmin/kas/afs_kasAdmin.c: strict-proto : ubik_Call nonsense
 libadmin/samples/rxstat_query_peer.c : all : util_RPCStatsStateGet types
 libadmin/samples/rxstat_query_process.c : all : util_RPCStatsStateGet types
 libadmin/test/client.c : all         : util_RPCStatsStateGet types
-ubik/ubikclient.c    : strict-protos : ubik_Call
 volser/vol-dump.c    : format        : afs_sfsize_t
 rxkad/ticket5.c      : format-truncation : inside included file v5der.c in the
                                        function _heim_time2generalizedtime, the
diff --git a/Makefile.in b/Makefile.in
index 57a11233f5..1a1590d0ad 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -758,7 +758,6 @@ clean2:
 	-/bin/rm -rf libafs_tree ${SYS_NAME}
 
 dist:
-	mkdir -p packages
 	./build-tools/make-release --dir=packages HEAD
 
 srpm: dist
@@ -864,6 +863,10 @@ distclean: clean
 	src/pam/Makefile \
 	src/platform/Makefile \
 	src/platform/${MKAFS_OSTYPE}/Makefile \
+	src/platform/DARWIN/AFSPreference/Info.plist \
+	src/platform/DARWIN/PrivilegedHelper/Makefile \
+	src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist \
+	src/platform/DARWIN/PrivilegedHelper/privhelper.c \
 	src/platform/DARWIN/growlagent/Makefile \
 	src/procmgmt/Makefile \
 	src/procmgmt/test/Makefile \
diff --git a/NEWS b/NEWS
index d8f7bfbcd6..973cd5b191 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,154 @@
                        User-Visible OpenAFS Changes
 
+OpenAFS 1.8.14pre1
+
+  All platforms
+
+    * Build system fixes for building shared libraries (16098, 16099,
+      16117)
+
+    * Fix crashes due to incorrect Rx security class reference
+      counting (15850, 15851)
+
+    * Display rxdebug free and allocated counters as unsigned values
+      (15801)
+
+    * Fix error handling in `vos`, `fs`, and `volinfo` command line
+      tools (15817, 16081)
+
+    * Fix build error when building static libraries when SWIG is
+      installed (16100, 16101)
+
+    * Fix handling invalid timestamps values in 'bos getrestart'
+      (16442)
+
+  All server platforms
+
+    * Fix a bug that caused vlserver to crash during startup when
+      launched with a very long -trace command line argument (16010)
+
+    * Several misleading file server log messages have been corrected
+      and more messages are issued during startup (16016, 16020,
+      16021)
+
+    * Improve file server performance and restart time on servers
+      handling a large number of callbacks (16017, 16018, 16019,
+      16022, 16023)
+
+    * The RXAFS_StoreACL() RPC op code has been renumbered from 134 to
+      164 to identify AFS3 clients which may incorrectly add negative
+      access control entries to the normal rights list.  The old 134
+      op code is still supported, but is now deprecated and will be
+      removed in a future release.  A new file server command line
+      option (`-cve-2018-7168-enforce`) disables the deprecated 134 op
+      code to store ACLs. (16228, 16230)
+
+    * Rx services now log the IP address they bind to during startup
+      to improve network diagnostics (16095)
+
+    * The volume server now logs messages about volume transactions
+      interrupted by a volume server shutdown. (16123)
+
+  All client platforms
+
+    * Updated the CellServDB to the latest version from grand.central.org
+      (16537)
+
+  All unix clients
+
+    * Fix client shutdown when the client was started with -rxbind
+      (16011, 16012, 16065)
+
+    * The output of `fs getfid -literal` is now correct when the path
+      is a broken symlink or the dynroot directory (16079)
+
+    * The `fs getfid` command now displays the FID even if it cannot
+      retrieve cell information (16080)
+
+    * Create the AFS mount point directory (usually /afs) with
+      directory permissions of 0555 instead of 0755 when the cache
+      manager is started with the --dynroot option. This fixes an
+      issue on RedHat-based systems which expect the /afs directory to
+      have 0555 permissions (16378)
+
+    * Reduce unnecessary `lstat` calls in the `fs` command to improve
+      performance (16102)
+
+    * Avoid a possible crash when a client cache size configuration is
+      greatly reduced and then the client is restarted (16103)
+
+  Linux
+
+    * Build system changes to support building on Gentoo (16130,
+      16131)
+
+    * Build system changes to support building on Fedora 42 (16379,
+      16380)
+
+    * Update RedHat-based packing to continue to build binaries
+      without link-time optimization (LTO) (16426)
+
+  Linux client
+
+    * Critical fix for a crash or hang that could occur when a process
+      received a signal while waiting for AFS3 network packets. This
+      is especially critical for Go applications which make heavy use
+      of signals (16007, 16008)
+
+    * Add support for Linux kernel 6.14 (16276, 16277, 16542, 16543)
+
+    * Add support for building kernel modules for hardened kernels
+      (16382, 16383)
+
+    * Systemd integration has been improved in the RedHat-based
+      contributed packaging files (16104, 16105, 16106, 16107)
+
+    * RPM packaging fixes (16416, 16417)
+
+    * Fix `unsupported NO_WEAK_MODULES value` error when building the
+      kernel module with recent versions of DKMS (16420, 16423)
+
+    * Update the RedHat-based RPM packaging files to support RedHat 10
+      (16422)
+
+    * Add support for Linux kernel 6.15 (16418, 16419, 16427, 16428,
+      16429, 16430, 16431)
+
+    * Add support for Linux kernel 6.16 (16498, 16499, 16500, 16501,
+      16502, 16519)
+
+  MacOS client
+
+    * Functionality of the OpenAFS Preference Pane is restored on
+      macOS 10.8 and later. This includes enabling/disabling startup,
+      starting/stopping the client, and editing OpenAFS configuration
+      files (16066, 16067, 16068, 16069, 16070, 16071, 16072, 16073,
+      16074, 16260, 16444, 16505)
+
+    * Avoid ENOENT errors on unparented vnodes (16179)
+
+    * Improve build system compatibility with recent Xcode versions
+      (16180, 16182, 16183, 16185, 16186, 16187, 16188, 16190)
+
+    * Add support for macOS 15.x (Sequoia) (16189)
+
+    * Add support for macOS 26 (Tahoe) (16433)
+
+    * Fix a kernel module build error for arm64 (16512)
+
+    * Add support for OpenAFS command line programs such as bos, fs,
+      and cmdebug on macOS arm64 platforms (16518)
+
+  Solaris
+
+    * Fix compiler detection when both GCC and Solaris Studio are
+      installed (16097)
+
+  AIX
+
+    * Add support for building with clang-based XLC 17.1 (15810,
+      15811, 15812)
+
 OpenAFS 1.8.13.2
 
   Linux clients
diff --git a/acinclude.m4 b/acinclude.m4
index 812bece986..3ca97b41e0 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -24,7 +24,6 @@ AC_TYPE_SIZE_T
 dnl Checks for programs.
 AC_PROG_INSTALL
 AC_PROG_LN_S
-AC_PROG_RANLIB
 AC_PROG_YACC
 OPENAFS_LEX
 
diff --git a/build-tools/make-release b/build-tools/make-release
index a8ba7baeb6..df545a1c89 100755
--- a/build-tools/make-release
+++ b/build-tools/make-release
@@ -6,26 +6,53 @@ use Getopt::Long;
 use Pod::Usage;
 use File::Path;
 use File::Temp;
+use File::Basename;
+use Cwd;
 
 my $help;
 my $man;
 my $tagPoint;
 my $last;
 my $outDir = ".";
+my $errorCount = 0;
+
+# Find a command in the PATH.
+sub which {
+    my $command = shift;
+    my @paths = split(/:/, $ENV{'PATH'});
+    my $path;
+
+    # Add some common locations for the commands we need.
+    push(@paths, qw(/sbin /usr/bin /usr/local/bin));
+
+    # Search for the command.
+    foreach $path (@paths) {
+        my $bin = File::Spec->catfile($path, $command);
+        if (-x $bin) {
+            return $bin;  # Return the first one found.
+        }
+    }
+    return undef;
+}
 
-GetOptions("help|?" => \$help,
-	   "man" => \$man,
-	   "tagpoint=s" => \$tagPoint,
- 	   "last=s" => \$last,
-	   "dir=s" => \$outDir) or pod2usage(2);
+GetOptions(
+    "help|?" => \$help,
+    "man" => \$man,
+    "tagpoint=s" => \$tagPoint,
+    "last=s" => \$last,
+    "dir=s" => \$outDir,
+) or pod2usage(2);
 
 pod2usage(1) if $help;
 pod2usage(-exitstatus => 0, -verbose => 2) if $man;
 
 my $tagName = shift;
-my $version = shift;
+my $notused = shift;  # Used to be "version".
 
 pod2usage(2) if !defined($tagName);
+if (defined $notused) {
+    warn "Warning: argument '$notused' is ignored.\n";
+}
 
 # Tag the repository
 
@@ -35,23 +62,29 @@ if ($tagPoint) {
 
     # Push the tag upstream
     system ("git push ssh://gerrit.openafs.org:29418/openafs tag $tagName") == 0
-    	or die "git push failed with : $!";
+        or die "git push failed with : $!";
 }
 
-$version = `git describe --abbrev=4 $tagName`;
+my $version = `git describe --abbrev=4 $tagName`;
 chomp $version;
-$version=~s/openafs-[^-]*-//;
-$version=~s/_/./g;
+if (!$version) {
+    die "Failed to describe $tagName.\n";
+}
+my $suffix = $version;
+$suffix =~ s/openafs-[^-]*-//;
+$suffix =~ s/_/./g;
+my $name = "openafs-$suffix";
 
 # Grab the tagged code into a temporary directory
 
-my $name = "openafs-".$version;
-
 my $tempDir = File::Temp::tempdir();
 system ("git archive --format=tar --prefix=$name/ $tagName ".
-	" | tar -C $tempDir -x") == 0
+        " | tar -C $tempDir -x") == 0
     or die "Git archive failed with: $?";
 
+# Make the output path, if not already present.
+File::Path::mkpath($outDir);
+
 # Construct the ChangeLog
 if ($last) {
     system("git log $last..$tagName > $outDir/ChangeLog");
@@ -60,7 +93,10 @@ if ($last) {
 }
 
 # Describe the tree
-system("git describe --abbrev=4 $tagName > $tempDir/$name/.version");
+open(my $fh, ">", "$tempDir/$name/.version") or
+    die "Failed to open $tempDir/$name/.version: $!\n";
+print $fh "$version\n";
+close($fh);
 
 # Run regen.sh to create the rest of the tree
 system ("cd $tempDir/$name && ./regen.sh") == 0
@@ -89,62 +125,107 @@ if ($last) {
     push @toCompress, "$outDir/$name.diff";
 }
 
-my @toMD5;
+my @toMD;
 
 # Compress everything that needs squashing,
-# and also set up a list for md5 checksumming.
+# and also set up a list for checksumming.
 foreach my $file (@toCompress) {
     system("gzip < $file > $file.gz") == 0
-	or die "Unable to create gzip file of '$file' : $!";
-    push @toMD5, "$file.gz";
+        or die "Unable to create gzip file of '$file' : $!";
+    push @toMD, "$file.gz";
 
     system("bzip2 < $file > $file.bz2") == 0
-	or die "Unable to create bzip file of '$file' : $!";
-    push @toMD5, "$file.bz2";
+        or die "Unable to create bzip file of '$file' : $!";
+    push @toMD, "$file.bz2";
 
     # Delete the uncompressed tar files.
     if ($file =~ /\.tar$/) {
       unlink($file);
     } else {
-      # Otherwise, queue this file for md5 checksumming.
-      push @toMD5, $file;
+      # Otherwise, queue this file for checksumming.
+      push @toMD, $file;
     }
 }
 
-foreach my $file (@toMD5) {
-    if (-x "/sbin/md5") {
-	system("/sbin/md5 -q $file > $file.md5");
-    } elsif (-x "/usr/bin/md5sum") {
-	system("/usr/bin/md5sum $file > $file.md5");
+# Generate message digest files.
+
+my $cwd = getcwd() or die "Failed getcwd(): $!";
+my $md5 = which('md5');
+my $md5sum = which('md5sum');
+my $shasum = which("shasum");
+my $sha256sum = which("sha256sum");
+
+foreach my $pathname (@toMD) {
+    my $directory = dirname($pathname);
+    my $file = basename($pathname);
+    my $rc;
+
+    chdir($directory) or die "Failed cd $directory: $!";
+
+    if ($md5) {
+        $rc = system("$md5 -q $file > $file.md5");
+        if ($rc != 0) {
+            warn "Command failed: $md5 -q $file, code=$rc";
+            $errorCount += 1;
+        }
+    } elsif ($md5sum) {
+        $rc = system("$md5sum $file > $file.md5");
+        if ($rc != 0) {
+            warn "Command failed: md5sum $file, code=$rc";
+            $errorCount += 1;
+        }
     } else {
-	print STDERR "No md5 utiltiy found. Not producing checksums\n";
+        warn "MD5 utility not found. Not producing $file.md5";
+        $errorCount += 1;
     }
+
+    if ($shasum) {
+        $rc = system("$shasum -a 256 $file > $file.sha256");
+        if ($rc != 0) {
+            warn "Command failed: $shasum -a 256 $file, code=$rc";
+            $errorCount += 1;
+        }
+    } elsif ($sha256sum) {
+        $rc = system("$sha256sum $file > $file.sha256");
+        if ($rc != 0) {
+            warn "Command failed: $sha256sum $file, code=$rc";
+            $errorCount += 1;
+        }
+    } else {
+        warn "SHA256 utility program not found. Not producing $file.sha256";
+        $errorCount += 1;
+    }
+
+    chdir($cwd) or die "Failed cd $cwd: $!";
+}
+
+if ($errorCount != 0) {
+    die "Failed to create all files; $errorCount errors encountered.";
 }
- 
 
 __END__
 
 =head1 NAME
 
-make_release - Make an OpenAFS release from git
+make-release - Make an OpenAFS release from git
 
 =head1 SYNOPSIS
 
-make_release [options] <tag> [<version>]
+make-release [options] <tag>
 
  Options:
-    --help	         brief help message
-    --man	         full documentation
+    --help               brief help message
+    --man                full documentation
     --tagpoint <object>  create new tag
     --last <object>      generate changelog and diffs from this point
     --dir <dir>          output results into this directory
 
 =head1 DESCRIPTION
 
-make_release constructs an OpenAFS release from a local git clone. If run
+make-release constructs an OpenAFS release from a local git clone. If run
 with just the standard arguments, it will extract the contents of the
 specified tag into the current directory, creating src and doc tarballs,
-gziping and bziping them, and generating md5 hashes. It will also create a
+gzipping and bzipping them, and generating digest files. It will also create a
 ChangeLog file, listing all of the changes in that release.
 
 This standard behaviour may be modified by the following options
@@ -155,14 +236,14 @@ This standard behaviour may be modified by the following options
 
 =item B<--last> I<object>
 
-Generate the ChangeLog starting from I<object>. Also generate a 
+Generate the ChangeLog starting from I<object>. Also generate a
 openafs-$version.diff file in the output directory containing all of the
 changes between I<object> and the current tag
 
 =item B<--dir> I<directory>
 
 Instead of generating all of the output in the current directory, place it
-in <directory>, which must already exist.
+in <directory>, which is created if it does not already exist.
 
 =item B<--tagpoint> I<commit|branch>
 
@@ -170,4 +251,6 @@ Rather than using an existing tag, create a new one on the specified commit,
 or on the tip of the specified branch. This will GPG sign the new tag, and
 push it into gerrit.
 
+=back
+
 =cut
diff --git a/configure-libafs.ac b/configure-libafs.ac
index 444b849f94..2f66d6fa9b 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.14d2
+MACOS_VERSION=1.8.14fc1
 
 AC_SUBST([MACOS_VERSION])
 
diff --git a/configure.ac b/configure.ac
index e34cf1c6ef..4ef4b98b91 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.14d2
+MACOS_VERSION=1.8.14fc1
 
 AC_SUBST([MACOS_VERSION])
 
@@ -14,8 +14,6 @@ AS_IF([test -z "$CFLAGS"], [CFLAGS=" "])
 
 AC_USE_SYSTEM_EXTENSIONS
 
-AFS_LT_INIT
-
 AC_PROG_CC
 
 AC_PATH_PROGS([PATH_CPP], [cpp], [${CC-cc} -E], [$PATH:/lib:/usr/ccs/lib])
@@ -101,25 +99,25 @@ AC_SUBST([AKLOG_KRB5_LIBS])
 dnl Checks for summary
 OPENAFS_SUMMARY_CHECK_NAMEI
 
-AS_IF([test -d 'doc/man-pages'],
+AS_IF([test -d "$srcdir/doc/man-pages"],
     [MAN_MAKEFILE="doc/man-pages/Makefile doc/man-pages/install-man"],
     [MAN_MAKEFILE=])
-AS_IF([test -f 'doc/xml/AdminGuide/Makefile.in'],
+AS_IF([test -f "$srcdir/doc/xml/AdminGuide/Makefile.in"],
     [ADMINGUIDE_MAKEFILE="doc/xml/AdminGuide/Makefile"],
     [ADMINGUIDE_MAKEFILE=])
-AS_IF([test -f 'doc/xml/QuickStartUnix/Makefile.in'],
+AS_IF([test -f "$srcdir/doc/xml/QuickStartUnix/Makefile.in"],
     [QSUNIX_MAKEFILE="doc/xml/QuickStartUnix/Makefile"],
     [QSUNIX_MAKEFILE=])
-AS_IF([test -f 'doc/xml/UserGuide/Makefile.in'],
+AS_IF([test -f "$srcdir/doc/xml/UserGuide/Makefile.in"],
     [USERGUIDE_MAKEFILE="doc/xml/UserGuide/Makefile"],
     [USERGUIDE_MAKEFILE=])
-AS_IF([test -f 'doc/xml/AdminRef/Makefile.in'],
+AS_IF([test -f "$srcdir/doc/xml/AdminRef/Makefile.in"],
     [ADMINREF_MAKEFILE="doc/xml/AdminRef/Makefile"],
     [ADMINREF_MAKEFILE=])
-AS_IF([test -f 'doc/xml/mobi-fixup.xsl.in'],
+AS_IF([test -f "$srcdir/doc/xml/mobi-fixup.xsl.in"],
     [MOBI_FIXUP_XSL="doc/xml/mobi-fixup.xsl"],
     [MOBI_FIXUP_XSL=])
-AS_IF([test -f 'doc/doxygen/Doxyfile.in'],
+AS_IF([test -f "$srcdir/doc/doxygen/Doxyfile.in"],
     [DOXYFILE="doc/doxygen/Doxyfile"],
     [DOXYFILE=])
 
@@ -214,6 +212,10 @@ AC_CONFIG_FILES([
     src/pam/Makefile
     src/platform/Makefile
     src/platform/${MKAFS_OSTYPE}/Makefile
+    src/platform/DARWIN/AFSPreference/Info.plist
+    src/platform/DARWIN/PrivilegedHelper/Makefile
+    src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist
+    src/platform/DARWIN/PrivilegedHelper/privhelper.c
     src/platform/DARWIN/growlagent/Makefile
     src/procmgmt/Makefile
     src/procmgmt/test/Makefile
diff --git a/doc/man-pages/Makefile.in b/doc/man-pages/Makefile.in
index 882dd48c55..0b6664264b 100644
--- a/doc/man-pages/Makefile.in
+++ b/doc/man-pages/Makefile.in
@@ -43,9 +43,11 @@ dest: prep-noinstall
 	chmod +x install-man
 	mkdir -p $(DEST)/man/man1 $(DEST)/man/man3 \
 	         $(DEST)/man/man5 $(DEST)/man/man8
-	set -e; for M in man1/*.1 man3/*.3 man5/*.5 man8/*.8 ; do \
+	set -e; orig_pwd=`pwd` ; cd $(srcdir) ; \
+	for M in man1/*.1 man3/*.3 man5/*.5 man8/*.8 ; do \
+	    cd $$orig_pwd ; \
 	    if ! [ -e $$M.noinstall ] ; then \
-		./install-man $$M $(DEST)/man/$$M ; \
+		./install-man $(srcdir)/$$M $(DEST)/man/$$M ; \
 	    fi ; \
 	done
 	set -e; for M in ${LINKEDPAGES}; do \
@@ -69,9 +71,11 @@ install: prep-noinstall $(MAN1) $(MAN8)
 	chmod +x install-man
 	mkdir -p $(DESTDIR)$(mandir)/man1 $(DESTDIR)$(mandir)/man3 \
 	    $(DESTDIR)$(mandir)/man5 $(DESTDIR)$(mandir)/man8
-	set -e; for M in man1/*.1 man3/*.3 man5/*.5 man8/*.8 ; do \
+	set -e; orig_pwd=`pwd` ; cd $(srcdir) ; \
+	for M in man1/*.1 man3/*.3 man5/*.5 man8/*.8 ; do \
+	    cd $$orig_pwd ; \
 	    if ! [ -e $$M.noinstall ] ; then \
-		./install-man $$M $(DESTDIR)$(mandir)/$$M ; \
+		./install-man $(srcdir)/$$M $(DESTDIR)$(mandir)/$$M ; \
 	    fi; \
 	done
 	set -e; for M in ${LINKEDPAGES}; do \
diff --git a/doc/man-pages/pod1/fs_getfid.pod b/doc/man-pages/pod1/fs_getfid.pod
index 91007b77b8..5177894e1a 100644
--- a/doc/man-pages/pod1/fs_getfid.pod
+++ b/doc/man-pages/pod1/fs_getfid.pod
@@ -45,7 +45,7 @@ ignored.
 =head1 OUTPUT
 
 The output contains the name of the file or directory, the FID, and the
-volume containing the FID.  The Windows version also outputs the object
+cell containing the FID.  The Windows version also outputs the object
 type instead of using "File" to describe all objects.
 
 =head1 EXAMPLES
@@ -53,10 +53,10 @@ type instead of using "File" to describe all objects.
 On Unix:
 
    % fs getfid .
-   File . (536870918.1.1) contained in volume 536870918
+   File . (536870918.1.1) located in cell example.com
 
    % fs getfid /afs/example.com/foo 
-   File /afs/example.com/foo (536870918.20404.20997) contained in volume 536870918
+   File /afs/example.com/foo (536870918.20404.20997) located in cell example.com
 
 On Windows:
 
diff --git a/doc/man-pages/pod1/rxgen.pod b/doc/man-pages/pod1/rxgen.pod
index dc05a71610..263350789b 100644
--- a/doc/man-pages/pod1/rxgen.pod
+++ b/doc/man-pages/pod1/rxgen.pod
@@ -669,7 +669,7 @@ Sample CLIENT code:
     vldb_list       linkedvldbs;
     vldblist        vllist, vllist1;
 
-    bzero(&linkedvldbs, sizeof(vldb_list));
+    memset(&linkedvldbs, 0, sizeof(vldb_list));
     code = VL_LinkedList(&attributes, &nentries, &linkedvldbs);
     if (!code) {
         printf("We got %d vldb entries\n", nentries);
diff --git a/doc/man-pages/pod8/afsd.pod b/doc/man-pages/pod8/afsd.pod
index 65a27a6306..255db59b0a 100644
--- a/doc/man-pages/pod8/afsd.pod
+++ b/doc/man-pages/pod8/afsd.pod
@@ -538,6 +538,9 @@ feature is recommended only for temporary access to a volume.  Linux-based
 cache managers provide this dynamic mount feature even when dynamic root
 (B<-dynroot>, B<-dynroot-sparse>) is not in effect.
 
+When B<-dynroot> is provided, the permission mode bits for the dynamic F</afs>
+directory are set to C<0555>.
+
 =item B<-dynroot-sparse>
 
 In addition to operating in the manner described for dynroot above,
diff --git a/doc/man-pages/pod8/fragments/fileserver-options.pod b/doc/man-pages/pod8/fragments/fileserver-options.pod
index 1652303609..56f8ec3a3a 100644
--- a/doc/man-pages/pod8/fragments/fileserver-options.pod
+++ b/doc/man-pages/pod8/fragments/fileserver-options.pod
@@ -282,6 +282,13 @@ restarted.  This option is provided for compatibility with older versions.
 Offer the SANEACLS capability for the fileserver.  This option is
 currently unimplemented.
 
+-item B<-cve-2018-7168-enforce>
+
+To address L<CVE-2018-7168|https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7168>
+disable fileserver opcode RXAFS_StoreACL (134).  This opcode was replaced
+with RXAFS_StoreACL (164).  The opcode 164 is always available; this option serves
+only to disable the old opcode 134, for which client intent is unreliable.
+
 =item B<-help>
 
 Prints the online help for this command. All other valid options are
diff --git a/doc/man-pages/pod8/fragments/fileserver-synopsis.pod b/doc/man-pages/pod8/fragments/fileserver-synopsis.pod
index 203d7a36b8..ed60009c8c 100644
--- a/doc/man-pages/pod8/fragments/fileserver-synopsis.pod
+++ b/doc/man-pages/pod8/fragments/fileserver-synopsis.pod
@@ -40,6 +40,7 @@ B<fileserver>
     S<<< [B<-mrafslogs>] >>>
     S<<< [B<-transarc-logs>] >>>
     S<<< [B<-saneacls>] >>>
+    S<<< [B<-cve-2018-7168-enforce>] >>>
     S<<< [B<-help>] >>>
     S<<< [B<-vhandle-setaside> <I<fds reserved for non-cache io>>] >>>
     S<<< [B<-vhandle-max-cachesize> <I<max open files>>] >>>
diff --git a/doc/protocol/rx-spec.h b/doc/protocol/rx-spec.h
index f8e42c150d..d3ad9b05d9 100644
--- a/doc/protocol/rx-spec.h
+++ b/doc/protocol/rx-spec.h
@@ -4389,7 +4389,7 @@
  * \par
  * \#define rx_Read(call, buf, nbytes) 
  * \n ((call)->nLeft > (nbytes) ? 
- * \n bcopy((call)->bufPtr, (buf), (nbytes)), 
+ * \n memcpy((buf), (call)->bufPtr, (nbytes)),
  * \n (call)->nLeft -= (nbytes), (call)->bufPtr += (nbytes), (nbytes) 
  * \n : rx_ReadProc((call), (buf), (nbytes))) 
  * \par
@@ -4410,7 +4410,7 @@
  * \par
  * \#define rx_Write(call, buf, nbytes) 
  * \n ((call)->nFree > (nbytes) ? 
- * \n bcopy((buf), (call)->bufPtr, (nbytes)), 
+ * \n memcpy((call)->bufPtr, (buf), (nbytes)),
  * \n (call)->nFree -= (nbytes), 
  * \n (call)->bufPtr += (nbytes), (nbytes) 
  * \n : rx_WriteProc((call), (buf), (nbytes))) 
@@ -5269,7 +5269,7 @@
  * 		pn, rn, hostEntP->h_length, sizeof(u_long)); 
  * 		exit(1); 
  * 	} 
- * 	bcopy(hostEntP->h_addr, (char *)&hostIPAddr, sizeof(hostIPAddr)); 
+ * 	memcpy(&hostIPAddr, hostEntP->h_addr, sizeof(hostIPAddr));
  * 	return(hostIPAddr); 
  * } /* GetIpAddress */
  * \endcode
diff --git a/doc/xml/AdminGuide/Makefile.in b/doc/xml/AdminGuide/Makefile.in
index caf48ac668..d2978cc150 100644
--- a/doc/xml/AdminGuide/Makefile.in
+++ b/doc/xml/AdminGuide/Makefile.in
@@ -12,6 +12,7 @@
 #
 # HTML_XSL is possibly specific to Debian and may need to be modified on other
 # systems.
+srcdir=@srcdir@
 
 BOOK = auagd000
 
@@ -33,22 +34,29 @@ DOCBOOK2PDF = @DOCBOOK2PDF@
 KINDLEGEN = @KINDLEGEN@
 DBTOEPUB = $(DOCBOOK_STYLESHEETS)/epub/bin/dbtoepub
 
+XSL_FLAGS = --path '@abs_builddir@'
+
 index.html: $(SRCS)
-	$(XSLTPROC) --param navig.graphics 1 \
+	$(XSLTPROC) $(XSL_FLAGS) \
+	    --param navig.graphics 1 \
 	    --param use.id.as.filename 1 \
-	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) $(BOOK).xml
+	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) \
+	    $(srcdir)/$(BOOK).xml
 
 $(BOOK).pdf: $(SRCS)
 	if test "x$(DOCBOOK2PDF)" = "xfop"; then \
-		$(XSLTPROC) $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl $(BOOK).xml > $(BOOK).fo; \
+		$(XSLTPROC) $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl \
+		    $(srcdir)/$(BOOK).xml > $(BOOK).fo; \
 		$(DOCBOOK2PDF) $(BOOK).fo $(BOOK).pdf; \
 	else \
-		$(DOCBOOK2PDF) $(BOOK).xml; \
+		$(DOCBOOK2PDF) --output=$@ --xslt-opts="$(XSL_FLAGS)" \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).epub: $(SRCS)
 	if test -x "$(DBTOEPUB)" ; then \
-		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl $(BOOK).xml; \
+		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).mobi: $(BOOK).epub
@@ -57,7 +65,7 @@ $(BOOK).mobi: $(BOOK).epub
 	fi
 
 check:
-	xmllint --noout --valid $(BOOK).xml
+	xmllint $(XSL_FLAGS) --noout --valid $(srcdir)/$(BOOK).xml
 
 clean:
 	rm -f *.aux *.epub *.fo *.html *.log *.mobi *.out *.pdf
diff --git a/doc/xml/AdminRef/.gitignore b/doc/xml/AdminRef/.gitignore
new file mode 100644
index 0000000000..9950af464a
--- /dev/null
+++ b/doc/xml/AdminRef/.gitignore
@@ -0,0 +1,19 @@
+# After changing this file, please run
+#     git ls-files -i --exclude-standard
+# to check that you haven't inadvertently ignored any tracked files.
+
+*.aux
+*.chm
+*.epub
+*.html
+*.fo
+*.log
+*.mobi
+*.out
+*.pdf
+
+Makefile
+version.xml
+entities.dtd
+sect*.xml
+sect*/
diff --git a/doc/xml/AdminRef/Makefile.in b/doc/xml/AdminRef/Makefile.in
index a9d78d6a55..06e2ce50e5 100644
--- a/doc/xml/AdminRef/Makefile.in
+++ b/doc/xml/AdminRef/Makefile.in
@@ -1,4 +1,5 @@
 # Makefile to build the AFS Reference Guide for Unix.
+srcdir=@srcdir@
 
 BOOK = auarf000
 
@@ -9,27 +10,33 @@ VERSION=version
 include @TOP_OBJDIR@/src/config/Makefile.version
 
 SRCS     = $(BOOK).xml preface.xml $(VERSION).xml \
-	   entities.dtd sect1.xml sect5.xml sect8.xml
+	   entities.dtd sect1.xml sect3.xml sect5.xml sect8.xml
 DOCBOOK_STYLESHEETS = @DOCBOOK_STYLESHEETS@
 XSLTPROC = @XSLTPROC@ --stringparam variablelist.as.blocks 1 --param use.id.as.filename 1
 DOCBOOK2PDF = @DOCBOOK2PDF@
 DBTOEPUB = $(DOCBOOK_STYLESHEETS)/epub/bin/dbtoepub
 KINDLEGEN = @KINDLEGEN@
 
-entities.dtd sect1.xml sect5.xml sect8.xml:
-	./generate-xml.pl $(TOP_SRCDIR)
+XSL_FLAGS = --path '@abs_builddir@'
+
+entities.dtd sect1.xml sect3.xml sect5.xml sect8.xml:
+	$(srcdir)/generate-xml.pl $(TOP_SRCDIR)
 
 $(BOOK).pdf: $(SRCS)
 	if test "x$(DOCBOOK2PDF)" = "xfop"; then \
-		$(XSLTPROC) $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl $(BOOK).xml > $(BOOK).fo; \
+		$(XSLTPROC) $(XSL_FLAGS) \
+		    $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl \
+		    $(srcdir)/$(BOOK).xml > $(BOOK).fo; \
 		$(DOCBOOK2PDF) $(BOOK).fo $(BOOK).pdf; \
 	else \
-		$(DOCBOOK2PDF) $(BOOK).xml; \
+		$(DOCBOOK2PDF) --output=$@ --xslt-opts="$(XSL_FLAGS)" \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).epub: $(SRCS)
 	if test -x "$(DBTOEPUB)" ; then \
-		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl $(BOOK).xml; \
+		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).mobi: $(BOOK).epub
@@ -38,9 +45,9 @@ $(BOOK).mobi: $(BOOK).epub
 	fi
 
 check:
-	xmllint --noout --valid $(BOOK).xml
+	xmllint $(XSL_FLAGS) --noout --valid $(srcdir)/$(BOOK).xml
 
 clean:
 	rm -f $(BOOK).pdf $(BOOK).mobi $(BOOK).epub $(BOOK).fo \
-		entities.dtd sect1.xml sect5.xml sect8.xml $(VERSION).xml
-	rm -rf sect1 sect5 sect8
+		entities.dtd sect1.xml sect3.xml sect5.xml sect8.xml $(VERSION).xml
+	rm -rf sect1 sect3 sect5 sect8
diff --git a/doc/xml/AdminRef/auarf000.xml b/doc/xml/AdminRef/auarf000.xml
index 6cbe7dce9f..6422759722 100644
--- a/doc/xml/AdminRef/auarf000.xml
+++ b/doc/xml/AdminRef/auarf000.xml
@@ -4,6 +4,7 @@
 <!ENTITY version SYSTEM "version.xml">
 <!ENTITY preface SYSTEM "preface.xml">
 <!ENTITY sect1 SYSTEM "sect1.xml">
+<!ENTITY sect3 SYSTEM "sect3.xml">
 <!ENTITY sect5 SYSTEM "sect5.xml">
 <!ENTITY sect8 SYSTEM "sect8.xml">
 <!ENTITY % entities SYSTEM "entities.dtd">
@@ -61,6 +62,11 @@
     &sect1;
   </reference>
 
+  <reference>
+    <title>AFS Library Reference</title>
+    &sect3;
+  </reference>
+
   <reference>
     <title>AFS System Files</title>
     &sect5;
diff --git a/doc/xml/AdminRef/generate-xml.pl b/doc/xml/AdminRef/generate-xml.pl
index f414bc699e..c6a2f51b77 100755
--- a/doc/xml/AdminRef/generate-xml.pl
+++ b/doc/xml/AdminRef/generate-xml.pl
@@ -2,35 +2,46 @@
     eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
 	if $running_under_some_shell;
 
-@sections = ('1', '5', '8');
+@sections = ('1', '3', '5', '8');
 
 $TOP_SRCDIR = shift @ARGV;
+$srcdir = sprintf "%s/../doc/xml/AdminRef", $TOP_SRCDIR;
 $doc_man_pages = sprintf "%s/../doc/man-pages", $TOP_SRCDIR;
 
 open(ENTITIES, ">entities.dtd") || die;
 
 foreach $section (@sections) {
     printf "generating section %s...\n", $section;
+    my @entities = ();
 
     mkdir(sprintf "sect%d", $section);
     opendir($DIR, sprintf "%s/pod%d", $doc_man_pages, $section) || die;
-    open(SECT, sprintf ">sect%d.xml", $section) || die;
     while ($podfile = readdir($DIR)) {
 	next unless $podfile =~ /\.pod$/;
 
 	($xmlfile = $podfile) =~ s/\.pod$/.xml/;
 	($entity = $xmlfile) =~ s/\.xml$//;
 
-	printf "pod2refentry < %s > %s\n", $podfile, $xmlfile;
+	printf "%s/pod2refentry < %s > %s\n", $srcdir, $podfile, $xmlfile;
 
-	system(sprintf "./pod2refentry --section=%d < %s/pod%d/%s > sect%d/%s",
-	    $section, $doc_man_pages, $section, $podfile, $section, $xmlfile);
+	my $rc = system(sprintf "%s/pod2refentry --section=%d < %s/pod%d/%s > sect%d/%s",
+	    $srcdir, $section, $doc_man_pages, $section, $podfile, $section, $xmlfile);
+	if ($rc != 0) {
+	    die "Failed to generate sect${section}/${xmlfile}: $rc\n";
+	}
 
 	printf ENTITIES "<!ENTITY %s%s SYSTEM \"sect%d/%s\">\n",
 	    $entity, $section, $section, $xmlfile;
-	printf SECT "&%s%s;\n", $entity, $section;
+
+	push(@entities, $entity);
     }
     closedir($DIR);
+
+    open(SECT, sprintf ">sect%d.xml", $section) || die;
+    foreach $entity (sort(@entities)) {
+	printf SECT "&%s%s;\n", $entity, $section;
+    }
+
     close(SECT);
 }
 
diff --git a/doc/xml/QuickStartUnix/Makefile.in b/doc/xml/QuickStartUnix/Makefile.in
index b309015ce2..ae3443d711 100644
--- a/doc/xml/QuickStartUnix/Makefile.in
+++ b/doc/xml/QuickStartUnix/Makefile.in
@@ -12,6 +12,7 @@
 #
 # HTML_XSL is specific to Debian and will need to be modified on other
 # systems until we have a better mechanism for finding the correct path.
+srcdir=@srcdir@
 
 BOOK = auqbg000
 
@@ -31,22 +32,30 @@ DOCBOOK2PDF = @DOCBOOK2PDF@
 DBTOEPUB = $(DOCBOOK_STYLESHEETS)/epub/bin/dbtoepub
 KINDLEGEN = @KINDLEGEN@
 
+XSL_FLAGS = --path '@abs_builddir@'
+
 index.html: $(SRCS)
-	$(XSLTPROC) --param navig.graphics 1 \
+	$(XSLTPROC) $(XSL_FLAGS) \
+	    --param navig.graphics 1 \
 	    --param use.id.as.filename 1 \
-	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) $(BOOK).xml
+	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) \
+	    $(srcdir)/$(BOOK).xml
 
 $(BOOK).pdf: $(SRCS)
 	if test "x$(DOCBOOK2PDF)" = "xfop"; then \
-		$(XSLTPROC) $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl $(BOOK).xml > $(BOOK).fo; \
+		$(XSLTPROC) $(XSL_FLAGS) \
+		    $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl \
+		    $(srcdir)/$(BOOK).xml > $(BOOK).fo; \
 		$(DOCBOOK2PDF) $(BOOK).fo $(BOOK).pdf; \
 	else \
-		$(DOCBOOK2PDF) $(BOOK).xml; \
+		$(DOCBOOK2PDF) --output=$@ --xslt-opts="$(XSL_FLAGS)" \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).epub: $(SRCS)
 	if test -x "$(DBTOEPUB)" ; then \
-		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl $(BOOK).xml; \
+		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).mobi: $(BOOK).epub
@@ -55,7 +64,7 @@ $(BOOK).mobi: $(BOOK).epub
 	fi
 
 check:
-	xmllint --noout --valid $(BOOK).xml
+	xmllint $(XSL_FLAGS) --noout --valid $(srcdir)/$(BOOK).xml
 
 clean:
 	rm -f *.aux *.epub *.fo *.html *.log *.mobi *.out *.pdf
diff --git a/doc/xml/UserGuide/Makefile.in b/doc/xml/UserGuide/Makefile.in
index 1a0fe66d62..41048648c0 100644
--- a/doc/xml/UserGuide/Makefile.in
+++ b/doc/xml/UserGuide/Makefile.in
@@ -12,6 +12,7 @@
 #
 # HTML_XSL is possibly specific to Debian and may need to be modified on other
 # systems.
+srcdir=@srcdir@
 
 BOOK = auusg000
 
@@ -31,22 +32,30 @@ DOCBOOK2PDF = @DOCBOOK2PDF@
 DBTOEPUB = $(DOCBOOK_STYLESHEETS)/epub/bin/dbtoepub
 KINDLEGEN = @KINDLEGEN@
 
+XSL_FLAGS = --path '@abs_builddir@'
+
 index.html: $(SRCS)
-	$(XSLTPROC) --param navig.graphics 1 \
+	$(XSLTPROC) $(XSL_FLAGS) \
+	    --param navig.graphics 1 \
 	    --param use.id.as.filename 1 \
-	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) $(BOOK).xml
+	    --stringparam navig.graphics.path ../ $(DOCBOOK_STYLESHEETS)/$(HTML_XSL) \
+	    $(srcdir)/$(BOOK).xml
 
 $(BOOK).pdf: $(SRCS)
 	if test "x$(DOCBOOK2PDF)" = "xfop"; then \
-		$(XSLTPROC) $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl $(BOOK).xml > $(BOOK).fo; \
+		$(XSLTPROC) $(XSL_FLAGS) \
+		    $(DOCBOOK_STYLESHEETS)/fo/docbook.xsl \
+		    $(srcdir)/$(BOOK).xml > $(BOOK).fo; \
 		$(DOCBOOK2PDF) $(BOOK).fo $(BOOK).pdf; \
 	else \
-		$(DOCBOOK2PDF) $(BOOK).xml; \
+		$(DOCBOOK2PDF) --output=$@ --xslt-opts="$(XSL_FLAGS)" \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).epub: $(SRCS)
 	if test -x "$(DBTOEPUB)" ; then \
-		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl $(BOOK).xml; \
+		$(DBTOEPUB) -s $(TOP_SRCDIR)/../doc/xml/mobi-fixup.xsl \
+		    $(srcdir)/$(BOOK).xml; \
 	fi
 
 $(BOOK).mobi: $(BOOK).epub
@@ -55,7 +64,7 @@ $(BOOK).mobi: $(BOOK).epub
 	fi
 
 check:
-	xmllint --noout --valid $(BOOK).xml
+	xmllint $(XSL_FLAGS) --noout --valid $(srcdir)/$(BOOK).xml
 
 clean:
 	rm -f *.aux *.epub *.fo *.html *.log *.mobi *.out *.pdf
diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c
index 87e4ac5f89..ffe5f70ae8 100644
--- a/src/WINNT/afsd/cm_ioctl.c
+++ b/src/WINNT/afsd/cm_ioctl.c
@@ -545,6 +545,8 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
 
             rxconnp = cm_GetRxConn(connp);
             code = RXAFS_StoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
+	    if (code == RXGEN_OPCODE)
+		code = RXAFS_OldStoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
             rx_PutConnection(rxconnp);
 
         } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &fileStatus, &volSync, NULL, NULL, code));
diff --git a/src/WINNT/install/NSIS/CellServDB b/src/WINNT/install/NSIS/CellServDB
index 63e3330a38..4d6e83a52e 100644
--- a/src/WINNT/install/NSIS/CellServDB
+++ b/src/WINNT/install/NSIS/CellServDB
@@ -1,4 +1,4 @@
->grand.central.org      #GCO Public CellServDB 31 Oct 2023
+>grand.central.org      #GCO Public CellServDB 15 Aug 2025
 18.9.48.14                      #grand.mit.edu
 128.2.13.219                    #grand-old-opry.central.org
 >wu-wien.ac.at          #University of Economics, Vienna, Austria
@@ -21,14 +21,12 @@
 132.216.24.122                  #germain.sums.math.mcgill.ca
 132.216.24.125                  #turing.sums.math.mcgill.ca
 >ualberta.ca            #University of Alberta
-129.128.1.131                   #file13.ucs.ualberta.ca
-129.128.98.17                   #mystery.ucs.ualberta.ca
 129.128.125.40                  #drake.ucs.ualberta.ca
 >cern.ch                #European Laboratory for Particle Physics, Geneva
-137.138.54.120                  #afsdb13.cern.ch
 188.184.21.218                  #afsdb11.cern.ch
 188.184.23.130                  #afsdb14.cern.ch
 188.184.81.230                  #afsdb12.cern.ch
+188.185.50.42                   #afsdb13.cern.ch
 >ams.cern.ch            #AMS Experiment
 >epfl.ch                #Swiss Federal Institute of Technology at Lausanne
 128.178.109.111                 #kd1.epfl.ch
@@ -57,9 +55,9 @@
 195.113.0.37                    #obelix.ruk.cuni.cz
 195.113.0.40                    #sal.ruk.cuni.cz
 >ics.muni.cz            #Masaryk university
-147.228.240.30                  #afs-plzen.meta.zcu.cz
+78.128.242.247                  #afs-plzen2.meta.zcu.cz
+78.128.246.55                   #afs-praha2.grid.cesnet.cz
 147.251.3.244                   #kuduk1.ics.muni.cz
-195.113.214.10                  #afs-praha.grid.cesnet.cz
 >zcu.cz                 #University of West Bohemia, Czech Republic
 147.228.10.18                   #sauron.zcu.cz
 147.228.52.10                   #oknos.zcu.cz
@@ -92,8 +90,8 @@
 129.187.10.56                   #afs3.lrz-muenchen.de
 129.187.10.57                   #afs2.lrz-muenchen.de
 >ipp-garching.mpg.de    #Institut fuer Plasmaphysik
-130.183.9.5                     #afs-db1.rzg.mpg.de
-130.183.14.14                   #afs-db3.bc.rzg.mpg.de
+130.183.9.5                     #afs-db1.mpcdf.mpg.de
+130.183.14.14                   #afs-db3.mpcdf.mpg.de
 130.183.30.30                   #afs-db4.mpcdf.mpg.de
 >mpe.mpg.de             #MPE cell
 130.183.130.7                   #irafs1.mpe-garching.mpg.de
@@ -230,9 +228,6 @@
 129.170.30.144                  #dbicafs2.dartmouth.edu
 129.170.30.145                  #dbicafs3.dartmouth.edu
 >northstar.dartmouth.edu #Dartmouth College Research Computing
-129.170.137.194                 #halley.dartmouth.edu
-129.170.137.195                 #andromeda.dartmouth.edu
-129.170.137.196                 #kuiper.dartmouth.edu
 >cs.hm.edu              #Department Computer Science Munich University Of Applied Science
 129.187.208.31                  #afs1.cs.hm.edu
 >eecs.harvard.edu       #Harvard - EECS
@@ -274,9 +269,9 @@
 136.142.8.20                    #afs10.srv.cis.pitt.edu
 136.142.8.21                    #afs11.srv.cis.pitt.edu
 >cs.pitt.edu            #University of Pittsburgh - Computer Science
-136.142.55.232                  #afs01.cs.pitt.edu
-136.142.55.233                  #afs02.cs.pitt.edu
-136.142.55.234                  #afs03.cs.pitt.edu
+136.142.42.38                   #afs04.cs.pitt.edu
+136.142.42.39                   #afs05.cs.pitt.edu
+136.142.42.40                   #afs06.cs.pitt.edu
 >psc.edu                #PSC (Pittsburgh Supercomputing Center)
 128.182.59.182                  #shaggy.psc.edu
 128.182.66.184                  #velma.psc.edu
@@ -293,11 +288,6 @@
 137.112.7.13                    #afs3.rose-hulman.edu
 >cs.rose-hulman.edu     #Rose-Hulman CS Department
 137.112.40.10                   #galaxy.cs.rose-hulman.edu
->rpi.edu                #Rensselaer Polytechnic Institute
-128.113.22.11                   #saul.server.rpi.edu
-128.113.22.12                   #joab.server.rpi.edu
-128.113.22.13                   #korah.server.rpi.edu
-128.113.22.14                   #achan.server.rpi.edu
 >hep.sc.edu             #University of South Carolina, Dept. of Physics
 129.252.78.77                   #cpeven.physics.sc.edu
 >cs.stanford.edu        #Stanford University Computer Science Department
@@ -308,10 +298,6 @@
 171.64.7.222                    #afsdb1.stanford.edu
 171.64.7.234                    #afsdb2.stanford.edu
 171.64.7.246                    #afsdb3.stanford.edu
->slac.stanford.edu      #Stanford Linear Accelerator Center
-134.79.18.25                    #afsdb1.slac.stanford.edu
-134.79.18.26                    #afsdb2.slac.stanford.edu
-134.79.18.27                    #afsdb3.slac.stanford.edu
 >physics.ucsb.edu       #UC Santa Barbara, Physics Dept
 128.111.18.161                  #ledzeppelin.physics.ucsb.edu
 >cats.ucsc.edu          #University of California, Santa Cruz
@@ -403,10 +389,6 @@
 152.66.241.6                    #afs.iit.bme.hu
 >kfki.hu                #Wigner Research Centre for Physics - Budapest, Hungary
 148.6.2.109                     #afs0.kfki.hu
->rnd.ru.is              #Reykjavik University Research and Development Network
-130.208.242.66                  #lithium.rnd.ru.is.
-130.208.242.67                  #beryllium.rnd.ru.is.
-130.208.242.68                  #boron.rnd.ru.is.
 >caspur.it              #CASPUR Inter-University Computing Consortium, Rome
 193.204.5.45                    #pomodoro.caspur.it
 193.204.5.46                    #banana.caspur.it
@@ -581,9 +563,6 @@
 130.237.244.139                 #srv05.fysik.su.se
 >f9.ijs.si              #F9, Jozef Stefan Institue
 194.249.156.1                   #brenta.ijs.si
->p-ng.si                #University of Nova Gorica
-193.2.120.2                     #solkan.p-ng.si
-193.2.120.9                     #sabotin.p-ng.si
 >ung.si                 #University of Nova Gorica
 193.2.120.63                    #afs1.ung.si
 >ihep.su                #Institute for High-Energy Physics
diff --git a/src/WINNT/install/wix/CellServDB b/src/WINNT/install/wix/CellServDB
index 63e3330a38..4d6e83a52e 100644
--- a/src/WINNT/install/wix/CellServDB
+++ b/src/WINNT/install/wix/CellServDB
@@ -1,4 +1,4 @@
->grand.central.org      #GCO Public CellServDB 31 Oct 2023
+>grand.central.org      #GCO Public CellServDB 15 Aug 2025
 18.9.48.14                      #grand.mit.edu
 128.2.13.219                    #grand-old-opry.central.org
 >wu-wien.ac.at          #University of Economics, Vienna, Austria
@@ -21,14 +21,12 @@
 132.216.24.122                  #germain.sums.math.mcgill.ca
 132.216.24.125                  #turing.sums.math.mcgill.ca
 >ualberta.ca            #University of Alberta
-129.128.1.131                   #file13.ucs.ualberta.ca
-129.128.98.17                   #mystery.ucs.ualberta.ca
 129.128.125.40                  #drake.ucs.ualberta.ca
 >cern.ch                #European Laboratory for Particle Physics, Geneva
-137.138.54.120                  #afsdb13.cern.ch
 188.184.21.218                  #afsdb11.cern.ch
 188.184.23.130                  #afsdb14.cern.ch
 188.184.81.230                  #afsdb12.cern.ch
+188.185.50.42                   #afsdb13.cern.ch
 >ams.cern.ch            #AMS Experiment
 >epfl.ch                #Swiss Federal Institute of Technology at Lausanne
 128.178.109.111                 #kd1.epfl.ch
@@ -57,9 +55,9 @@
 195.113.0.37                    #obelix.ruk.cuni.cz
 195.113.0.40                    #sal.ruk.cuni.cz
 >ics.muni.cz            #Masaryk university
-147.228.240.30                  #afs-plzen.meta.zcu.cz
+78.128.242.247                  #afs-plzen2.meta.zcu.cz
+78.128.246.55                   #afs-praha2.grid.cesnet.cz
 147.251.3.244                   #kuduk1.ics.muni.cz
-195.113.214.10                  #afs-praha.grid.cesnet.cz
 >zcu.cz                 #University of West Bohemia, Czech Republic
 147.228.10.18                   #sauron.zcu.cz
 147.228.52.10                   #oknos.zcu.cz
@@ -92,8 +90,8 @@
 129.187.10.56                   #afs3.lrz-muenchen.de
 129.187.10.57                   #afs2.lrz-muenchen.de
 >ipp-garching.mpg.de    #Institut fuer Plasmaphysik
-130.183.9.5                     #afs-db1.rzg.mpg.de
-130.183.14.14                   #afs-db3.bc.rzg.mpg.de
+130.183.9.5                     #afs-db1.mpcdf.mpg.de
+130.183.14.14                   #afs-db3.mpcdf.mpg.de
 130.183.30.30                   #afs-db4.mpcdf.mpg.de
 >mpe.mpg.de             #MPE cell
 130.183.130.7                   #irafs1.mpe-garching.mpg.de
@@ -230,9 +228,6 @@
 129.170.30.144                  #dbicafs2.dartmouth.edu
 129.170.30.145                  #dbicafs3.dartmouth.edu
 >northstar.dartmouth.edu #Dartmouth College Research Computing
-129.170.137.194                 #halley.dartmouth.edu
-129.170.137.195                 #andromeda.dartmouth.edu
-129.170.137.196                 #kuiper.dartmouth.edu
 >cs.hm.edu              #Department Computer Science Munich University Of Applied Science
 129.187.208.31                  #afs1.cs.hm.edu
 >eecs.harvard.edu       #Harvard - EECS
@@ -274,9 +269,9 @@
 136.142.8.20                    #afs10.srv.cis.pitt.edu
 136.142.8.21                    #afs11.srv.cis.pitt.edu
 >cs.pitt.edu            #University of Pittsburgh - Computer Science
-136.142.55.232                  #afs01.cs.pitt.edu
-136.142.55.233                  #afs02.cs.pitt.edu
-136.142.55.234                  #afs03.cs.pitt.edu
+136.142.42.38                   #afs04.cs.pitt.edu
+136.142.42.39                   #afs05.cs.pitt.edu
+136.142.42.40                   #afs06.cs.pitt.edu
 >psc.edu                #PSC (Pittsburgh Supercomputing Center)
 128.182.59.182                  #shaggy.psc.edu
 128.182.66.184                  #velma.psc.edu
@@ -293,11 +288,6 @@
 137.112.7.13                    #afs3.rose-hulman.edu
 >cs.rose-hulman.edu     #Rose-Hulman CS Department
 137.112.40.10                   #galaxy.cs.rose-hulman.edu
->rpi.edu                #Rensselaer Polytechnic Institute
-128.113.22.11                   #saul.server.rpi.edu
-128.113.22.12                   #joab.server.rpi.edu
-128.113.22.13                   #korah.server.rpi.edu
-128.113.22.14                   #achan.server.rpi.edu
 >hep.sc.edu             #University of South Carolina, Dept. of Physics
 129.252.78.77                   #cpeven.physics.sc.edu
 >cs.stanford.edu        #Stanford University Computer Science Department
@@ -308,10 +298,6 @@
 171.64.7.222                    #afsdb1.stanford.edu
 171.64.7.234                    #afsdb2.stanford.edu
 171.64.7.246                    #afsdb3.stanford.edu
->slac.stanford.edu      #Stanford Linear Accelerator Center
-134.79.18.25                    #afsdb1.slac.stanford.edu
-134.79.18.26                    #afsdb2.slac.stanford.edu
-134.79.18.27                    #afsdb3.slac.stanford.edu
 >physics.ucsb.edu       #UC Santa Barbara, Physics Dept
 128.111.18.161                  #ledzeppelin.physics.ucsb.edu
 >cats.ucsc.edu          #University of California, Santa Cruz
@@ -403,10 +389,6 @@
 152.66.241.6                    #afs.iit.bme.hu
 >kfki.hu                #Wigner Research Centre for Physics - Budapest, Hungary
 148.6.2.109                     #afs0.kfki.hu
->rnd.ru.is              #Reykjavik University Research and Development Network
-130.208.242.66                  #lithium.rnd.ru.is.
-130.208.242.67                  #beryllium.rnd.ru.is.
-130.208.242.68                  #boron.rnd.ru.is.
 >caspur.it              #CASPUR Inter-University Computing Consortium, Rome
 193.204.5.45                    #pomodoro.caspur.it
 193.204.5.46                    #banana.caspur.it
@@ -581,9 +563,6 @@
 130.237.244.139                 #srv05.fysik.su.se
 >f9.ijs.si              #F9, Jozef Stefan Institue
 194.249.156.1                   #brenta.ijs.si
->p-ng.si                #University of Nova Gorica
-193.2.120.2                     #solkan.p-ng.si
-193.2.120.9                     #sabotin.p-ng.si
 >ung.si                 #University of Nova Gorica
 193.2.120.63                    #afs1.ung.si
 >ihep.su                #Institute for High-Energy Physics
diff --git a/src/afs/AIX/osi_vfsops.c b/src/afs/AIX/osi_vfsops.c
index 71c1553ac9..2aea66a73f 100644
--- a/src/afs/AIX/osi_vfsops.c
+++ b/src/afs/AIX/osi_vfsops.c
@@ -124,7 +124,7 @@ afs_root_nolock(struct vfs *afsp, struct vnode **avpp)
 	}
 	credp = crref();
 	if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		afs_globalVp = tvp;
diff --git a/src/afs/DARWIN/osi_inode.c b/src/afs/DARWIN/osi_inode.c
index e3d6866384..6ed3763f4b 100644
--- a/src/afs/DARWIN/osi_inode.c
+++ b/src/afs/DARWIN/osi_inode.c
@@ -27,6 +27,7 @@ extern struct ucred *afs_osi_credp;
 extern int afs_CacheFSType;
 
 #ifdef AFS_DARWIN80_ENV
+int
 getinode(fs, dev, inode, vpp, perror)
     mount_t fs;
     vnode_t *vpp;
@@ -56,7 +57,7 @@ getinode(fs, dev, inode, vpp, perror)
     }
 }    
     
-  
+int
 igetinode(vfsp, dev, inode, vpp, va, perror)
     vnode_t *vpp;
     mount_t vfsp;
diff --git a/src/afs/DARWIN/osi_vfsops.c b/src/afs/DARWIN/osi_vfsops.c
index 27bc7ba330..08d9ad34c8 100644
--- a/src/afs/DARWIN/osi_vfsops.c
+++ b/src/afs/DARWIN/osi_vfsops.c
@@ -65,7 +65,7 @@ int
 afs_statfs(struct mount *mp, STATFS_TYPE *abp, CTX_TYPE ctx);
 #ifdef AFS_DARWIN80_ENV
 int
-afs_mount(struct mount *mp, vnode_t *devvp, user_addr_t data, vfs_context_t ctx)
+afs_mount(struct mount *mp, vnode_t devvp, user_addr_t data, vfs_context_t ctx)
 #else
 int
 afs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, CTX_TYPE ctx)
@@ -257,7 +257,7 @@ again:
 	    ? &afs_rootFid : (struct VenusFid *)mdata;
 
 	if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
-	    tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(rootFid, &treq);
 #ifdef AFS_DARWIN80_ENV
             if (tvp) {
 	        AFS_GUNLOCK();
@@ -531,7 +531,7 @@ afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     return ENOTSUP;
 }
 
-typedef (*PFI) ();
+typedef int (*PFI) ();
 extern int vfs_opv_numops;	/* The total number of defined vnode operations */
 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
 int
diff --git a/src/afs/DARWIN/osi_vnodeops.c b/src/afs/DARWIN/osi_vnodeops.c
index a92ed53586..494b3628b3 100644
--- a/src/afs/DARWIN/osi_vnodeops.c
+++ b/src/afs/DARWIN/osi_vnodeops.c
@@ -160,7 +160,7 @@ struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
     {VOPPREF(blktooff_desc), (VOPFUNC)afs_vop_blktooff},	/* blktooff */
     {VOPPREF(offtoblk_desc), (VOPFUNC)afs_vop_offtoblk},	/* offtoblk */
     {VOPPREF(bwrite_desc), (VOPFUNC)vn_bwrite},
-    {NULL, (void (*)())NULL}
+    {NULL}
 };
 struct vnodeopv_desc afs_vnodeop_opv_desc =
     { &afs_vnodeop_p, afs_vnodeop_entries };
@@ -203,7 +203,7 @@ struct vnodeopv_entry_desc afs_dead_vnodeop_entries[] = {
     {VOPPREF(blktooff_desc), (VOPFUNC)err_blktooff},	/* blktooff */
     {VOPPREF(offtoblk_desc), (VOPFUNC)err_offtoblk},	/* offtoblk */
     {VOPPREF(bwrite_desc), (VOPFUNC)err_bwrite},
-    {NULL, (void (*)())NULL}
+    {NULL}
 };
 struct vnodeopv_desc afs_dead_vnodeop_opv_desc =
     { &afs_dead_vnodeop_p, afs_dead_vnodeop_entries };
@@ -1838,6 +1838,7 @@ afs_vop_reclaim(ap)
 /*
  * Return POSIX pathconf information applicable to ufs filesystems.
  */
+int
 afs_vop_pathconf(ap)
      struct VOPPROT(pathconf_args)	/* {
 				 * struct vnode *a_vp;
diff --git a/src/afs/FBSD/osi_vfsops.c b/src/afs/FBSD/osi_vfsops.c
index 8a979db6d7..9fb3f0f235 100644
--- a/src/afs/FBSD/osi_vfsops.c
+++ b/src/afs/FBSD/osi_vfsops.c
@@ -209,7 +209,7 @@ tryagain:
 	error = 0;
     } else {
 	if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		gvp = afs_globalVp;
diff --git a/src/afs/HPUX/osi_vfsops.c b/src/afs/HPUX/osi_vfsops.c
index 46faca7433..04966f5721 100644
--- a/src/afs/HPUX/osi_vfsops.c
+++ b/src/afs/HPUX/osi_vfsops.c
@@ -128,7 +128,7 @@ afs_root(struct vfs *afsp, struct vnode **avpp, char *unused1)
 
 	if (!(code = afs_InitReq(&treq, p_cred(u.u_procp)))
 	    && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		afs_globalVp = tvp;
diff --git a/src/afs/IRIX/osi_vfsops.c b/src/afs/IRIX/osi_vfsops.c
index 54362a1d5f..5b29ed215f 100644
--- a/src/afs/IRIX/osi_vfsops.c
+++ b/src/afs/IRIX/osi_vfsops.c
@@ -248,7 +248,7 @@ afs_root(OSI_VFS_ARG(afsp), avpp)
 
 	if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
 	    && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		afs_globalVp = tvp;
@@ -483,7 +483,7 @@ afs_vget(OSI_VFS_DECL(afsp), vnode_t ** avcp, struct fid * fidp)
 	if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
 	    goto out;
 	*avcp =
-	    (vnode_t *) afs_GetVCache(&vfid, &treq, NULL, (struct vcache *)0);
+	    (vnode_t *) afs_GetVCache(&vfid, &treq);
 	if (!*avcp) {
 	    code = EIO;
 	}
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index e8b8f100ed..2d75ed6ca3 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -48,7 +48,7 @@ SetPageError(struct page *p)
 # define kthread_complete_and_exit complete_and_exit
 #endif
 
-#if defined(STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT) && !defined(DCACHE_NEED_AUTOMOUNT)
+#if defined(STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT) && !defined(HAVE_DCACHE_NEED_AUTOMOUNT)
 # define DCACHE_NEED_AUTOMOUNT DMANAGED_AUTOMOUNT
 #endif
 
@@ -123,31 +123,28 @@ afs_posix_test_lock(struct file *fp, struct file_lock *flp) {
 #endif
 }
 
-#ifdef DCACHE_NFSFS_RENAMED
 static inline void
-afs_linux_clear_nfsfs_renamed(struct dentry *dp) {
+afs_linux_clear_nfsfs_renamed(struct dentry *dp)
+{
     spin_lock(&dp->d_lock);
     dp->d_flags &= ~DCACHE_NFSFS_RENAMED;
     spin_unlock(&dp->d_lock);
 }
 
 static inline void
-afs_linux_set_nfsfs_renamed(struct dentry *dp) {
+afs_linux_set_nfsfs_renamed(struct dentry *dp)
+{
     spin_lock(&dp->d_lock);
     dp->d_flags |= DCACHE_NFSFS_RENAMED;
     spin_unlock(&dp->d_lock);
 }
 
 static inline int
-afs_linux_nfsfs_renamed(struct dentry *dp) {
+afs_linux_nfsfs_renamed(struct dentry *dp)
+{
     return dp->d_flags & DCACHE_NFSFS_RENAMED;
 }
 
-#else
-static inline void afs_linux_clear_nfsfs_renamed(void) { return; }
-static inline void afs_linux_set_nfsfs_renamed(void) { return; }
-#endif
-
 #ifndef HAVE_LINUX_HLIST_UNHASHED
 static void
 hlist_unhashed(const struct hlist_node *h) {
@@ -161,7 +158,8 @@ hlist_unhashed(const struct hlist_node *h) {
 
 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN) && \
     !defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN_WITHFLAGS) && \
-    !defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN_NOFLAGS)
+    !defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN_NOFLAGS) && \
+    !defined(HAVE_LINUX_FILEMAP_GET_FOLIO)
 static inline struct page *
 grab_cache_page_write_begin(struct address_space *mapping, pgoff_t index,
 			    unsigned int flags) {
@@ -309,6 +307,18 @@ afs_linux_cred_is_current(afs_ucred_t *cred)
 }
 #endif
 
+/* Folio / Page wrappers */
+
+static inline pgoff_t
+afs_page_index(struct page *p)
+{
+#if defined(STRUCT_PAGE_HAS___FOLIO_INDEX)
+    return p->__folio_index;
+#else
+    return p->index;
+#endif
+}
+
 #ifndef HAVE_LINUX_PAGE_OFFSET
 static inline loff_t
 page_offset(struct page *pp)
@@ -835,4 +845,81 @@ afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs)
 
 #endif /* D_ALIAS_IS_HLIST */
 
+static inline void
+afs_page_wait_locked(struct page *p)
+{
+#if defined(HAVE_LINUX_FOLIO_WAIT_LOCKED)
+    return folio_wait_locked(page_folio(p));
+#else
+    return wait_on_page_locked(p);
+#endif
+}
+static inline void
+afs_put_page(struct page *p)
+{
+#if defined(HAVE_LINUX_FOLIO_WAIT_LOCKED)
+    return folio_put(page_folio(p));
+#else
+    return put_page(p);
+#endif
+}
+
+/*
+ * Test to see if the folio associated with a page is locked.
+ * Compatibility function for when the code is dealing with pages and is
+ * referencing the head page of a folio instead of referencing the folio directly.
+ */
+static inline int
+afs_FolioLocked(struct page *page)
+{
+#if defined(HAVE_LINUX_READAHEAD_FOLIO)
+    return folio_test_locked(page_folio(page));
+#else
+    return PageLocked(page);
+#endif
+}
+
+/*
+ * Unlock the folio associated with a page.
+ * Compatibility function for when the code is dealing with pages and is
+ * referencing the head page of a folio instead of referencing the folio directly.
+ */
+static inline void
+afs_unlock_folio(struct page *page)
+{
+#if defined(HAVE_LINUX_READAHEAD_FOLIO)
+    folio_unlock(page_folio(page));
+#else
+    unlock_page(page);
+#endif
+}
+
+#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD)
+static inline struct page *
+afs_readahead_folio(struct readahead_control *rac)
+{
+# if defined(HAVE_LINUX_READAHEAD_FOLIO)
+    struct folio *folio;
+
+    folio = __readahead_folio(rac);
+    if (folio == NULL) {
+	return NULL;
+    }
+    return folio_page(folio, 0);
+# else
+    return readahead_page(rac);
+# endif
+}
+#endif
+
+static inline struct dentry *
+afs_lookup_noperm(char *name, struct dentry *dp)
+{
+#if defined(HAVE_LINUX_LOOKUP_NOPERM)
+    return lookup_noperm(&QSTR(name), dp);
+#else
+    return lookup_one_len(name, dp, strlen(name));
+#endif
+}
+
 #endif /* AFS_LINUX_OSI_COMPAT_H */
diff --git a/src/afs/LINUX/osi_export.c b/src/afs/LINUX/osi_export.c
index 631500146f..3a40eaec15 100644
--- a/src/afs/LINUX/osi_export.c
+++ b/src/afs/LINUX/osi_export.c
@@ -424,7 +424,7 @@ static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
     tfid = tvp->mtpoint;
     afs_PutVolume(tvp, READ_LOCK);
 
-    tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+    tvc = afs_GetVCache(&tfid, areq);
     if (!tvc) {
 #ifdef OSI_EXPORT_DEBUG
 	printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
@@ -486,7 +486,7 @@ static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
 	afs_DestroyAttr(vattr);
 	return ERR_PTR(-afs_CheckCode(code, NULL, 101));
     }
-    vcp = afs_GetVCache(afid, treq, NULL, NULL);
+    vcp = afs_GetVCache(afid, treq);
     if (vcp == NULL) {
 #ifdef OSI_EXPORT_DEBUG
 	printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
@@ -689,7 +689,7 @@ static int afs_export_get_name(struct dentry *parent, char *name,
 	       data.fid.Cell,      data.fid.Fid.Volume,
 	       data.fid.Fid.Vnode, data.fid.Fid.Unique);
 #endif
-	vcp = afs_GetVCache(&data.fid, treq, NULL, NULL);
+	vcp = afs_GetVCache(&data.fid, treq);
 	if (vcp) {
 	    ObtainReadLock(&vcp->lock);
 	    if (strlen(vcp->linkData + 1) <= NAME_MAX)
diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c
index 0fc9beba06..d3b00af70a 100644
--- a/src/afs/LINUX/osi_module.c
+++ b/src/afs/LINUX/osi_module.c
@@ -136,6 +136,7 @@ afs_cleanup(void)
 }
 
 MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
+MODULE_DESCRIPTION("OpenAFS AFS filesystem client");
 module_init(afs_init);
 module_exit(afs_cleanup);
 
diff --git a/src/afs/LINUX/osi_pag_module.c b/src/afs/LINUX/osi_pag_module.c
index 7e8e4f15bc..6442077d5b 100644
--- a/src/afs/LINUX/osi_pag_module.c
+++ b/src/afs/LINUX/osi_pag_module.c
@@ -107,6 +107,7 @@ afspag_cleanup(void)
 }
 
 MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
+MODULE_DESCRIPTION("OpenAFS standalone PAG manager");
 module_init(afspag_init);
 module_exit(afspag_cleanup);
 
diff --git a/src/afs/LINUX/osi_pagecopy.c b/src/afs/LINUX/osi_pagecopy.c
index 061d8c640f..131b041fe5 100644
--- a/src/afs/LINUX/osi_pagecopy.c
+++ b/src/afs/LINUX/osi_pagecopy.c
@@ -228,8 +228,8 @@ static int afs_pagecopy_thread(void *unused) {
 	for (;;) {
 	    sleeppage = afs_pagecopy_checkworkload();
 	    if (sleeppage) {
-		wait_on_page_locked(sleeppage);
-		put_page(sleeppage);
+		afs_page_wait_locked(sleeppage);
+		afs_put_page(sleeppage);
 	    } else {
 		break;
 	    }
diff --git a/src/afs/LINUX/osi_sleep.c b/src/afs/LINUX/osi_sleep.c
index cdf22115fe..2c5aa53386 100644
--- a/src/afs/LINUX/osi_sleep.c
+++ b/src/afs/LINUX/osi_sleep.c
@@ -131,17 +131,15 @@ afs_addevent(char *event)
 /* Release the specified event */
 #define relevent(evp) ((evp)->refcount--)
 
-/* afs_osi_SleepSig
- *
- * Waits for an event to be notified, returning early if a signal
- * is received.  Returns EINTR if signaled, and 0 otherwise.
- */
-int
-afs_osi_SleepSig(void *event)
+static int
+afs_linux_sleep(void *event, int killable)
 {
     struct afs_event *evp;
     int seq;
     int code;
+    sigset_t saved_set;
+
+    sigemptyset(&saved_set);
 
     evp = afs_getevent(event);
     if (!evp) {
@@ -152,7 +150,24 @@ afs_osi_SleepSig(void *event)
     seq = evp->seq;
 
     AFS_GUNLOCK();
+
+    SIG_LOCK(current);
+    saved_set = current->blocked;
+    if (killable) {
+	siginitsetinv(&current->blocked, sigmask(SIGKILL));
+    } else {
+	sigfillset(&current->blocked);
+    }
+    RECALC_SIGPENDING(current);
+    SIG_UNLOCK(current);
+
     code = wait_event_freezable(evp->cond, seq != evp->seq);
+
+    SIG_LOCK(current);
+    current->blocked = saved_set;
+    RECALC_SIGPENDING(current);
+    SIG_UNLOCK(current);
+
     AFS_GLOCK();
 
     if (code == -ERESTARTSYS)
@@ -164,6 +179,17 @@ afs_osi_SleepSig(void *event)
     return code;
 }
 
+/* afs_osi_SleepSig
+ *
+ * Waits for an event to be notified, returning early if a signal
+ * is received.  Returns EINTR if signaled, and 0 otherwise.
+ */
+int
+afs_osi_SleepSig(void *event)
+{
+    return afs_linux_sleep(event, 1);
+}
+
 /* afs_osi_Sleep -- waits for an event to be notified, ignoring signals.
  * - NOTE: that on Linux, there are circumstances in which TASK_INTERRUPTIBLE
  *   can wake up, even if all signals are blocked
@@ -174,20 +200,7 @@ afs_osi_SleepSig(void *event)
 void
 afs_osi_Sleep(void *event)
 {
-    sigset_t saved_set;
-
-    SIG_LOCK(current);
-    saved_set = current->blocked;
-    sigfillset(&current->blocked);
-    RECALC_SIGPENDING(current);
-    SIG_UNLOCK(current);
-
-    afs_osi_SleepSig(event);
-
-    SIG_LOCK(current);
-    current->blocked = saved_set;
-    RECALC_SIGPENDING(current);
-    SIG_UNLOCK(current);
+    afs_linux_sleep(event, 0);
 }
 
 /* afs_osi_TimedSleep
diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c
index 43644f44b5..874aa59fdf 100644
--- a/src/afs/LINUX/osi_vcache.c
+++ b/src/afs/LINUX/osi_vcache.c
@@ -213,7 +213,7 @@ osi_ResetRootVCache(afs_uint32 volid)
     credp = crref();
     if (afs_CreateReq(&treq, credp))
 	goto out;
-    vcp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
+    vcp = afs_GetVCache(&afs_rootFid, treq);
     if (!vcp)
 	goto out;
     afs_getattr(vcp, &vattr, credp);
diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c
index bb49a5ce21..18506474ee 100644
--- a/src/afs/LINUX/osi_vfsops.c
+++ b/src/afs/LINUX/osi_vfsops.c
@@ -204,7 +204,7 @@ afs_root(struct super_block *afsp)
 	}
 
 	if (!(code = afs_CreateReq(&treq, credp)) && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, treq);
 	    if (tvp) {
 		struct inode *ip = AFSTOV(tvp);
 		struct vattr *vattr = NULL;
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 519c5da150..9508b11d27 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -546,7 +546,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
 	    afid.Fid.Unique = ntohl(de->fid.vunique);
 	    if ((avc->f.states & CForeign) == 0 && (ntohl(de->fid.vnode) & 1)) {
 		type = DT_DIR;
-	    } else if ((tvc = afs_FindVCache(&afid, 0, 0))) {
+	    } else if ((tvc = afs_FindVCache(&afid, 0))) {
 		if (tvc->mvstat != AFS_MVSTAT_FILE) {
 		    type = DT_DIR;
 		} else if (((tvc->f.states) & (CStatd | CTruth))) {
@@ -1382,42 +1382,70 @@ check_dentry_race(struct dentry *dp)
 }
 #endif /* D_SPLICE_ALIAS_RACE */
 
-/* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
- * In kernels 2.2.10 and above, we are passed an additional flags var which
- * may have either the LOOKUP_FOLLOW OR LOOKUP_DIRECTORY set in which case
- * we are advised to follow the entry if it is a link or to make sure that
- * it is a directory. But since the kernel itself checks these possibilities
- * later on, we shouldn't have to do it until later. Perhaps in the future..
+/*
+ * Wrapper functions to obtain a stable dentry d_name.
+ * When d_revalidate is called, the dentry's d_dname is unstable.
+ * The function take_dentry_name_snapshot provides a stable name.
+ */
+#if defined(HAVE_LINUX_TAKE_DENTRY_NAME_SNAPSHOT)
+static inline const char *
+get_stable_dentry_name(struct name_snapshot *s, struct dentry *dp)
+{
+    take_dentry_name_snapshot(s, dp);
+# if defined(LINUX_STRUCT_NAME_SNAPSHOT_USES_QSTR)
+    return s->name.name;
+# else
+    return s->name;
+# endif
+}
+static inline void
+release_stable_dentry_name(struct name_snapshot *s)
+{
+    return release_dentry_name_snapshot(s);
+}
+#else
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
+#  error "Missing take_dentry_name_snapshot"
+# endif
+/*
+ * For older versions of Linux (prior to the availablity of
+ * take_dentry_name_snapshot), fall back to just using the unstable version of
+ * the dentry d_name.  Several of the filesystems within the Linux code base at
+ * this level are also using an unstable dentry d_name.
+ */
+struct name_snapshot {
+    int dummy;
+};
+static inline const char *
+get_stable_dentry_name(struct name_snapshot *s, struct dentry *dp)
+{
+    return dp->d_name.name;
+}
+static inline void
+release_stable_dentry_name(struct name_snapshot *s)
+{
+    return;
+}
+#endif /* HAVE_LINUX_TAKE_DENTRY_NAME_SNAPSHOT */
+
+/*
+ * Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
  *
- * The code here assumes that on entry the global lock is not held
+ * @param[in] pvcp  vcache for the parent directory containing 'dp'
+ * @param[in] dp    the dentry we are checking
  */
 static int
-#if defined(DOP_REVALIDATE_TAKES_UNSIGNED)
-afs_linux_dentry_revalidate(struct dentry *dp, unsigned int flags)
-#elif defined(DOP_REVALIDATE_TAKES_NAMEIDATA)
-afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
-#else
-afs_linux_dentry_revalidate(struct dentry *dp, int flags)
-#endif
+dentry_revalidate_common(struct vcache *pvcp, struct dentry *dp)
 {
     cred_t *credp = NULL;
-    struct vcache *vcp, *pvcp, *tvc = NULL;
-    struct dentry *parent;
+    struct vcache *vcp, *tvc = NULL;
     int valid;
     struct afs_fakestat_state fakestate;
     int force_drop = 0;
     afs_uint32 parent_dv;
     int code = 0;
-
-#ifdef LOOKUP_RCU
-    /* We don't support RCU path walking */
-# if defined(DOP_REVALIDATE_TAKES_UNSIGNED)
-    if (flags & LOOKUP_RCU)
-# else
-    if (nd->flags & LOOKUP_RCU)
-# endif
-       return -ECHILD;
-#endif
+    struct name_snapshot dname;
+    const char *name;
 
 #ifdef D_SPLICE_ALIAS_RACE
     if (check_dentry_race(dp)) {
@@ -1426,6 +1454,8 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
     }
 #endif
 
+    name = get_stable_dentry_name(&dname, dp);
+
     AFS_GLOCK();
     afs_InitFakeStat(&fakestate);
 
@@ -1446,7 +1476,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 		if (code) {
 		    goto error;
 		}
-		if ((strcmp(dp->d_name.name, ".directory") == 0)) {
+		if ((strcmp(name, ".directory") == 0)) {
 		    tryEvalOnly = 1;
 		}
 		if (tryEvalOnly)
@@ -1462,13 +1492,11 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 		    goto bad_dentry;
 		}
 	    }
-	} else if (vcp->mvstat == AFS_MVSTAT_ROOT && *dp->d_name.name != '/') {
+	} else if (vcp->mvstat == AFS_MVSTAT_ROOT && name[0] != '/') {
 	    osi_Assert(vcp->mvid.parent != NULL);
 	}
 
-	parent = dget_parent(dp);
-	pvcp = VTOAFS(parent->d_inode);
-	parent_dv = parent_vcache_dv(parent->d_inode, credp);
+	parent_dv = parent_vcache_dv(AFSTOV(pvcp), credp);
 
 	/* If the parent's DataVersion has changed or the vnode
 	 * is longer valid, we need to do a full lookup.  VerifyVCache
@@ -1481,7 +1509,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 	    if (credp == NULL) {
 		credp = crref();
 	    }
-	    code = afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
+	    code = afs_lookup(pvcp, (char *)name, &tvc, credp);
             code = filter_enoent(code);
 	    if (code == ENOENT) {
 		/* ENOENT is not an error here. */
@@ -1492,7 +1520,6 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 	    if (code) {
 		/* We couldn't perform the lookup, so we don't know if the
 		 * dentry is valid or not. */
-		dput(parent);
 		goto error;
 	    }
 
@@ -1515,19 +1542,16 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 		 * _not_ okay. Force it to be unhashed, since the given name
 		 * doesn't point to this file anymore.
 		 */
-		dput(parent);
 		force_drop = 1;
 		goto bad_dentry;
 	    }
 
 	    code = afs_CreateAttr(&vattr);
 	    if (code) {
-		dput(parent);
 		goto error;
 	    }
 
 	    if (afs_getattr(vcp, vattr, credp)) {
-		dput(parent);
 		afs_DestroyAttr(vattr);
 		code = EIO;
 		goto error;
@@ -1542,23 +1566,15 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 	/* should we always update the attributes at this point? */
 	/* unlikely--the vcache entry hasn't changed */
 
-	dput(parent);
-
     } else {
-
 	/* 'dp' represents a cached negative lookup. */
 
-	parent = dget_parent(dp);
-	pvcp = VTOAFS(parent->d_inode);
-	parent_dv = parent_vcache_dv(parent->d_inode, credp);
+	parent_dv = parent_vcache_dv(AFSTOV(pvcp), credp);
 
 	if (parent_dv > dp->d_time || !(pvcp->f.states & CStatd)
 	    || afs_IsDynroot(pvcp)) {
-	    dput(parent);
 	    goto bad_dentry;
 	}
-
-	dput(parent);
     }
 
   good_dentry:
@@ -1593,6 +1609,8 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
     if (credp)
 	crfree(credp);
 
+    release_stable_dentry_name(&dname);
+
 #ifdef ERRORS_FROM_D_REVALIDATE
     if (code != 0) {
 	/*
@@ -1634,6 +1652,52 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 #endif
 }
 
+#if defined(DOP_REVALIDATE_TAKES_PARENT_INODE)
+static int
+afs_linux_dentry_revalidate(struct inode *parent_inode, const struct qstr *name,
+			    struct dentry *dp, unsigned int flags)
+{
+    if ((flags & LOOKUP_RCU) != 0) {
+	return -ECHILD;
+    }
+    return dentry_revalidate_common(VTOAFS(parent_inode), dp);
+}
+#else
+# if defined(DOP_REVALIDATE_TAKES_UNSIGNED)
+static int
+afs_linux_dentry_revalidate(struct dentry *dp, unsigned int flags)
+# elif defined(DOP_REVALIDATE_TAKES_NAMEIDATA)
+static int
+afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
+# else
+static int
+afs_linux_dentry_revalidate(struct dentry *dp, int flags)
+# endif
+{
+    int code;
+    struct dentry *parent;
+
+# ifdef LOOKUP_RCU
+    /* We don't support RCU path walking */
+#  if defined(DOP_REVALIDATE_TAKES_UNSIGNED)
+    if ((flags & LOOKUP_RCU) != 0) {
+       return -ECHILD;
+    }
+#  else
+    if ((nd->flags & LOOKUP_RCU) != 0) {
+       return -ECHILD;
+    }
+#  endif
+# endif
+
+    parent = dget_parent(dp);
+    code = dentry_revalidate_common(VTOAFS(parent->d_inode), dp);
+    dput(parent);
+
+    return code;
+}
+#endif /* DOP_REVALIDATE_TAKES_PARENT_INODE */
+
 static void
 afs_dentry_iput(struct dentry *dp, struct inode *ip)
 {
@@ -1967,8 +2031,7 @@ afs_linux_sillyrename(struct inode *dir, struct dentry *dentry,
 	__name = afs_newname();
 	AFS_GUNLOCK();
 
-	__dp = lookup_one_len(__name, dentry->d_parent, strlen(__name));
-
+	__dp = afs_lookup_noperm(__name, dentry->d_parent);
 	if (IS_ERR(__dp)) {
 	    osi_FreeSmallSpace(__name);
 	    return EBUSY;
@@ -2065,8 +2128,11 @@ out:
     crfree(credp);
     return afs_convert_code(code);
 }
-
-#if defined(IOP_TAKES_MNT_IDMAP)
+#if defined(HAVE_LINUX_INODE_OPERATIONS_MKDIR_RETURN_DENTRY)
+static struct dentry *
+afs_linux_mkdir(struct mnt_idmap *idmap, struct inode *dip,
+		struct dentry *dp, umode_t mode)
+#elif defined(IOP_TAKES_MNT_IDMAP)
 static int
 afs_linux_mkdir(struct mnt_idmap *idmap, struct inode *dip,
 		struct dentry *dp, umode_t mode)
@@ -2117,7 +2183,12 @@ out:
     AFS_GUNLOCK();
 
     crfree(credp);
+
+#if defined(HAVE_LINUX_INODE_OPERATIONS_MKDIR_RETURN_DENTRY)
+    return ERR_PTR(afs_convert_code(code));
+#else
     return afs_convert_code(code);
+#endif
 }
 
 static int
@@ -2343,7 +2414,7 @@ afs_page_cache_alloc(struct address_space *cachemapping)
     if (folio == NULL) {
 	return NULL;
     }
-    return &folio->page;
+    return folio_page(folio, 0);
 #else
     return page_cache_alloc(cachemapping);
 #endif
@@ -2419,7 +2490,7 @@ afs_linux_read_cache(struct file *cachefp, struct page *page,
 	 * even when an error is returned. */
 	code = mapping_read_page(cachemapping, cachepage);
 	if (!code && !task) {
-	    wait_on_page_locked(cachepage);
+	    afs_page_wait_locked(cachepage);
 	}
     } else {
         unlock_page(cachepage);
@@ -2445,8 +2516,9 @@ afs_linux_read_cache(struct file *cachefp, struct page *page,
         unlock_page(page);
     }
 
-    if (cachepage)
-	put_page(cachepage);
+    if (cachepage != NULL) {
+	afs_put_page(cachepage);
+    }
 
     return code;
 }
@@ -2728,28 +2800,31 @@ afs_linux_bypass_readahead(struct readahead_control *rac)
     iovecp = ancr->auio->uio_iov;
 
     for (page_ix = 0; page_ix < num_pages; ++page_ix) {
-	pp = readahead_page(rac);
-	if (pp == NULL)
+	pp = afs_readahead_folio(rac);
+	if (pp == NULL) {
 	    break;
+	}
 
 	isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_SHIFT;
-	if (pp->index > isize) {
-	    if (PageLocked(pp))
-		unlock_page(pp);
-	    put_page(pp);
+	if (afs_page_index(pp) > isize) {
+	    if (afs_FolioLocked(pp)) {
+		afs_unlock_folio(pp);
+	    }
+	    afs_put_page(pp);
 	    continue;
 	}
 
 	if (page_ix == 0) {
 	    offset = page_offset(pp);
 	    ancr->offset = ancr->auio->uio_offset = offset;
-	    base_index = pp->index;
+	    base_index = afs_page_index(pp);
 	}
 	iovecp[page_ix].iov_len = PAGE_SIZE;
-	if (base_index != pp->index) {
-	    if (PageLocked(pp))
-		 unlock_page(pp);
-	    put_page(pp);
+	if (base_index != afs_page_index(pp)) {
+	    if (afs_FolioLocked(pp)) {
+		 afs_unlock_folio(pp);
+	    }
+	    afs_put_page(pp);
 	    iovecp[page_ix].iov_base = NULL;
 	    base_index++;
 	    ancr->length -= PAGE_SIZE;
@@ -2990,7 +3065,7 @@ afs_linux_readpage(struct file *fp, struct page *pp)
 static int
 afs_linux_read_folio(struct file *fp, struct folio *folio)
 {
-    struct page *pp = &folio->page;
+    struct page *pp = folio_page(folio, 0);
 
     return afs_linux_readpage(fp, pp);
 }
@@ -3125,25 +3200,25 @@ afs_linux_readahead(struct readahead_control *rac)
 
     afs_lru_cache_init(&lrupages);
 
-    while ((page = readahead_page(rac)) != NULL) {
+    while ((page = afs_readahead_folio(rac)) != NULL) {
 	offset = page_offset(page);
 
 	code = get_dcache_readahead(&tdc, &cacheFp, avc, offset);
 	if (code != 0) {
-	    if (PageLocked(page)) {
-		unlock_page(page);
+	    if (afs_FolioLocked(page)) {
+		afs_unlock_folio(page);
 	    }
-	    put_page(page);
+	    afs_put_page(page);
 	    goto done;
 	}
 
 	if (tdc != NULL) {
 	    /* afs_linux_read_cache will unlock the page */
 	    afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupages, task);
-	} else if (PageLocked(page)) {
-	    unlock_page(page);
+	} else if (afs_FolioLocked(page)) {
+	    afs_unlock_folio(page);
 	}
-	put_page(page);
+	afs_put_page(page);
     }
 
  done:
@@ -3396,16 +3471,165 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
 }
 
 static int
-#ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
+afs_linux_begin_writeback(struct vcache *vcp, cred_t **acredp)
+{
+    int code;
+
+    AFS_GLOCK();
+    ObtainWriteLock(&vcp->lock, 537);
+    code = afs_linux_prepare_writeback(vcp);
+    if (code == AOP_WRITEPAGE_ACTIVATE) {
+	goto done;
+    }
+
+    /* Grab the creds structure currently held in the vnode, and
+     * get a reference to it, in case it goes away ... */
+    *acredp = vcp->cred;
+    if (*acredp != NULL) {
+	crhold(*acredp);
+    } else {
+	*acredp = crref();
+    }
+
+ done:
+    ReleaseWriteLock(&vcp->lock);
+    AFS_GUNLOCK();
+    return code;
+}
+
+static int
+afs_linux_end_writeback(struct vcache *vcp, cred_t **acredp, int written_size, unsigned int requested_size)
+{
+    int code;
+
+    AFS_GLOCK();
+    ObtainWriteLock(&vcp->lock, 538);
+
+    /* As much as we might like to ignore a file server error here,
+     * and just try again when we close(), unfortunately StoreAllSegments
+     * will invalidate our chunks if the server returns a permanent error,
+     * so we need to at least try and get that error back to the user
+     */
+    if (written_size == requested_size) {
+	code = afs_linux_dopartialwrite(vcp, *acredp);
+    } else {
+	code = 0;
+    }
+
+    afs_linux_complete_writeback(vcp);
+    ReleaseWriteLock(&vcp->lock);
+    crfree(*acredp);
+    *acredp = NULL;
+    AFS_GUNLOCK();
+    return code;
+}
+
+#if defined(LINUX_WRITEPAGES_USES_FOLIOS)
+/*
+ * Callback function for write_cache_pages
+ */
+static int
+afs_linux_writefolio_cb(struct folio *folio, struct writeback_control *wbc, void *priv)
+{
+    struct inode *inode;
+    struct page *pp;
+    struct address_space *mapping;
+    struct vcache *vcp;
+    cred_t *credp;
+    loff_t isize;
+
+    unsigned int to;
+
+    int code = 0;
+    int code1 = 0;
+
+    /*
+     * Ensure that huge page support wasn't slipped in without being explititly
+     * setup for the filesystem.
+     */
+    osi_Assert(!folio_test_large(folio));
+
+    folio_get(folio);
+
+    pp = folio_page(folio, 0);
+    mapping = folio->mapping;
+    to = folio_size(folio);
+
+    inode = mapping->host;
+    vcp = VTOAFS(inode);
+    isize = i_size_read(inode);
+
+    /* Don't defeat an earlier truncate */
+    if (folio_pos(folio) >= isize) {
+	folio_start_writeback(folio);
+	folio_unlock(folio);
+	goto done;
+    }
+    code = afs_linux_begin_writeback(vcp, &credp);
+    if (code == AOP_WRITEPAGE_ACTIVATE) {
+	/* WRITEPAGE_ACTIVATE is the only return value that permits us
+	 * to return with the folio still locked */
+	return code;
+    }
+
+    folio_start_writeback(folio);
+
+    folio_mark_uptodate(folio);
+
+    /* We can unlock the folio here, because it's protected by the
+     * folio_writeback flag. This should make us less vulnerable to
+     * deadlocking in afs_write and afs_DoPartialWrite
+     */
+    folio_unlock(folio);
+
+    /* If this is the final folio, then just write the number of bytes that
+     * are actually in it */
+    if ((isize - folio_pos(folio)) < to) {
+	to = isize - folio_pos(folio);
+    }
+
+    code = afs_linux_page_writeback(inode, pp, 0, to, credp);
+
+    code1 = afs_linux_end_writeback(vcp, &credp, code, to);
+
+ done:
+    folio_end_writeback(folio);
+    folio_put(folio);
+
+    /* code1 is either 0, or the error code from a partial write */
+    if (code1) {
+	return code1;
+    }
+
+    /* code is either 0, the negative error code from afs_write, or the size of
+     * the data that wasn't written by afs_write.
+     * "to" is the amount of data that was requested to be written.
+     */
+    if (code == to) {
+	return 0;
+    }
+
+    return code;
+}
+
+static int
+afs_linux_write_pages(struct address_space *mapping, struct writeback_control *wbc)
+{
+    return write_cache_pages(mapping, wbc, afs_linux_writefolio_cb, NULL);
+}
+
+#else /* LINUX_WRITEPAGES_USES_FOLIOS */
+static int
+# ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
 afs_linux_writepage(struct page *pp, struct writeback_control *wbc)
-#else
+# else
 afs_linux_writepage(struct page *pp)
-#endif
+# endif
 {
     struct address_space *mapping = pp->mapping;
     struct inode *inode;
     struct vcache *vcp;
-    cred_t *credp;
+    cred_t *credp = NULL;
     unsigned int to = PAGE_SIZE;
     loff_t isize;
     int code = 0;
@@ -3424,27 +3648,13 @@ afs_linux_writepage(struct page *pp)
 	goto done;
     }
 
-    AFS_GLOCK();
-    ObtainWriteLock(&vcp->lock, 537);
-    code = afs_linux_prepare_writeback(vcp);
+    code = afs_linux_begin_writeback(vcp, &credp);
     if (code == AOP_WRITEPAGE_ACTIVATE) {
 	/* WRITEPAGE_ACTIVATE is the only return value that permits us
 	 * to return with the page still locked */
-	ReleaseWriteLock(&vcp->lock);
-	AFS_GUNLOCK();
 	return code;
     }
 
-    /* Grab the creds structure currently held in the vnode, and
-     * get a reference to it, in case it goes away ... */
-    credp = vcp->cred;
-    if (credp)
-	crhold(credp);
-    else
-	credp = crref();
-    ReleaseWriteLock(&vcp->lock);
-    AFS_GUNLOCK();
-
     set_page_writeback(pp);
 
     SetPageUptodate(pp);
@@ -3462,21 +3672,7 @@ afs_linux_writepage(struct page *pp)
 
     code = afs_linux_page_writeback(inode, pp, 0, to, credp);
 
-    AFS_GLOCK();
-    ObtainWriteLock(&vcp->lock, 538);
-
-    /* As much as we might like to ignore a file server error here,
-     * and just try again when we close(), unfortunately StoreAllSegments
-     * will invalidate our chunks if the server returns a permanent error,
-     * so we need to at least try and get that error back to the user
-     */
-    if (code == to)
-	code1 = afs_linux_dopartialwrite(vcp, credp);
-
-    afs_linux_complete_writeback(vcp);
-    ReleaseWriteLock(&vcp->lock);
-    crfree(credp);
-    AFS_GUNLOCK();
+    code1 = afs_linux_end_writeback(vcp, &credp, code, to);
 
 done:
     end_page_writeback(pp);
@@ -3490,6 +3686,7 @@ done:
 
     return code;
 }
+#endif /* LINUX_WRITEPAGES_USES_FOLIOS */
 
 /* afs_linux_permission
  * Check access rights - returns error if can't check or permission denied.
@@ -3597,24 +3794,15 @@ afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
     return 0;
 }
 
-#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
-# if defined(HAVE_LINUX_WRITE_BEGIN_END_FOLIO)
+#if defined(HAVE_LINUX_WRITE_BEGIN_END_FOLIO)
 static int
 afs_linux_write_end(struct file *file, struct address_space *mapping,
 		    loff_t pos, unsigned len, unsigned copied,
 		    struct folio *folio, void *fsdata)
-# else
-static int
-afs_linux_write_end(struct file *file, struct address_space *mapping,
-		    loff_t pos, unsigned len, unsigned copied,
-		    struct page *page, void *fsdata)
-# endif
 {
     int code;
     unsigned int from = pos & (PAGE_SIZE - 1);
-# if defined(HAVE_LINUX_WRITE_BEGIN_END_FOLIO)
-    struct page *page = &folio->page;
-# endif
+    struct page *page = folio_page(folio, 0);
 
     code = afs_linux_commit_write(file, page, from, from + copied);
 
@@ -3623,12 +3811,79 @@ afs_linux_write_end(struct file *file, struct address_space *mapping,
     return code;
 }
 
-# if defined(HAVE_LINUX_WRITE_BEGIN_END_FOLIO)
+# if defined(HAVE_LINUX_FILEMAP_GET_FOLIO)
 static int
 afs_linux_write_begin(struct file *file, struct address_space *mapping,
 		      loff_t pos, unsigned len,
 		      struct folio **foliop, void **fsdata)
-# elif defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN_NOFLAGS)
+{
+    struct page *page;
+    pgoff_t index = pos >> PAGE_SHIFT;
+    unsigned int from = pos & (PAGE_SIZE - 1);
+    int code;
+
+    *foliop = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, mapping_gfp_mask(mapping));
+    if (IS_ERR(*foliop)) {
+	return PTR_ERR(*foliop);
+    }
+    page = folio_page(*foliop, 0);
+    code = afs_linux_prepare_write(file, page, from, from + len);
+    if (code != 0) {
+	folio_unlock(*foliop);
+	folio_put(*foliop);
+	*foliop = NULL;
+    }
+    return code;
+}
+# else /* HAVE_LINUX_FILEMAP_GET_FOLIO */
+static int
+afs_linux_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len,
+		      struct folio **foliop, void **fsdata)
+{
+    struct page *page;
+    pgoff_t index = pos >> PAGE_SHIFT;
+    unsigned int from = pos & (PAGE_SIZE - 1);
+    int code;
+
+    page = grab_cache_page_write_begin(mapping, index);
+    if (page == NULL) {
+	return -ENOMEM;
+    }
+
+    code = afs_linux_prepare_write(file, page, from, from + len);
+    if (code) {
+	unlock_page(page);
+	put_page(page);
+	page = NULL;
+    }
+
+    if (page != NULL) {
+	*foliop = page_folio(page);
+    }
+
+    return code;
+}
+# endif /* HAVE_LINUX_FILEMAP_GET_FOLIO */
+
+#elif defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
+
+static int
+afs_linux_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata)
+{
+    int code;
+    unsigned int from = pos & (PAGE_SIZE - 1);
+
+    code = afs_linux_commit_write(file, page, from, from + copied);
+
+    unlock_page(page);
+    put_page(page);
+    return code;
+}
+
+# if defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN_NOFLAGS)
 static int
 afs_linux_write_begin(struct file *file, struct address_space *mapping,
 		      loff_t pos, unsigned len,
@@ -3654,11 +3909,7 @@ afs_linux_write_begin(struct file *file, struct address_space *mapping,
 	return -ENOMEM;
     }
 
-# if defined(HAVE_LINUX_WRITE_BEGIN_END_FOLIO)
-    *foliop = page_folio(page);
-# else
     *pagep = page;
-# endif
 
     code = afs_linux_prepare_write(file, page, from, from + len);
     if (code) {
@@ -3668,7 +3919,7 @@ afs_linux_write_begin(struct file *file, struct address_space *mapping,
 
     return code;
 }
-#endif /* STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN */
+#endif /* HAVE_LINUX_WRITE_BEGIN_END_FOLIO */
 
 #ifndef STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT
 static void *
@@ -3726,9 +3977,13 @@ static struct address_space_operations afs_file_aops = {
 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD)
   .readahead =		afs_linux_readahead,
 #else
-  .readpages = 		afs_linux_readpages,
+  .readpages =		afs_linux_readpages,
 #endif
+#if defined(LINUX_WRITEPAGES_USES_FOLIOS)
+  .writepages =		afs_linux_write_pages,
+#else
   .writepage =		afs_linux_writepage,
+#endif
 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_DIRTY_FOLIO) && \
     defined(HAVE_LINUX_BLOCK_DIRTY_FOLIO)
   .dirty_folio =	block_dirty_folio,
@@ -3800,7 +4055,7 @@ afs_symlink_filler(struct file *file, struct page *page)
 static int
 afs_symlink_filler_folio(struct file *file, struct folio *folio)
 {
-    struct page *page = &folio->page;
+    struct page *page = folio_page(folio, 0);
     return afs_symlink_filler(file, page);
 }
 #endif
diff --git a/src/afs/NBSD/osi_vfsops.c b/src/afs/NBSD/osi_vfsops.c
index 5032a1dd9e..73bb8e7c36 100644
--- a/src/afs/NBSD/osi_vfsops.c
+++ b/src/afs/NBSD/osi_vfsops.c
@@ -353,7 +353,7 @@ tryagain:
 
 	if (!(code = afs_InitReq(&treq, osi_curcred()))
 	    && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 
 	    if (tvp) {
 		if (afs_globalVp) {
diff --git a/src/afs/OBSD/osi_vfsops.c b/src/afs/OBSD/osi_vfsops.c
index e7729261ea..e357e62705 100644
--- a/src/afs/OBSD/osi_vfsops.c
+++ b/src/afs/OBSD/osi_vfsops.c
@@ -343,7 +343,7 @@ afs_root(struct mount *mp, struct vnode **vpp)
     AFS_GLOCK();
     if (!(code = afs_InitReq(&treq, osi_curcred()))
 	&& !(code = afs_CheckInit())) {
-	tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	tvp = afs_GetVCache(&afs_rootFid, &treq);
 	if (tvp) {
 	    /* There is really no reason to over-hold this bugger--it's held
 	     * by the root filesystem reference. */
diff --git a/src/afs/SOLARIS/osi_vfsops.c b/src/afs/SOLARIS/osi_vfsops.c
index f3f9bd33c9..ef59a567dc 100644
--- a/src/afs/SOLARIS/osi_vfsops.c
+++ b/src/afs/SOLARIS/osi_vfsops.c
@@ -178,7 +178,7 @@ again:
 
 	if (!(code = afs_InitReq(&treq, proc->p_cred))
 	    && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		if (afs_globalVp) {
diff --git a/src/afs/UKERNEL/osi_vfsops.c b/src/afs/UKERNEL/osi_vfsops.c
index cfae3d3d79..a76d4bdd18 100644
--- a/src/afs/UKERNEL/osi_vfsops.c
+++ b/src/afs/UKERNEL/osi_vfsops.c
@@ -76,7 +76,7 @@ afs_root(OSI_VFS_DECL(afsp), struct vnode **avpp)
 
 	if (!(code = afs_InitReq(&treq, get_user_struct()->u_cred))
 	    && !(code = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+	    tvp = afs_GetVCache(&afs_rootFid, &treq);
 	    /* we really want this to stay around */
 	    if (tvp) {
 		afs_globalVp = tvp;
diff --git a/src/afs/VNOPS/afs_vnop_access.c b/src/afs/VNOPS/afs_vnop_access.c
index c8e5c20616..042d781fb1 100644
--- a/src/afs/VNOPS/afs_vnop_access.c
+++ b/src/afs/VNOPS/afs_vnop_access.c
@@ -145,7 +145,7 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
 	    dirFid.Fid.Vnode = avc->f.parent.vnode;
 	    dirFid.Fid.Unique = avc->f.parent.unique;
 	    /* Avoid this GetVCache call */
-	    tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
+	    tvc = afs_GetVCache(&dirFid, areq);
 	    if (tvc) {
 		dirBits = afs_GetAccessBits(tvc, arights, areq);
 		afs_PutVCache(tvc);
diff --git a/src/afs/VNOPS/afs_vnop_create.c b/src/afs/VNOPS/afs_vnop_create.c
index 23d5588e23..9a17c70c0a 100644
--- a/src/afs/VNOPS/afs_vnop_create.c
+++ b/src/afs/VNOPS/afs_vnop_create.c
@@ -178,10 +178,10 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
 	    newFid.Fid.Volume = adp->f.fid.Fid.Volume;
 	    tvc = NULL;
 	    if (newFid.Fid.Unique == 0) {
-		tvc = afs_LookupVCache(&newFid, treq, NULL, adp, aname);
+		tvc = afs_LookupVCache(&newFid, treq, adp, aname);
 	    }
 	    if (!tvc)		/* lookup failed or wasn't called */
-		tvc = afs_GetVCache(&newFid, treq, NULL, NULL);
+		tvc = afs_GetVCache(&newFid, treq);
 
 	    if (tvc) {
 		/* if the thing exists, we need the right access to open it.
@@ -433,7 +433,7 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
      * freeing of the vnode will change evenZaps.  Don't need to update the VLRU
      * queue, since the find will only succeed in the event of a create race, and 
      * then the vcache will be at the front of the VLRU queue anyway...  */
-    if (!(tvc = afs_FindVCache(&newFid, 0, DO_STATS))) {
+    if (!(tvc = afs_FindVCache(&newFid, DO_STATS))) {
 	tvc = afs_NewVCache(&newFid, hostp);
 	if (tvc) {
 	    int finalCBs;
diff --git a/src/afs/VNOPS/afs_vnop_dirops.c b/src/afs/VNOPS/afs_vnop_dirops.c
index 596651324d..f75b18a484 100644
--- a/src/afs/VNOPS/afs_vnop_dirops.c
+++ b/src/afs/VNOPS/afs_vnop_dirops.c
@@ -228,7 +228,7 @@ afs_mkdir(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
 	ReleaseWriteLock(&tvc->lock);
     } else {
     	/* now we're done with parent dir, create the real dir's cache entry */
-	tvc = afs_GetVCache(&newFid, treq, NULL, NULL);
+	tvc = afs_GetVCache(&newFid, treq);
     	if (tvc) {
 	    code = 0;
 	    *avcp = tvc;
@@ -323,16 +323,14 @@ afs_rmdir(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
 	unlinkFid.Fid.Vnode = 0;
 	code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
 	if (code == 0) {
-	    afs_int32 cached = 0;
-
 	    unlinkFid.Cell = adp->f.fid.Cell;
 	    unlinkFid.Fid.Volume = adp->f.fid.Fid.Volume;
 	    if (unlinkFid.Fid.Unique == 0) {
 		tvc =
-		    afs_LookupVCache(&unlinkFid, treq, &cached, adp, aname);
+		    afs_LookupVCache(&unlinkFid, treq, adp, aname);
 	    } else {
 		ObtainReadLock(&afs_xvcache);
-		tvc = afs_FindVCache(&unlinkFid, 0, 1 /* do xstats */ );
+		tvc = afs_FindVCache(&unlinkFid, 1 /* do xstats */ );
 		ReleaseReadLock(&afs_xvcache);
 	    }
 	}
@@ -394,7 +392,7 @@ afs_rmdir(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
 	    code = afs_dir_Lookup(tdc, aname, &tfid.Fid);
 
 	    ObtainSharedLock(&afs_xvcache, 764);
-	    tvc = afs_FindVCache(&tfid, 0, 1 /* do xstats */ );
+	    tvc = afs_FindVCache(&tfid, 1 /* do xstats */ );
 	    ReleaseSharedLock(&afs_xvcache);
 	    
 	    if (!tvc) {
diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c
index 0fbe4e8f95..db60c9c68d 100644
--- a/src/afs/VNOPS/afs_vnop_lookup.c
+++ b/src/afs/VNOPS/afs_vnop_lookup.c
@@ -327,6 +327,112 @@ afs_InitFakeStat(struct afs_fakestat_state *state)
     state->need_release = 0;
 }
 
+#ifdef AFS_DARWIN80_ENV
+/*
+ * Finalize a volume root vcache, after resolving a mountpoint.
+ *
+ * When we create a vcache on macOS, we need to fill in some macOS-specific
+ * info that is usually done by calling afs_darwin_finalizevnode() in the
+ * syscall that creates the vcache (e.g., creat() or a lookup). But when using
+ * fakestat, we resolve a mountpoint into the corresponding volume root vcache
+ * internally, and so we may create a vcache for the root dir, but we don't
+ * have the arguments of a syscall to provide to afs_darwin_finalizevnode().
+ *
+ * So after we have resolved a mountpoint to a root vcache, in this function we
+ * try to finalize the root vcache, and figure out the parent dir and 'name' to
+ * give to macOS for it. If we don't provide a parent for the vcache, macOS may
+ * throw bogus ENOENT errors in the future when trying to use the dir.
+ *
+ * \param a_rootvp  vcache we are finalizing (vcache for a volume root). If an
+ *		    error is returned, we free the given reference before
+ *		    returning, and set this to NULL. On success, this is
+ *		    vnode_ref()d.
+ * \param mvc   vcache of the mtpt pointing to root_vp
+ * \param areq	vrequest
+ * \param canblock  1 if we can hit the net, 0 otherwise
+ *
+ * \returns 0 on success, or error code otherwise
+ */
+static int
+afs_darwin_finalize_volroot(struct vcache **a_rootvp, struct vcache *mvc,
+			    struct vrequest *areq, int canblock)
+{
+    struct vcache *root_vp = *a_rootvp;
+    struct vcache *parent = NULL;
+    const char *rname = NULL;
+    int code, flags;
+
+    if (root_vp->mvstat != AFS_MVSTAT_ROOT) {
+	code = EINVAL;
+	goto done_locked;
+    }
+    root_vp->f.m.Type = VDIR;
+
+    if (root_vp->mvid.parent != NULL) {
+	if (!canblock) {
+	    ObtainReadLock(&afs_xvcache);
+	    parent = afs_FindVCache(root_vp->mvid.parent, 0);
+	    ReleaseReadLock(&afs_xvcache);
+	} else {
+	    parent = afs_GetVCache(root_vp->mvid.parent, areq);
+	}
+    }
+
+    AFS_GUNLOCK();
+
+    code = afs_darwin_finalizevnode(root_vp, NULL, NULL, 0, 0);
+    if (code != 0) {
+	/* afs_darwin_finalizevnode releases the ref to root_vp on error. */
+	root_vp = NULL;
+	goto done;
+    }
+
+    vnode_ref(AFSTOV(root_vp));
+
+    if (vnode_isvroot(AFSTOV(root_vp))) {
+	goto done;
+    }
+
+    if (parent == NULL) {
+	/* Don't let the caller use root_vp if we can't set a parent. */
+	struct vnode *vfs_parent = vnode_getparent(AFSTOV(root_vp));
+	if (vfs_parent != NULL) {
+	    /* ...but if it already has a parent, that's okay. */
+	    vnode_put(vfs_parent);
+	    goto done;
+	}
+	code = EIO;
+	goto done;
+    }
+
+    flags = VNODE_UPDATE_PARENT | VNODE_UPDATE_CACHE;
+    rname = vnode_getname(AFSTOV(mvc));
+    if (rname != NULL) {
+	flags |= VNODE_UPDATE_NAME;
+    }
+
+    vnode_update_identity(AFSTOV(root_vp), AFSTOV(parent), rname, 0, 0, flags);
+
+    if (rname != NULL) {
+	vnode_putname(rname);
+    }
+
+ done:
+    AFS_GLOCK();
+
+ done_locked:
+    if (parent != NULL) {
+	afs_PutVCache(parent);
+    }
+    if (root_vp != NULL && code != 0) {
+	afs_PutVCache(root_vp);
+	root_vp = NULL;
+    }
+    *a_rootvp = root_vp;
+    return code;
+}
+#endif /* AFS_DARWIN80_ENV */
+
 /*
  * afs_EvalFakeStat_int
  *
@@ -339,7 +445,7 @@ static int
 afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
 		     struct vrequest *areq, int canblock)
 {
-    struct vcache *tvc, *root_vp;
+    struct vcache *tvc;
     struct volume *tvolp = NULL;
     int code = 0;
 
@@ -372,34 +478,18 @@ afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
 	}
     }
     if (tvc->mvid.target_root && (tvc->f.states & CMValid)) {
+	struct vcache *root_vp;
 	if (!canblock) {
-	    afs_int32 retry;
-
-	    do {
-		retry = 0;
-		ObtainReadLock(&afs_xvcache);
-		root_vp = afs_FindVCache(tvc->mvid.target_root, &retry, 0);
-		if (root_vp && retry) {
-		    ReleaseReadLock(&afs_xvcache);
-		    afs_PutVCache(root_vp);
-		}
-	    } while (root_vp && retry);
+	    ObtainReadLock(&afs_xvcache);
+	    root_vp = afs_FindVCache(tvc->mvid.target_root, 0);
 	    ReleaseReadLock(&afs_xvcache);
 	} else {
-	    root_vp = afs_GetVCache(tvc->mvid.target_root, areq, NULL, NULL);
+	    root_vp = afs_GetVCache(tvc->mvid.target_root, areq);
 	}
 	if (!root_vp) {
 	    code = canblock ? EIO : 0;
 	    goto done;
 	}
-#ifdef AFS_DARWIN80_ENV
-        root_vp->f.m.Type = VDIR;
-        AFS_GUNLOCK();
-        code = afs_darwin_finalizevnode(root_vp, NULL, NULL, 0, 0);
-        AFS_GLOCK();
-        if (code) goto done;
-        vnode_ref(AFSTOV(root_vp));
-#endif
 	if (tvolp && !afs_InReadDir(root_vp)) {
 	    /* Is this always kosher?  Perhaps we should instead use
 	     * NBObtainWriteLock to avoid potential deadlock.
@@ -410,6 +500,13 @@ afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
 	    *root_vp->mvid.parent = tvolp->dotdot;
 	    ReleaseWriteLock(&root_vp->lock);
 	}
+#ifdef AFS_DARWIN80_ENV
+	code = afs_darwin_finalize_volroot(&root_vp, tvc, areq, canblock);
+	if (code != 0) {
+	    code = canblock ? code : 0;
+	    goto done;
+	}
+#endif
 	state->need_release = 1;
 	state->root_vp = root_vp;
 	*avcp = root_vp;
@@ -724,7 +821,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     int i;
     struct VenusFid afid;	/* file ID we are using now */
     struct VenusFid tfid;	/* another temp. file ID */
-    afs_int32 retry;		/* handle low-level SGI MP race conditions */
+    afs_int32 retry;		/* handle low-level VFS race conditions */
     long volStates;		/* flags from vol structure */
     struct volume *volp = 0;	/* volume ptr */
     struct VenusFid dotdot = {0, {0, 0, 0}};
@@ -870,15 +967,8 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 	    tfid.Fid.Volume = adp->f.fid.Fid.Volume;
 	    tfid.Fid.Vnode = ntohl(dirEntryp->fid.vnode);
 	    tfid.Fid.Unique = ntohl(dirEntryp->fid.vunique);
-	    do {
-		retry = 0;
-		ObtainSharedLock(&afs_xvcache, 130);
-		tvcp = afs_FindVCache(&tfid, &retry, IS_SLOCK /* no stats | LRU */ );
-		if (tvcp && retry) {
-		    ReleaseSharedLock(&afs_xvcache);
-		    afs_PutVCache(tvcp);
-		}
-	    } while (tvcp && retry);
+	    ObtainSharedLock(&afs_xvcache, 130);
+	    tvcp = afs_FindVCache(&tfid, IS_SLOCK /* no stats | LRU */ );
 	    if (!tvcp) {	/* otherwise, create manually */
 		UpgradeSToWLock(&afs_xvcache, 129);
 		tvcp = afs_NewBulkVCache(&tfid, hostp, statSeqNo);
@@ -1009,12 +1099,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 		afid.Fid.Vnode = fidsp[i].Vnode;
 		afid.Fid.Unique = fidsp[i].Unique;
 
-		do {
-		    retry = 0;
-		    ObtainReadLock(&afs_xvcache);
-		    tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */);
-		    ReleaseReadLock(&afs_xvcache);
-		} while (tvcp && retry);
+		ObtainReadLock(&afs_xvcache);
+		tvcp = afs_FindVCache(&afid, 0 /* !stats&!lru */);
+		ReleaseReadLock(&afs_xvcache);
 
 		if (!tvcp) {
 		    continue;
@@ -1170,12 +1257,10 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 	afid.Fid.Volume = adp->f.fid.Fid.Volume;
 	afid.Fid.Vnode = fidsp[i].Vnode;
 	afid.Fid.Unique = fidsp[i].Unique;
-	do {
-	    retry = 0;
-	    ObtainReadLock(&afs_xvcache);
-	    tvcp = afs_FindVCache(&afid, &retry, 0/* !stats&!lru */);
-	    ReleaseReadLock(&afs_xvcache);
-	} while (tvcp && retry);
+
+	ObtainReadLock(&afs_xvcache);
+	tvcp = afs_FindVCache(&afid, 0/* !stats&!lru */);
+	ReleaseReadLock(&afs_xvcache);
 
 	/* The entry may no longer exist */
 	if (tvcp == NULL) {
@@ -1349,12 +1434,10 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 	afid.Fid.Volume = adp->f.fid.Fid.Volume;
 	afid.Fid.Vnode = fidsp[i].Vnode;
 	afid.Fid.Unique = fidsp[i].Unique;
-	do {
-	    retry = 0;
-	    ObtainReadLock(&afs_xvcache);
-	    tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */);
-	    ReleaseReadLock(&afs_xvcache);
-	} while (tvcp && retry);
+
+	ObtainReadLock(&afs_xvcache);
+	tvcp = afs_FindVCache(&afid, 0 /* !stats&!lru */);
+	ReleaseReadLock(&afs_xvcache);
 	if (tvcp != NULL) {
 	    if ((tvcp->f.states & CBulkFetching)
 		&& (tvcp->f.m.Length == statSeqNo)) {
@@ -1526,7 +1609,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 	}
 	/* otherwise we have the fid here, so we use it */
 	/*printf("Getting vcache\n");*/
-	tvc = afs_GetVCache(adp->mvid.parent, treq, NULL, NULL);
+	tvc = afs_GetVCache(adp->mvid.parent, treq);
 	afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid.parent,
 		   ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code);
 	*avcp = tvc;
@@ -1630,7 +1713,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 	    tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
 	    tfid.Fid.Unique = volid;
 	}
-	*avcp = tvc = afs_GetVCache(&tfid, treq, NULL, NULL);
+	*avcp = tvc = afs_GetVCache(&tfid, treq);
 	code = (tvc ? 0 : EIO);
 	hit = 1;
 	goto done;
@@ -1646,7 +1729,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 	struct VenusFid tfid;
 
 	afs_GetDynrootMountFid(&tfid);
-	*avcp = tvc = afs_GetVCache(&tfid, treq, NULL, NULL);
+	*avcp = tvc = afs_GetVCache(&tfid, treq);
 	code = 0;
 	hit = 1;
 	goto done;
@@ -1820,16 +1903,12 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 	 * dirCookie tells us where to start prefetching from.
 	 */
 	if (afs_ShouldTryBulkStat(adp)) {
-	    afs_int32 retry;
 	    /* if the entry is not in the cache, or is in the cache,
 	     * but hasn't been statd, then do a bulk stat operation.
 	     */
-	    do {
-		retry = 0;
-		ObtainReadLock(&afs_xvcache);
-		tvc = afs_FindVCache(&tfid, &retry, 0 /* !stats,!lru */ );
-		ReleaseReadLock(&afs_xvcache);
-	    } while (tvc && retry);
+	    ObtainReadLock(&afs_xvcache);
+	    tvc = afs_FindVCache(&tfid, 0 /* !stats,!lru */ );
+	    ReleaseReadLock(&afs_xvcache);
 
 	    if (!tvc || !(tvc->f.states & CStatd))
 		bulkcode = afs_DoBulkStat(adp, dirCookie, treq);
@@ -1854,12 +1933,11 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 	 * the file has not yet been looked up.
 	 */
 	if (!tvc) {
-	    afs_int32 cached = 0;
 	    if (!tfid.Fid.Unique && (adp->f.states & CForeign)) {
-		tvc = afs_LookupVCache(&tfid, treq, &cached, adp, tname);
+		tvc = afs_LookupVCache(&tfid, treq, adp, tname);
 	    }
 	    if (!tvc && !bulkcode) {	/* lookup failed or wasn't called */
-		tvc = afs_GetVCache(&tfid, treq, &cached, NULL);
+		tvc = afs_GetVCache(&tfid, treq);
 	    }
 	}			/* if !tvc */
     }				/* sub-block just to reduce stack usage */
@@ -1919,9 +1997,9 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 		    if (tvolp && (tvolp->states & VForeign)) {
 			/* XXXX tvolp has ref cnt on but not locked! XXX */
 			tvc =
-			    afs_GetRootVCache(tvc->mvid.target_root, treq, NULL, tvolp);
+			    afs_GetRootVCache(tvc->mvid.target_root, treq, tvolp);
 		    } else {
-			tvc = afs_GetVCache(tvc->mvid.target_root, treq, NULL, NULL);
+			tvc = afs_GetVCache(tvc->mvid.target_root, treq);
 		    }
 		    afs_PutVCache(uvc);	/* we're done with it */
 
diff --git a/src/afs/VNOPS/afs_vnop_readdir.c b/src/afs/VNOPS/afs_vnop_readdir.c
index 573d021b0f..320f04f591 100644
--- a/src/afs/VNOPS/afs_vnop_readdir.c
+++ b/src/afs/VNOPS/afs_vnop_readdir.c
@@ -257,7 +257,7 @@ afs_readdir_type(struct vcache *avc, struct DirEntry *ade)
 	return DT_DIR;
     }
     ObtainReadLock(&afs_xvcache);
-    if ((tvc = afs_FindVCache(&tfid, 0, 0))) {
+    if ((tvc = afs_FindVCache(&tfid, 0))) {
         ReleaseReadLock(&afs_xvcache);
 	if (tvc->mvstat != AFS_MVSTAT_FILE) {
 	    afs_PutVCache(tvc);
diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c
index 9e0e86eb4f..a8b3755824 100644
--- a/src/afs/VNOPS/afs_vnop_remove.c
+++ b/src/afs/VNOPS/afs_vnop_remove.c
@@ -255,17 +255,15 @@ afs_remove(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
 	if (tdc) {
 	    code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
 	    if (code == 0) {
-		afs_int32 cached = 0;
-
 		unlinkFid.Cell = adp->f.fid.Cell;
 		unlinkFid.Fid.Volume = adp->f.fid.Fid.Volume;
 		if (unlinkFid.Fid.Unique == 0) {
 		    tvc =
-			afs_LookupVCache(&unlinkFid, treq, &cached, adp,
+			afs_LookupVCache(&unlinkFid, treq, adp,
 					 aname);
 		} else {
 		    ObtainReadLock(&afs_xvcache);
-		    tvc = afs_FindVCache(&unlinkFid, 0, DO_STATS);
+		    tvc = afs_FindVCache(&unlinkFid, DO_STATS);
 		    ReleaseReadLock(&afs_xvcache);
 		}
 	    }
@@ -437,7 +435,7 @@ afs_remunlink(struct vcache *avc, int doit)
 	    dirFid.Fid.Volume = avc->f.fid.Fid.Volume;
 	    dirFid.Fid.Vnode = avc->f.parent.vnode;
 	    dirFid.Fid.Unique = avc->f.parent.unique;
-	    adp = afs_GetVCache(&dirFid, treq, NULL, NULL);
+	    adp = afs_GetVCache(&dirFid, treq);
 
 	    if (adp) {
 		tdc = afs_FindDCache(adp, (afs_size_t) 0);
diff --git a/src/afs/VNOPS/afs_vnop_rename.c b/src/afs/VNOPS/afs_vnop_rename.c
index fcf2bcb690..12b9962489 100644
--- a/src/afs/VNOPS/afs_vnop_rename.c
+++ b/src/afs/VNOPS/afs_vnop_rename.c
@@ -201,7 +201,7 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
 	fileFid.Cell = aodp->f.fid.Cell;
 	fileFid.Fid.Volume = aodp->f.fid.Fid.Volume;
 	ObtainSharedLock(&afs_xvcache, 754);
-	tvc = afs_FindVCache(&fileFid, 0 , 1);
+	tvc = afs_FindVCache(&fileFid, 1);
 	ReleaseSharedLock(&afs_xvcache);
 
 	if (tvc) {
@@ -361,10 +361,10 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
 	unlinkFid.Cell = aodp->f.fid.Cell;
 	tvc = NULL;
 	if (!unlinkFid.Fid.Unique) {
-	    tvc = afs_LookupVCache(&unlinkFid, areq, NULL, aodp, aname1);
+	    tvc = afs_LookupVCache(&unlinkFid, areq, aodp, aname1);
 	}
 	if (!tvc)		/* lookup failed or wasn't called */
-	    tvc = afs_GetVCache(&unlinkFid, areq, NULL, NULL);
+	    tvc = afs_GetVCache(&unlinkFid, areq);
 
 	if (tvc) {
 	    ObtainWriteLock(&tvc->lock, 151);
@@ -392,9 +392,9 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
 	fileFid.Fid.Volume = aodp->f.fid.Fid.Volume;
 	fileFid.Cell = aodp->f.fid.Cell;
 	if (!fileFid.Fid.Unique)
-	    tvc = afs_LookupVCache(&fileFid, areq, NULL, andp, aname2);
+	    tvc = afs_LookupVCache(&fileFid, areq, andp, aname2);
 	else
-	    tvc = afs_GetVCache(&fileFid, areq, NULL, (struct vcache *)0);
+	    tvc = afs_GetVCache(&fileFid, areq);
 	if (tvc && (vType(tvc) == VDIR)) {
 	    ObtainWriteLock(&tvc->lock, 152);
 	    tdc1 = afs_FindDCache(tvc, (afs_size_t) 0);
diff --git a/src/afs/VNOPS/afs_vnop_strategy.c b/src/afs/VNOPS/afs_vnop_strategy.c
index 4aeb87a4ab..c7564fe161 100644
--- a/src/afs/VNOPS/afs_vnop_strategy.c
+++ b/src/afs/VNOPS/afs_vnop_strategy.c
@@ -71,7 +71,7 @@ int afs_ustrategy(struct buf *abp)
     if ((abp->b_flags & B_READ) == B_READ) {
 #endif
 	/* read b_bcount bytes into kernel address b_un.b_addr starting
-	 * at byte DEV_BSIZE * b_blkno.  Bzero anything we can't read,
+	 * at byte DEV_BSIZE * b_blkno.  Zero anything we can't read,
 	 * and finally call iodone(abp).  File is in abp->b_vp.  Credentials
 	 * are from u area??
 	 */
diff --git a/src/afs/afs_analyze.c b/src/afs/afs_analyze.c
index d927ec5248..4f06a5cf55 100644
--- a/src/afs/afs_analyze.c
+++ b/src/afs/afs_analyze.c
@@ -315,7 +315,7 @@ afs_ClearStatus(struct VenusFid *afid, int op, struct volume *avp)
     if (tvp) {
 	struct vcache *tvc;
 	ObtainReadLock(&afs_xvcache);
-	if ((tvc = afs_FindVCache(afid, 0, 0))) {
+	if ((tvc = afs_FindVCache(afid, 0))) {
 	    ReleaseReadLock(&afs_xvcache);
 	    afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB | AFS_STALEVC_NODNLC,
 				 CUnique);
diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c
index 45b3f55eb6..105b557fbb 100644
--- a/src/afs/afs_call.c
+++ b/src/afs/afs_call.c
@@ -106,6 +106,7 @@ static int
 afs_InitSetup(int preallocs)
 {
     int code;
+    afs_uint32 host;
 
     if (afs_InitSetup_done)
 	return EAGAIN;
@@ -134,6 +135,14 @@ afs_InitSetup(int preallocs)
     /* start RX */
     if(!afscall_set_rxpck_received)
     rx_extraPackets = AFS_NRXPACKETS;	/* smaller # of packets */
+
+    host = ntohl(rx_bindhost);
+    afs_warn("afs: Binding rx to %d.%d.%d.%d:%d\n",
+             (host >> 24),
+             (host >> 16) & 0xff,
+             (host >>  8) & 0xff,
+             (host)       & 0xff,
+             7001);
     code = rx_InitHost(rx_bindhost, htons(7001));
     if (code) {
 	afs_warn("AFS: RX failed to initialize %d).\n", code);
diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c
index 35fd594732..250bc6d545 100644
--- a/src/afs/afs_dcache.c
+++ b/src/afs/afs_dcache.c
@@ -104,55 +104,29 @@ afs_int32 afs_dcentries;	/*!< In-memory dcache entries */
 int dcacheDisabled = 0;
 
 struct afs_cacheOps afs_UfsCacheOps = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    osi_UFSOpen,
-    osi_UFSTruncate,
-    afs_osi_Read,
-    afs_osi_Write,
-    osi_UFSClose,
-    afs_UFSReadUIO,
-    afs_UFSWriteUIO,
-    afs_UFSGetDSlot,
-    afs_UFSGetVolSlot,
-    afs_UFSHandleLink,
-#else
-    .open 	= osi_UFSOpen,
-    .truncate	= osi_UFSTruncate,
-    .fread	= afs_osi_Read,
-    .fwrite	= afs_osi_Write,
-    .close	= osi_UFSClose,
-    .vreadUIO	= afs_UFSReadUIO,
-    .vwriteUIO	= afs_UFSWriteUIO,
-    .GetDSlot	= afs_UFSGetDSlot,
-    .GetVolSlot = afs_UFSGetVolSlot,
-    .HandleLink	= afs_UFSHandleLink,
-#endif
+    AFS_STRUCT_INIT(.open,	osi_UFSOpen),
+    AFS_STRUCT_INIT(.truncate,	osi_UFSTruncate),
+    AFS_STRUCT_INIT(.fread,	afs_osi_Read),
+    AFS_STRUCT_INIT(.fwrite,	afs_osi_Write),
+    AFS_STRUCT_INIT(.close,	osi_UFSClose),
+    AFS_STRUCT_INIT(.vreadUIO,	afs_UFSReadUIO),
+    AFS_STRUCT_INIT(.vwriteUIO,	afs_UFSWriteUIO),
+    AFS_STRUCT_INIT(.GetDSlot,	afs_UFSGetDSlot),
+    AFS_STRUCT_INIT(.GetVolSlot, afs_UFSGetVolSlot),
+    AFS_STRUCT_INIT(.HandleLink, afs_UFSHandleLink),
 };
 
 struct afs_cacheOps afs_MemCacheOps = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    afs_MemCacheOpen,
-    afs_MemCacheTruncate,
-    afs_MemReadBlk,
-    afs_MemWriteBlk,
-    afs_MemCacheClose,
-    afs_MemReadUIO,
-    afs_MemWriteUIO,
-    afs_MemGetDSlot,
-    afs_MemGetVolSlot,
-    afs_MemHandleLink,
-#else
-    .open	= afs_MemCacheOpen,
-    .truncate	= afs_MemCacheTruncate,
-    .fread	= afs_MemReadBlk,
-    .fwrite	= afs_MemWriteBlk,
-    .close	= afs_MemCacheClose,
-    .vreadUIO	= afs_MemReadUIO,
-    .vwriteUIO	= afs_MemWriteUIO,
-    .GetDSlot	= afs_MemGetDSlot,
-    .GetVolSlot	= afs_MemGetVolSlot,
-    .HandleLink	= afs_MemHandleLink,
-#endif
+    AFS_STRUCT_INIT(.open,	afs_MemCacheOpen),
+    AFS_STRUCT_INIT(.truncate,	afs_MemCacheTruncate),
+    AFS_STRUCT_INIT(.fread,	afs_MemReadBlk),
+    AFS_STRUCT_INIT(.fwrite,	afs_MemWriteBlk),
+    AFS_STRUCT_INIT(.close,	afs_MemCacheClose),
+    AFS_STRUCT_INIT(.vreadUIO,	afs_MemReadUIO),
+    AFS_STRUCT_INIT(.vwriteUIO,	afs_MemWriteUIO),
+    AFS_STRUCT_INIT(.GetDSlot,	afs_MemGetDSlot),
+    AFS_STRUCT_INIT(.GetVolSlot, afs_MemGetVolSlot),
+    AFS_STRUCT_INIT(.HandleLink, afs_MemHandleLink),
 };
 
 int cacheDiskType;		/*Type of backing disk for cache */
@@ -791,7 +765,7 @@ afs_GetDownD(int anumber, int *aneedSpace, afs_int32 buckethint)
 		/* xdcache is lower than the xvcache lock */
 		ReleaseWriteLock(&afs_xdcache);
 		ObtainReadLock(&afs_xvcache);
-		tvc = afs_FindVCache(afid, 0, 0 /* no stats, no vlru */ );
+		tvc = afs_FindVCache(afid, 0 /* no stats, no vlru */ );
 		ReleaseReadLock(&afs_xvcache);
 		ObtainWriteLock(&afs_xdcache, 527);
 		skip = 0;
@@ -1988,7 +1962,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
 
     shortcut = 0;
 
-    /* check hints first! (might could use bcmp or some such...) */
+    /* check hints first! */
     if ((tdc = avc->dchint)) {
 	int dcLocked;
 
diff --git a/src/afs/afs_disconnected.c b/src/afs/afs_disconnected.c
index 03ff90f7ea..b11c0ca618 100644
--- a/src/afs/afs_disconnected.c
+++ b/src/afs/afs_disconnected.c
@@ -263,7 +263,7 @@ afs_GetVnodeName(struct vcache *avc, struct VenusFid *afid, char *aname,
 
 	/* Get the parent dir's vcache that contains the shadow fid. */
 	ObtainSharedLock(&afs_xvcache, 755);
-	parent_vc = afs_FindVCache(&parent_fid, 0, 1);
+	parent_vc = afs_FindVCache(&parent_fid, 1);
 	ReleaseSharedLock(&afs_xvcache);
 	if (!parent_vc) {
 	    return ENETDOWN;
@@ -334,7 +334,7 @@ chk_del_children_hook(void *hdata, char *aname, afs_int32 vnode,
     tfid.Fid.Unique = unique;
 
     ObtainSharedLock(&afs_xvcache, 757);
-    tvc = afs_FindVCache(&tfid, 0, 1);
+    tvc = afs_FindVCache(&tfid, 1);
     ReleaseSharedLock(&afs_xvcache);
 
     /* Count unfinished dirty children. */
@@ -415,7 +415,7 @@ fix_children_fids_hook(void *hdata, char *aname, afs_int32 vnode,
 
 	/* Get the vcache. */
 	ObtainSharedLock(&afs_xvcache, 759);
-	tvc = afs_FindVCache(&tfid, 0, 1);
+	tvc = afs_FindVCache(&tfid, 1);
 	ReleaseSharedLock(&afs_xvcache);
 
 	/* Change the fields. */
@@ -519,7 +519,7 @@ afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
     }
 
     ObtainSharedLock(&afs_xvcache, 766);
-    *adp = afs_FindVCache(afid, 0, 1);
+    *adp = afs_FindVCache(afid, 1);
     ReleaseSharedLock(&afs_xvcache);
     if (!*adp) {
 	/* printf("afs_GetParentVCache: Couldn't find parent dir's vcache\n"); */
@@ -1371,7 +1371,7 @@ afs_GenShadowFid(struct VenusFid *afid)
 
 	/* Is this a used vnode? */
     	ObtainSharedLock(&afs_xvcache, 762);
-    	tvc = afs_FindVCache(afid, 0, 1);
+    	tvc = afs_FindVCache(afid, 1);
     	ReleaseSharedLock(&afs_xvcache);
 	if (tvc)
 	    afs_PutVCache(tvc);
diff --git a/src/afs/afs_dynroot.c b/src/afs/afs_dynroot.c
index 37200abc13..8f0877d13a 100644
--- a/src/afs/afs_dynroot.c
+++ b/src/afs/afs_dynroot.c
@@ -301,7 +301,6 @@ afs_dynroot_addDirEnt(struct DirHeader *dirHeader, int *curPageP,
 void
 afs_DynrootInvalidate(void)
 {
-    afs_int32 retry;
     struct vcache *tvc;
     struct VenusFid tfid;
 
@@ -314,12 +313,9 @@ afs_DynrootInvalidate(void)
     ReleaseWriteLock(&afs_dynrootDirLock);
 
     afs_GetDynrootFid(&tfid);
-    do {
-	retry = 0;
-	ObtainReadLock(&afs_xvcache);
-	tvc = afs_FindVCache(&tfid, &retry, 0);
-	ReleaseReadLock(&afs_xvcache);
-    } while (retry);
+    ObtainReadLock(&afs_xvcache);
+    tvc = afs_FindVCache(&tfid, 0);
+    ReleaseReadLock(&afs_xvcache);
     if (tvc) {
 	afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, CUnique);
 	afs_PutVCache(tvc);
@@ -576,7 +572,7 @@ afs_GetDynroot(char **dynrootDir, int *dynrootLen,
 	status->DataVersion = afs_dynrootVersion;
 	status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
 	status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
-	status->UnixModeBits = 0755;
+	status->UnixModeBits = 0555;
 	status->ParentVnode = 1;
 	status->ParentUnique = 1;
 	status->dataVersionHigh = afs_dynrootVersionHigh;
diff --git a/src/afs/afs_fetchstore.c b/src/afs/afs_fetchstore.c
index 97d0671811..5b9e08c3fd 100644
--- a/src/afs/afs_fetchstore.c
+++ b/src/afs/afs_fetchstore.c
@@ -309,48 +309,26 @@ afs_GenericStoreProc(struct storeOps *ops, void *rock,
 
 static
 struct storeOps rxfs_storeUfsOps = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    rxfs_storeUfsPrepare,
-    rxfs_storeUfsRead,
-    rxfs_storeUfsWrite,
-    rxfs_storeStatus,
-    rxfs_storePadd,
-    rxfs_storeClose,
-    rxfs_storeDestroy,
-    afs_GenericStoreProc
-#else
-    .prepare = 	rxfs_storeUfsPrepare,
-    .read =	rxfs_storeUfsRead,
-    .write =	rxfs_storeUfsWrite,
-    .status =	rxfs_storeStatus,
-    .padd =	rxfs_storePadd,
-    .close =	rxfs_storeClose,
-    .destroy =	rxfs_storeDestroy,
-    .storeproc = afs_GenericStoreProc
-#endif
+    AFS_STRUCT_INIT(.prepare,	rxfs_storeUfsPrepare),
+    AFS_STRUCT_INIT(.read,	rxfs_storeUfsRead),
+    AFS_STRUCT_INIT(.write,	rxfs_storeUfsWrite),
+    AFS_STRUCT_INIT(.status,	rxfs_storeStatus),
+    AFS_STRUCT_INIT(.padd,	rxfs_storePadd),
+    AFS_STRUCT_INIT(.close,	rxfs_storeClose),
+    AFS_STRUCT_INIT(.destroy,	rxfs_storeDestroy),
+    AFS_STRUCT_INIT(.storeproc,	afs_GenericStoreProc),
 };
 
 static
 struct storeOps rxfs_storeMemOps = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    rxfs_storeMemPrepare,
-    rxfs_storeMemRead,
-    rxfs_storeMemWrite,
-    rxfs_storeStatus,
-    rxfs_storePadd,
-    rxfs_storeClose,
-    rxfs_storeDestroy,
-    afs_GenericStoreProc
-#else
-    .prepare =	rxfs_storeMemPrepare,
-    .read = 	rxfs_storeMemRead,
-    .write = 	rxfs_storeMemWrite,
-    .status =	rxfs_storeStatus,
-    .padd =	rxfs_storePadd,
-    .close = 	rxfs_storeClose,
-    .destroy =	rxfs_storeDestroy,
-    .storeproc = afs_GenericStoreProc
-#endif
+    AFS_STRUCT_INIT(.prepare,	rxfs_storeMemPrepare),
+    AFS_STRUCT_INIT(.read,	rxfs_storeMemRead),
+    AFS_STRUCT_INIT(.write,	rxfs_storeMemWrite),
+    AFS_STRUCT_INIT(.status,	rxfs_storeStatus),
+    AFS_STRUCT_INIT(.padd,	rxfs_storePadd),
+    AFS_STRUCT_INIT(.close,	rxfs_storeClose),
+    AFS_STRUCT_INIT(.destroy,	rxfs_storeDestroy),
+    AFS_STRUCT_INIT(.storeproc,	afs_GenericStoreProc),
 };
 
 static afs_int32
@@ -866,20 +844,20 @@ rxfs_fetchMore(void *r, afs_int32 *length, afs_uint32 *moredata)
 
 static
 struct fetchOps rxfs_fetchUfsOps = {
-    rxfs_fetchMore,
-    rxfs_fetchUfsRead,
-    rxfs_fetchUfsWrite,
-    rxfs_fetchClose,
-    rxfs_fetchDestroy
+    AFS_STRUCT_INIT(.more,	rxfs_fetchMore),
+    AFS_STRUCT_INIT(.read,	rxfs_fetchUfsRead),
+    AFS_STRUCT_INIT(.write,	rxfs_fetchUfsWrite),
+    AFS_STRUCT_INIT(.close,	rxfs_fetchClose),
+    AFS_STRUCT_INIT(.destroy,	rxfs_fetchDestroy),
 };
 
 static
 struct fetchOps rxfs_fetchMemOps = {
-    rxfs_fetchMore,
-    rxfs_fetchMemRead,
-    rxfs_fetchMemWrite,
-    rxfs_fetchClose,
-    rxfs_fetchDestroy
+    AFS_STRUCT_INIT(.more,	rxfs_fetchMore),
+    AFS_STRUCT_INIT(.read,	rxfs_fetchMemRead),
+    AFS_STRUCT_INIT(.write,	rxfs_fetchMemWrite),
+    AFS_STRUCT_INIT(.close,	rxfs_fetchClose),
+    AFS_STRUCT_INIT(.destroy,	rxfs_fetchDestroy),
 };
 
 static afs_int32
diff --git a/src/afs/afs_osi.h b/src/afs/afs_osi.h
index e3f0e0ccb2..aab68b8643 100644
--- a/src/afs/afs_osi.h
+++ b/src/afs/afs_osi.h
@@ -278,11 +278,27 @@ typedef struct {
  * and kernel space. Call these to avoid taking page faults while
  * holding the global lock.
  */
-#if defined(CAST_USER_ADDR_T) && !defined(UKERNEL) && !defined(AFS_DARWIN100_ENV)
-#define __U(X) CAST_USER_ADDR_T((X))
+
+#if defined(AFS_DARWIN_ENV)
+/*
+ * Don't use CAST_USER_ADDR_T for [10.6, 10.15), due to issues with mixing
+ * 32/64-bit userspace and kernelspace. All other versions are okay.
+ */
+# if defined(AFS_DARWIN190_ENV) || !defined(AFS_DARWIN100_ENV)
+#  define USE_CAST_USER_ADDR_T
+# endif
+#endif
+
+#if defined(CAST_USER_ADDR_T) && !defined(UKERNEL) && defined(USE_CAST_USER_ADDR_T)
+/*
+ * CAST_USER_ADDR_T is a Darwin-provided macro. Only use it for copyin/copyout
+ * for certain ranges of Darwin versions specified above.
+ */
+# define __U(X) CAST_USER_ADDR_T((X))
 #else
-#define __U(X) (X)
+# define __U(X) (X)
 #endif
+
 #ifdef AFS_GLOBAL_SUNLOCK
 
 #define AFS_COPYIN(SRC,DST,LEN,CODE)				\
diff --git a/src/afs/afs_osi_vget.c b/src/afs/afs_osi_vget.c
index e9c6cc4847..cec48821ea 100644
--- a/src/afs/afs_osi_vget.c
+++ b/src/afs/afs_osi_vget.c
@@ -62,7 +62,7 @@ afs_osi_vget(struct vcache **avcpp, struct fid *afidp, struct vrequest *areqp)
 	/* didn't find an entry. */
 	code = afs_CreateReq(&treq, afs_osi_credp);
 	if (code == 0) {
-	    *avcpp = afs_GetVCache(&vfid, treq, NULL, NULL);
+	    *avcpp = afs_GetVCache(&vfid, treq);
 	    afs_DestroyReq(treq);
 	}
     }
diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c
index faafdd3d2d..f6049f0f29 100644
--- a/src/afs/afs_pioctl.c
+++ b/src/afs/afs_pioctl.c
@@ -1451,9 +1451,12 @@ DECL_PIOCTL(PSetAcl)
 	if (tconn) {
 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
 	    RX_AFS_GUNLOCK();
-	    code =
-		RXAFS_StoreACL(rxconn, (struct AFSFid *)&avc->f.fid.Fid,
-			       &acl, &OutStatus, &tsync);
+	    code = RXAFS_StoreACL(rxconn, (struct AFSFid *)&avc->f.fid.Fid,
+				  &acl, &OutStatus, &tsync);
+	    if (code == RXGEN_OPCODE)
+		code = RXAFS_OldStoreACL(rxconn,
+					 (struct AFSFid *)&avc->f.fid.Fid,
+					 &acl, &OutStatus, &tsync);
 	    RX_AFS_GLOCK();
 	    XSTATS_END_TIME;
 	} else
@@ -2299,9 +2302,9 @@ DECL_PIOCTL(PNewStatMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-	tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+	tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-	tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+	tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
 	code = EIO;
@@ -3360,9 +3363,9 @@ DECL_PIOCTL(PRemoveMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-	tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+	tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-	tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+	tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
 	code = EIO;
@@ -4911,9 +4914,9 @@ DECL_PIOCTL(PFlushMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-	tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+	tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-	tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+	tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
 	code = EIO;
@@ -5049,7 +5052,7 @@ DECL_PIOCTL(PPrefetchFromTape)
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
 
-    tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+    tvc = afs_GetVCache(&tfid, areq);
     if (!tvc) {
 	afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
 		   ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &avc->f.fid);
@@ -5120,7 +5123,7 @@ DECL_PIOCTL(PFsCmd)
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
 
-    tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+    tvc = afs_GetVCache(&tfid, areq);
     afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD, ICL_TYPE_POINTER, tvc,
 	       ICL_TYPE_INT32, Inputs->command, ICL_TYPE_FID, &tfid);
     if (!tvc)
diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
index 0e7f8a258d..fb236e92a5 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -1038,8 +1038,7 @@ extern struct osi_file *afs_vcacheMetaInodep;
 
 extern void afs_FlushReclaimedVcaches(void);
 void afs_vcacheInit(int astatSize);
-extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 * retry,
-				     afs_int32 flag);
+extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 flag);
 extern void afs_BadFetchStatus(struct afs_conn *tc);
 extern int afs_CheckFetchStatus(struct afs_conn *tc,
                                 struct AFSFetchStatus *status);
@@ -1051,13 +1050,12 @@ extern afs_int32 afs_FlushVCBs(afs_int32 lockit);
 extern void afs_InactiveVCache(struct vcache *avc, afs_ucred_t *acred);
 extern struct vcache *afs_LookupVCache(struct VenusFid *afid,
 				       struct vrequest *areq,
-				       afs_int32 * cached, struct vcache *adp,
+				       struct vcache *adp,
 				       char *aname);
 extern void afs_FlushAllVCaches(void);
 extern int afs_FlushVCache(struct vcache *avc, int *slept);
 extern struct vcache *afs_GetRootVCache(struct VenusFid *afid,
 					struct vrequest *areq,
-					afs_int32 * cached,
 					struct volume *tvolp);
 extern struct vcache *afs_NewVCache(struct VenusFid *afid,
 				    struct server *serverp);
@@ -1065,8 +1063,7 @@ extern struct vcache *afs_NewBulkVCache(struct VenusFid *afid,
 					struct server *serverp, int seq);
 extern int afs_VerifyVCache2(struct vcache *avc, struct vrequest *areq);
 extern struct vcache *afs_GetVCache(struct VenusFid *afid,
-				    struct vrequest *areq, afs_int32 * cached,
-				    struct vcache *avc);
+				    struct vrequest *areq);
 extern void afs_PutVCache(struct vcache *avc);
 extern int afs_RefVCache(struct vcache *avc);
 
diff --git a/src/afs/afs_syscall.c b/src/afs/afs_syscall.c
index 03a70da444..6ac7cc273e 100644
--- a/src/afs/afs_syscall.c
+++ b/src/afs/afs_syscall.c
@@ -655,7 +655,7 @@ Afs_syscall()
 				   uap->parm4, p->td_ucred);
 #elif defined(AFS_DARWIN80_ENV)
 	    code =
-		afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
+		afs_syscall_pioctl((char *)uap->parm1, uap->parm2, (caddr_t)uap->parm3,
 				   uap->parm4, kauth_cred_get());
 #elif defined(AFS_NBSD40_ENV)
 	    code =
diff --git a/src/afs/afs_user.c b/src/afs/afs_user.c
index 5631b37d0c..c87c35bfaa 100644
--- a/src/afs/afs_user.c
+++ b/src/afs/afs_user.c
@@ -335,7 +335,7 @@ afs_ComputePAGStats(void)
 
     /*
      * Initialize the tallies, then sweep through each hash chain.  We
-     * can't bzero the structure, since some fields are cumulative over
+     * can't zero the structure, since some fields are cumulative over
      * the CM's lifetime.
      */
     authP = &(afs_stats_cmfullperf.authent);
diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c
index f500b65a3d..285bd84d31 100644
--- a/src/afs/afs_vcache.c
+++ b/src/afs/afs_vcache.c
@@ -1362,7 +1362,7 @@ afs_VerifyVCache2(struct vcache *avc, struct vrequest *areq)
     ReleaseWriteLock(&avc->lock);
 
     /* fetch the status info */
-    tvc = afs_GetVCache(&avc->f.fid, areq, NULL, avc);
+    tvc = afs_GetVCache(&avc->f.fid, areq);
     if (!tvc)
 	return EIO;
     /* Put it back; caller has already incremented vrefCount */
@@ -1747,8 +1747,6 @@ afs_RemoteLookup(struct VenusFid *afid, struct vrequest *areq,
  * \param afid File ID.
  * \param areq Ptr to associated vrequest structure, specifying the
  *  user whose authentication tokens will be used.
- * \param avc Caller may already have a vcache for this file, which is
- *  already held.
  *
  * \note Environment:
  *	The cache entry is returned with an increased vrefCount field.
@@ -1768,42 +1766,21 @@ afs_RemoteLookup(struct VenusFid *afid, struct vrequest *areq,
  *	locking directories in a constant order.
  *
  * \note NB.  NewVCache -> FlushVCache presently (4/10/95) drops the xvcache lock.
- *
- * \note Might have a vcache structure already, which must
- *  already be held by the caller
  */
 struct vcache *
-afs_GetVCache(struct VenusFid *afid, struct vrequest *areq,
-	      afs_int32 * cached, struct vcache *avc)
+afs_GetVCache(struct VenusFid *afid, struct vrequest *areq)
 {
 
     afs_int32 code, newvcache = 0;
     struct vcache *tvc;
     struct volume *tvp;
-    afs_int32 retry;
 
     AFS_STATCNT(afs_GetVCache);
 
-    if (cached)
-	*cached = 0;		/* Init just in case */
-
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-  loop:
-#endif
-
     ObtainSharedLock(&afs_xvcache, 5);
 
-    tvc = afs_FindVCache(afid, &retry, DO_STATS | DO_VLRU | IS_SLOCK);
-    if (tvc && retry) {
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-	ReleaseSharedLock(&afs_xvcache);
-	spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
-	goto loop;
-#endif
-    }
+    tvc = afs_FindVCache(afid, DO_STATS | DO_VLRU | IS_SLOCK);
     if (tvc) {
-	if (cached)
-	    *cached = 1;
 	osi_Assert((tvc->f.states & CVInit) == 0);
 	/* If we are in readdir, return the vnode even if not statd */
 	if ((tvc->f.states & CStatd) || afs_InReadDir(tvc)) {
@@ -1989,7 +1966,6 @@ afs_GetVCache(struct VenusFid *afid, struct vrequest *areq,
  *
  * \param afid
  * \param areq
- * \param cached Is element cached? If NULL, don't answer.
  * \param adp
  * \param aname
  *
@@ -1997,7 +1973,7 @@ afs_GetVCache(struct VenusFid *afid, struct vrequest *areq,
  */
 struct vcache *
 afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
-		 afs_int32 * cached, struct vcache *adp, char *aname)
+		 struct vcache *adp, char *aname)
 {
     afs_int32 code, now, newvcache = 0;
     struct VenusFid nfid;
@@ -2008,33 +1984,17 @@ afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
     struct AFSVolSync tsync;
     struct server *serverp = 0;
     afs_int32 origCBs;
-    afs_int32 retry;
 
     AFS_STATCNT(afs_GetVCache);
-    if (cached)
-	*cached = 0;		/* Init just in case */
-
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-  loop1:
-#endif
 
     ObtainReadLock(&afs_xvcache);
-    tvc = afs_FindVCache(afid, &retry, DO_STATS /* no vlru */ );
+    tvc = afs_FindVCache(afid, DO_STATS /* no vlru */ );
 
     if (tvc) {
 	ReleaseReadLock(&afs_xvcache);
-	if (retry) {
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-	    spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
-	    goto loop1;
-#endif
-	}
 	ObtainReadLock(&tvc->lock);
 
 	if (tvc->f.states & CStatd) {
-	    if (cached) {
-		*cached = 1;
-	    }
 	    ReleaseReadLock(&tvc->lock);
 	    return tvc;
 	}
@@ -2060,20 +2020,8 @@ afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
 	    afs_RemoteLookup(&adp->f.fid, areq, aname, &nfid, &OutStatus,
 	                     &CallBack, &serverp, &tsync);
 
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-  loop2:
-#endif
-
     ObtainSharedLock(&afs_xvcache, 6);
-    tvc = afs_FindVCache(&nfid, &retry, DO_VLRU | IS_SLOCK/* no xstats now */ );
-    if (tvc && retry) {
-#if	defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
-	ReleaseSharedLock(&afs_xvcache);
-	spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
-	goto loop2;
-#endif
-    }
-
+    tvc = afs_FindVCache(&nfid, DO_VLRU | IS_SLOCK/* no xstats now */ );
     if (!tvc) {
 	/* no cache entry, better grab one */
 	UpgradeSToWLock(&afs_xvcache, 22);
@@ -2159,7 +2107,7 @@ afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
 
 struct vcache *
 afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq,
-		  afs_int32 * cached, struct volume *tvolp)
+		  struct volume *tvolp)
 {
     afs_int32 code = 0, i, newvcache = 0, haveStatus = 0;
     afs_int32 getNewFid = 0;
@@ -2270,8 +2218,6 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq,
 	newvcache = 1;
 	afs_stats_cmperf.vcacheMisses++;
     } else {
-	if (cached)
-	    *cached = 1;
 	afs_stats_cmperf.vcacheHits++;
 	UpgradeSToWLock(&afs_xvcache, 24);
 	if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
@@ -2671,8 +2617,6 @@ afs_RefVCache(struct vcache *tvc)
  * Find a vcache entry given a fid.
  *
  * \param afid Pointer to the fid whose cache entry we desire.
- * \param retry (SGI-specific) tell the caller to drop the lock on xvcache,
- *  unlock the vnode, and try again.
  * \param flag Bit 1 to specify whether to compute hit statistics.  Not
  *  set if FindVCache is called as part of internal bookkeeping.
  *
@@ -2682,7 +2626,7 @@ afs_RefVCache(struct vcache *tvc)
  */
 
 struct vcache *
-afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
+afs_FindVCache(struct VenusFid *afid, afs_int32 flag)
 {
 
     struct vcache *tvc;
@@ -2794,8 +2738,6 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
  *
  * \param avcp Fill in pointer if we found one and only one.
  * \param afid Pointer to the fid whose cache entry we desire.
- * \param retry (SGI-specific) tell the caller to drop the lock on xvcache,
- *             unlock the vnode, and try again.
  * \param flags bit 1 to specify whether to compute hit statistics.  Not
  *             set if FindVCache is called as part of internal bookkeeping.
  *
diff --git a/src/afsd/CellServDB b/src/afsd/CellServDB
index 63e3330a38..4d6e83a52e 100644
--- a/src/afsd/CellServDB
+++ b/src/afsd/CellServDB
@@ -1,4 +1,4 @@
->grand.central.org      #GCO Public CellServDB 31 Oct 2023
+>grand.central.org      #GCO Public CellServDB 15 Aug 2025
 18.9.48.14                      #grand.mit.edu
 128.2.13.219                    #grand-old-opry.central.org
 >wu-wien.ac.at          #University of Economics, Vienna, Austria
@@ -21,14 +21,12 @@
 132.216.24.122                  #germain.sums.math.mcgill.ca
 132.216.24.125                  #turing.sums.math.mcgill.ca
 >ualberta.ca            #University of Alberta
-129.128.1.131                   #file13.ucs.ualberta.ca
-129.128.98.17                   #mystery.ucs.ualberta.ca
 129.128.125.40                  #drake.ucs.ualberta.ca
 >cern.ch                #European Laboratory for Particle Physics, Geneva
-137.138.54.120                  #afsdb13.cern.ch
 188.184.21.218                  #afsdb11.cern.ch
 188.184.23.130                  #afsdb14.cern.ch
 188.184.81.230                  #afsdb12.cern.ch
+188.185.50.42                   #afsdb13.cern.ch
 >ams.cern.ch            #AMS Experiment
 >epfl.ch                #Swiss Federal Institute of Technology at Lausanne
 128.178.109.111                 #kd1.epfl.ch
@@ -57,9 +55,9 @@
 195.113.0.37                    #obelix.ruk.cuni.cz
 195.113.0.40                    #sal.ruk.cuni.cz
 >ics.muni.cz            #Masaryk university
-147.228.240.30                  #afs-plzen.meta.zcu.cz
+78.128.242.247                  #afs-plzen2.meta.zcu.cz
+78.128.246.55                   #afs-praha2.grid.cesnet.cz
 147.251.3.244                   #kuduk1.ics.muni.cz
-195.113.214.10                  #afs-praha.grid.cesnet.cz
 >zcu.cz                 #University of West Bohemia, Czech Republic
 147.228.10.18                   #sauron.zcu.cz
 147.228.52.10                   #oknos.zcu.cz
@@ -92,8 +90,8 @@
 129.187.10.56                   #afs3.lrz-muenchen.de
 129.187.10.57                   #afs2.lrz-muenchen.de
 >ipp-garching.mpg.de    #Institut fuer Plasmaphysik
-130.183.9.5                     #afs-db1.rzg.mpg.de
-130.183.14.14                   #afs-db3.bc.rzg.mpg.de
+130.183.9.5                     #afs-db1.mpcdf.mpg.de
+130.183.14.14                   #afs-db3.mpcdf.mpg.de
 130.183.30.30                   #afs-db4.mpcdf.mpg.de
 >mpe.mpg.de             #MPE cell
 130.183.130.7                   #irafs1.mpe-garching.mpg.de
@@ -230,9 +228,6 @@
 129.170.30.144                  #dbicafs2.dartmouth.edu
 129.170.30.145                  #dbicafs3.dartmouth.edu
 >northstar.dartmouth.edu #Dartmouth College Research Computing
-129.170.137.194                 #halley.dartmouth.edu
-129.170.137.195                 #andromeda.dartmouth.edu
-129.170.137.196                 #kuiper.dartmouth.edu
 >cs.hm.edu              #Department Computer Science Munich University Of Applied Science
 129.187.208.31                  #afs1.cs.hm.edu
 >eecs.harvard.edu       #Harvard - EECS
@@ -274,9 +269,9 @@
 136.142.8.20                    #afs10.srv.cis.pitt.edu
 136.142.8.21                    #afs11.srv.cis.pitt.edu
 >cs.pitt.edu            #University of Pittsburgh - Computer Science
-136.142.55.232                  #afs01.cs.pitt.edu
-136.142.55.233                  #afs02.cs.pitt.edu
-136.142.55.234                  #afs03.cs.pitt.edu
+136.142.42.38                   #afs04.cs.pitt.edu
+136.142.42.39                   #afs05.cs.pitt.edu
+136.142.42.40                   #afs06.cs.pitt.edu
 >psc.edu                #PSC (Pittsburgh Supercomputing Center)
 128.182.59.182                  #shaggy.psc.edu
 128.182.66.184                  #velma.psc.edu
@@ -293,11 +288,6 @@
 137.112.7.13                    #afs3.rose-hulman.edu
 >cs.rose-hulman.edu     #Rose-Hulman CS Department
 137.112.40.10                   #galaxy.cs.rose-hulman.edu
->rpi.edu                #Rensselaer Polytechnic Institute
-128.113.22.11                   #saul.server.rpi.edu
-128.113.22.12                   #joab.server.rpi.edu
-128.113.22.13                   #korah.server.rpi.edu
-128.113.22.14                   #achan.server.rpi.edu
 >hep.sc.edu             #University of South Carolina, Dept. of Physics
 129.252.78.77                   #cpeven.physics.sc.edu
 >cs.stanford.edu        #Stanford University Computer Science Department
@@ -308,10 +298,6 @@
 171.64.7.222                    #afsdb1.stanford.edu
 171.64.7.234                    #afsdb2.stanford.edu
 171.64.7.246                    #afsdb3.stanford.edu
->slac.stanford.edu      #Stanford Linear Accelerator Center
-134.79.18.25                    #afsdb1.slac.stanford.edu
-134.79.18.26                    #afsdb2.slac.stanford.edu
-134.79.18.27                    #afsdb3.slac.stanford.edu
 >physics.ucsb.edu       #UC Santa Barbara, Physics Dept
 128.111.18.161                  #ledzeppelin.physics.ucsb.edu
 >cats.ucsc.edu          #University of California, Santa Cruz
@@ -403,10 +389,6 @@
 152.66.241.6                    #afs.iit.bme.hu
 >kfki.hu                #Wigner Research Centre for Physics - Budapest, Hungary
 148.6.2.109                     #afs0.kfki.hu
->rnd.ru.is              #Reykjavik University Research and Development Network
-130.208.242.66                  #lithium.rnd.ru.is.
-130.208.242.67                  #beryllium.rnd.ru.is.
-130.208.242.68                  #boron.rnd.ru.is.
 >caspur.it              #CASPUR Inter-University Computing Consortium, Rome
 193.204.5.45                    #pomodoro.caspur.it
 193.204.5.46                    #banana.caspur.it
@@ -581,9 +563,6 @@
 130.237.244.139                 #srv05.fysik.su.se
 >f9.ijs.si              #F9, Jozef Stefan Institue
 194.249.156.1                   #brenta.ijs.si
->p-ng.si                #University of Nova Gorica
-193.2.120.2                     #solkan.p-ng.si
-193.2.120.9                     #sabotin.p-ng.si
 >ung.si                 #University of Nova Gorica
 193.2.120.63                    #afs1.ung.si
 >ihep.su                #Institute for High-Energy Physics
diff --git a/src/afsd/afsd.c b/src/afsd/afsd.c
index 02d84fb63b..80bce727e5 100644
--- a/src/afsd/afsd.c
+++ b/src/afsd/afsd.c
@@ -747,7 +747,7 @@ doGetXFileNumber(char *fname, char filechar, int maxNum)
      * Reject it if it's out of range, otherwise return it.
      */
     computedVNumber = atoi(++fname);
-    if (computedVNumber < cacheFiles)
+    if (computedVNumber < maxNum)
 	return (computedVNumber);
     else
 	return (-1);
diff --git a/src/afsd/afsd.h b/src/afsd/afsd.h
index a30d565f52..764f455ad1 100644
--- a/src/afsd/afsd.h
+++ b/src/afsd/afsd.h
@@ -10,10 +10,6 @@
 #ifndef AFSD_AFSD_H
 #define AFSD_AFSD_H
 
-#ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
-#endif
-
 extern int afsd_debug;
 extern int afsd_verbose;
 extern char *afsd_cacheMountDir;
diff --git a/src/afsd/vsys.c b/src/afsd/vsys.c
index 6b5d3b9bc8..c5d21e5850 100644
--- a/src/afsd/vsys.c
+++ b/src/afsd/vsys.c
@@ -19,6 +19,7 @@
 #ifdef HAVE_STDINT_H
 # include <stdint.h>
 #endif
+#include <afs/afssyscalls.h>
 
 
 #include <afs/afs_args.h>
diff --git a/src/aklog/linked_list.c b/src/aklog/linked_list.c
index 289d645bea..3e9eae14c5 100644
--- a/src/aklog/linked_list.c
+++ b/src/aklog/linked_list.c
@@ -40,7 +40,7 @@ void ll_init(linked_list *list)
     }
 
     /* This sets everything to zero, which is what we want. */
-    bzero((char *)list, sizeof(linked_list));
+    memset(list, 0, sizeof(linked_list));
 }
 
 ll_node *ll_add_node(linked_list *list, ll_end which_end)
diff --git a/src/bozo/bos_util.c b/src/bozo/bos_util.c
index 62293a270b..97709a9edb 100644
--- a/src/bozo/bos_util.c
+++ b/src/bozo/bos_util.c
@@ -136,7 +136,7 @@ main(int argc, char **argv)
 	    exit(1);
 	}
 	kvno = atoi(argv[2]);
-	bzero(tkey, sizeof(tkey));
+	memset(tkey, 0, sizeof(tkey));
 	code = kname_parse(name, inst, realm, argv[4]);
 	if (code != 0) {
 	    printf("Invalid kerberos name\n");
diff --git a/src/bozo/bosserver.c b/src/bozo/bosserver.c
index 371cb638e4..f5b8e45b8a 100644
--- a/src/bozo/bosserver.c
+++ b/src/bozo/bosserver.c
@@ -1172,11 +1172,7 @@ main(int argc, char **argv, char **envp)
 	host = GetRxBindAddress();
     }
     for (i = 0; i < 10; i++) {
-	if (rxBind) {
-	    code = rx_InitHost(host, htons(AFSCONF_NANNYPORT));
-	} else {
-	    code = rx_Init(htons(AFSCONF_NANNYPORT));
-	}
+	code = rx_InitHost(host, htons(AFSCONF_NANNYPORT));
 	if (code) {
 	    bozo_Log("can't initialize rx: code=%d\n", code);
 	    sleep(3);
diff --git a/src/bucoord/ubik_db_if.c b/src/bucoord/ubik_db_if.c
index 9a05459410..d88233e85d 100644
--- a/src/bucoord/ubik_db_if.c
+++ b/src/bucoord/ubik_db_if.c
@@ -13,14 +13,10 @@
 #include <afs/stds.h>
 
 #include <roken.h>
-
-#ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
-#endif
-
 #include <afs/cmd.h>
 #include <afs/auth.h>
 #include <afs/cellconfig.h>
+#define UBIK_LEGACY_CALLITER 1
 #include <ubik.h>
 #include <afs/afsint.h>
 #include <afs/volser.h>
@@ -1001,7 +997,7 @@ static struct ubikCallState uServer;
  */
 
 static afs_int32
-ubik_Call_SingleServer(int (*aproc) (), struct ubik_client *aclient,
+ubik_Call_SingleServer(ubik_call_func aproc, struct ubik_client *aclient,
 		       afs_int32 aflags, long p1, long p2, long p3,
 		       long p4, long p5, long p6, long p7, long p8,
 		       long p9, long p10, long p11, long p12, long p13,
@@ -1141,7 +1137,7 @@ ubik_Call_SingleServer_BUDB_GetVolumes(struct ubik_client *aclient,
 				       afs_int32 *dbUpdate,
 				       budb_volumeList *volumes)
 {
-    return ubik_Call_SingleServer(BUDB_GetVolumes, aclient, aflags,
+    return ubik_Call_SingleServer((ubik_call_func)BUDB_GetVolumes, aclient, aflags,
 				  (long)majorVersion, (long)flags, (long)name,
 				  (long)start, (long)end, (long)index,
 				  (long)nextIndex, (long)dbUpdate,
@@ -1154,7 +1150,7 @@ ubik_Call_SingleServer_BUDB_DumpDB(struct ubik_client *aclient,
 				   afs_int32 maxLength, charListT *charListPtr,
 				   afs_int32 *flags)
 {
-    return ubik_Call_SingleServer(BUDB_DumpDB, aclient, aflags, (long)firstcall,
+    return ubik_Call_SingleServer((ubik_call_func)BUDB_DumpDB, aclient, aflags, (long)firstcall,
 				  (long)maxLength, (long)charListPtr,
 				  (long)flags, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 				  0);
diff --git a/src/budb/database.c b/src/budb/database.c
index a68b1f241c..ce5c2ad9a9 100644
--- a/src/budb/database.c
+++ b/src/budb/database.c
@@ -213,7 +213,7 @@ UpdateCache(struct ubik_trans *ut, void *rock)
 		db.h.lastUpdate = db.h.lastDumpId = htonl(time(0));
 		db.h.eofPtr = htonl(sizeof(db.h));
 
-		/* text ptrs cleared by bzero */
+		/* text ptrs cleared by memset */
 		ht_DBInit();
 
 		code = dbwrite(ut, 0, (char *)&db.h, sizeof(db.h));
diff --git a/src/budb/server.c b/src/budb/server.c
index 5bbdec81f1..968897378e 100644
--- a/src/budb/server.c
+++ b/src/budb/server.c
@@ -371,6 +371,7 @@ main(int argc, char **argv)
     struct afsconf_cell *cellinfo = NULL;
     time_t currentTime;
     afs_int32 code = 0;
+    char hoststr[16];
     afs_uint32 host = ntohl(INADDR_ANY);
     int r;
 
@@ -534,10 +535,18 @@ main(int argc, char **argv)
         }
         if (ccode == 1) {
             host = SHostAddrs[0];
-	    rx_InitHost(host, htons(AFSCONF_BUDBPORT));
 	}
     }
 
+    Log("buserver binding rx to %s:%d\n",
+        afs_inet_ntoa_r(host, hoststr), AFSCONF_BUDBPORT);
+    code = rx_InitHost(host, htons(AFSCONF_BUDBPORT));
+    if (code) {
+	LogError(code, "rx init failed\n");
+	afs_com_err(whoami, code, "rx init failed");
+	ERROR(code);
+    }
+
     /* Disable jumbograms */
     rx_SetNoJumbo();
 
diff --git a/src/butc/tcmain.c b/src/butc/tcmain.c
index a243da780a..6a5daa21bc 100644
--- a/src/butc/tcmain.c
+++ b/src/butc/tcmain.c
@@ -843,6 +843,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
 #else
     PROCESS dbWatcherPid;
 #endif
+    char hoststr[16];
     afs_uint32 host = htonl(INADDR_ANY);
     char *auditFileName = NULL;
     char *auditInterface = NULL;
@@ -1080,6 +1081,8 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
             host = SHostAddrs[0];
     }
 
+    TLog(0, "butc binding rx to %s:%d\n",
+         afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset);
     code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset));
     if (code) {
 	TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
diff --git a/src/cf/linux-checks.m4 b/src/cf/linux-checks.m4
index 81a015e7dc..01406c4d4e 100644
--- a/src/cf/linux-checks.m4
+++ b/src/cf/linux-checks.m4
@@ -41,6 +41,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
         OPENAFS_LINUX_KERNEL_SIG_CHECKS
         OPENAFS_LINUX_KERNEL_HEADER_CHECKS
         OPENAFS_LINUX_KERNEL_TYPE_CHECKS
+	OPENAFS_LINUX_KERNEL_SYMBOL_CHECKS
         OPENAFS_LINUX_KERNEL_STRUCT_CHECKS
         OPENAFS_LINUX_KERNEL_FUNC_CHECKS
         OPENAFS_LINUX_KERNEL_ASSORTED_CHECKS
diff --git a/src/cf/linux-kernel-assorted.m4 b/src/cf/linux-kernel-assorted.m4
index aea7b2bd73..85af7179c3 100644
--- a/src/cf/linux-kernel-assorted.m4
+++ b/src/cf/linux-kernel-assorted.m4
@@ -17,6 +17,7 @@ LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA
 LINUX_IOP_I_PUT_LINK_TAKES_COOKIE
 LINUX_DOP_D_DELETE_TAKES_CONST
 LINUX_DOP_D_REVALIDATE_TAKES_NAMEIDATA
+LINUX_DOP_D_REVALIDATE_TAKES_PARENT_INODE
 LINUX_FOP_F_FLUSH_TAKES_FL_OWNER_T
 LINUX_FOP_F_FSYNC_TAKES_DENTRY
 LINUX_FOP_F_FSYNC_TAKES_RANGE
@@ -60,8 +61,14 @@ LINUX_KERNEL_READ_OFFSET_IS_LAST
 LINUX_KEYRING_SEARCH_TAKES_RECURSE
 LINUX_GENERIC_FILLATTR_TAKES_REQUEST_MASK
 LINUX_FILE_LOCK_CORE
-])
+LINUX_WRITEPAGES_USES_FOLIOS
+
+dnl If take_dentry_name_snapshot isn't present
+dnl don't bother checking if name_snapshot uses qstr
+AS_IF([test "x$ac_cv_linux_func_take_dentry_name_snapshot" = "xyes"],
+ [LINUX_STRUCT_NAME_SNAPSHOT_USES_QSTR])
 
+])
 
 AC_DEFUN([OPENAFS_LINUX_KERNEL_MORE_ASSORTED_CHECKS],[
 if test -f "$LINUX_KERNEL_PATH/include/linux/in_systm.h"; then
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 598114671e..175db00eaf 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -124,7 +124,8 @@ AC_CHECK_LINUX_FUNC([proc_create],
                     [proc_create(NULL, 0, NULL, NULL);])
 AC_CHECK_LINUX_FUNC([rcu_read_lock],
                     [#include <linux/rcupdate.h>],
-                    [rcu_read_lock();])
+		    [rcu_read_lock();
+		     rcu_read_unlock();])
 AC_CHECK_LINUX_FUNC([set_nlink],
                     [#include <linux/fs.h>],
                     [set_nlink(NULL, 1);])
@@ -175,6 +176,13 @@ AC_CHECK_LINUX_FUNC([in_compat_syscall],
                     [#include <linux/compat.h>],
                     [in_compat_syscall();])
 
+dnl Linux 4.13 introduced take_dentry_name_snapshot
+AC_CHECK_LINUX_FUNC([take_dentry_name_snapshot],
+		    [[#include <linux/dcache.h>
+		      static struct name_snapshot dname;
+		      static struct dentry *dp;]],
+		    [[take_dentry_name_snapshot(&dname, dp);]])
+
 dnl lru_cache_add exported in Linux 5.8
 dnl    replaces lru_cache_add_file
 dnl removed in linux 6.1.  folio_add_lru is a replacement
@@ -328,6 +336,37 @@ AC_CHECK_LINUX_FUNC([write_begin_end_folio],
 		    [[aops->write_begin(file, mapping, 0, 0, &foliop, fsdata);
 		      aops->write_end(file, mapping, 0, 0, 0, foliop, fsdata);]])
 
+dnl Linux 5.16 added folio_wait_locked and updated wait_on_page_locked to be
+dnl just a wrapper for folio_wait_locked.  Linux 6.15 removed wait_on_paged_locked
+AC_CHECK_LINUX_FUNC([folio_wait_locked],
+		    [[#include <linux/pagemap.h>
+		      #include <linux/fs.h>]],
+		    [[folio_wait_locked(NULL);]])
+
+dnl Linux 5.16 added __filemap_get_folio to replace grab_cache_page_write_begin
+dnl Linux 6.15 removed grab_cache_page_write_begin
+AC_CHECK_LINUX_FUNC([filemap_get_folio],
+                    [[#include <linux/pagemap.h>
+                      #include <linux/fs.h>
+                      static struct folio *folio;]],
+                    [[folio = __filemap_get_folio(NULL, 0, 0, 0);]])
+
+dnl Linux 6.16, lookup_noperm replaces lookup_one_len
+AC_CHECK_LINUX_FUNC([lookup_noperm],
+		    [[#include <linux/namei.h>
+		      #include <linux/dcache.h>
+		      static struct dentry *dp;]],
+		    [[dp = lookup_noperm(NULL, NULL);]])
+dnl Linux 5.17 introduced __readahead_folio and updated
+dnl readahead_page as a wrapper for __readahead_folio.
+dnl Linux 6.16, removed readahead_page.
+dnl Don't use readahead_folio(), because it has different behavior
+dnl (it performs a put on the folio).
+AC_CHECK_LINUX_FUNC([readahead_folio],
+		    [[#include <linux/pagemap.h>
+		      static struct folio *folio;]],
+		    [[folio = __readahead_folio(NULL);]])
+
 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-sig.m4 b/src/cf/linux-kernel-sig.m4
index 5301f35036..c9b8fe8ed5 100644
--- a/src/cf/linux-kernel-sig.m4
+++ b/src/cf/linux-kernel-sig.m4
@@ -41,4 +41,13 @@ dnl define.
 AS_IF([test AS_VAR_GET([ac_cv_linux_operation_inode_operations_create_mnt_idmap]) = yes],
       [AC_DEFINE([IOP_TAKES_MNT_IDMAP], 1,
                  [define if inodeops require struct mnt_idmap])])
+
+dnl Linux 6.15 changed the return value for inode_operations.mkdir to a struct dentry *
+AC_CHECK_LINUX_OPERATION([inode_operations], [mkdir], [return_dentry],
+                         [#include <linux/fs.h>],
+                         [struct dentry *],
+                         [struct mnt_idmap *idmap,
+                         struct inode *inode, struct dentry *dentry,
+                         umode_t umode])
+
 ])
\ No newline at end of file
diff --git a/src/cf/linux-kernel-struct.m4 b/src/cf/linux-kernel-struct.m4
index 5cd346fb52..24841e9f32 100644
--- a/src/cf/linux-kernel-struct.m4
+++ b/src/cf/linux-kernel-struct.m4
@@ -60,6 +60,9 @@ AC_CHECK_LINUX_STRUCT([task_struct], [sigmask_lock], [sched.h])
 AC_CHECK_LINUX_STRUCT([task_struct], [tgid], [sched.h])
 AC_CHECK_LINUX_STRUCT([task_struct], [thread_info], [sched.h])
 AC_CHECK_LINUX_STRUCT([task_struct], [total_link_count], [sched.h])
+dnl Linux 6.16 changed page.index to page.__folio_index;
+AC_CHECK_LINUX_STRUCT([page], [__folio_index], [mm_types.h])
+
 LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_SIGNAL_RLIM
 
 dnl Check for typed structure elements
diff --git a/src/cf/linux-kernel-symbol.m4 b/src/cf/linux-kernel-symbol.m4
new file mode 100644
index 0000000000..79493dc3ee
--- /dev/null
+++ b/src/cf/linux-kernel-symbol.m4
@@ -0,0 +1,7 @@
+AC_DEFUN([OPENAFS_LINUX_KERNEL_SYMBOL_CHECKS],[
+dnl Type existence checks
+
+dnl Linux 2.6.38 introduced DCACHE_NEED_AUTOMOUNT, and Linux 6.15 converted it
+dnl from a #define to an enum.
+AC_CHECK_LINUX_SYMBOL([DCACHE_NEED_AUTOMOUNT], [dcache.h])
+])
diff --git a/src/cf/linux-test1.m4 b/src/cf/linux-test1.m4
index 010a4464f2..fbe3c1aa80 100644
--- a/src/cf/linux-test1.m4
+++ b/src/cf/linux-test1.m4
@@ -23,6 +23,7 @@ $2
 } 
 
 MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
+MODULE_DESCRIPTION("openafs conftest");
 _ACEOF
     echo make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir $SPARSE_MAKEFLAGS modules KBUILD_VERBOSE=1 >&AS_MESSAGE_LOG_FD &&
     make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir $SPARSE_MAKEFLAGS modules KBUILD_VERBOSE=1 >&AS_MESSAGE_LOG_FD 2>conftest.err &&
@@ -178,6 +179,19 @@ AC_DEFUN([AC_CHECK_LINUX_TYPE],
                        [Define if kernel defines $1])
  ])
 
+dnl AC_CHECK_LINUX_SYMBOL([sym], [includes])
+dnl Linux 6.15 has started converting some defines into enums
+dnl for constants that we use, a simple #ifdef no longer works
+AC_DEFUN([AC_CHECK_LINUX_SYMBOL],
+ [AC_CHECK_LINUX_BUILD([for symbol $1],
+                       [ac_cv_linux_symbol_$1_exists],
+                       [#include <linux/$2>],
+                       [static int _test_ = $1; ],
+                       AS_TR_CPP(HAVE_$1),
+                       [Define if kernel defines symbol $1])
+ ])
+
+
 dnl AC_CHECK_LINUX_STRUCT([structure], [element], [includes])
 AC_DEFUN([AC_CHECK_LINUX_STRUCT],
  [AC_CHECK_LINUX_TYPED_STRUCT([struct $1], [$2], [$3])
diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4
index b22930690e..9139f24358 100644
--- a/src/cf/linux-test4.m4
+++ b/src/cf/linux-test4.m4
@@ -855,6 +855,20 @@ AC_DEFUN([LINUX_KEYRING_SEARCH_TAKES_RECURSE], [
                        [])
 ])
 
+dnl Linux 5.2 changed struct name_snapshot.name from a const char* to a
+dnl struct qstr.
+AC_DEFUN([LINUX_STRUCT_NAME_SNAPSHOT_USES_QSTR],[
+    AC_CHECK_LINUX_BUILD([whether struct name_snapshot uses qstr],
+			 [ac_cv_linux_name_snapshot_uses_qstr],
+			 [[#include <linux/dcache.h>
+			   struct qstr *a;
+			   struct name_snapshot ns;]],
+			 [[if (&ns.name == a) printk("yes\n");]],
+			 [[LINUX_STRUCT_NAME_SNAPSHOT_USES_QSTR]],
+			 [[define if struct name_snapshot uses qstr]],
+			 [[-Werror]])
+])
+
 dnl Linux 6.6 added the 'request_mask' parameter to generic_fillattr.
 AC_DEFUN([LINUX_GENERIC_FILLATTR_TAKES_REQUEST_MASK], [
   AC_CHECK_LINUX_BUILD([whether generic_fillattr has the request_mask parameter],
@@ -885,3 +899,41 @@ AC_DEFUN([LINUX_FILE_LOCK_CORE], [
                        [define if file_lock_core exists],
                        [])
 ])
+
+dnl linux 6.14 updated dentry_operations.d_revalidate with 2 additional
+dnl parameters, the inode of the parent directory and the name the dentry
+dnl is expected to have.  Using these are optional.  Both parameters are
+dnl stable.
+AC_DEFUN([LINUX_DOP_D_REVALIDATE_TAKES_PARENT_INODE], [
+  AC_CHECK_LINUX_BUILD([whether dop.d_revalidate takes inode and qstr],
+                       [ac_cv_linux_func_d_revalidate_takes_parent_inode],
+                       [#include <linux/fs.h>
+                       #include <linux/namei.h>
+                       static int reval(struct inode  *parent_inode, const struct qstr *name,
+			                struct dentry *d, unsigned int flags) { return 0; }
+                       struct dentry_operations dops;],
+                       [dops.d_revalidate = reval;],
+                       [DOP_REVALIDATE_TAKES_PARENT_INODE],
+                       [define if your dops.d_revalidate takes a parent inode],
+                       [-Werror])
+])
+
+dnl Linux 6.16 removed the address_space_operations writepage as part
+dnl of Linux's page to folio transistion. Convert from providing aop->writepage
+dnl to providing aop->writepages and use Linux's write_cache_pages with a callback.
+dnl Test to see whether write_cache_pages uses folios to determine if writepages
+dnl should be implemented.
+AC_DEFUN([LINUX_WRITEPAGES_USES_FOLIOS], [
+  AC_CHECK_LINUX_BUILD([whether aop.writepages can use folios],
+                       [ac_cv_linux_writepages_uses_folios],
+                       [[#include <linux/writeback.h>
+                         #include <linux/mm_types.h>
+                         static int writepages_cb(struct folio *folio,
+                                                  struct writeback_control *wbc,
+                                                  void *priv) { return 0; }]],
+                       [[static int code;
+                         code = write_cache_pages(NULL, NULL, writepages_cb, NULL);]],
+                       [[LINUX_WRITEPAGES_USES_FOLIOS]],
+                       [[define if aop.writepages can use folios]],
+                       [[-Werror]])
+])
diff --git a/src/cf/macos.m4 b/src/cf/macos.m4
new file mode 100644
index 0000000000..cb5201aa1f
--- /dev/null
+++ b/src/cf/macos.m4
@@ -0,0 +1,41 @@
+dnl
+dnl Set KINCLUDES and KROOT for building the kernel module on macos.
+dnl
+dnl The include path needed for building kernel extensions moved from
+dnl /System/Library/Frameworks/Kernel.framework/Headers
+dnl to
+dnl /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers
+dnl sometime around darwin_180. Detect which path exists, and use the first one
+dnl we find, preferring the "CommandLineTools" (clt) path, then the path from
+dnl 'xcrun --show-sdk-path'.
+dnl
+AC_DEFUN([OPENAFS_MACOS_KINCLUDES], [
+
+  clt_kroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
+  xcode_kroot="$(xcrun --show-sdk-path)"
+  hdr_path=/System/Library/Frameworks/Kernel.framework/Headers
+
+  AC_MSG_CHECKING([for path to macOS kernel extension headers])
+  KINCLUDES=
+  for KROOT in "$clt_kroot" "$xcode_kroot" '' ; do
+    AS_IF([test -e "$KROOT$hdr_path"],
+     [KINCLUDES="-I$KROOT$hdr_path"
+      AC_MSG_RESULT([$KINCLUDES])
+      break])
+  done
+
+  AS_IF([test x"$KINCLUDES" = x],
+   [AC_MSG_RESULT([none])
+    AS_CASE([$enable_kernel_module],
+     [yes],
+       [AC_MSG_ERROR([Cannot find kernel extension headers (${hdr_path})])],
+     [maybe],
+       [enable_kernel_module="no"
+	AC_MSG_WARN(m4_normalize([
+	  Cannot find kernel extension headers (${hdr_path}), disabling
+	  building the kernel module])
+	)])])
+
+  AC_SUBST([KROOT])
+  AC_SUBST([KINCLUDES])
+])
diff --git a/src/cf/options.m4 b/src/cf/options.m4
index 4b20ae8a42..4b9345326e 100644
--- a/src/cf/options.m4
+++ b/src/cf/options.m4
@@ -250,6 +250,21 @@ AC_ARG_WITH([dot],
         [use graphviz dot to generate dependency graphs with doxygen (defaults to autodetect)]),
         [], [with_dot="maybe"])
 
+AC_ARG_WITH([macos-app-key],
+        AS_HELP_STRING([--with-macos-app-key=key],
+        [macOS: use the given app key to sign the code (optional, defaults to no key)]),
+        [AC_SUBST([MACOS_APP_KEY], [$withval])])
+
+AC_ARG_WITH([macos-inst-key],
+        AS_HELP_STRING([--with-macos-inst-key=key],
+        [macOS: use the given inst key to sign the installer (optional, defaults to no key)]),
+        [AC_SUBST([MACOS_INST_KEY], [$withval])])
+
+AC_ARG_WITH([macos-keychain-profile],
+        AS_HELP_STRING([--with-macos-keychain-profile=profile],
+        [macOS: use the given keychain profile to notarize the package (optional, defaults to no profile)]),
+        [AC_SUBST([MACOS_KEYCHAIN_PROFILE], [$withval])])
+
 enable_login="no"
 
 ])
@@ -300,6 +315,44 @@ else
                 VFSCK="vfsck"
         fi
 fi
+
+AS_IF([test "x$with_macos_app_key" != "x"], [
+    # Retrieve the Team ID (OU field) associated with a certificate. MACOS_TEAM_ID is extracted from the
+    # certificate subject using openssl and awk.
+    #
+    # The output from 'openssl x509 -noout -subject' can either look like:
+    # subject=UID=SKMME9E2Y8, CN=Developer ID Application: Org (SKMME9E2Y8), OU=SKMME9E2Y8, O=Org, C=US
+    # or:
+    # subject= /UID=SKMME9E2Y8/CN=Developer ID Application: Org (SKMME9E2Y8)/OU=SKMME9E2Y8/O=Org/C=US
+    macos_app_key="$with_macos_app_key"
+    AC_MSG_CHECKING([for macOS team ID])
+
+    macos_cert=$(security find-certificate -c "$macos_app_key" -p 2>/dev/null)
+    AS_IF([test x"$macos_cert" = x],
+	  [AC_MSG_ERROR([Failed to retrieve the certificate for app key: $macos_app_key])])
+
+    macos_subject=$(echo "$macos_cert" | openssl x509 -noout -subject 2>/dev/null)
+    AS_IF([test x"$macos_subject" = x],
+	  [AC_MSG_ERROR([Failed to process the certificate using openssl])])
+
+    MACOS_TEAM_ID=$(echo "$macos_subject" | \
+		    awk 'BEGIN { FS="OU=" } {print $[]2}' | \
+		    awk 'BEGIN { FS="," } {print $[]1}' | \
+		    awk 'BEGIN { FS="/" } {print $[]1}')
+    AS_IF([test x"$MACOS_TEAM_ID" = x],
+	  [AC_MSG_ERROR([Failed to extract the macOS Team ID])])
+
+    # The MACOS_TEAM_ID should just be a string of alphanumeric characters; if
+    # it contains a delimeter like '/' or '=', then something has clearly gone
+    # wrong. Bail out early if so, so we don't build packages with the wrong
+    # team ID in them.
+    AS_CASE(["$MACOS_TEAM_ID"],
+     [*/*|*,*|*=*], [AC_MSG_ERROR([Failed parsing macOS Team ID: $MACOS_TEAM_ID])])
+
+    AC_MSG_RESULT([$MACOS_TEAM_ID])
+    AC_SUBST([MACOS_TEAM_ID])
+])
+
 ])
 
 AC_DEFUN([OPENAFS_MORE_OPTION_TESTS],[
@@ -337,4 +390,12 @@ fi
 if test "x$enable_pthreaded_ubik" = "xyes"; then
 ENABLE_PTHREADED_UBIK=yes
 fi
+
+dnl If the libtool --disable-shared option is specified, comment out the
+dnl @SHARED_ONLY@ lines in our Makefiles.
+AS_IF([test x"$enable_shared" = xyes],
+ [SHARED_ONLY=],
+ [SHARED_ONLY=#])
+AC_SUBST([SHARED_ONLY])
+
 ])
diff --git a/src/cf/osconf.m4 b/src/cf/osconf.m4
index 843998542e..ff6028adde 100644
--- a/src/cf/osconf.m4
+++ b/src/cf/osconf.m4
@@ -24,26 +24,14 @@ PAM_DBG=-g
 PAM_OPTMZ=
 
 dnl standard programs
-AC_PROG_RANLIB
-AC_CHECK_PROGS(AS, as, [false])
+AC_REQUIRE([AC_PROG_RANLIB])
+AC_CHECK_TOOL(AS, as, [false])
 AC_CHECK_PROGS(MV, mv, [false])
 AC_CHECK_PROGS(RM, rm, [false])
-AC_CHECK_PROGS(LD, ld, [false])
+AC_CHECK_TOOL(LD, ld, [false])
 AC_CHECK_PROGS(CP, cp, [false])
 AC_CHECK_PROGS(GENCAT, gencat, [false])
 
-dnl if ar is not present, libtool.m4 (provided by libtool) sets AR to false
-dnl if strip is not present, libtool.m4 (provided by libtool) sets STRIP to :
-AS_IF([test "x$AR" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'ar'])])
-AS_IF([test "x$AS" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'as'])])
-AS_IF([test "x$MV" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'mv'])])
-AS_IF([test "x$RM" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'rm'])])
-AS_IF([test "x$LD" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'ld'])])
-AS_IF([test "x$CP" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'cp'])])
-AS_IF([test "x$GENCAT" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'gencat'])])
-
-dnl TODO - need to disable STRIP if we are doing debugging in any user space code
-
 case $AFS_SYSNAME in
 	alpha_linux_22 | alpha_linux_24 | alpha_linux_26)
 		CCOBJ="\$(CC) -fPIC"
@@ -51,7 +39,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -61,7 +48,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -80,7 +66,6 @@ case $AFS_SYSNAME in
 		PAM_LIBS="/usr/lib/libpam.1"
 		RANLIB="/usr/bin/ranlib"
 		RM="/bin/rm"
-		SHLIB_LDFLAGS="-b -Bsymbolic"
 		SHLIB_SUFFIX="sl"
 		VFSCK_CFLAGS="-D_FILE64"
 		XCFLAGS0="-ldld -lc -Wp,-H200000 -Wl,-a,archive -DAUTH_DBM_LOG +z -Wl,+k -D_LARGEFILE64_SOURCE"
@@ -105,7 +90,6 @@ case $AFS_SYSNAME in
 		PAM_LIBS="/usr/lib/libpam.1"
 		RANLIB="/usr/bin/ranlib"
 		RM="/bin/rm"
-		SHLIB_LDFLAGS="-b -Bsymbolic"
 		SHLIB_SUFFIX="sl"
 		VFSCK_CFLAGS="-I/usr/old/usr/include -D_FILE64"
 		XCFLAGS0="-ldld -lc -Wp,-H200000 -Wl,-a,archive -DAUTH_DBM_LOG +z -Wl,+k -D_LARGEFILE64_SOURCE"
@@ -130,7 +114,6 @@ case $AFS_SYSNAME in
 		PAM_LIBS="/usr/lib/hpux32/libpam.so"
 		RANLIB="/usr/bin/ranlib"
 		RM="/bin/rm"
-		SHLIB_LDFLAGS="-b -Bsymbolic"
 		SHLIB_SUFFIX="sl"
 		VFSCK_CFLAGS="-I/usr/old/usr/include -D_FILE64"
 		XCFLAGS0="-ldld -lc -Wp,-H200000 -Wl,-a,archive_shared -DAUTH_DBM_LOG +z -Wl,+k -D_LARGEFILE64_SOURCE"
@@ -144,7 +127,6 @@ case $AFS_SYSNAME in
 		MT_CFLAGS='-pthread -D_REENTRANT'
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-pipe -fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS="-pipe"
 		;;
@@ -153,7 +135,6 @@ case $AFS_SYSNAME in
 		MT_CFLAGS='-pthread -D_REENTRANT'
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-pipe -fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS="-pipe"
 		;;
@@ -161,7 +142,6 @@ case $AFS_SYSNAME in
 	amd64_fbsd_*)
 		MT_CFLAGS='-pthread -D_REENTRANT'
 		PAM_CFLAGS="-O2 -pipe -fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS="-O2 -pipe -fPIC"
 		;;
@@ -171,7 +151,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-pipe -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS="-pipe"
 		;;
@@ -180,7 +159,6 @@ case $AFS_SYSNAME in
 		MT_LIBS='${XLIBS}'
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-pipe -fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS="-pipe"
 		;;
@@ -191,7 +169,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		XCFLAGS="-G0"
 		SHLIB_LINKER="${CC} -shared"
 		;;
@@ -203,7 +180,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -211,7 +187,6 @@ case $AFS_SYSNAME in
 		MT_CFLAGS='-pthread -D_REENTRANT'
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_CFLAGS="-fPIC"
 		SHLIB_LINKER="${CC} -shared -m64"
 		XCFLAGS="-m64"
@@ -229,7 +204,6 @@ case $AFS_SYSNAME in
 		OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -242,7 +216,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -254,7 +227,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-pipe -fpic"
 		SHLIB_CFLAGS="-fpic"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		XCFLAGS=
 		;;
@@ -263,8 +235,6 @@ case $AFS_SYSNAME in
 		CC="cc"
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS='-D_REENTRANT'
-		KROOT=
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		LWP_OPTMZ="-O2"
 		REGEX_OBJ="regex.lo"
 		XCFLAGS="-no-cpp-precomp"
@@ -278,8 +248,6 @@ case $AFS_SYSNAME in
 		CC="cc"
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS="-D_REENTRANT"
-		KROOT=
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		KERN_OPTMZ="-Os"
 		LWP_OPTMZ="-Os"
 		OPTMZ="-Os"
@@ -294,8 +262,6 @@ case $AFS_SYSNAME in
 	*_darwin_90)
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS="-D_REENTRANT"
-		KROOT=
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		LD="cc"
 		KERN_OPTMZ="-Os"
 		LWP_OPTMZ="-Os"
@@ -312,8 +278,6 @@ case $AFS_SYSNAME in
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS="-D_REENTRANT"
 		MT_LIBS="${LIB_AFSDB} -framework CoreFoundation"
-		KROOT=
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		LD="cc"
 		KERN_OPTMZ="-Os"
 		LWP_OPTMZ="-Os"
@@ -332,8 +296,6 @@ case $AFS_SYSNAME in
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS="-D_REENTRANT"
 		MT_LIBS='${XLIBS}'
-		KROOT=
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		LD="cc"
 		KERN_OPTMZ="-Os"
 		LWP_OPTMZ="-Os"
@@ -347,12 +309,10 @@ case $AFS_SYSNAME in
 		XLIBS="${LIB_AFSDB} -framework CoreFoundation"
 		;;
 
-	*_darwin_190 | *_darwin_200 | *_darwin_210 | *_darwin_220 | *_darwin_230)
+	*_darwin_190 | *_darwin_200 | *_darwin_210 | *_darwin_220 | *_darwin_230 | *_darwin_240 | *_darwin_250)
 		AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
 		MT_CFLAGS="-D_REENTRANT"
 		MT_LIBS='${XLIBS}'
-		KROOT='/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
-		KINCLUDES='-I$(KROOT)/System/Library/Frameworks/Kernel.framework/Headers'
 		LD="cc"
 		KERN_OPTMZ="-Os"
 		LWP_OPTMZ="-Os"
@@ -372,7 +332,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -428,7 +387,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		SHLIB_LINKER="${CC} -shared"
 		;;
 
@@ -440,7 +398,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x -Xlinker -Bsymbolic"
 		OPTMZ=-O
 		XCFLAGS="-D__s390x__"
 		SHLIB_LINKER="${CC} -shared"
@@ -501,7 +458,6 @@ case $AFS_SYSNAME in
 		PAM_OPTMZ=-O2
 		PAM_CFLAGS="-Dlinux -DLINUX_PAM -fPIC"
 		SHLIB_CFLAGS="-fPIC"
-		SHLIB_LDFLAGS="-shared -Xlinker -x"
 		XCFLAGS64="-m64"
 		XLDFLAGS64="-m64"
 		SHLIB_LINKER="${CC} -shared"
@@ -514,7 +470,6 @@ case $AFS_SYSNAME in
 		PAM_CFLAGS="-KPIC"
 		PAM_LIBS="-lc -lpam -lsocket -lnsl -lm"
 		SHLIB_CFLAGS="-KPIC"
-		SHLIB_LDFLAGS="-G -Bsymbolic"
 		XCFLAGS64='${XCFLAGS} -m64'
 		XCFLAGS="-dy -Bdynamic"
 		XLIBS="${LIB_AFSDB} -lsocket -lnsl -lintl -ldl"
@@ -551,7 +506,6 @@ case $AFS_SYSNAME in
 		PAM_CFLAGS="-KPIC"
 		PAM_LIBS="-lc -lpam -lsocket -lnsl -lm"
 		SHLIB_CFLAGS="-KPIC"
-		SHLIB_LDFLAGS="-G -Bsymbolic"
 		XCFLAGS0="-dy -Bdynamic"
 		XCFLAGS64="${XCFLAGS0} -m64"
 		XCFLAGS="${XCFLAGS0} ${XARCHFLAGS}"
@@ -564,8 +518,34 @@ case $AFS_SYSNAME in
 
 esac
 
+AS_CASE([$AFS_SYSNAME],
+	[*_fbsd_*],
+	dnl FreeBSD 13+ no longer provides a standalone /usr/bin/as in
+	dnl the base system, but we can use the compiler (clang) as an
+	dnl assembler.
+	[AS_IF([test x"$AS" = xfalse],
+	       [AS="$CC"])],
+
+	[*_darwin_*],
+	  [OPENAFS_MACOS_KINCLUDES]
+)
+
 MT_CFLAGS="${MT_CFLAGS} -DAFS_PTHREAD_ENV"
 
+AFS_LT_INIT
+
+dnl if ar is not present, libtool.m4 (provided by libtool) sets AR to false
+dnl if strip is not present, libtool.m4 (provided by libtool) sets STRIP to :
+AS_IF([test "x$AR" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'ar'])])
+AS_IF([test "x$AS" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'as'])])
+AS_IF([test "x$MV" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'mv'])])
+AS_IF([test "x$RM" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'rm'])])
+AS_IF([test "x$LD" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'ld'])])
+AS_IF([test "x$CP" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'cp'])])
+AS_IF([test "x$GENCAT" = "xfalse"], [AC_MSG_ERROR([cannot find required command 'gencat'])])
+
+dnl TODO - need to disable STRIP if we are doing debugging in any user space code
+
 #
 # Defaults for --enable-optimize-kernel
 #
@@ -747,7 +727,6 @@ AC_SUBST(REGEX_OBJ)
 AC_SUBST(RM)
 AC_SUBST(RXDEBUG)
 AC_SUBST(SHLIB_CFLAGS)
-AC_SUBST(SHLIB_LDFLAGS)
 AC_SUBST(SHLIB_LINKER)
 AC_SUBST(SHLIB_SUFFIX)
 AC_SUBST(TSM_IMPORTS)
@@ -767,8 +746,5 @@ AC_SUBST(XLDFLAGS)
 AC_SUBST(XLDFLAGS64)
 AC_SUBST(XLIBS)
 AC_SUBST(YACC)
-AC_SUBST(KROOT)
-AC_SUBST(KINCLUDES)
-
 
 ])
diff --git a/src/cf/swig.m4 b/src/cf/swig.m4
index 81a8999d0d..e88cf7fb75 100644
--- a/src/cf/swig.m4
+++ b/src/cf/swig.m4
@@ -14,6 +14,16 @@ AC_DEFUN([OPENAFS_SWIG],
   [with_swig=check])
 
 LIBUAFS_BUILD_PERL=
+
+dnl Building with swig requires shared library support.  If --disable-shared
+dnl was specified, turn off auto detection (with a notice).  If --with-swig=yes
+dnl generate an error message
+AS_IF([test "x$enable_shared" != "xyes" && test "x$with_swig" != "xno"],
+  [AS_IF([test "x$with_swig" = "xyes"],
+     [AC_MSG_ERROR([--with-swig is incompatible with --disable-shared])],
+     [with_swig=no
+      AC_MSG_NOTICE([--disable-shared specified, swig autodetection is disabled])])])
+
 AS_IF([test "x$with_swig" != "xno"],
   [AC_CHECK_PROG([SWIG], [swig], [swig])
   AS_IF([test "x$SWIG" = "xswig"],
diff --git a/src/cf/sysname.m4 b/src/cf/sysname.m4
index aa4ad2cb42..d852801047 100644
--- a/src/cf/sysname.m4
+++ b/src/cf/sysname.m4
@@ -88,155 +88,157 @@ else
                         ;;
                 powerpc-apple-darwin7*)
                         AFS_SYSNAME="ppc_darwin_70"
-                        OSXSDK="macosx10.3"
+			XCODEBUILD_FLAGS="-sdk macosx10.3"
                         ;;
                 powerpc-apple-darwin8.*)
                         AFS_SYSNAME="ppc_darwin_80"
-                        OSXSDK="macosx10.4"
+			XCODEBUILD_FLAGS="-sdk macosx10.4"
                         ;;
                 i386-apple-darwin8.*)
                         AFS_SYSNAME="x86_darwin_80"
-                        OSXSDK="macosx10.4"
+			XCODEBUILD_FLAGS="-sdk macosx10.4"
                         ;;
                 powerpc-apple-darwin9.*)
                         AFS_SYSNAME="ppc_darwin_90"
-                        OSXSDK="macosx10.5"
+			XCODEBUILD_FLAGS="-sdk macosx10.5"
                         ;;
                 i386-apple-darwin9.*)
                         AFS_SYSNAME="x86_darwin_90"
-                        OSXSDK="macosx10.5"
+			XCODEBUILD_FLAGS="-sdk macosx10.5"
                         ;;
                 i?86-apple-darwin10.*)
                         AFS_SYSNAME="x86_darwin_100"
-                        OSXSDK="macosx10.6"
+			XCODEBUILD_FLAGS="-sdk macosx10.6"
                         ;;
                 x86_64-apple-darwin10.*)
                         AFS_SYSNAME="x86_darwin_100"
-                        OSXSDK="macosx10.6"
+			XCODEBUILD_FLAGS="-sdk macosx10.6"
                         ;;
                 arm-apple-darwin10.*)
                         AFS_SYSNAME="arm_darwin_100"
-                        OSXSDK="iphoneos4.0"
+			XCODEBUILD_FLAGS="-sdk iphoneos4.0"
                         ;;
                 x86_64-apple-darwin11.*)
                         AFS_SYSNAME="x86_darwin_110"
-                        OSXSDK="macosx10.7"
+			XCODEBUILD_FLAGS="-sdk macosx10.7"
                         ;;
                 i?86-apple-darwin11.*)
                         AFS_SYSNAME="x86_darwin_110"
-                        OSXSDK="macosx10.7"
+			XCODEBUILD_FLAGS="-sdk macosx10.7"
                         ;;
                 x86_64-apple-darwin12.*)
                         AFS_SYSNAME="x86_darwin_120"
-                        OSXSDK="macosx10.8"
+			XCODEBUILD_FLAGS="-sdk macosx10.8"
                         ;;
                 i?86-apple-darwin12.*)
                         AFS_SYSNAME="x86_darwin_120"
-                        OSXSDK="macosx10.8"
+			XCODEBUILD_FLAGS="-sdk macosx10.8"
                         ;;
                 x86_64-apple-darwin13.*)
                         AFS_SYSNAME="x86_darwin_130"
-                        OSXSDK="macosx10.9"
+			XCODEBUILD_FLAGS="-sdk macosx10.9"
                         ;;
                 i?86-apple-darwin13.*)
                         AFS_SYSNAME="x86_darwin_130"
-                        OSXSDK="macosx10.9"
+			XCODEBUILD_FLAGS="-sdk macosx10.9"
                         ;;
                 x86_64-apple-darwin14.*)
                         AFS_SYSNAME="x86_darwin_140"
-                        OSXSDK="macosx10.10"
+			XCODEBUILD_FLAGS="-sdk macosx10.10"
                         ;;
                 i?86-apple-darwin14.*)
                         AFS_SYSNAME="x86_darwin_140"
-                        OSXSDK="macosx10.10"
+			XCODEBUILD_FLAGS="-sdk macosx10.10"
                         ;;
                 x86_64-apple-darwin15.*)
                         AFS_SYSNAME="x86_darwin_150"
-                        OSXSDK="macosx10.11"
+			XCODEBUILD_FLAGS="-sdk macosx10.11"
                         ;;
                 i?86-apple-darwin15.*)
                         AFS_SYSNAME="x86_darwin_150"
-                        OSXSDK="macosx10.11"
+			XCODEBUILD_FLAGS="-sdk macosx10.11"
                         ;;
                 x86_64-apple-darwin16.*)
                         AFS_SYSNAME="x86_darwin_160"
-                        OSXSDK="macosx10.12"
+			XCODEBUILD_FLAGS="-sdk macosx10.12"
                         ;;
                 i?86-apple-darwin16.*)
                         AFS_SYSNAME="x86_darwin_160"
-                        OSXSDK="macosx10.12"
+			XCODEBUILD_FLAGS="-sdk macosx10.12"
                         ;;
                 x86_64-apple-darwin17.*)
                         AFS_SYSNAME="x86_darwin_170"
-                        OSXSDK="macosx10.13"
+			XCODEBUILD_FLAGS="-sdk macosx10.13"
                         ;;
                 i?86-apple-darwin17.*)
                         AFS_SYSNAME="x86_darwin_170"
-                        OSXSDK="macosx10.13"
+			XCODEBUILD_FLAGS="-sdk macosx10.13"
                         ;;
 		x86_64-apple-darwin18.*)
 			AFS_SYSNAME="x86_darwin_180"
-			OSXSDK="macosx10.14"
 			;;
 		i?86-apple-darwin18.*)
 			AFS_SYSNAME="x86_darwin_180"
-			OSXSDK="macosx10.14"
 			;;
 		x86_64-apple-darwin19.*)
 			AFS_SYSNAME="x86_darwin_190"
-			OSXSDK="macosx10.15"
 			;;
 		i?86-apple-darwin19.*)
 			AFS_SYSNAME="x86_darwin_190"
-			OSXSDK="macosx10.15"
 			;;
 		x86_64-apple-darwin20.*)
 			AFS_SYSNAME="x86_darwin_200"
-			OSXSDK="macosx11.0"
 			;;
 		arm-apple-darwin20.*)
 			AFS_SYSNAME="arm_darwin_200"
-			OSXSDK="macosx11.0"
 			;;
 		aarch64-apple-darwin20.*)
 			AFS_SYSNAME="arm_darwin_200"
-			OSXSDK="macosx11.0"
 			;;
 		x86_64-apple-darwin21.*)
 			AFS_SYSNAME="x86_darwin_210"
-			OSXSDK="macosx12.0"
 			;;
 		arm-apple-darwin21.*)
 			AFS_SYSNAME="arm_darwin_210"
-			OSXSDK="macosx12.0"
 			;;
 		aarch64-apple-darwin21.*)
 			AFS_SYSNAME="arm_darwin_210"
-			OSXSDK="macosx12.0"
 			;;
 		x86_64-apple-darwin22.*)
 			AFS_SYSNAME="x86_darwin_220"
-			OSXSDK="macosx13.0"
 			;;
 		arm-apple-darwin22.*)
 			AFS_SYSNAME="arm_darwin_220"
-			OSXSDK="macosx13.0"
 			;;
 		aarch64-apple-darwin22.*)
 			AFS_SYSNAME="arm_darwin_220"
-			OSXSDK="macosx13.0"
 			;;
 		x86_64-apple-darwin23.*)
 			AFS_SYSNAME="x86_darwin_230"
-			OSXSDK="macosx14.0"
 			;;
 		arm-apple-darwin23.*)
 			AFS_SYSNAME="arm_darwin_230"
-			OSXSDK="macosx14.0"
 			;;
 		aarch64-apple-darwin23.*)
 			AFS_SYSNAME="arm_darwin_230"
-			OSXSDK="macosx14.0"
+			;;
+		x86_64-apple-darwin24.*)
+			AFS_SYSNAME="x86_darwin_240"
+			;;
+		arm-apple-darwin24.*)
+			AFS_SYSNAME="arm_darwin_240"
+			;;
+		aarch64-apple-darwin24.*)
+			AFS_SYSNAME="arm_darwin_240"
+			;;
+		x86_64-apple-darwin25.*)
+			AFS_SYSNAME="x86_darwin_250"
+			;;
+		arm-apple-darwin25.*)
+			AFS_SYSNAME="arm_darwin_250"
+			;;
+		aarch64-apple-darwin25.*)
+			AFS_SYSNAME="arm_darwin_250"
 			;;
                 sparc-sun-solaris2.8)
                         AFS_SYSNAME="sun4x_58"
@@ -382,7 +384,7 @@ case $AFS_SYSNAME in
                 AC_CHECK_HEADERS(crt_externs.h)
                 DARWIN_PLIST=src/libafs/afs.${AFS_SYSNAME}.plist
                 DARWIN_INFOFILE=afs.${AFS_SYSNAME}.plist
-                AC_SUBST(OSXSDK)
+		AC_SUBST([XCODEBUILD_FLAGS])
                 ;;
 esac
 
@@ -441,6 +443,12 @@ case $AFS_SYSNAME in
         *_darwin_230)
                 AFS_PARAM=param.darwin_230.h
                 ;;
+        *_darwin_240)
+                AFS_PARAM=param.darwin_240.h
+                ;;
+        *_darwin_250)
+                AFS_PARAM=param.darwin_250.h
+                ;;
         *)
                 AFS_PARAM=param.${AFS_SYSNAME}.h
                 ;;
diff --git a/src/config/Makefile.config.in b/src/config/Makefile.config.in
index d4b9063dac..1a7117d9f9 100644
--- a/src/config/Makefile.config.in
+++ b/src/config/Makefile.config.in
@@ -100,7 +100,6 @@ ROKEN_HEADERS = @ROKEN_HEADERS@
 ROKEN_LTLIBOBJS = @LTLIBOBJS@
 SED = @SED@
 SHLIB_CFLAGS = @SHLIB_CFLAGS@
-SHLIB_LDFLAGS = @SHLIB_LDFLAGS@
 SHLIB_LINKER = @SHLIB_LINKER@
 SHLIB_SUFFIX = @SHLIB_SUFFIX@
 SYS_NAME = @AFS_SYSNAME@
@@ -237,12 +236,6 @@ PTH_LDFLAGS=$(MODULE_LDFLAGS) $(COMMON_LDFLAGS) $(MT_LDFLAGS)
 PTH_CCRULE        =$(RUN_CC) $(CC_WRAPPER) $(MT_CC) $(CPPFLAGS_$(@)) $(PTH_CFLAGS) $(CFLAGS_$(@)) -o $@ -c
 PTH_CCRULE_NOQ=$(RUN_CC_NOQ) $(CC_WRAPPER) $(MT_CC) $(CPPFLAGS_$(@)) $(PTH_CFLAGS) $(CFLAGS_$(@)) -o $@ -c
 
-# Shared
-SHD_CFLAGS=$(MODULE_CFLAGS) $(COMMON_CFLAGS) $(MT_CFLAGS) $(SHLIB_CFLAGS)
-SHD_LDFLAGS=$(MODULE_LDFLAGS) $(COMMON_LDFLAGS) $(SHLIB_LDFLAGS)
-SHD_CCRULE        =$(RUN_CC) $(CC_WRAPPER) $(MT_CC) $(CPPFLAGS_$(@)) $(SHD_CFLAGS) $(CFLAGS_$(@)) -o $@ -c
-SHD_CCRULE_NOQ=$(RUN_CC_NOQ) $(CC_WRAPPER) $(MT_CC) $(CPPFLAGS_$(@)) $(SHD_CFLAGS) $(CFLAGS_$(@)) -o $@ -c
-
 # Libtool - for objects that are part of pthread-only libraries
 LT_CCRULE=$(RUN_CC) $(LIBTOOL) --quiet --mode=compile --tag=CC \
 	      $(CC_WRAPPER) $(MT_CC) $(CPPFLAGS_$(@)) $(PTH_CFLAGS) $(CFLAGS_$(@)) -o $@ -c
@@ -260,7 +253,9 @@ LT_LDLIB_shlib_common=$(LIBTOOL) --quiet --mode=link --tag=CC \
 
 LT_LDLIB_shlib=$(LT_LDLIB_shlib_common) -export-symbols $(srcdir)/$@.sym
 
-LT_LDLIB_shlib_missing=$(LT_LDLIB_shlib_common) -export-symbols-regex \
+LT_LDLIB_shlib_only=$(LT_LDLIB_shlib_common) -shared -export-symbols $(srcdir)/$@.sym
+
+LT_LDLIB_shlib_missing=$(LT_LDLIB_shlib_common) -shared -export-symbols-regex \
 	"($$(sed -e 's/^/^/' -e 's/$$/$$|/' -e '$$ s/|$$//' $(srcdir)/$@.sym | \
 	tr -d '\n'))"
 
diff --git a/src/config/NTMakefile.amd64_w2k b/src/config/NTMakefile.amd64_w2k
index b8ed6dff32..b0380d2627 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=1302
+AFSPRODUCT_VER_PATCH=1400
 !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 83b434899d..2079667d39 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=1302
+AFSPRODUCT_VER_PATCH=1400
 !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 91f2791fcc..18028ccb56 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=1302
+AFSPRODUCT_VER_PATCH=1400
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/config/afs_sysnames.h b/src/config/afs_sysnames.h
index 196a5d9f2f..98863594c4 100644
--- a/src/config/afs_sysnames.h
+++ b/src/config/afs_sysnames.h
@@ -103,6 +103,10 @@
 #define SYS_NAME_ID_arm_darwin_220       550
 #define SYS_NAME_ID_amd64_darwin_230     551
 #define SYS_NAME_ID_arm_darwin_230       552
+#define SYS_NAME_ID_amd64_darwin_240     553
+#define SYS_NAME_ID_arm_darwin_240       554
+#define SYS_NAME_ID_amd64_darwin_250     555
+#define SYS_NAME_ID_arm_darwin_250       556
 
 #define SYS_NAME_ID_next_mach20		 601
 #define SYS_NAME_ID_next_mach30		 602
diff --git a/src/config/param.darwin_200.h b/src/config/param.darwin_200.h
index 5f91464c5c..94c98669e5 100644
--- a/src/config/param.darwin_200.h
+++ b/src/config/param.darwin_200.h
@@ -37,9 +37,6 @@
 #  define AFS_NEW_BKG                 1
 #  define NEED_IOCTL32
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_GCPAGS                  0
@@ -114,9 +111,6 @@
 #  define DARWIN_REFBASE              0
 #  define AFS_WARNUSER_MARINER_ENV    1
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_UIOSYS                  UIO_SYSSPACE
diff --git a/src/config/param.darwin_210.h b/src/config/param.darwin_210.h
index 475965255d..691843a306 100644
--- a/src/config/param.darwin_210.h
+++ b/src/config/param.darwin_210.h
@@ -38,9 +38,6 @@
 #  define AFS_NEW_BKG                 1
 #  define NEED_IOCTL32
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_GCPAGS                  0
@@ -116,9 +113,6 @@
 #  define DARWIN_REFBASE              0
 #  define AFS_WARNUSER_MARINER_ENV    1
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_UIOSYS                  UIO_SYSSPACE
diff --git a/src/config/param.darwin_220.h b/src/config/param.darwin_220.h
index c799c7f8a3..938284138f 100644
--- a/src/config/param.darwin_220.h
+++ b/src/config/param.darwin_220.h
@@ -39,9 +39,6 @@
 #  define AFS_NEW_BKG                 1
 #  define NEED_IOCTL32
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_GCPAGS                  0
@@ -118,9 +115,6 @@
 #  define DARWIN_REFBASE              0
 #  define AFS_WARNUSER_MARINER_ENV    1
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_UIOSYS                  UIO_SYSSPACE
diff --git a/src/config/param.darwin_230.h b/src/config/param.darwin_230.h
index 000ebb0e28..14c42d27da 100644
--- a/src/config/param.darwin_230.h
+++ b/src/config/param.darwin_230.h
@@ -40,9 +40,6 @@
 #  define AFS_NEW_BKG                 1
 #  define NEED_IOCTL32
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_GCPAGS                  0
@@ -120,9 +117,6 @@
 #  define DARWIN_REFBASE              0
 #  define AFS_WARNUSER_MARINER_ENV    1
 
-/* File system entry (used if mount.h doesn't define MOUNT_AFS) */
-#  define AFS_MOUNT_AFS               "afs"
-
 #  define AFS_HAVE_FFS                1	/* Use system's ffs. */
 
 #  define AFS_UIOSYS                  UIO_SYSSPACE
diff --git a/src/config/param.darwin_240.h b/src/config/param.darwin_240.h
new file mode 100644
index 0000000000..139e09c2ba
--- /dev/null
+++ b/src/config/param.darwin_240.h
@@ -0,0 +1,201 @@
+#ifndef AFS_PARAM_H
+# define AFS_PARAM_H
+
+# ifndef UKERNEL
+/* This section for kernel libafs compiles only */
+
+#  define AFS_ENV                     1
+#  define AFS_64BIT_ENV               1	/* Defines afs_int32 as int, not long. */
+#  define AFS_64BIT_CLIENT            1
+#  define AFS_64BIT_IOPS_ENV          1
+#  define AFS_64BIT_SIZEOF            1 /* seriously? */
+
+#  include <afs/afs_sysnames.h>
+
+#  define AFS_DARWIN_ENV
+#  define AFS_DARWIN70_ENV
+#  define AFS_DARWIN80_ENV
+#  define AFS_DARWIN90_ENV
+#  define AFS_DARWIN100_ENV
+#  define AFS_DARWIN110_ENV
+#  define AFS_DARWIN120_ENV
+#  define AFS_DARWIN130_ENV
+#  define AFS_DARWIN140_ENV
+#  define AFS_DARWIN150_ENV
+#  define AFS_DARWIN160_ENV
+#  define AFS_DARWIN170_ENV
+#  define AFS_DARWIN180_ENV
+#  define AFS_DARWIN190_ENV
+#  define AFS_DARWIN200_ENV
+#  define AFS_DARWIN210_ENV
+#  define AFS_DARWIN220_ENV
+#  define AFS_DARWIN230_ENV
+#  define AFS_DARWIN240_ENV
+#  undef  AFS_NONFSTRANS
+#  define AFS_NONFSTRANS
+#  define AFS_SYSCALL                 230
+#  define AFS_NAMEI_ENV               1
+#  define DARWIN_REFBASE              3
+#  define AFS_WARNUSER_MARINER_ENV    1
+#  define AFS_CACHE_VNODE_PATH
+#  define AFS_NEW_BKG                 1
+#  define NEED_IOCTL32
+
+#  define AFS_HAVE_FFS                1	/* Use system's ffs. */
+
+#  define AFS_GCPAGS                  0
+#  define RXK_UPCALL_ENV              1
+#  define RXK_TIMEDSLEEP_ENV          1
+#  define AFS_USERSPACE_IP_ADDR       1
+#  define AFS_SOCKPROXY_ENV           1
+
+#  ifdef KERNEL
+#   undef MACRO_BEGIN
+#   undef MACRO_END
+
+#   include <kern/macro_help.h>
+
+#   define AFS_GLOBAL_SUNLOCK         1
+#   define AFS_VFS34                  1	/* What is VFS34??? */
+
+#   define afsio_iov                  uio_iov
+#   define afsio_iovcnt               uio_iovcnt
+#   define afsio_offset               uio_offset
+#   define afsio_seg                  uio_segflg
+#   define afsio_resid                uio_resid
+
+#   define AFS_UIOSYS                 UIO_SYSSPACE
+#   define AFS_UIOUSER                UIO_USERSPACE
+#   define AFS_CLBYTES                CLBYTES
+#   define AFS_KALLOC(x)              _MALLOC(x, M_TEMP, M_WAITOK)
+#   define AFS_KFREE(x,y)             _FREE(x,M_TEMP)
+
+#   define v_count                    v_usecount
+#   define v_vfsp                     v_mount
+#   define vfs_bsize                  mnt_stat.f_bsize
+#   define vfs_fsid                   mnt_stat.f_fsid
+#   define va_nodeid                  va_fileid
+#   define vfs_vnodecovered           mnt_vnodecovered
+#   define direct                     dirent
+
+#   define BIND_8_COMPAT
+#  endif /* KERNEL */
+
+# else /* !defined(UKERNEL) */
+
+/* This section for user space compiles only */
+
+#  define AFS_ENV                     1
+#  define AFS_64BIT_ENV               1	/* Defines afs_int32 as int, not long. */
+#  define AFS_64BIT_CLIENT            1
+
+#  include <afs/afs_sysnames.h>
+
+#  define AFS_USERSPACE_ENV
+#  define AFS_USR_DARWIN_ENV
+#  define AFS_USR_DARWIN70_ENV
+#  define AFS_USR_DARWIN80_ENV
+#  define AFS_USR_DARWIN90_ENV
+#  define AFS_USR_DARWIN100_ENV
+#  define AFS_USR_DARWIN110_ENV
+#  define AFS_USR_DARWIN120_ENV
+#  define AFS_USR_DARWIN130_ENV
+#  define AFS_USR_DARWIN140_ENV
+#  define AFS_USR_DARWIN150_ENV
+#  define AFS_USR_DARWIN160_ENV
+#  define AFS_USR_DARWIN170_ENV
+#  define AFS_USR_DARWIN180_ENV
+#  define AFS_USR_DARWIN190_ENV
+#  define AFS_USR_DARWIN200_ENV
+#  define AFS_USR_DARWIN210_ENV
+#  define AFS_USR_DARWIN220_ENV
+#  define AFS_USR_DARWIN230_ENV
+#  define AFS_USR_DARWIN240_ENV
+
+#  undef  AFS_NONFSTRANS
+#  define AFS_NONFSTRANS
+
+#  define AFS_SYSCALL                 230
+#  define DARWIN_REFBASE              0
+#  define AFS_WARNUSER_MARINER_ENV    1
+
+#  define AFS_HAVE_FFS                1	/* Use system's ffs. */
+
+#  define AFS_UIOSYS                  UIO_SYSSPACE
+#  define AFS_UIOUSER                 UIO_USERSPACE
+
+#  define AFS_GCPAGS                  0	/* if nonzero, garbage collect PAGs */
+#  define RXK_LISTENER_ENV            1
+
+#  define AFS_VFS34                   1	/* What is VFS34??? */
+
+#  define afsio_iov                   uio_iov
+#  define afsio_iovcnt                uio_iovcnt
+#  define afsio_offset                uio_offset
+#  define afsio_seg                   uio_segflg
+#  define afsio_resid                 uio_resid
+
+#  define VATTR_NULL                  usr_vattr_null
+
+#  define AFS_DIRENT
+#  ifndef CMSERVERPREF
+#   define CMSERVERPREF
+#  endif
+
+#  define BIND_8_COMPAT
+# endif /* !defined(UKERNEL) */
+
+/* Machine / Operating system information */
+# if defined(__amd64__)
+
+#  define AFS_X86_ENV                 1
+#  define AFS_64BITUSERPOINTER_ENV    1
+
+#  define sys_x86_darwin_12           1
+#  define sys_x86_darwin_13           1
+#  define sys_x86_darwin_14           1
+#  define sys_x86_darwin_60           1
+#  define sys_x86_darwin_70           1
+#  define sys_x86_darwin_80           1
+#  define sys_x86_darwin_90           1
+#  define sys_x86_darwin_100          1
+#  define sys_amd64_darwin_100        1
+#  define sys_amd64_darwin_110        1
+#  define sys_amd64_darwin_120        1
+#  define sys_amd64_darwin_130        1
+#  define sys_amd64_darwin_140        1
+#  define sys_amd64_darwin_150        1
+#  define sys_amd64_darwin_160        1
+#  define sys_amd64_darwin_170        1
+#  define sys_amd64_darwin_180        1
+#  define sys_amd64_darwin_190        1
+#  define sys_amd64_darwin_200        1
+#  define sys_amd64_darwin_210        1
+#  define sys_amd64_darwin_220        1
+#  define sys_amd64_darwin_230        1
+#  define sys_amd64_darwin_240        1
+
+#  define SYS_NAME                    "amd64_darwin_240"
+#  define SYS_NAME_ID                 SYS_NAME_ID_amd64_darwin_240
+#  define AFSLITTLE_ENDIAN            1
+
+# elif defined(__arm64__)
+
+#  define AFS_ARM_ENV                 1
+#  define AFS_ARM64_DARWIN_ENV        1
+
+#  define sys_arm_darwin_200          1
+#  define sys_arm_darwin_210          1
+#  define sys_arm_darwin_220          1
+#  define sys_arm_darwin_230          1
+#  define sys_arm_darwin_240          1
+
+#  define SYS_NAME                    "arm_darwin_240"
+#  define SYS_NAME_ID                 SYS_NAME_ID_arm_darwin_240
+#  define AFSLITTLE_ENDIAN            1
+
+# else
+# error Unsupported architecture
+# endif /* __amd64__ */
+
+#endif /* AFS_PARAM_H */
diff --git a/src/config/param.darwin_250.h b/src/config/param.darwin_250.h
new file mode 100644
index 0000000000..bd1ba03c28
--- /dev/null
+++ b/src/config/param.darwin_250.h
@@ -0,0 +1,205 @@
+#ifndef AFS_PARAM_H
+# define AFS_PARAM_H
+
+# ifndef UKERNEL
+/* This section for kernel libafs compiles only */
+
+#  define AFS_ENV                     1
+#  define AFS_64BIT_ENV               1	/* Defines afs_int32 as int, not long. */
+#  define AFS_64BIT_CLIENT            1
+#  define AFS_64BIT_IOPS_ENV          1
+#  define AFS_64BIT_SIZEOF            1 /* seriously? */
+
+#  include <afs/afs_sysnames.h>
+
+#  define AFS_DARWIN_ENV
+#  define AFS_DARWIN70_ENV
+#  define AFS_DARWIN80_ENV
+#  define AFS_DARWIN90_ENV
+#  define AFS_DARWIN100_ENV
+#  define AFS_DARWIN110_ENV
+#  define AFS_DARWIN120_ENV
+#  define AFS_DARWIN130_ENV
+#  define AFS_DARWIN140_ENV
+#  define AFS_DARWIN150_ENV
+#  define AFS_DARWIN160_ENV
+#  define AFS_DARWIN170_ENV
+#  define AFS_DARWIN180_ENV
+#  define AFS_DARWIN190_ENV
+#  define AFS_DARWIN200_ENV
+#  define AFS_DARWIN210_ENV
+#  define AFS_DARWIN220_ENV
+#  define AFS_DARWIN230_ENV
+#  define AFS_DARWIN240_ENV
+#  define AFS_DARWIN250_ENV
+#  undef  AFS_NONFSTRANS
+#  define AFS_NONFSTRANS
+#  define AFS_SYSCALL                 230
+#  define AFS_NAMEI_ENV               1
+#  define DARWIN_REFBASE              3
+#  define AFS_WARNUSER_MARINER_ENV    1
+#  define AFS_CACHE_VNODE_PATH
+#  define AFS_NEW_BKG                 1
+#  define NEED_IOCTL32
+
+#  define AFS_HAVE_FFS                1	/* Use system's ffs. */
+
+#  define AFS_GCPAGS                  0
+#  define RXK_UPCALL_ENV              1
+#  define RXK_TIMEDSLEEP_ENV          1
+#  define AFS_USERSPACE_IP_ADDR       1
+#  define AFS_SOCKPROXY_ENV           1
+
+#  ifdef KERNEL
+#   undef MACRO_BEGIN
+#   undef MACRO_END
+
+#   include <kern/macro_help.h>
+
+#   define AFS_GLOBAL_SUNLOCK         1
+#   define AFS_VFS34                  1	/* What is VFS34??? */
+
+#   define afsio_iov                  uio_iov
+#   define afsio_iovcnt               uio_iovcnt
+#   define afsio_offset               uio_offset
+#   define afsio_seg                  uio_segflg
+#   define afsio_resid                uio_resid
+
+#   define AFS_UIOSYS                 UIO_SYSSPACE
+#   define AFS_UIOUSER                UIO_USERSPACE
+#   define AFS_CLBYTES                CLBYTES
+#   define AFS_KALLOC(x)              _MALLOC(x, M_TEMP, M_WAITOK)
+#   define AFS_KFREE(x,y)             _FREE(x,M_TEMP)
+
+#   define v_count                    v_usecount
+#   define v_vfsp                     v_mount
+#   define vfs_bsize                  mnt_stat.f_bsize
+#   define vfs_fsid                   mnt_stat.f_fsid
+#   define va_nodeid                  va_fileid
+#   define vfs_vnodecovered           mnt_vnodecovered
+#   define direct                     dirent
+
+#   define BIND_8_COMPAT
+#  endif /* KERNEL */
+
+# else /* !defined(UKERNEL) */
+
+/* This section for user space compiles only */
+
+#  define AFS_ENV                     1
+#  define AFS_64BIT_ENV               1	/* Defines afs_int32 as int, not long. */
+#  define AFS_64BIT_CLIENT            1
+
+#  include <afs/afs_sysnames.h>
+
+#  define AFS_USERSPACE_ENV
+#  define AFS_USR_DARWIN_ENV
+#  define AFS_USR_DARWIN70_ENV
+#  define AFS_USR_DARWIN80_ENV
+#  define AFS_USR_DARWIN90_ENV
+#  define AFS_USR_DARWIN100_ENV
+#  define AFS_USR_DARWIN110_ENV
+#  define AFS_USR_DARWIN120_ENV
+#  define AFS_USR_DARWIN130_ENV
+#  define AFS_USR_DARWIN140_ENV
+#  define AFS_USR_DARWIN150_ENV
+#  define AFS_USR_DARWIN160_ENV
+#  define AFS_USR_DARWIN170_ENV
+#  define AFS_USR_DARWIN180_ENV
+#  define AFS_USR_DARWIN190_ENV
+#  define AFS_USR_DARWIN200_ENV
+#  define AFS_USR_DARWIN210_ENV
+#  define AFS_USR_DARWIN220_ENV
+#  define AFS_USR_DARWIN230_ENV
+#  define AFS_USR_DARWIN240_ENV
+#  define AFS_USR_DARWIN250_ENV
+
+#  undef  AFS_NONFSTRANS
+#  define AFS_NONFSTRANS
+
+#  define AFS_SYSCALL                 230
+#  define DARWIN_REFBASE              0
+#  define AFS_WARNUSER_MARINER_ENV    1
+
+#  define AFS_HAVE_FFS                1	/* Use system's ffs. */
+
+#  define AFS_UIOSYS                  UIO_SYSSPACE
+#  define AFS_UIOUSER                 UIO_USERSPACE
+
+#  define AFS_GCPAGS                  0	/* if nonzero, garbage collect PAGs */
+#  define RXK_LISTENER_ENV            1
+
+#  define AFS_VFS34                   1	/* What is VFS34??? */
+
+#  define afsio_iov                   uio_iov
+#  define afsio_iovcnt                uio_iovcnt
+#  define afsio_offset                uio_offset
+#  define afsio_seg                   uio_segflg
+#  define afsio_resid                 uio_resid
+
+#  define VATTR_NULL                  usr_vattr_null
+
+#  define AFS_DIRENT
+#  ifndef CMSERVERPREF
+#   define CMSERVERPREF
+#  endif
+
+#  define BIND_8_COMPAT
+# endif /* !defined(UKERNEL) */
+
+/* Machine / Operating system information */
+# if defined(__amd64__)
+
+#  define AFS_X86_ENV                 1
+#  define AFS_64BITUSERPOINTER_ENV    1
+
+#  define sys_x86_darwin_12           1
+#  define sys_x86_darwin_13           1
+#  define sys_x86_darwin_14           1
+#  define sys_x86_darwin_60           1
+#  define sys_x86_darwin_70           1
+#  define sys_x86_darwin_80           1
+#  define sys_x86_darwin_90           1
+#  define sys_x86_darwin_100          1
+#  define sys_amd64_darwin_100        1
+#  define sys_amd64_darwin_110        1
+#  define sys_amd64_darwin_120        1
+#  define sys_amd64_darwin_130        1
+#  define sys_amd64_darwin_140        1
+#  define sys_amd64_darwin_150        1
+#  define sys_amd64_darwin_160        1
+#  define sys_amd64_darwin_170        1
+#  define sys_amd64_darwin_180        1
+#  define sys_amd64_darwin_190        1
+#  define sys_amd64_darwin_200        1
+#  define sys_amd64_darwin_210        1
+#  define sys_amd64_darwin_220        1
+#  define sys_amd64_darwin_230        1
+#  define sys_amd64_darwin_240        1
+#  define sys_amd64_darwin_250        1
+
+#  define SYS_NAME                    "amd64_darwin_250"
+#  define SYS_NAME_ID                 SYS_NAME_ID_amd64_darwin_250
+#  define AFSLITTLE_ENDIAN            1
+
+# elif defined(__arm64__)
+
+#  define AFS_ARM_ENV                 1
+#  define AFS_ARM64_DARWIN_ENV        1
+
+#  define sys_arm_darwin_200          1
+#  define sys_arm_darwin_210          1
+#  define sys_arm_darwin_220          1
+#  define sys_arm_darwin_230          1
+#  define sys_arm_darwin_240          1
+#  define sys_arm_darwin_250          1
+
+#  define SYS_NAME                    "arm_darwin_250"
+#  define SYS_NAME_ID                 SYS_NAME_ID_arm_darwin_250
+#  define AFSLITTLE_ENDIAN            1
+
+# else
+# error Unsupported architecture
+# endif /* __amd64__ */
+
+#endif /* AFS_PARAM_H */
diff --git a/src/config/param.rs_aix72.h b/src/config/param.rs_aix72.h
index 82c13e965b..e46bad0ea2 100644
--- a/src/config/param.rs_aix72.h
+++ b/src/config/param.rs_aix72.h
@@ -53,8 +53,8 @@
 #ifndef _POWER
 #define _POWER		1	/* _POWERseries!                */
 #endif
-#ifndef COMPAT_43
-#define COMPAT_43
+#if !defined(__clang__) && !defined(COMPAT_43)
+# define COMPAT_43
 #endif
 
 #define KERNEL_HAVE_UERROR 1
diff --git a/src/config/param.rs_aix73.h b/src/config/param.rs_aix73.h
index 8de75999d4..34459438d2 100644
--- a/src/config/param.rs_aix73.h
+++ b/src/config/param.rs_aix73.h
@@ -54,8 +54,8 @@
 #ifndef _POWER
 #define _POWER		1	/* _POWERseries!                */
 #endif
-#ifndef COMPAT_43
-#define COMPAT_43
+#if !defined(__clang__) && !defined(COMPAT_43)
+# define COMPAT_43
 #endif
 
 #define KERNEL_HAVE_UERROR 1
diff --git a/src/config/stds.h b/src/config/stds.h
index 8ae6834345..ae030149f6 100644
--- a/src/config/stds.h
+++ b/src/config/stds.h
@@ -305,6 +305,12 @@ hdr_static_inline(unsigned long long) afs_printable_uint64_lu(afs_uint64 d) { re
 # define AFS_FALLTHROUGH do {} while(0)
 #endif
 
+#if defined(HAVE_STRUCT_LABEL_SUPPORT)
+# define AFS_STRUCT_INIT(member, value) member = (value)
+#else
+# define AFS_STRUCT_INIT(member, value) (value)
+#endif
+
 /*
  * Conditionally remove unreached statements under Solaris Studio.
  */
diff --git a/src/crypto/hcrypto/Makefile.in b/src/crypto/hcrypto/Makefile.in
index 16abc10b7a..32622696e9 100644
--- a/src/crypto/hcrypto/Makefile.in
+++ b/src/crypto/hcrypto/Makefile.in
@@ -42,9 +42,12 @@ UPSTREAM= ${TOP_SRCDIR}/external/heimdal
 
 MODULE_INCLUDE=-I${srcdir} -I${TOP_INCDIR}/hcrypto -I$(UPSTREAM)/hcrypto
 
+@SHARED_ONLY@SHARED_LIBS = libafshcrypto.la
+@SHARED_ONLY@SHARED_SHLIBS_TOP = ${TOP_LIBDIR}/libafshcrypto.$(SHLIB_SUFFIX)
+
 all: @hcrypto_all_target@
 
-all-internal: ${HEADERS} ${TOP_LIBDIR}/libafshcrypto.$(SHLIB_SUFFIX) \
+all-internal: ${HEADERS} $(SHARED_SHLIBS_TOP) \
 	${TOP_LIBDIR}/libafshcrypto.a \
 	${TOP_LIBDIR}/libafshcrypto_lwp.a
 
@@ -54,14 +57,14 @@ buildtools: ${HEADERS} ${TOP_LIBDIR}/libafshcrypto.a
 
 install: @hcrypto_install_target@
 
-install-internal: libafshcrypto.la libafshcrypto.a
-	${LT_INSTALL_DATA} libafshcrypto.la ${DESTDIR}${libdir}/libafshcrypto.la
-	${RM} ${DESTDIR}${libdir}/libafshcrypto.la
+install-internal: $(SHARED_LIBS) libafshcrypto.a
+	@SHARED_ONLY@${LT_INSTALL_DATA} libafshcrypto.la ${DESTDIR}${libdir}/libafshcrypto.la
+	@SHARED_ONLY@${RM} ${DESTDIR}${libdir}/libafshcrypto.la
 	${INSTALL_DATA} libafshcrypto.a ${DESTDIR}${libdir}/libafshcrypto.a
 
-dest: libafshcrypto.la libafshcrypto.a
-	${LT_INSTALL_DATA} libafshcrypto.la ${DEST}/lib/libafshcrypto.la
-	${RM} ${DEST}/lib/libafshcrypto.la
+dest: $(SHARED_LIBS) libafshcrypto.a
+	@SHARED_ONLY@${LT_INSTALL_DATA} libafshcrypto.la ${DEST}/lib/libafshcrypto.la
+	@SHARED_ONLY@${RM} ${DEST}/lib/libafshcrypto.la
 	${INSTALL_DATA} libafshcrypto.a ${DEST}/lib/libafshcrypto.a
 
 clean:
@@ -71,8 +74,8 @@ clean:
 
 $(LT_objs): $(HEADERS)
 
-libafshcrypto.la: libafshcrypto.la.sym $(LT_objs)
-	$(LT_LDLIB_shlib) $(LT_objs) $(LT_libs)
+libafshcrypto.la: libafshcrypto.la.sym $(LT_objs) libafshcrypto.a
+	$(LT_LDLIB_shlib_only) $(LT_objs) $(LT_libs)
 
 libafshcrypto.a: $(LT_objs)
 	$(LT_LDLIB_static) $(LT_objs)
@@ -80,8 +83,8 @@ libafshcrypto.a: $(LT_objs)
 libafshcrypto_lwp.a: $(LT_objs)
 	$(LT_LDLIB_lwp) $(LT_objs)
 
-test_cipher: test_cipher.lo libafshcrypto.la
-	$(LT_LDRULE_static) test_cipher.lo libafshcrypto.la
+test_cipher: test_cipher.lo libafshcrypto.a
+	$(LT_LDRULE_static) test_cipher.lo libafshcrypto.a
 
 ${TOP_INCDIR}/hcrypto/aes.h: ${UPSTREAM}/hcrypto/aes.h
 	${INSTALL_DATA} $? $@
diff --git a/src/crypto/hcrypto/kernel/rand-timer.c b/src/crypto/hcrypto/kernel/rand-timer.c
index 3a7023555b..6ef71737cd 100644
--- a/src/crypto/hcrypto/kernel/rand-timer.c
+++ b/src/crypto/hcrypto/kernel/rand-timer.c
@@ -5,7 +5,7 @@
  * Contains no copyrightable content.
  */
 #include <config.h>
-
+#include <stds.h>
 #include <rand.h>
 #include "randi.h"
 
@@ -43,12 +43,12 @@ timer_status(void)
 }
 
 const RAND_METHOD hc_rand_timer_method = {
-    timer_seed,
-    timer_bytes,
-    timer_cleanup,
-    timer_add,
-    timer_pseudorand,
-    timer_status
+    AFS_STRUCT_INIT(.seed,	timer_seed),
+    AFS_STRUCT_INIT(.bytes,	timer_bytes),
+    AFS_STRUCT_INIT(.cleanup,	timer_cleanup),
+    AFS_STRUCT_INIT(.add,	timer_add),
+    AFS_STRUCT_INIT(.pseudorand, timer_pseudorand),
+    AFS_STRUCT_INIT(.status,	timer_status),
 };
 
 const RAND_METHOD *
diff --git a/src/fsint/afsint.xg b/src/fsint/afsint.xg
index cdcd07a293..b0a64ae8ea 100644
--- a/src/fsint/afsint.xg
+++ b/src/fsint/afsint.xg
@@ -447,7 +447,8 @@ StoreData(
   AFSVolSync *Sync
 ) split = 133;
 
-StoreACL(
+/* Deprecated - CVE-2018-7168 */
+OldStoreACL(
   IN  AFSFid *Fid,
   AFSOpaque *AccessList,
   OUT AFSFetchStatus *OutStatus,
@@ -657,6 +658,8 @@ DFSSymlink(
   AFSVolSync *Sync
 ) = 163;
 
+/* StoreACL (164) is declared below to avoid changing rxstat function indices. */
+
 FsCmd(
   IN AFSFid *Fid,
   IN struct FsCmdInputs *Inputs,
@@ -736,6 +739,13 @@ GetStatistics64(
     OUT ViceStatistics64 *Statistics
 ) = 65542;
 
+StoreACL(
+  IN  AFSFid *Fid,
+  AFSOpaque *AccessList,
+  OUT AFSFetchStatus *OutStatus,
+  AFSVolSync *Sync
+) = 164;
+
 /* rx osd. put here now to hold version numbers.
 ServerPath(
   IN  AFSFid *Fid,
diff --git a/src/kauth/admin_tools.c b/src/kauth/admin_tools.c
index 769a9a9ace..a260341e06 100644
--- a/src/kauth/admin_tools.c
+++ b/src/kauth/admin_tools.c
@@ -16,10 +16,6 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
-#endif
-
 #include <roken.h>
 #include <afs/opr.h>
 #include <afs/opr_assert.h>
@@ -517,7 +513,7 @@ ka_islocked(char *name, char *instance, afs_uint32 * when)
     do {
 	tempwhen = 0;
 	code =
-	    ubik_CallIter(KAM_LockStatus, conn, UPUBIKONLY, &count, (long) name,
+	    ubik_CallIter((ubik_call_func)KAM_LockStatus, conn, UPUBIKONLY, &count, (long) name,
 			  (long) instance, (long) &tempwhen, 0, 0, 0,
 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	if (code) {
@@ -554,7 +550,7 @@ Unlock(struct cmd_syndesc *as, void *arock)
 
     count = 0;
     do {
-	code = ubik_CallIter(KAM_Unlock, conn, 0, &count, (long) name, (long) instance,
+	code = ubik_CallIter((ubik_call_func)KAM_Unlock, conn, 0, &count, (long) name, (long) instance,
 			     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	if (code && (code != UNOSERVERS)) {
 	    server = 0;
diff --git a/src/kauth/authclient.c b/src/kauth/authclient.c
index c64f330edf..b5059e1bdd 100644
--- a/src/kauth/authclient.c
+++ b/src/kauth/authclient.c
@@ -17,7 +17,6 @@
 #include <afs/opr.h>
 
 #ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
 #endif
 
@@ -425,9 +424,9 @@ CheckTicketAnswer(ka_BBS * oanswer, afs_int32 challenge,
  * this doesn't handle UNOTSYNC very well, should use ubik_Call if you care
  */
 static afs_int32
-kawrap_ubik_Call(int (*aproc) (), struct ubik_client *aclient,
-                 afs_int32 aflags, void *p1, void *p2, void *p3, void *p4,
-                 void *p5, void *p6, void *p7, void *p8)
+kawrap_ubik_Call(ubik_call_func aproc, struct ubik_client *aclient,
+		 afs_int32 aflags, void *p1, void *p2, void *p3, void *p4,
+		 void *p5, void *p6, void *p7, void *p8)
 {
     afs_int32 code, lcode;
     int count;
@@ -530,7 +529,7 @@ ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * con
 
     version = 2;
     code =
-	kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
+	kawrap_ubik_Call((ubik_call_func)KAA_AuthenticateV2, conn, 0, name, instance,
 			 (void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
     if (code == RXGEN_OPCODE) {
 	oanswer.SeqLen = 0;
diff --git a/src/kauth/ka-forwarder.c b/src/kauth/ka-forwarder.c
index 8d82acc576..55d46064fc 100644
--- a/src/kauth/ka-forwarder.c
+++ b/src/kauth/ka-forwarder.c
@@ -108,7 +108,7 @@ setup_servers(int argc, char **argv)
 		fprintf(stderr, "%s: unknown host %s\n", prog, host);
 		exit(1);
 	    }
-	    bcopy(h->h_addr, &fwdaddr, 4);
+	    memcpy(&fwdaddr, h->h_addr, 4);
 	}
 
 	servers[i].sin_family = AF_INET;
@@ -221,8 +221,8 @@ main(int argc, char **argv)
 
 	    to = &reply;
 	    reply.sin_family = AF_INET;
-	    bcopy(bufp, &reply.sin_addr.s_addr, 4);
-	    bcopy(bufp + 4, &reply.sin_port, 2);
+	    memcpy(&reply.sin_addr.s_addr, bufp, 4);
+	    memcpy(&reply.sin_port, bufp + 4, 2);
 	    sendptr = bufp + 8;
 	    sendlen = rv - 8;
 	}
@@ -232,8 +232,8 @@ main(int argc, char **argv)
 	    cur_server = (cur_server + 1) % num_servers;
 	    to = &servers[cur_server];
 
-	    bcopy(&from.sin_addr.s_addr, bufp - 8, 4);
-	    bcopy(&from.sin_port, bufp - 4, 2);
+	    memcpy(bufp - 8, &from.sin_addr.s_addr, 4);
+	    memcpy(bufp - 4, &from.sin_port, 2);
 
 	    sendptr = bufp - 8;
 	    sendlen = rv + 8;
diff --git a/src/kauth/kaserver.c b/src/kauth/kaserver.c
index 844ecda157..5524bb3a5b 100644
--- a/src/kauth/kaserver.c
+++ b/src/kauth/kaserver.c
@@ -169,6 +169,7 @@ main(int argc, char *argv[])
     int level;			/* security level for Ubik */
     afs_int32 i;
     char clones[MAXHOSTSPERCELL];
+    char hoststr[16];
     afs_uint32 host = ntohl(INADDR_ANY);
     char *auditFileName = NULL;
     struct logOptions logopts;
@@ -410,10 +411,17 @@ main(int argc, char *argv[])
         }
         if (ccode == 1) {
             host = SHostAddrs[0];
-	    rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
 	}
     }
 
+    ViceLog(0, ("kaserver binding rx to %s:%d\n",
+            afs_inet_ntoa_r(host, hoststr), AFSCONF_KAUTHPORT));
+    code = rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
+    if (code) {
+	afs_com_err(whoami, code, "rx init failed");
+	exit(2);
+    }
+
     /* Disable jumbograms */
     rx_SetNoJumbo();
 
diff --git a/src/kauth/knfs.c b/src/kauth/knfs.c
index 8b6dd8297a..020ab3c8c2 100644
--- a/src/kauth/knfs.c
+++ b/src/kauth/knfs.c
@@ -260,7 +260,7 @@ NFSCopyToken(afs_int32 ahost, afs_int32 auid)
     char space[1200];
     struct ClearToken ct;
     afs_int32 index, newIndex;
-    afs_int32 temp;		/* for bcopy */
+    afs_int32 temp;
     char *tp;
     struct ViceIoctl blob;
 
diff --git a/src/kopenafs/Makefile.in b/src/kopenafs/Makefile.in
index 7a1c8f5582..22ab1249a3 100644
--- a/src/kopenafs/Makefile.in
+++ b/src/kopenafs/Makefile.in
@@ -24,7 +24,10 @@ MODULE_INCLUDE	= -I. -I${srcdir} -I../sys
 SFLAGS		= -I${TOP_INCDIR}
 SYS		= ${srcdir}/../sys
 
-all: ${TOP_LIBDIR}/libkopenafs.${SHLIB_SUFFIX} ${TOP_LIBDIR}/libkopenafs.a \
+@SHARED_ONLY@SHARED_LIBS = libkopenafs.la
+@SHARED_ONLY@SHARED_SHLIBS_TOP = ${TOP_LIBDIR}/libkopenafs.${SHLIB_SUFFIX}
+
+all: $(SHARED_SHLIBS_TOP) ${TOP_LIBDIR}/libkopenafs.a \
 		${TOP_INCDIR}/kopenafs.h
 
 ${TOP_LIBDIR}/libkopenafs.${SHLIB_SUFFIX}: libkopenafs.la
@@ -74,31 +77,31 @@ syscall.lo: $(SYS)/syscall.s
 libkopenafs.a: $(LT_objs)
 	$(LT_LDLIB_static) $(LT_objs)
 
-libkopenafs.la: libkopenafs.la.sym $(LT_objs)
-	$(LT_LDLIB_shlib) $(LT_objs)
+libkopenafs.la: libkopenafs.la.sym $(LT_objs) libkopenafs.a
+	$(LT_LDLIB_shlib_only) $(LT_objs)
 
-test-unlog: test-unlog.lo libkopenafs.la
-	$(LT_LDRULE_static) test-unlog.lo libkopenafs.la $(XLIBS)
+test-unlog: test-unlog.lo libkopenafs.a
+	$(LT_LDRULE_static) test-unlog.lo libkopenafs.a $(XLIBS)
 
-test-setpag: test-setpag.lo libkopenafs.la
-	$(LT_LDRULE_static) test-setpag.lo libkopenafs.la $(XLIBS)
+test-setpag: test-setpag.lo libkopenafs.a
+	$(LT_LDRULE_static) test-setpag.lo libkopenafs.a $(XLIBS)
 
 #
 # Installation targets
 #
-install: libkopenafs.la libkopenafs.a
+install: $(SHARED_LIBS) libkopenafs.a
 	${INSTALL} -d ${DESTDIR}${libdir}
 	${INSTALL} -d ${DESTDIR}${includedir}
-	${LT_INSTALL_DATA} libkopenafs.la ${DESTDIR}${libdir}/libkopenafs.la
-	${RM} ${DESTDIR}${libdir}/libkopenafs.la
+	@SHARED_ONLY@${LT_INSTALL_DATA} libkopenafs.la ${DESTDIR}${libdir}/libkopenafs.la
+	@SHARED_ONLY@${RM} ${DESTDIR}${libdir}/libkopenafs.la
 	${INSTALL_DATA} libkopenafs.a ${DESTDIR}${libdir}/libkopenafs.a
 	${INSTALL_DATA} ${srcdir}/kopenafs.h ${DESTDIR}${includedir}/kopenafs.h
 
-dest: libkopenafs.la libkopenafs.a
+dest: $(SHARED_LIBS) libkopenafs.a
 	${INSTALL} -d ${DEST}/lib
 	${INSTALL} -d ${DEST}/include
-	${LT_INSTALL_DATA} libkopenafs.la ${DEST}/lib/libkopenafs.la
-	${RM} ${DEST}/lib/libkopenafs.la
+	@SHARED_ONLY@${LT_INSTALL_DATA} libkopenafs.la ${DEST}/lib/libkopenafs.la
+	@SHARED_ONLY@${RM} ${DEST}/lib/libkopenafs.la
 	${INSTALL_DATA} libkopenafs.a ${DEST}/lib/libkopenafs.a
 	${INSTALL_DATA} ${srcdir}/kopenafs.h ${DEST}/include/kopenafs.h
 
diff --git a/src/libadmin/kas/afs_kasAdmin.c b/src/libadmin/kas/afs_kasAdmin.c
index 25a8c28519..08ff64cd96 100644
--- a/src/libadmin/kas/afs_kasAdmin.c
+++ b/src/libadmin/kas/afs_kasAdmin.c
@@ -13,10 +13,6 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
-#endif
-
 #include <roken.h>
 
 #include <rx/rx.h>
@@ -713,7 +709,7 @@ GetPrincipalLockStatus(const kas_server_p kaserver, const kas_identity_p who,
     do {
 	locked = 0;
 	tst =
-	    ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
+	    ubik_CallIter((ubik_call_func)KAM_LockStatus, kaserver->servers, UPUBIKONLY,
 			  &count, (long)who->principal, (long)who->instance, (long)&locked, 0,
 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	if (tst == 0) {
@@ -1272,7 +1268,7 @@ kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
 
     do {
 	tst =
-	    ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
+	    ubik_CallIter((ubik_call_func)KAM_Unlock, kaserver.servers, 0, &count,
 			  (long)who->principal, (long)who->instance, 0, 0, 0,
 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	if (tst && (tst != UNOSERVERS)) {
diff --git a/src/libafs/.gitignore b/src/libafs/.gitignore
index 4ff29e7026..b3e1268907 100644
--- a/src/libafs/.gitignore
+++ b/src/libafs/.gitignore
@@ -10,8 +10,7 @@
 /MakefileProto.*
 !/MakefileProto.*.in
 /afs
-/afs.x86_darwin_90.plist
-/afs.x86_darwin_100.plist
+/afs.*_darwin_*.plist
 /afsint
 /asm
 /asm-generic
diff --git a/src/libafs/MakefileProto.DARWIN.in b/src/libafs/MakefileProto.DARWIN.in
index 751ed5ff8d..cd4b9c3be0 100644
--- a/src/libafs/MakefileProto.DARWIN.in
+++ b/src/libafs/MakefileProto.DARWIN.in
@@ -63,8 +63,20 @@ OBJ_arm64=$(shell echo "${ARCH_arm64}" | grep -q -w yes && echo "$@.arm64")
 
 <all -ppc_darwin_70 -ppc_darwin_80 -x86_darwin_80 -ppc_darwin_90 -x86_darwin_90>
 KLINKER=-Xlinker -kext
+
 <all>
-MODLD=$(CC) -static $(KOPTS_DBUG) -nostdlib $(patsubst arm64,arm64e,$(ARCHFLAGS))
+
+# On arm64, we must link the kernel module with '-arch arm64e', even though
+# '-arch arm64' is the default on arm64. So, if '-arch arm64' is in our
+# ARCHFLAGS, translate it into '-arch arm64e'. And if no ARCHFLAGS are set at
+# all, we must set '-arch arm64e'.
+KERN_ARCHFLAGS = $(patsubst arm64,arm64e,$(ARCHFLAGS))
+ifeq ($(KERN_ARCHFLAGS),)
+  ifeq ($(ARCH_arm64),yes)
+    KERN_ARCHFLAGS=-arch arm64e
+  endif
+endif
+MODLD=$(CC) -static $(KOPTS_DBUG) -nostdlib $(KERN_ARCHFLAGS)
 
 <all>
 
diff --git a/src/libafs/afs.arm_darwin_240.plist.in b/src/libafs/afs.arm_darwin_240.plist.in
new file mode 100644
index 0000000000..a1385718c5
--- /dev/null
+++ b/src/libafs/afs.arm_darwin_240.plist.in
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>afs</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.openafs.filesystems.afs</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>8.0</string>
+	<key>CFBundleName</key>
+	<string>afs</string>
+	<key>CFBundlePackageType</key>
+	<string>KEXT</string>
+	<key>CFBundleShortVersionString</key>
+	<string>@MACOS_VERSION@</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>@MACOS_VERSION@</string>
+	<key>OSBundleLibraries</key>
+	<dict>
+		<key>com.apple.kpi.bsd</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.mach</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.libkern</key>
+		<string>8.0</string>
+	</dict>
+</dict>
+</plist>
diff --git a/src/libafs/afs.arm_darwin_250.plist.in b/src/libafs/afs.arm_darwin_250.plist.in
new file mode 100644
index 0000000000..a1385718c5
--- /dev/null
+++ b/src/libafs/afs.arm_darwin_250.plist.in
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>afs</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.openafs.filesystems.afs</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>8.0</string>
+	<key>CFBundleName</key>
+	<string>afs</string>
+	<key>CFBundlePackageType</key>
+	<string>KEXT</string>
+	<key>CFBundleShortVersionString</key>
+	<string>@MACOS_VERSION@</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>@MACOS_VERSION@</string>
+	<key>OSBundleLibraries</key>
+	<dict>
+		<key>com.apple.kpi.bsd</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.mach</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.libkern</key>
+		<string>8.0</string>
+	</dict>
+</dict>
+</plist>
diff --git a/src/libafs/afs.x86_darwin_240.plist.in b/src/libafs/afs.x86_darwin_240.plist.in
new file mode 100644
index 0000000000..a1385718c5
--- /dev/null
+++ b/src/libafs/afs.x86_darwin_240.plist.in
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>afs</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.openafs.filesystems.afs</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>8.0</string>
+	<key>CFBundleName</key>
+	<string>afs</string>
+	<key>CFBundlePackageType</key>
+	<string>KEXT</string>
+	<key>CFBundleShortVersionString</key>
+	<string>@MACOS_VERSION@</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>@MACOS_VERSION@</string>
+	<key>OSBundleLibraries</key>
+	<dict>
+		<key>com.apple.kpi.bsd</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.mach</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.libkern</key>
+		<string>8.0</string>
+	</dict>
+</dict>
+</plist>
diff --git a/src/libafs/afs.x86_darwin_250.plist.in b/src/libafs/afs.x86_darwin_250.plist.in
new file mode 100644
index 0000000000..a1385718c5
--- /dev/null
+++ b/src/libafs/afs.x86_darwin_250.plist.in
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>afs</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.openafs.filesystems.afs</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>8.0</string>
+	<key>CFBundleName</key>
+	<string>afs</string>
+	<key>CFBundlePackageType</key>
+	<string>KEXT</string>
+	<key>CFBundleShortVersionString</key>
+	<string>@MACOS_VERSION@</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>@MACOS_VERSION@</string>
+	<key>OSBundleLibraries</key>
+	<dict>
+		<key>com.apple.kpi.bsd</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.mach</key>
+		<string>8.0.0</string>
+		<key>com.apple.kpi.libkern</key>
+		<string>8.0</string>
+	</dict>
+</dict>
+</plist>
diff --git a/src/libafsauthent/Makefile.in b/src/libafsauthent/Makefile.in
index 1993b8fb07..adc88500f7 100644
--- a/src/libafsauthent/Makefile.in
+++ b/src/libafsauthent/Makefile.in
@@ -34,19 +34,21 @@ LT_deps = \
 
 LT_libs = $(LIB_hcrypto) $(LIB_roken) $(LIB_crypt) $(LIB_AFSDB) $(MT_LIBS)
 
-all: libafsauthent.la libafsauthent_pic.la \
+@SHARED_ONLY@SHARED_LIBS = libafsauthent.la
+
+all: $(SHARED_LIBS) libafsauthent_pic.la \
 	$(TOP_LIBDIR)/libafsauthent.a \
 	$(TOP_LIBDIR)/libafsauthent_pic.a
 
-libafsauthent.la: libafsauthent.la.sym $(LT_objs) $(LT_deps) libafsauthent_pic.la
-	$(LT_LDLIB_shlib) $(LT_objs) $(LT_deps) $(LT_libs)
+libafsauthent.la: libafsauthent.la.sym $(LT_objs) $(LT_deps) libafsauthent_pic.la libafsauthent.a
+	$(LT_LDLIB_shlib_only) $(LT_objs) $(LT_deps) $(LT_libs)
 
 libafsauthent_pic.la: $(LT_objs)
 	$(LT_LDLIB_pic) $(LT_objs)
 
 # On AIX, libtool can only produce one of shared and static libraries in a
 # given invocation, so we need separate rules.
-libafsauthent.a: $(LT_objs) libafsauthent.la
+libafsauthent.a: $(LT_objs)
 	$(LT_LDLIB_static) $(LT_objs)
 
 ${TOP_LIBDIR}/libafsauthent.a: libafsauthent.a
@@ -59,10 +61,10 @@ clean:
 	$(LT_CLEAN)
 	$(RM) -f *.o libafsauthent.a
 
-install: libafsauthent.la libafsauthent.a libafsauthent_pic.la
+install: $(SHARED_LIBS) libafsauthent.a libafsauthent_pic.la
 	${INSTALL} -d ${DESTDIR}${libdir}
-	${LT_INSTALL_DATA} libafsauthent.la ${DESTDIR}${libdir}/libafsauthent.la
-	${RM} ${DESTDIR}${libdir}/libafsauthent.la
+	@SHARED_ONLY@${LT_INSTALL_DATA} libafsauthent.la ${DESTDIR}${libdir}/libafsauthent.la
+	@SHARED_ONLY@${RM} ${DESTDIR}${libdir}/libafsauthent.la
 	${INSTALL_DATA}  libafsauthent.a ${DESTDIR}${libdir}/libafsauthent.a
 	${INSTALL_DATA}  .libs/libafsauthent_pic.a ${DESTDIR}${libdir}/libafsauthent_pic.a
 
diff --git a/src/libafscp/afscp_acl.c b/src/libafscp/afscp_acl.c
index f9cd3740dc..5632feebf7 100644
--- a/src/libafscp/afscp_acl.c
+++ b/src/libafscp/afscp_acl.c
@@ -104,6 +104,9 @@ afscp_StoreACL(const struct afscp_venusfid *dir, struct AFSOpaque *acl)
 	if (server && server->naddrs > 0) {
 	    for (j = 0; j < server->naddrs; j++) {
 		code = RXAFS_StoreACL(server->conns[j], &df, acl, &dfst, &vs);
+		if (code == RXGEN_OPCODE)
+		    code = RXAFS_OldStoreACL(server->conns[j], &df, acl,
+					     &dfst, &vs);
 		if (code >= 0)
 		    break;
 	    }
diff --git a/src/libafsrpc/Makefile.in b/src/libafsrpc/Makefile.in
index dc03648c61..1ae56626d8 100644
--- a/src/libafsrpc/Makefile.in
+++ b/src/libafsrpc/Makefile.in
@@ -31,7 +31,9 @@ LT_deps =
 
 LT_libs = $(LIB_hcrypto) $(LIB_roken) $(MT_LIBS)
 
-all: libafsrpc.la libafsrpc.a libafsrpc_pic.la \
+@SHARED_ONLY@SHARED_LIBS = libafsrpc.la
+
+all: $(SHARED_LIBS) libafsrpc.a libafsrpc_pic.la \
 	$(TOP_LIBDIR)/libafsrpc.a \
 	$(TOP_LIBDIR)/libafsrpc_pic.a
 
@@ -39,13 +41,13 @@ all: libafsrpc.la libafsrpc.a libafsrpc_pic.la \
 # there doesn't seem to be any way to get libtool to remember this requirement
 # when it links the libafsrpc_sys.la convenience library.
 
-libafsrpc.la: libafsrpc.la.sym $(LT_objs) $(LT_deps) libafsrpc_pic.la
+libafsrpc.la: libafsrpc.la.sym $(LT_objs) $(LT_deps) libafsrpc_pic.la libafsrpc.a
 	@set -e; set -x; case "$(SYS_NAME)" in \
 	rs_aix*) \
-	    $(LT_LDLIB_shlib) -Wl,-bI:../sys/afsl.exp \
+	    $(LT_LDLIB_shlib_only) -Wl,-bI:../sys/afsl.exp \
 		$(LT_objs) $(LT_deps) $(LT_libs) ;; \
 	*) \
-	    $(LT_LDLIB_shlib) $(LT_objs) $(LT_deps) $(LT_libs);; \
+	    $(LT_LDLIB_shlib_only) $(LT_objs) $(LT_deps) $(LT_libs);; \
 	esac
 
 libafsrpc_pic.la: $(LT_objs)
@@ -54,7 +56,7 @@ libafsrpc_pic.la: $(LT_objs)
 # AIX needs libafsrpc to also be linked against the syscall import list
 # On most platforms, libtool will make shared and static libraries at the
 # same time, but not on AIX, so we need separate rules.
-libafsrpc.a: $(LT_objs) libafsrpc.la
+libafsrpc.a: $(LT_objs)
 	$(LT_LDLIB_static) $(LT_objs)
 	@set -e; set -x; case "${SYS_NAME}" in \
 	    rs_aix*) \
@@ -67,17 +69,17 @@ ${TOP_LIBDIR}/libafsrpc.a: libafsrpc.a
 ${TOP_LIBDIR}/libafsrpc_pic.a: libafsrpc_pic.la
 	${INSTALL_DATA} .libs/libafsrpc_pic.a $@
 
-install: libafsrpc.la libafsrpc.a libafsrpc_pic.la
+install: $(SHARED_LIBS) libafsrpc.a libafsrpc_pic.la
 	${INSTALL} -d ${DESTDIR}${libdir}
-	$(LT_INSTALL_DATA) libafsrpc.la $(DESTDIR)$(libdir)/libafsrpc.la
-	$(RM) $(DESTDIR)$(libdir)/libafsrpc.la
+	@SHARED_ONLY@$(LT_INSTALL_DATA) libafsrpc.la $(DESTDIR)$(libdir)/libafsrpc.la
+	@SHARED_ONLY@$(RM) $(DESTDIR)$(libdir)/libafsrpc.la
 	$(INSTALL_DATA) libafsrpc.a $(DESTDIR)$(libdir)/libafsrpc.a
 	$(INSTALL_DATA) .libs/libafsrpc_pic.a $(DESTDIR)$(libdir)/libafsrpc_pic.a
 
-dest: libafsrpc.la libafsrpc.a
+dest: $(SHARED_LIBS) libafsrpc.a
 	${INSTALL} -d ${DEST}/lib
-	${LT_INSTALL_DATA} libafsrpc.la ${DEST}/lib/libafsrpc.la
-	${RM} ${DEST}/lib/libafsrpc.la
+	@SHARED_ONLY@${LT_INSTALL_DATA} libafsrpc.la ${DEST}/lib/libafsrpc.la
+	@SHARED_ONLY@${RM} ${DEST}/lib/libafsrpc.la
 	${INSTALL_DATA} libafsrpc.a ${DEST}/lib/libafsrpc.a
 	${INSTALL_DATA} .libs/libafsrpc_pic.a ${DEST}/lib/libafsrpc_pic.a
 
diff --git a/src/libuafs/Makefile.common.in b/src/libuafs/Makefile.common.in
index 9416050271..8d66ca74fe 100644
--- a/src/libuafs/Makefile.common.in
+++ b/src/libuafs/Makefile.common.in
@@ -194,9 +194,6 @@ ${TOP_LIBDIR}/libuafs_pic.a: libuafs_pic.la
 
 $(LT_objs): h
 
-libuafs.la: $(LT_objs)
-	$(LT_LDLIB_shlib) $(LT_objs)
-
 libuafs.a: $(LT_objs)
 	$(LT_LDLIB_static) $(LT_objs)
 
diff --git a/src/libuafs/MakefileProto.AIX.in b/src/libuafs/MakefileProto.AIX.in
index 881b3c935f..ee5f5f7195 100644
--- a/src/libuafs/MakefileProto.AIX.in
+++ b/src/libuafs/MakefileProto.AIX.in
@@ -30,7 +30,4 @@ AFS_OS_CLEAN = \
 	*.exp \
 	export.h
 
-# To get __file__ you need to specify the language level C99 to xlc_r
-CFLAGS_afs_osi_pag.lo=-qlanglvl=stdc99
-
 include Makefile.common
diff --git a/src/lwp/iomgr.c b/src/lwp/iomgr.c
index 82b576fe2a..b317eb2eb8 100644
--- a/src/lwp/iomgr.c
+++ b/src/lwp/iomgr.c
@@ -47,7 +47,6 @@
 #include "lwp.h"
 #include "timer.h"
 
-typedef unsigned char bool;
 #define FALSE	0
 #define TRUE	1
 
@@ -356,7 +355,7 @@ static void *IOMGR(void *dummy)
 	int code;
 	struct TM_Elem *earliest;
 	struct timeval timeout, junk;
-	bool woke_someone;
+	int woke_someone;
 
 	FD_ZERO(&IOMGR_readfds);
 	FD_ZERO(&IOMGR_writefds);
@@ -651,7 +650,7 @@ static void SigHandler (int signo)
    to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
 static int SignalSignals (void)
 {
-    bool gotone = FALSE;
+    int gotone = FALSE;
     int i;
     void *(*p)(void *);
     afs_int32 stackSize;
diff --git a/src/lwp/process.c b/src/lwp/process.c
index 75026e2e78..1a9538c31a 100644
--- a/src/lwp/process.c
+++ b/src/lwp/process.c
@@ -126,6 +126,8 @@ Need offset to SP in jmp_buf for this platform.
 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
 typedef __uint64_t jmp_buf_type;
 #endif
+#elif defined(AFS_ARM64_DARWIN_ENV)
+typedef __uint64_t jmp_buf_type;
 #else
 #if defined(AFS_ALPHA_LINUX_ENV) || defined(AFS_PPC64_LINUX_ENV)
 typedef long jmp_buf_type;
diff --git a/src/lwp/timer.c b/src/lwp/timer.c
index b9172944df..3032b5640a 100644
--- a/src/lwp/timer.c
+++ b/src/lwp/timer.c
@@ -30,7 +30,6 @@
 
 
 
-typedef unsigned char bool;
 #define FALSE	0
 #define TRUE	1
 
@@ -107,7 +106,7 @@ static bool geq(struct timeval *t1, struct timeval *t2)
 }
 */
 
-static bool
+static int
 blocking(struct TM_Elem *t)
 {
     return (t->TotalTime.tv_sec < 0 || t->TotalTime.tv_usec < 0);
diff --git a/src/packaging/MacOS/OpenAFS.post_install b/src/packaging/MacOS/OpenAFS.post_install
index 620ddaeb89..98d700fae0 100644
--- a/src/packaging/MacOS/OpenAFS.post_install
+++ b/src/packaging/MacOS/OpenAFS.post_install
@@ -156,6 +156,43 @@ fi
 #start the new launchd daemon
 launchctl load -w /Library/LaunchDaemons/org.openafs.filesystems.afs.plist
 
+# Install and start our privileged helper
+PRIVHELPER="/Library/PreferencePanes/OpenAFS.prefPane/Contents/Library/LaunchServices/org.openafs.privhelper"
+if [[ -f "$PRIVHELPER" ]]; then
+    if [[ ! -d "/Library/PrivilegedHelperTools" ]]; then
+	mkdir -p "/Library/PrivilegedHelperTools"
+	chmod 755 "/Library/PrivilegedHelperTools"
+	chown -R root:wheel "/Library/PrivilegedHelperTools"
+    fi
+
+    cp -f "$PRIVHELPER" "/Library/PrivilegedHelperTools"
+    if [[ $? -eq 0 ]]; then
+	chmod 755 "/Library/PrivilegedHelperTools/org.openafs.privhelper"
+	PRIVDAEMON="/Library/LaunchDaemons/privhelper-launchd.plist"
+	cat > "$PRIVDAEMON" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>org.openafs.privhelper</string>
+        <key>MachServices</key>
+        <dict>
+                <key>org.openafs.privhelper</key>
+                <true/>
+        </dict>
+        <key>ProgramArguments</key>
+        <array>
+                <string>/Library/PrivilegedHelperTools/org.openafs.privhelper</string>
+        </array>
+</dict>
+</plist>
+EOF
+	chmod 644 "$PRIVDAEMON"
+	launchctl load -w "$PRIVDAEMON"
+    fi
+fi
+
 if [ $majorvers -ge 19 ]; then
     # Assume that, if /afs is not present, either OpenAFS is being installed for
     # the first time or the system was not rebooted after the installation.
diff --git a/src/packaging/MacOS/OpenAFS.pre_upgrade b/src/packaging/MacOS/OpenAFS.pre_upgrade
index 2877dc6978..1dbcb20f73 100644
--- a/src/packaging/MacOS/OpenAFS.pre_upgrade
+++ b/src/packaging/MacOS/OpenAFS.pre_upgrade
@@ -1,6 +1,7 @@
 #!/bin/sh
 DAEMON=/private/var/db/openafs/etc/launchafs.sh
 DAEMON_LAUNCHD_SCRIPT=/Library/LaunchDaemons/org.openafs.filesystems.afs.plist
+PRIVHELPER_LAUNCHD_SCRIPT=/Library/LaunchDaemons/privhelper-launchd.plist
 DAEMON_UP=$(ps -ef | grep "$DAEMON_NAME" | grep -v grep | wc -l)
 PREFERENCE_PANE=/Library/PreferencePanes/OpenAFS.prefPane
 
@@ -41,6 +42,10 @@ else
 
 	launchctl unload -w $DAEMON_LAUNCHD_SCRIPT
   fi
+
+  if [ -f $PRIVHELPER_LAUNCHD_SCRIPT ]; then
+	launchctl unload -w $PRIVHELPER_LAUNCHD_SCRIPT
+  fi
 fi
 
 if [ -d /Library/PreferencePanes/OpenAFS.prefPane ]; then
diff --git a/src/packaging/MacOS/ReadMe.rtf.24 b/src/packaging/MacOS/ReadMe.rtf.24
new file mode 100644
index 0000000000..40b7d1ea8a
--- /dev/null
+++ b/src/packaging/MacOS/ReadMe.rtf.24
@@ -0,0 +1,7 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww9000\viewh9000\viewkind0
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+
+\f0\fs24 \cf0 This release of OpenAFS is targeted at MacOS 15.X (Sequoia) and is not recommended for use with any other version.}
diff --git a/src/packaging/MacOS/ReadMe.rtf.25 b/src/packaging/MacOS/ReadMe.rtf.25
new file mode 100644
index 0000000000..0b1f67838d
--- /dev/null
+++ b/src/packaging/MacOS/ReadMe.rtf.25
@@ -0,0 +1,7 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww9000\viewh9000\viewkind0
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+
+\f0\fs24 \cf0 This release of OpenAFS is targeted at MacOS 26.X (Tahoe) and is not recommended for use with any other version.}
diff --git a/src/packaging/MacOS/Uninstall b/src/packaging/MacOS/Uninstall
index dabef2d175..22526f425c 100755
--- a/src/packaging/MacOS/Uninstall
+++ b/src/packaging/MacOS/Uninstall
@@ -76,8 +76,7 @@ sub main
     if ($do_nothing == 0) {
     my @rmcmd = ('osascript', '-e', "do shell script \"/bin/rm -f @rmfiles; /bin/rmdir @rmdirs; /bin/rm -rf @rmpkg\" with administrator privileges");
     system @rmcmd;
-    my $retcode = $? >> 8;
-    if ($retcode != 0) {
+    if ($? != 0) {
            print_warning ("Warning:  There may have been a problem uninstalling\n");
     }
     }
diff --git a/src/packaging/MacOS/Uninstall.14.15 b/src/packaging/MacOS/Uninstall.14.15
index 460fcebd81..662a94687f 100755
--- a/src/packaging/MacOS/Uninstall.14.15
+++ b/src/packaging/MacOS/Uninstall.14.15
@@ -12,7 +12,7 @@ use File::Basename;
 
 use vars qw ($do_nothing $print_donothing_removals $receipts_dir $verbose $noisy_warnings);
 use vars qw ($suppress_spin $spin_counter $spin_state $spin_slower_downer);
-use vars qw (%exception_list $gen_dirs @gen_files @rmfiles @rmdirs @rmpkg);
+use vars qw (%exception_list $gen_dirs @gen_files @rmfiles @rmdirs @rmpkg $privhelper);
 
 #----------------------------------------------------------------------------------------
 
@@ -24,6 +24,8 @@ $noisy_warnings = 0;
 # One of rm -rf in this script uses $receipts_dir -- change with care.
 $receipts_dir = "/Library/Receipts";
 
+$privhelper="/Library/LaunchDaemons/privhelper-launchd.plist";
+
 %exception_list = (
 );
 
@@ -38,6 +40,8 @@ $gen_dirs = { };
     "/var/db/openafs/etc/CellServDB.master.last",
     "/var/db/openafs/etc/CellServDB",
     "/var/db/openafs/etc/config/settings.plist",
+    "/Library/LaunchDaemons/privhelper-launchd.plist",
+    "/Library/PrivilegedHelperTools/org.openafs.privhelper",
 );
 
 #----------------------------------------------------------------------------------------
@@ -73,13 +77,12 @@ sub main {
 	# earlier output. The final 'tr' in the pipeline here turns them back
 	# into \n newlines. pkgutil --forget at least will print output like
 	# "Forgot package 'foo'".
-	my $rmcmd = "osascript -e 'do shell script \"/bin/rm -f @rmfiles; " .
-		    "/bin/rmdir @rmdirs; echo @rmpkg | xargs -n 1 " .
-		    "/usr/sbin/pkgutil --forget\" with administrator " .
-		    "privileges' | tr '\\r' '\\n'";
+	my $rmcmd = "osascript -e 'do shell script \"/bin/launchctl unload -w $privhelper; " .
+		    "/bin/rm -f @rmfiles; /bin/rmdir @rmdirs; " .
+		    "echo @rmpkg | xargs -n 1 /usr/sbin/pkgutil --forget\" " .
+		    "with administrator privileges' | tr '\\r' '\\n'";
 	system $rmcmd;
-	my $retcode = $? >> 8;
-	if ($retcode != 0) {
+	if ($? != 0) {
 	    print_warning ("Warning:  There may have been a problem uninstalling\n");
 	}
     }
diff --git a/src/packaging/MacOS/notarize.pl b/src/packaging/MacOS/notarize.pl
index 026563012b..e20d93f3af 100755
--- a/src/packaging/MacOS/notarize.pl
+++ b/src/packaging/MacOS/notarize.pl
@@ -32,69 +32,79 @@
 #
 # On success, the following output can be expected:
 #
-# $ sudo notarize.pl foo@bar.com "@keychain:PASSWORD" OpenAFS.dmg
+# $ sudo notarize.pl keychain-profile OpenAFS.dmg
 #
-# notarize.pl: submitting package...
-# notarize.pl: checking status...
-# notarize.pl: checking status...
-# notarize.pl: checking status...
-# (...)
-# notarize.pl: checking status...
+# notarize.pl: processing package...
 # notarize.pl: package successfully notarized
 
 use strict;
 use File::Which;
 
 sub usage {
-    print(STDERR "usage: notarize.pl <username> <password> <package>\n");
-    print(STDERR "\tusername: apple id\n");
-    print(STDERR "\tpassword: password of your apple id account\n");
+    print(STDERR "usage: notarize.pl <profile> <package>\n");
+    print(STDERR "\tprofile: keychain-profile for the credentials to be used\n");
     print(STDERR "\tpackage: package to be notarized\n");
     print(STDERR "\tnote: must be root\n");
-    print(STDERR "\t      <password> can be a reference to a keychain item.\n");
-    print(STDERR "\t      <password> as cleartext is not recommended.\n");
-    print(STDERR "e.g.: \$ sudo notarize.pl foo\@bar.com \"\@keychain:PASSWORD\" OpenAFS.dmg\n\n");
+    print(STDERR "e.g.: \$ sudo notarize.pl keychain-profile OpenAFS.dmg\n\n");
     exit(1);
 }
 
 sub check_prerequisites {
-    my (@ARGS) = @_;
+    my ($profile, $package) = @_;
 
     if ($> != 0) {
 	print(STDERR "error: must be root\n\n");
 	usage();
     }
-    if (scalar @ARGS != 3) {
-	print(STDERR "error: check arguments\n\n");
-	usage();
-    }
     if (!which('xcrun')) {
 	print(STDERR "error: xcrun not found in \$PATH\n\n");
 	usage();
     }
-    if (not -e $ARGS[2]) {
+
+    # Check if the given keychain-profile exists
+    my $output = qx(xcrun notarytool history --keychain-profile "$profile" 2>&1);
+    if ($? != 0) {
+	my $exitcode = $? >> 8;
+	print(STDERR "error: exit code $exitcode (status $?)\n");
+	print(STDERR $output);
+	exit(1);
+    }
+
+    # Check if the given package exists
+    if (not -e $package) {
 	print(STDERR "error: package not found\n\n");
+	exit(1);
     }
 }
 
-sub submit_package {
-    my ($username, $password, $package) = @_;
-
-    print(STDOUT "notarize.pl: submitting package...\n");
+sub process_package {
+    my ($profile, $package) = @_;
 
-    my $output = qx(xcrun altool -t osx -f "$package" --primary-bundle-id org.openafs.OpenAFS --notarize-app --username "$username" --password "$password" 2>&1);
-    my $exitcode = $? >> 8;
+    print(STDOUT "notarize.pl: processing package...\n");
 
-    if ($exitcode) {
-	print(STDERR "error: $exitcode\n");
+    # returns after submitting and processing the package, or times out if it
+    # takes longer than 5 minutes
+    my $output = qx(xcrun notarytool submit "$package" --keychain-profile "$profile" --wait --timeout 5m 2>&1);
+    if ($? != 0) {
+	my $exitcode = $? >> 8;
+	print(STDERR "error: exit code $exitcode (status $?)\n");
 	print(STDERR $output);
 	exit(1);
     }
     # $output looks like the following sample:
     #
-    # No errors uploading 'OpenAFS.dmg'.
-    # RequestUUID = 565a4d1b-9608-47a6-aba9-53136c991bb8
-    $output =~ m{RequestUUID = ([A-Za-z0-9\-]+)};
+    # Conducting pre-submission checks for OpenAFS.dmg and initiating connection
+    # to the Apple notary service...
+    # Submission ID received
+    #   id: fe4249d2-c3f7-428e-8bcd-8af665e57189
+    # Successfully uploaded file
+    #   id: fe4249d2-c3f7-428e-8bcd-8af665e57189
+    #   path: ./OpenAFS.dmg
+    # Waiting for processing to complete. Wait timeout is set to 300.0 second(s).
+    # Current status: In Progress... Current status: Accepted...... Processing complete
+    #   id: fe4249d2-c3f7-428e-8bcd-8af665e57189
+    #   status: Accepted
+    $output =~ m{id: ([A-Za-z0-9\-]+)};
     if (not defined $1) {
 	print(STDERR "error: uuid not found\n");
 	exit(1);
@@ -102,67 +112,16 @@ sub submit_package {
     return $1;
 }
 
-sub check_status {
-    my ($username, $password, $uuid) = @_;
-    my $output;
-    my $status;
-    my $exitcode;
-
-    while (1) {
-	print(STDOUT "notarize.pl: checking status...\n");
-	$output = qx(xcrun altool --notarization-info "$uuid" --username "$username" --password "$password" 2>&1);
-	$exitcode = $? >> 8;
-
-	if ($exitcode) {
-	    print(STDERR "error: $exitcode\n");
-	    print(STDERR $output);
-	    exit(1);
-	}
-	# $output looks like the following samples:
-	#
-	# First, second, ..., (N-1)'th attempts:
-	#
-	# No errors getting notarization info.
-	#
-	# Date: 2019-11-26 21:07:46 +0000
-	# Hash: 4e10ebb01518de9eb007d4579006acda2d6ff773fe040d97786bcc686ec93gg1
-	# RequestUUID: 565a4d1b-9608-47a6-aba9-53136c991bb8
-	# Status: in progress
-	#
-	# N'th attempt:
-	#
-	# No errors getting notarization info.
-	#
-	# Date: 2019-11-26 21:07:46 +0000
-	# Hash: 4e10ebb01518de9eb007d4579006acda2d6ff773fe040d97786bcc686ec93gg1
-	# RequestUUID: 565a4d1b-9608-47a6-aba9-53136c991bb8
-	# Status: in progress
-	# Status Code: 0
-	# Status Message: Package Approved
-	$output =~ m{Status Code: (\d+)};
-	if (defined $1) {
-	    $status = $1;
-	    last;
-	}
-	sleep(5);
-    }
-    if ($status) {
-	print(STDERR "error: $status (uuid: $uuid)\n");
-	print(STDERR $output);
-	exit(1);
-    }
-}
-
 sub notarize_package {
     my ($package, $uuid) = @_;
 
     print(STDOUT "notarize.pl: notarizing package...\n");
 
     my $output = qx(xcrun stapler staple -v "$package" 2>&1);
-    my $exitcode = $? >> 8;
-
-    if ($exitcode) {
+    if ($? != 0) {
+	my $exitcode = $? >> 8;
 	print(STDERR "error: package could not be notarized (uuid: $uuid)\n");
+	print(STDERR "error: exit code $exitcode (status $?)\n");
 	print(STDERR $output);
 	exit(1);
     }
@@ -172,13 +131,16 @@ sub notarize_package {
 sub main {
     my (@ARGS) = @_;
 
-    check_prerequisites(@ARGS);
-    my $username = $ARGS[0];
-    my $password = $ARGS[1];
-    my $package = $ARGS[2];
+    if (scalar @ARGS != 2) {
+	print(STDERR "error: check arguments\n\n");
+	usage();
+    }
+    my $profile = $ARGS[0];
+    my $package = $ARGS[1];
+
+    check_prerequisites($profile, $package);
 
-    my $uuid = submit_package($username, $password, $package);
-    check_status($username, $password, $uuid);
+    my $uuid = process_package($profile, $package);
     notarize_package($package, $uuid);
 
     exit(0);
diff --git a/src/packaging/MacOS/pkgbuild.sh.in b/src/packaging/MacOS/pkgbuild.sh.in
index edaa7212d6..84b74cc3b0 100644
--- a/src/packaging/MacOS/pkgbuild.sh.in
+++ b/src/packaging/MacOS/pkgbuild.sh.in
@@ -6,20 +6,11 @@ usage() {
     exec >&2
 
     echo 'Usage: pkgbuild.sh [-x] [--app-key <appkey>] [--inst-key <instkey>]'
-    echo '                   [--apple-id <appleid> <password>]'
+    echo '                   [--keychain-profile <profile>]'
     echo '                   [--pass N] [--csdb <CellServDB>] <binary-dir>'
     echo
     echo '--app-key and --inst-key are for signing. -x prints all comamnds as '
-    echo 'they are run. --apple-id is for notarizing.'
-    echo
-    echo 'Note: the password associated with <appleid> can be a reference to a'
-    echo 'keychain item. Including your password as cleartext is not'
-    echo 'recommended. e.g.'
-    echo
-    echo '--apple-id foo@bar.com "@keychain:PASSWORD"'
-    echo
-    echo 'In this case, keychain must hold a keychain item named PASSWORD with'
-    echo 'an account matching foo@bar.com.'
+    echo 'they are run. --keychain-profile is for notarizing.'
     echo
     echo 'By default, all passes are run. Available passes:'
     echo '    --pass 1: prepare pkgroot'
@@ -38,12 +29,11 @@ anypass=0
 PASS1=
 PASS2=
 
-APP_KEY=
-INST_KEY=
-APPLE_ID=
-APPLE_PW=
+APP_KEY="@MACOS_APP_KEY@"
+INST_KEY="@MACOS_INST_KEY@"
 DEST_DIR=
 CSDB=
+KEYCHAIN_PROFILE="@MACOS_KEYCHAIN_PROFILE@"
 
 CODESIGN_OPTS=
 
@@ -60,10 +50,8 @@ while [ x"$#" != x0 ] ; do
 	INST_KEY="$1"
 	shift
 	;;
-    --apple-id)
-	APPLE_ID="$1"
-	shift
-	APPLE_PW="$1"
+    --keychain-profile)
+	KEYCHAIN_PROFILE="$1"
 	shift
 	;;
     --csdb)
@@ -181,6 +169,14 @@ elif [ x"$majorvers" = x23 ]; then
     RELNAME="Sonoma"
     THISREL=19
     OSVER=14
+elif [ x"$majorvers" = x24 ]; then
+    RELNAME="Sequoia"
+    THISREL=20
+    OSVER=15
+elif [ x"$majorvers" = x25 ]; then
+    RELNAME="Tahoe"
+    THISREL=26
+    OSVER=26
 
 
 elif [ x"$majorvers" = x ] ; then
@@ -583,8 +579,8 @@ if [ x"$PASS2" = x1 ]; then
     echo
     echo "Created $CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg
 
-    if [ x"$APPLE_ID" != x ] ; then
+    if [ x"$KEYCHAIN_PROFILE" != x ] ; then
 	echo "Notarizing package..."
-	./notarize.pl "$APPLE_ID" "$APPLE_PW" "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
+	./notarize.pl "$KEYCHAIN_PROFILE" "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
     fi
 fi
diff --git a/src/packaging/RedHat/openafs-client-systemd-helper.sh b/src/packaging/RedHat/openafs-client-systemd-helper.sh
new file mode 100755
index 0000000000..df8bdcf0ae
--- /dev/null
+++ b/src/packaging/RedHat/openafs-client-systemd-helper.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# systemd helper script for openafs-client.service. This is only intended to be
+# called from the openafs-client.service unit file.
+
+set -e
+
+UMOUNT_TIMEOUT=30
+
+[ -f /etc/sysconfig/openafs ] && . /etc/sysconfig/openafs
+
+case $1 in
+    ExecStart)
+	if fs sysname >/dev/null 2>&1 ; then
+	    # If we previously tried to stop the client and failed (because
+	    # e.g. /afs was in use), our unit will be deactivated but the
+	    # client will keep running. So if we're starting up, but the client
+	    # is currently running, do not perform the startup sequence but
+	    # just return success, to let the unit activate, so stopping the
+	    # unit can go through the shutdown sequence again.
+	    echo AFS client appears to be running -- skipping startup
+	    exit 0
+	fi
+	sed -n 'w/usr/vice/etc/CellServDB' /usr/vice/etc/CellServDB.local /usr/vice/etc/CellServDB.dist
+	chmod 0644 /usr/vice/etc/CellServDB
+
+	# If the kernel module is already initialized from a previous client
+	# run, it must be unloaded and loaded again. So if the module is
+	# currently loaded, unload it in case it was (partly) initialized.
+	if lsmod | grep -wq ^openafs ; then
+	    /sbin/rmmod --verbose openafs
+	fi
+	/sbin/modprobe --verbose openafs
+	exec /usr/vice/etc/afsd $AFSD_ARGS
+	;;
+
+    ExecStop)
+	if /bin/umount --verbose /afs ; then
+	    exit 0
+	else
+	    echo "Failed to unmount /afs: $?"
+	fi
+
+	state=$(systemctl is-system-running || true)
+	if [ "$state" = stopping ] && [ x"$UMOUNT_TIMEOUT" != x ] && /bin/mountpoint --quiet /afs ; then
+	    # If we are shutting down the system, failing to umount /afs
+	    # can lead to longer delays later as systemd tries to forcibly
+	    # kill our afsd processes. So retry the umount a few times,
+	    # just in case other /afs-using processes just need a few
+	    # seconds to go away.
+	    echo "For system shutdown, retrying umount /afs for $UMOUNT_TIMEOUT secs"
+	    interval=3
+	    for (( i = 0; i < $UMOUNT_TIMEOUT; i += $interval )) ; do
+		sleep $interval
+		if /bin/umount --verbose /afs ; then
+		    exit 0
+		fi
+		if ! /bin/mountpoint --quiet /afs ; then
+		    echo "mountpoint /afs disappeared; bailing out"
+		    exit 0
+		fi
+	    done
+	    echo "Still cannot umount /afs, bailing out"
+	fi
+	exit 1
+	;;
+
+    ExecStopPost)
+	/usr/vice/etc/afsd -shutdown || true
+	/sbin/rmmod --verbose openafs || true
+	if lsmod | grep -wq ^openafs ; then
+	    echo "Cannot unload the OpenAFS client kernel module."
+	    echo "systemd will consider the openafs-client.service unit inactive, but the AFS client may still be running."
+	    echo "To stop the client, stop all access to /afs, and then either:"
+	    echo "stop the client manually:"
+	    echo "    umount /afs"
+	    echo "    rmmod openafs"
+	    echo "or start and stop the openafs-client.service unit:"
+	    echo "    systemctl start openafs-client.service"
+	    echo "    systemctl stop openafs-client.service"
+	    echo 'See "journalctl -u openafs-client.service" for details.'
+	    exit 1
+	fi
+	exit 0
+	;;
+esac
+
+echo "Usage: $0 {ExecStart|ExecStop|ExecStopPost}" >&2
+exit 1
diff --git a/src/packaging/RedHat/openafs-client.service b/src/packaging/RedHat/openafs-client.service
index f79240c7f6..5036709f3e 100644
--- a/src/packaging/RedHat/openafs-client.service
+++ b/src/packaging/RedHat/openafs-client.service
@@ -7,16 +7,13 @@ Before=remote-fs.target
 [Service]
 Type=forking
 RemainAfterExit=true
-EnvironmentFile=/etc/sysconfig/openafs
-ExecStartPre=/bin/bash -c "fs sysname > /dev/null 2>/dev/null; test $? -ne 0 || (echo AFS client appears to be running -- not starting && exit 1)"
-ExecStartPre=/bin/sed -n 'w/usr/vice/etc/CellServDB' /usr/vice/etc/CellServDB.local /usr/vice/etc/CellServDB.dist
-ExecStartPre=/bin/chmod 0644 /usr/vice/etc/CellServDB
-ExecStartPre=/sbin/modprobe openafs
-ExecStart=/usr/vice/etc/afsd $AFSD_ARGS
-ExecStop=/bin/umount /afs
-ExecStop=/usr/vice/etc/afsd -shutdown
-ExecStop=/sbin/rmmod openafs
-KillMode=none
+ExecStart=   /usr/vice/etc/openafs-client-systemd-helper.sh ExecStart
+ExecStop=    /usr/vice/etc/openafs-client-systemd-helper.sh ExecStop
+ExecStopPost=/usr/vice/etc/openafs-client-systemd-helper.sh ExecStopPost
+KillMode=process
+GuessMainPID=no
+SendSIGKILL=no
+KillSignal=SIGCONT
 
 [Install]
 WantedBy=multi-user.target remote-fs.target
diff --git a/src/packaging/RedHat/openafs-kmodtool b/src/packaging/RedHat/openafs-kmodtool
index 5ee68261cd..0a0abf86f1 100644
--- a/src/packaging/RedHat/openafs-kmodtool
+++ b/src/packaging/RedHat/openafs-kmodtool
@@ -42,7 +42,11 @@ get_verrel ()
   case "$verrel" in
     *.el[6-9].elrepo*)
                    verrel="`echo ${verrel} | sed -e 's/^\(.*.el[6-9].elrepo[^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
+    *.el[1-9][0-9].elrepo*)
+                   verrel="`echo ${verrel} | sed -e 's/^\(.*.el[1-9][0-9].elrepo[^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
     *.el[6-9]*)    verrel="`echo ${verrel} | sed -e 's/^\(.*.el[6-9][^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
+    *.el[1-9][0-9]*)
+                   verrel="`echo ${verrel} | sed -e 's/^\(.*.el[1-9][0-9][^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
     *.fc[1-9][0-9]*)
                    verrel="`echo ${verrel} | sed -e 's/^\(.*.fc[1-9][0-9][^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
     *.fc9*)        verrel="`echo ${verrel} | sed -e 's/^\(.*.fc9[^\.]*\)\.[^\.]\+.\?$/\1/'`" ;;
@@ -77,12 +81,16 @@ get_rpmtemplate ()
     case "$verrel" in
         *.el[6-9]*)
 	       kdep="kernel-%{_target_cpu} = ${verrel}${variant}"     ;;
+        *.el[1-9][0-9]*)
+	       kdep="kernel-%{_target_cpu} = ${verrel}${variant}"     ;;
         *.EL*) kdep="kernel${dashvariant}-%{_target_cpu} = ${verrel}" ;;
         *)     kdep="kernel-%{_target_cpu} = ${verrel}${variant}"     ;;
     esac
     case "$verrel" in
         *.el[6-9]*)
 	          kname="${verrel}.%{_target_cpu}${variant:+.${variant}}" ;;
+        *.el[1-9][0-9]*)
+	          kname="${verrel}.%{_target_cpu}${variant:++${variant}}" ;;
         *.fc[2-9][0-9]*)
 	          kname="${verrel}.%{_target_cpu}${variant:++${variant}}" ;;
         *.fc1[0-9]*)
diff --git a/src/packaging/RedHat/openafs.spec.in b/src/packaging/RedHat/openafs.spec.in
index 6481358a8c..f1dce8fb16 100644
--- a/src/packaging/RedHat/openafs.spec.in
+++ b/src/packaging/RedHat/openafs.spec.in
@@ -1,4 +1,4 @@
-# Openafs Spec $Revision$
+# Openafs Spec
 
 %define afsvers @PACKAGE_VERSION@
 %define pkgvers @LINUX_PKGVER@
@@ -6,6 +6,9 @@
 # for real releases make pkgrel 1 (or more for extra releases)
 %define pkgrel @LINUX_PKGREL@
 
+# Disable using lto (link time optimization)
+%global _lto_cflags %{nil}
+
 %{!?build_dkmspkg: %define build_dkmspkg 1}
 
 #
@@ -87,7 +90,7 @@ URL: http://www.openafs.org
 BuildRoot: %{_tmppath}/%{name}-%{version}-root
 Packager: OpenAFS Gatekeepers <openafs-gatekeepers@openafs.org>
 Group: Networking/Filesystems
-BuildRequires: %{?kdepend:%{kdepend}, } pam-devel, ncurses-devel, flex, bison
+BuildRequires: %{?kdepend:%{kdepend}, } pam-devel, ncurses-devel, make, flex, bison
 %if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
 BuildRequires: systemd-units
 %endif
@@ -107,7 +110,6 @@ BuildRequires: elfutils-devel
 
 ExclusiveArch: %{ix86} x86_64 ia64 s390 s390x sparc64 ppc ppc64 aarch64
 
-#    http://dl.openafs.org/dl/openafs/candidate/%{afsvers}/...
 Source0: http://www.openafs.org/dl/openafs/%{afsvers}/openafs-%{afsvers}-src.tar.bz2
 Source1: http://www.openafs.org/dl/openafs/%{afsvers}/openafs-%{afsvers}-doc.tar.bz2
 %define srcdir openafs-%{afsvers}
@@ -115,7 +117,7 @@ Source1: http://www.openafs.org/dl/openafs/%{afsvers}/openafs-%{afsvers}-doc.tar
 Source10: http://www.openafs.org/dl/openafs/%{afsvers}/RELNOTES-%{afsvers}
 Source11: http://www.openafs.org/dl/openafs/%{afsvers}/ChangeLog
 
-Source20: https://www.central.org/dl/cellservdb/CellServDB.2023-10-31
+Source20: https://www.central.org/dl/cellservdb/CellServDB.2025-08-16
 
 Source996: openafs-kvers-is.sh
 Source997: openafs-buildfedora.pl
@@ -327,7 +329,6 @@ module.
 Summary: OpenAFS client compatibility symlinks
 Requires: openafs = %{version}, openafs-client = %{version}
 Group: Networking/Filesystems
-Obsoletes: openafs-client-compat
 
 %description compat
 The AFS distributed filesystem.  AFS is a distributed filesystem
@@ -425,7 +426,6 @@ krb4 lookalike services.
 : @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 # Install OpenAFS src and doc
-#%setup -q -n %{srcdir}
 %setup -q -b 1 -n %{srcdir}
 
 ##############################################################################
@@ -820,6 +820,7 @@ mkdir -p $RPM_BUILD_ROOT%{_unitdir}
 mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/modules
 install -m 644 src/packaging/RedHat/openafs-client.service $RPM_BUILD_ROOT%{_unitdir}/openafs-client.service
 install -m 644 src/packaging/RedHat/openafs-server.service $RPM_BUILD_ROOT%{_unitdir}/openafs-server.service
+install -m 755 src/packaging/RedHat/openafs-client-systemd-helper.sh $RPM_BUILD_ROOT%{_prefix}/vice/etc/openafs-client-systemd-helper.sh
 %endif
 
 #-----------------------------------------------------------------------------
@@ -851,13 +852,13 @@ PACKAGE_VERSION="%{dkms_version}"
 # Items below here should not have to change with each driver version.
 PACKAGE_NAME="%{name}"
 MAKE[0]='./configure --with-linux-kernel-headers=${kernel_source_dir} --with-linux-kernel-packaging && make && case "${kernelver_array[0]}${kernelver[0]}" in 2.4.*) mv src/libafs/MODLOAD-*/libafs-* openafs.o ;; *) mv src/libafs/MODLOAD-*/openafs.ko . ;; esac'
-CLEAN="if [ -e src/libafs/Makefile ]; then make -C src/libafs clean; else true; fi"
+CLEAN=true
 
 BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
 DEST_MODULE_LOCATION[0]="/extra/$PACKAGE_NAME/"
 STRIP[0]=no
 AUTOINSTALL=yes
-NO_WEAK_MODULES="true"
+NO_WEAK_MODULES=yes
 
 EOF
 
@@ -1200,6 +1201,7 @@ dkms remove -m %{name} -v %{dkms_version} --rpm_safe_upgrade --all ||:
 %{initdir}/openafs-client
 %else
 %{_unitdir}/openafs-client.service
+%{_prefix}/vice/etc/openafs-client-systemd-helper.sh
 %endif
 %{_mandir}/man1/cmdebug.1.gz
 %{_mandir}/man1/up.1.gz
@@ -1451,7 +1453,7 @@ dkms remove -m %{name} -v %{dkms_version} --rpm_safe_upgrade --all ||:
 %{_mandir}/man8/akeyconvert.8.gz
 %{_mandir}/man8/asetkey.8.gz
 %endif
-%endif  # build_userspace
+%endif
 
 ##############################################################################
 ###
diff --git a/src/platform/DARWIN/AFSPreference/.gitignore b/src/platform/DARWIN/AFSPreference/.gitignore
index 43e35a4674..1e8c27a9a0 100644
--- a/src/platform/DARWIN/AFSPreference/.gitignore
+++ b/src/platform/DARWIN/AFSPreference/.gitignore
@@ -5,3 +5,4 @@ build/*
 *.mode2v3
 *.perspectivev3
 config
+Info.plist
diff --git a/src/platform/DARWIN/AFSPreference/AFSCommanderPref.m b/src/platform/DARWIN/AFSPreference/AFSCommanderPref.m
index 1a06b02289..15dd12b101 100644
--- a/src/platform/DARWIN/AFSPreference/AFSCommanderPref.m
+++ b/src/platform/DARWIN/AFSPreference/AFSCommanderPref.m
@@ -569,7 +569,7 @@
     
     case REMOVE_CELL_CONTROL_TAG:
     {
-	int index = 0;
+	NSUInteger index;
 	NSIndexSet *selectedIndex = [(NSTableView*)cellList selectedRowIndexes];
 	if( [selectedIndex count] > 0) {
 	    index = [selectedIndex firstIndex];
@@ -697,7 +697,7 @@
 // -------------------------------------------------------------------------------
 - (IBAction) unlog:(id) sender
 {
-    int index = -1;
+    NSUInteger index;
     NSIndexSet *selectedIndex = [tokensTable selectedRowIndexes];
     if( [selectedIndex count] > 0) {
 	index = [selectedIndex firstIndex];
@@ -750,14 +750,13 @@
 //  afsStartupSwitchEvent:
 // -------------------------------------------------------------------------------
 - (IBAction) afsStartupSwitchEvent:(id) sender {
-    NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
     //get the new state
     startAFSAtLogin = [checkButtonAfsAtBootTime state];
-    [PListManager launchctlStringCommandAuth:startAFSAtLogin?@"load":@"unload"
-		  option:[NSArray arrayWithObjects:@"-w", nil]
-		  plistName:@AFS_DAEMON_PATH
-		  helper:rootHelperApp
-		  withAuthRef:[[authView authorization] authorizationRef]];
+    if (startAFSAtLogin) {
+	[TaskUtil executePrivTask:"startup_enable"];
+    } else {
+	[TaskUtil executePrivTask:"startup_disable"];
+    }
 }
 
 
@@ -878,16 +877,13 @@
 {
     BOOL afsIsUp = [afsProperty checkAfsStatus];
     BOOL afsEnabledAtStartup = NO;
-    NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
 
     if ([self isUnlocked]) {
-	afsEnabledAtStartup = (
-	    [TaskUtil executeTaskWithAuth:@"/bin/launchctl"
-		      arguments:[NSArray arrayWithObjects:@"list",
-					 @"org.openafs.filesystems.afs", nil]
-		      helper:rootHelperApp
-		      withAuthRef:[[authView authorization] authorizationRef]
-	     ] == noErr)?YES:NO;
+	if ([TaskUtil executePrivTask:"startup_check"] == 0) {
+	    afsEnabledAtStartup = YES;
+	} else {
+	    afsEnabledAtStartup = NO;
+	}
 	[checkButtonAfsAtBootTime setState:afsEnabledAtStartup];
     }
 
@@ -941,14 +937,14 @@
 // -------------------------------------------------------------------------------
 - (IBAction) removeLink:(id) sender {
     if(!linkConfiguration) return;
-    int index = 0;
+    NSUInteger index;
     NSArray *keys = [linkConfiguration allKeys];
     NSIndexSet *linkToRemove = [tableViewLink selectedRowIndexes];
     if( [linkToRemove count] > 0) {
 	index = [linkToRemove firstIndex];
 	do {
 	    [linkConfiguration removeObjectForKey:[keys objectAtIndex:index]];
-	} while ((index = [linkToRemove indexGreaterThanIndex:index]) != -1);
+	} while ((index = [linkToRemove indexGreaterThanIndex:index]) != NSNotFound);
     }
 
     //write the new configuration
@@ -1043,6 +1039,17 @@
     [checkButtonAfsAtBootTime setEnabled:[self isUnlocked]];
     [installKRB5AuthAtLoginButton setEnabled:[self isUnlocked]];
 }
+
+// These are called when the user clicks on the lock icon in the prefpane to
+// authenticate to make system changes. Store a reference to the authorization
+// context that we can use for privileged operations.
+- (void)authorizationViewCreatedAuthorization:(SFAuthorizationView *)view {
+    [[AuthUtil shared] setAuthorization:[[authView authorization] authorizationRef]];
+}
+
+- (void)authorizationViewReleasedAuthorization:(SFAuthorizationView *)view {
+    [[AuthUtil shared] setAuthorization:nil];
+}
 @end
 
 @implementation AFSCommanderPref (NSTableDataSource)
diff --git a/src/platform/DARWIN/AFSPreference/AFSPropertyManager.h b/src/platform/DARWIN/AFSPreference/AFSPropertyManager.h
index 0ed4cd42dd..edc1dbcf9e 100644
--- a/src/platform/DARWIN/AFSPreference/AFSPropertyManager.h
+++ b/src/platform/DARWIN/AFSPreference/AFSPropertyManager.h
@@ -258,10 +258,9 @@
 /*!
  @function	 writeCacheInfo
  @abstract   Write the cache info down the file
- @param      filePath where to write the CacheInfo
  @result     return the execution error
  */
--(int) writeCacheInfo:(NSString*)filePath;
+-(int) writeCacheInfo;
 
 /*!
  @function	 readAfsdOption
@@ -292,14 +291,6 @@
  @param      filePath path of the new file with afs.conf file format
  */
 -(int) readNewAfsdOption:(NSString*)filePath;
-/*!
- @function	 writeAfsdOption
- @abstract   <#(description)#>
- @discussion <#(description)#>
- @param      <#(name) (description)#>
- @result     <#(description)#>
- */
--(int) writeAfsdOption:(NSString*)filePath;
 /*!
  @function	 writeOldAfsdOption
  @abstract   Write the cache manager parameter to file
@@ -307,13 +298,12 @@
  @param      filePath file path for file to write into
  @result     <#(description)#>
  */
--(int) writeOldAfsdOption:(NSString*)filePath;
+-(int) writeOldAfsdOption;
 /*!
  @function	 writeNewAfsdOption
  @abstract   Write the cache parameter to a file with the new format
- @param      filePath file path where write into
  */
--(int) writeNewAfsdOption:(NSString*)filePath;
+-(int) writeNewAfsdOption;
 /*!
  @function	 getAfsVersion
  @abstract   Return the string representing the afs version
@@ -387,7 +377,6 @@
 -(void) startup;
 -(void) scanIpForCell:(DBCellElement*) cellElement allIP:(NSString*)allIP;
 -(void) backupConfigurationFiles;
--(void) backupFile:(NSString*)localAfsFilePath;
 -(void) saveConfigurationFiles:(BOOL) makeBackup;
 -(void) saveCacheConfigurationFiles:(BOOL) makeBackup;
 -(void) installConfigurationFile:(NSString*)srcConfFile destPath:(NSString*) destPath;
diff --git a/src/platform/DARWIN/AFSPreference/AFSPropertyManager.m b/src/platform/DARWIN/AFSPreference/AFSPropertyManager.m
index e96fc747b4..8b57b087bb 100644
--- a/src/platform/DARWIN/AFSPreference/AFSPropertyManager.m
+++ b/src/platform/DARWIN/AFSPreference/AFSPropertyManager.m
@@ -402,7 +402,7 @@
 // -------------------------------------------------------------------------------
 //  writeCacheInfo:
 // -------------------------------------------------------------------------------
--(int) writeCacheInfo:(NSString*)filePath
+-(int) writeCacheInfo
 {
 	NSNumber *tmpNum = nil;
 	NSMutableString *cacheInfoContent = [[NSMutableString alloc] init];
@@ -427,10 +427,7 @@
 									 userInfo:nil];
 	[cacheInfoContent appendString:[tmpNum stringValue]];
 	
-	[cacheInfoContent writeToFile: [filePath stringByExpandingTildeInPath]
-					   atomically: YES 
-						 encoding: NSASCIIStringEncoding 
-							error: nil];
+	[TaskUtil executePrivTaskWrite:@"/etc/cacheinfo" data:cacheInfoContent];
 	
 	[cacheInfoContent release];
 	return noErr;
@@ -580,31 +577,10 @@
 }
 
 
-// -------------------------------------------------------------------------------
-//  writeCacheInfo:
-// -------------------------------------------------------------------------------
--(int) writeAfsdOption:(NSString*)filePath
-{
-	int result = 0;
-	@try{
-		if(useAfsdConfVersion) {
-			result = [self writeNewAfsdOption:filePath];			
-		} else {
-			result = [self writeOldAfsdOption:filePath];
-		}
-		
-	}@catch(NSException *e){
-		@throw e;
-	}@finally{
-		
-	}
-	return result;
-}
-
 // -------------------------------------------------------------------------------
 //  writeOldAfsdOption:
 // -------------------------------------------------------------------------------
--(int) writeOldAfsdOption:(NSString*)filePath;
+-(int) writeOldAfsdOption
 {
 	NSMutableString *oldConfFileContent = [[[NSMutableString alloc] init] autorelease];
 	//add afsd param
@@ -614,12 +590,9 @@
 	[oldConfFileContent appendString:@"\n"];
 	
 	//write content on file
-	[oldConfFileContent writeToFile: [filePath stringByExpandingTildeInPath]
-						 atomically: YES 
-						   encoding: NSASCIIStringEncoding 
-							  error: nil];
+	[TaskUtil executePrivTaskWrite:AFSD_OLD_PREFERENCE_FILE data:oldConfFileContent];
+
 	return noErr;
-	
 }
 
 // -------------------------------------------------------------------------------
@@ -629,7 +602,7 @@
 //  AFS_POST_INIT=afs_server_prefs
 //  AFS_PRE_SHUTDOWN=
 // -------------------------------------------------------------------------------
--(int) writeNewAfsdOption:(NSString*)filePath
+-(int) writeNewAfsdOption
 {
 	NSMutableString *newConfFileContent = [[[NSMutableString alloc] init] autorelease];
 	
@@ -652,10 +625,8 @@
 	[newConfFileContent appendString:@"\n"];
 	
 	//Write to file
-	[newConfFileContent writeToFile: [filePath stringByExpandingTildeInPath]
-						 atomically: YES 
-						   encoding: NSASCIIStringEncoding 
-							  error: nil];
+	[TaskUtil executePrivTaskWrite:AFSD_NEW_PREFERENCE_FILE data:newConfFileContent];
+
 	return noErr;
 }
 
@@ -1077,12 +1048,8 @@
 // -------------------------------------------------------------------------------
 -(void) shutdown
 {
-  NSString *rootHelperApp = [[NSBundle bundleForClass:[self class]] pathForResource:@"afshlp" ofType:@""];
     @try {
-	const char *stopArgs[] = {AFS_DAEMON_STARTUPSCRIPT, "stop", 0L};
-	[[AuthUtil shared] execUnixCommand:[rootHelperApp fileSystemRepresentation]
-			   args:stopArgs
-			   output:nil];
+	[TaskUtil executePrivTask:"afsd_stop"];
     }
     @catch (NSException * e) {
 	@throw e;
@@ -1097,12 +1064,8 @@
 // -------------------------------------------------------------------------------
 -(void) startup
 {
-  NSString *rootHelperApp = [[NSBundle bundleForClass:[self class]] pathForResource:@"afshlp" ofType:@""];
     @try {
-	const char *startArgs[] = {AFS_DAEMON_STARTUPSCRIPT, "start", 0L};
-	[[AuthUtil shared] execUnixCommand:[rootHelperApp fileSystemRepresentation]
-			   args:startArgs
-			   output:nil];
+	[TaskUtil executePrivTask:"afsd_start"];
     }
     @catch (NSException * e) {
 	@throw e;
@@ -1116,8 +1079,6 @@
 // -------------------------------------------------------------------------------
 -(void) saveConfigurationFiles:(BOOL) makeBackup
 {
-	NSError *err;
-	NSMutableString *filePath = [[NSMutableString alloc] initWithCapacity:256];
 	NSMutableString *cellServDBString = [[NSMutableString alloc] initWithCapacity:256];
 	NSMutableString *theseCellString = [[NSMutableString alloc] initWithCapacity:256];
 	DBCellElement *cellElement = nil;
@@ -1126,14 +1087,6 @@
 	@try{
 		[self exceptionOnInvalidPath];
 
-		// ThisCell
-		[filePath setString: @"/tmp/ThisCell"];
-		[cellName writeToFile: [filePath stringByExpandingTildeInPath]
-				   atomically:YES 
-					 encoding: NSASCIIStringEncoding 
-						error:nil];
-		// CellServDB
-		
 		for(int idx = 0; idx < [cellList count]; idx++){
 			cellElement = [cellList objectAtIndex:idx];
 			[cellServDBString appendString:[cellElement description]];
@@ -1143,45 +1096,18 @@
 			}
 		}
 		
-		
-		[filePath setString: @"/tmp/CellServDB"];
-		[cellServDBString writeToFile: [filePath stringByExpandingTildeInPath]
-						   atomically:YES 
-							 encoding:  NSUTF8StringEncoding 
-								error:&err];
-		
-		[filePath setString: @"/tmp/TheseCells"];
-		[theseCellString writeToFile: [filePath stringByExpandingTildeInPath]
-						   atomically:YES 
-							 encoding:  NSUTF8StringEncoding 
-								error:&err];
-		
 		if(makeBackup) [self backupConfigurationFiles];
 
-		// install ThisCell
-		[filePath setString: installationPath];
-		[filePath appendString: @"/etc/ThisCell"];
-		[self installConfigurationFile:@"/tmp/ThisCell" 
-							  destPath:filePath];		
-		
-		// install CellServDB
-		[filePath setString: installationPath];
-		[filePath appendString: @"/etc/CellServDB"];
-		[self installConfigurationFile:@"/tmp/CellServDB" 
-							  destPath:filePath];
-		
-		// install CellServDB
-		[filePath setString: installationPath];
-		[filePath appendString: @"/etc/TheseCells"];
-		[self installConfigurationFile:@"/tmp/TheseCells" 
-							  destPath:filePath];
+		[TaskUtil executePrivTaskWrite:@"/etc/ThisCell" data:cellName];
+		[TaskUtil executePrivTaskWrite:@"/etc/CellServDB" data:cellServDBString];
+		[TaskUtil executePrivTaskWrite:@"/etc/TheseCells" data:theseCellString];
 		
 	} @catch (NSException *e) {
 		@throw e;
 	}@finally {
 		// dispose all variable used
-		if(filePath) [filePath release];
 		if(cellServDBString) [cellServDBString release];
+		if(theseCellString) [theseCellString release];
 	}
 	
 }
@@ -1196,32 +1122,29 @@
 	@try{
 		[self exceptionOnInvalidPath];
 		
-		// cacheinfo file creation
-		[self writeCacheInfo:@"/tmp/cacheinfo"];
-		
-		//afsd.option or afs.conf file creation
-		[self writeAfsdOption:useAfsdConfVersion?AFSD_TMP_NEW_PREFERENCE_FILE:AFSD_TMP_OLD_PREFERENCE_FILE];
-		
 		// backup original file
 		if(makeBackup) {
 			//cacheinfo
-			[self backupFile:@"/etc/cacheinfo"];
+			[TaskUtil executePrivTaskBackup:@"/etc/cacheinfo"];
 			
 			//afsd.options
-			[self backupFile:useAfsdConfVersion?AFSD_NEW_PREFERENCE_FILE:AFSD_OLD_PREFERENCE_FILE];	
+			if (useAfsdConfVersion) {
+			    [TaskUtil executePrivTaskBackup:AFSD_NEW_PREFERENCE_FILE];
+			} else {
+			    [TaskUtil executePrivTaskBackup:AFSD_OLD_PREFERENCE_FILE];
+			}
 		}
+
+		// cacheinfo
+		[self writeCacheInfo];
 		
-		// install cacheinfo
-		[filePath setString:installationPath];
-		[filePath appendString: @"/etc/cacheinfo"];
-		[self installConfigurationFile:@"/tmp/cacheinfo" 
-							  destPath:filePath];		
-		
-		// install afsd.conf or afs.conf configuration file 
-		[filePath setString: installationPath];
-		[filePath appendString: useAfsdConfVersion?AFSD_NEW_PREFERENCE_FILE:AFSD_OLD_PREFERENCE_FILE];
-		[self installConfigurationFile:useAfsdConfVersion?AFSD_TMP_NEW_PREFERENCE_FILE:AFSD_TMP_OLD_PREFERENCE_FILE
-							  destPath:filePath];
+		if (useAfsdConfVersion) {
+		    // afs.conf
+		    [self writeNewAfsdOption];
+		} else {
+		    // afsd.options
+		    [self writeOldAfsdOption];
+		}
 		
 	} @catch (NSException *e) {
 		@throw e;
@@ -1272,13 +1195,13 @@
 
 	@try{
 		//This cell
-		[self backupFile:@"/etc/ThisCell"];
+		[TaskUtil executePrivTaskBackup:@"/etc/ThisCell"];
 	
 		//CellServDB
-		[self backupFile:@"/etc/CellServDB"];
+		[TaskUtil executePrivTaskBackup:@"/etc/CellServDB"];
 		
 		//TheseCell
-		[self backupFile:@"/etc/TheseCells"];
+		[TaskUtil executePrivTaskBackup:@"/etc/TheseCells"];
 		
 	} @catch (NSException *e) {
 		@throw e;
@@ -1287,51 +1210,33 @@
 }
 
 // -------------------------------------------------------------------------------
-//  -(void) backupFile:(NSString*)localAfsFilePath
-// -------------------------------------------------------------------------------
--(void) backupFile:(NSString*)localAfsFilePath
-{
-	NSString *srcString = nil;
-	NSMutableString *filePath = [[NSMutableString alloc] initWithCapacity:256];
-	OSStatus err = noErr;
-	@try{
-		[filePath setString: installationPath];
-		[filePath appendString: localAfsFilePath];
-		
-		//Check if the file at path exist
-		NSFileManager *fileManager = [NSFileManager defaultManager];
-		if(![fileManager fileExistsAtPath:[filePath stringByExpandingTildeInPath]]) return;
-		
-		// store the source path
-		srcString  = [filePath stringByExpandingTildeInPath];
-		[filePath appendString: @".afscommander_bk"];
-		
-		// check for presence of bk file
-		if(![[NSFileManager defaultManager] fileExistsAtPath:[filePath stringByExpandingTildeInPath]]){
-			// backup the file
-			err = [futil autorizedCopy:srcString 
-						  toPath:[filePath stringByExpandingTildeInPath]];
-		}
-	} @catch (NSException *e) {
-		@throw e;
-	} @finally {
-		if(filePath) [filePath release];
-	}
-}
-
-// -------------------------------------------------------------------------------
-//  checkAfsStatus:[NSArray arrayWithObjects:@"checkserver", nil];
+//  checkAfsStatus
+//   This is called at least once per 60s.
 // -------------------------------------------------------------------------------
 -(BOOL) checkAfsStatus
 {
 	BOOL result = NO;
-	NSString *dfResult = [TaskUtil executeTaskSearchingPath:@"/bin/df" args:[NSArray arrayWithObjects:nil]];
-	result = (dfResult?([dfResult rangeOfString:@AFS_FS_MOUNT].location != NSNotFound):NO);
-	return result;	
+	NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeLocalizedFormatDescriptionKey, nil];
+	NSArray *urls = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:keys options:0];
+
+	for (NSURL *url in urls) {
+	    NSError *error;
+	    NSString *volumeFormat;
+
+	    // volumeFormat will have value "Unknown (afs)" for a mounted AFS filesystem,
+	    // regardless of the mount directory specified by cacheinfo or the -mountdir option.
+	    [url getResourceValue:&volumeFormat forKey:NSURLVolumeLocalizedFormatDescriptionKey error:&error];
+
+	    if ([volumeFormat containsString:@"(afs)"]) {
+		result = YES;
+		break;
+	    }
+	}
+	return result;
 }
 
 // -------------------------------------------------------------------------------
-//  checkAfsStatus:[NSArray arrayWithObjects:@"checkserver", nil];
+//  checkAfsStatusForStartup
 // -------------------------------------------------------------------------------
 -(BOOL) checkAfsStatusForStartup {
 	BOOL result = NO;
diff --git a/src/platform/DARWIN/AFSPreference/AuthUtil.h b/src/platform/DARWIN/AFSPreference/AuthUtil.h
index f92156a64b..a82a9efe1c 100644
--- a/src/platform/DARWIN/AFSPreference/AuthUtil.h
+++ b/src/platform/DARWIN/AFSPreference/AuthUtil.h
@@ -12,11 +12,13 @@
 
 @interface AuthUtil : NSObject {
 	AuthorizationRef authorizationRef;
+	BOOL isAuthorizationRefOwned;
 }
 -(id) init;
 -(OSStatus) autorize;
 -(BOOL) deautorize;
 -(AuthorizationRef) authorization;
+-(void)setAuthorization:(AuthorizationRef)authRef;
 -(NSData*) extFormAuth;
 -(OSStatus) execUnixCommand:(const char*) commandPath args:(const char*[])args output:(NSMutableString*)output;
 +(AuthUtil*) shared;
diff --git a/src/platform/DARWIN/AFSPreference/AuthUtil.m b/src/platform/DARWIN/AFSPreference/AuthUtil.m
index f626dc3cbf..369a545e3d 100644
--- a/src/platform/DARWIN/AFSPreference/AuthUtil.m
+++ b/src/platform/DARWIN/AFSPreference/AuthUtil.m
@@ -76,6 +76,7 @@ static AuthUtil *sharedAuthUtil = nil;
 			if (status != errAuthorizationSuccess) {
 				return status;
 			}
+			isAuthorizationRefOwned = YES;
 		}
 		
 		flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
@@ -100,6 +101,7 @@ static AuthUtil *sharedAuthUtil = nil;
 	if(authorizationRef){
 		status = AuthorizationFree (authorizationRef, kAuthorizationFlagDefaults);
 		authorizationRef = 0L; 
+		isAuthorizationRefOwned = NO;
 	}
 	return status == noErr;
 }
@@ -113,6 +115,14 @@ static AuthUtil *sharedAuthUtil = nil;
 	return authorizationRef;
 }
 
+-(void)setAuthorization:(AuthorizationRef)authRef
+{
+    if (isAuthorizationRefOwned) {
+	[self deautorize];
+    }
+    authorizationRef = authRef;
+}
+
 // -------------------------------------------------------------------------------
 //  authorization:
 // -------------------------------------------------------------------------------
diff --git a/src/platform/DARWIN/AFSPreference/Info.plist b/src/platform/DARWIN/AFSPreference/Info.plist.in
similarity index 74%
rename from src/platform/DARWIN/AFSPreference/Info.plist
rename to src/platform/DARWIN/AFSPreference/Info.plist.in
index 2d3b14e20b..f330871cd3 100644
--- a/src/platform/DARWIN/AFSPreference/Info.plist
+++ b/src/platform/DARWIN/AFSPreference/Info.plist.in
@@ -30,5 +30,10 @@
 	<string>OpenAFS</string>
 	<key>NSPrincipalClass</key>
 	<string>AFSCommanderPref</string>
+	<key>SMPrivilegedExecutables</key>
+	<dict>
+		<key>org.openafs.privhelper</key>
+		<string>identifier "org.openafs.privhelper" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = @MACOS_TEAM_ID@</string>
+	</dict>
 </dict>
 </plist>
diff --git a/src/platform/DARWIN/AFSPreference/IpConfiguratorCommander.m b/src/platform/DARWIN/AFSPreference/IpConfiguratorCommander.m
index 70a50abb78..9768785ff4 100644
--- a/src/platform/DARWIN/AFSPreference/IpConfiguratorCommander.m
+++ b/src/platform/DARWIN/AFSPreference/IpConfiguratorCommander.m
@@ -49,6 +49,7 @@
 	[bkIPArray removeAllObjects];
 	[bkIPArray setArray:workIPArray];
 	[workIPArray release];
+	workIPArray = nil;
 }
 
 // -------------------------------------------------------------------------------
diff --git a/src/platform/DARWIN/AFSPreference/Krb5Util.m b/src/platform/DARWIN/AFSPreference/Krb5Util.m
index d9cc88c453..79cb6e7a9f 100644
--- a/src/platform/DARWIN/AFSPreference/Krb5Util.m
+++ b/src/platform/DARWIN/AFSPreference/Krb5Util.m
@@ -143,7 +143,7 @@
 			in.times.endtime = now + inTicketLifetime;
 			in.times.renew_till = now + inTicketLifetime;
 
-			krb5_cc_default(kcontext, &id);
+			ret = krb5_cc_default(kcontext, &id);
 			if (ret == 0) {
 				ret = krb5_cc_get_principal(kcontext, id,
 							    &me);
diff --git a/src/platform/DARWIN/AFSPreference/OpenAFS.xcodeproj/project.pbxproj b/src/platform/DARWIN/AFSPreference/OpenAFS.xcodeproj/project.pbxproj
index 8fbf8b895f..972e051e94 100644
--- a/src/platform/DARWIN/AFSPreference/OpenAFS.xcodeproj/project.pbxproj
+++ b/src/platform/DARWIN/AFSPreference/OpenAFS.xcodeproj/project.pbxproj
@@ -847,6 +847,7 @@
 				GCC_PREFIX_HEADER = AFSCommander_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Library/PreferencePanes";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = OpenAFS;
 				WRAPPER_EXTENSION = prefPane;
 				ZERO_LINK = YES;
@@ -865,6 +866,7 @@
 				GCC_PREFIX_HEADER = AFSCommander_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = OpenAFS;
 				WRAPPER_EXTENSION = prefPane;
 			};
@@ -884,6 +886,7 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				INSTALL_PATH = "";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				ONLY_ACTIVE_ARCH = NO;
 				PREBINDING = NO;
 				SKIP_INSTALL = NO;
@@ -904,6 +907,7 @@
 				GCC_ENABLE_OBJC_GC = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				ONLY_ACTIVE_ARCH = NO;
 				PREBINDING = NO;
 				VALID_ARCHS = "i386 ppc x86_64 armv6 arm64";
@@ -923,6 +927,7 @@
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INFOPLIST_FILE = AFSBackgrounder/resource/Info.plist;
 				INSTALL_PATH = "$(HOME)/Applications";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
@@ -946,6 +951,7 @@
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INFOPLIST_FILE = AFSBackgrounder/resource/Info.plist;
 				INSTALL_PATH = "$(HOME)/Applications";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
@@ -970,6 +976,7 @@
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INSTALL_PATH = "$(HOME)/bin";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
@@ -992,6 +999,7 @@
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INSTALL_PATH = "$(HOME)/bin";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
@@ -1016,6 +1024,7 @@
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INSTALL_PATH = "$(HOME)/bin";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
@@ -1038,6 +1047,7 @@
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
 				INSTALL_PATH = "$(HOME)/bin";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				OTHER_LDFLAGS = (
 					"-framework",
 					Foundation,
diff --git a/src/platform/DARWIN/AFSPreference/PListManager.h b/src/platform/DARWIN/AFSPreference/PListManager.h
index 44f90bffba..1284ffab14 100644
--- a/src/platform/DARWIN/AFSPreference/PListManager.h
+++ b/src/platform/DARWIN/AFSPreference/PListManager.h
@@ -75,12 +75,6 @@
  @discussion <#(comprehensive description)#>
 */ 
 +(void) launchctlCommand:(BOOL)enable userDomain:(BOOL)userDomain option:(NSArray*)option plistName:(NSString*)plistName;
-/*!
- @method     launchctlCommand
- @abstract   exec the launchctl command on a particular plist job
- @discussion <#(comprehensive description)#>
- */
-+(void) launchctlStringCommandAuth:(NSString*)operation option:(NSArray*)option plistName:(NSString*)plistName helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef;
 /*!
  @method     launchdJobState
  @abstract   check is a job has been submitted to launchd
diff --git a/src/platform/DARWIN/AFSPreference/PListManager.m b/src/platform/DARWIN/AFSPreference/PListManager.m
index 977f96236a..e049b2912f 100644
--- a/src/platform/DARWIN/AFSPreference/PListManager.m
+++ b/src/platform/DARWIN/AFSPreference/PListManager.m
@@ -314,31 +314,6 @@
 		  arguments:argument];
 }
 
-// -------------------------------------------------------------------------------
-//  launchctlCommand:
-// -------------------------------------------------------------------------------
-+(void) launchctlStringCommandAuth:(NSString *)operation
-			    option:(NSArray *)option
-			 plistName:(NSString *)plistName
-			    helper:(NSString *)helper
-		       withAuthRef:(AuthorizationRef)authRef
-{
-	NSMutableArray *argument = [NSMutableArray array];
-
-	//set the load unload
-	[argument addObject:operation];
-
-	//if there are load the user custom option
-	if(option) [argument addObjectsFromArray:option];
-
-	//construct the path
-	[argument addObject: plistName];
-
-	//exec the command
-	[TaskUtil executeTaskWithAuth:@"/bin/launchctl"
-		  arguments:argument helper:helper withAuthRef:authRef];
-}
-
 // -------------------------------------------------------------------------------
 //  launchdJobState:
 // -------------------------------------------------------------------------------
diff --git a/src/platform/DARWIN/AFSPreference/TaskUtil.h b/src/platform/DARWIN/AFSPreference/TaskUtil.h
index 459b68eaeb..e3b511c25d 100644
--- a/src/platform/DARWIN/AFSPreference/TaskUtil.h
+++ b/src/platform/DARWIN/AFSPreference/TaskUtil.h
@@ -10,11 +10,15 @@
 #include <Security/Authorization.h>
 #include <Security/AuthorizationTags.h>
 
+#define PRIVHELPER_ID	"org.openafs.privhelper"
+
 @interface TaskUtil : NSObject {
 }
 +(NSString*) searchExecutablePath:(NSString*)unixCommand;
 +(NSString*) executeTaskSearchingPath:(NSString*)unixCommand args:(NSArray*)args;
 +(NSString*) executeTask:(NSString*) taskName arguments:(NSArray *)args;
-+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args authExtForm:(NSData*)auth;
-+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef;
++(int) executePrivTask:(const char *)task filename:(char *)filename data:(char *)data;
++(int) executePrivTask:(const char *)task;
++(int) executePrivTaskBackup:(NSString *)filename;
++(int) executePrivTaskWrite:(NSString *)filename data:(NSString *)data;
 @end
diff --git a/src/platform/DARWIN/AFSPreference/TaskUtil.m b/src/platform/DARWIN/AFSPreference/TaskUtil.m
index 5eaed2dfdf..12d64caf11 100644
--- a/src/platform/DARWIN/AFSPreference/TaskUtil.m
+++ b/src/platform/DARWIN/AFSPreference/TaskUtil.m
@@ -6,6 +6,9 @@
 //  Copyright 2007 INFN - National Institute of Nuclear Physics. All rights reserved.
 //
 
+#import <ServiceManagement/ServiceManagement.h>
+#import <Security/Authorization.h>
+
 #import "TaskUtil.h"
 #import "AuthUtil.h"
 
@@ -72,78 +75,111 @@
 	return [result autorelease];
 }
 
+/**
+ * Perform a task that requires root access via privhelper.
+ *
+ * This performs a task that requires root access, like starting/stopping the
+ * client, or updating configuration files like CellServDB. This function sends
+ * the request to the privhelper daemon, which performs the actual actions for
+ * the task, and waits for a response.
+ *
+ * @param[in] task  The name of the task to perform (e.g. "startup_enable").
+ *		    See privhelper.c:ProcessRequest for what tasks we define.
+ * @param[in] filename	Used for the "backup"/"write" tasks. Don't specify this with
+ *			executePrivTask; use executePrivTaskBackup or
+ *			executePrivTaskWrite instead.
+ * @param[in] data	Used for the "write" task. Don't specify this with
+ *			executePrivTask; use executePrivTaskWrite instead.
+ *
+ * @returns Return status of the task
+ * @retval 0 success
+ * @retval -1 internal error
+ * @retval nonzero The return value of system() of a failed command for the
+ *                 task.
+ */
++(int) executePrivTask:(const char *)task filename:(char *)filename data:(char *)data {
+    int status = -1;
 
-// -------------------------------------------------------------------------------
-//  executeTask:
-// -------------------------------------------------------------------------------
-+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef {
-    const char *rootHelperApp = [helper fileSystemRepresentation];
-    OSStatus status;
-    AuthorizationFlags flags = kAuthorizationFlagDefaults;
-    int count = [args count];
-    char **myArguments = calloc(count + 2, sizeof(char *));
-    int i=0;
-
-    myArguments[0] = strdup([taskName UTF8String]);
-    for(i=0;i < count;i++) {
-	const char *string = [[args objectAtIndex:i] UTF8String];
-	if(!string)
-	    break;
-	myArguments[1+i] = strdup(string);
+    OSErr autherr = [[AuthUtil shared] autorize];
+    if (autherr != noErr) {
+	NSLog(@"executePrivTask: Could not get authorization: %d.", autherr);
+	return status;
     }
-    myArguments[1+i] = NULL;
 
-    // should use SMJobBless but we need to sign things...
-    status = AuthorizationExecuteWithPrivileges(authRef, rootHelperApp, flags, myArguments, NULL);
+    AuthorizationExternalForm extForm;
+    AuthorizationRef authRef = [[AuthUtil shared] authorization];
+    if (authRef == NULL) {
+	NSLog(@"executePrivTask: Authorization reference is null.");
+	return status;
+    }
 
-    i = 0;
-    while (myArguments[i] != NULL) {
-        free(myArguments[i]);
-        i++;
+    OSStatus code = AuthorizationMakeExternalForm(authRef, &extForm);
+    if (code != errAuthorizationSuccess) {
+	NSLog(@"executePrivTask: Could not serialize authorization: %d.", code);
+	return status;
     }
 
-    free(myArguments);
+    const uint64_t flags = XPC_CONNECTION_MACH_SERVICE_PRIVILEGED;
+    xpc_connection_t conn = xpc_connection_create_mach_service(PRIVHELPER_ID, NULL, flags);
+    if (conn == NULL) {
+	NSLog(@"executePrivTask: Could not create service connection.");
+	return status;
+    }
+
+    xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
+	NSLog(@"executePrivTask: Received unexpected event.");
+    });
+    xpc_connection_resume(conn);
+
+    xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
+    if (msg == NULL) {
+	NSLog(@"executePrivTask: Could not create XPC message.");
+	xpc_connection_cancel(conn);
+	xpc_release(conn);
+	return status;
+    }
+    xpc_dictionary_set_string(msg, "task", task);
+    xpc_dictionary_set_data(msg, "auth", &extForm, sizeof(extForm));
+    if (filename != NULL) {
+	xpc_dictionary_set_string(msg, "filename", filename);
+    }
+    if (data != NULL) {
+	xpc_dictionary_set_string(msg, "data", data);
+    }
+
+    xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, msg);
+    if (reply == NULL) {
+	NSLog(@"executePrivTask: No reply received for task: %s", task);
+	xpc_release(msg);
+	xpc_connection_cancel(conn);
+	xpc_release(conn);
+	return status;
+    }
+
+    xpc_object_t status_obj = xpc_dictionary_get_value(reply, "status");
+    if (status_obj != NULL && xpc_get_type(status_obj) == XPC_TYPE_INT64) {
+	status = (int)xpc_int64_get_value(status_obj);
+    } else {
+	NSLog(@"executePrivTask: Received invalid reply status for task: %s", task);
+    }
+
+    xpc_release(msg);
+    xpc_release(reply);
+    xpc_connection_cancel(conn);
+    xpc_release(conn);
+
     return status;
 }
 
-+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args authExtForm:(NSData*)auth {
-	NSString *result = nil;
-	int status = 0;
-	NSFileHandle *file = nil;
-	NSDictionary *environment =  [NSDictionary dictionaryWithObjectsAndKeys: @"$PATH:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",@"PATH",nil];
-	
-	NSPipe *pipe = [NSPipe pipe];
-	NSPipe *pipeIn = [NSPipe pipe];
-	NSTask *taskToRun  = [[NSTask alloc] init];
-	
-	[taskToRun setLaunchPath: taskName];
-	[taskToRun setArguments: args];
-	[taskToRun setEnvironment:environment];
-	[taskToRun setStandardOutput: pipe];
-	[taskToRun setStandardInput: pipeIn];
-	file = [pipe fileHandleForReading];
-	//Write to standard in
-	[taskToRun launch];
-	
-	NSFileHandle* taskInput = [[ taskToRun standardInput ] fileHandleForWriting ];
-	[taskInput writeData:auth];
-	[taskToRun waitUntilExit];
-	status = [taskToRun terminationStatus];
-	if (status == 0){
-		NSData *data = [file readDataToEndOfFile];
-		// remove the \n character from unix command
-		if([data length] > 0){
-			NSData *realData = [NSData dataWithBytes:[data bytes] 
-											  length:[data length]-1];
-			
-			[taskToRun release];
-			result = [[NSString alloc] initWithData: realData 
-										   encoding: NSUTF8StringEncoding];
-			[result release];
-		}
-	} else {
-	}
-	
-	return status;
++(int) executePrivTask:(const char *)task {
+    return [self executePrivTask:task filename:NULL data:NULL];
+}
+
++(int) executePrivTaskBackup:(NSString *)filename {
+    return [self executePrivTask:"backup" filename:[filename UTF8String] data:NULL];
+}
+
++(int) executePrivTaskWrite:(NSString *)filename data:(NSString *)data {
+    return [self executePrivTask:"write" filename:[filename UTF8String] data:[data UTF8String]];
 }
 @end
diff --git a/src/platform/DARWIN/AklogAuthPlugin/AklogAuthPlugin.xcodeproj/project.pbxproj b/src/platform/DARWIN/AklogAuthPlugin/AklogAuthPlugin.xcodeproj/project.pbxproj
index 5f9d9d562f..c1db4881a6 100644
--- a/src/platform/DARWIN/AklogAuthPlugin/AklogAuthPlugin.xcodeproj/project.pbxproj
+++ b/src/platform/DARWIN/AklogAuthPlugin/AklogAuthPlugin.xcodeproj/project.pbxproj
@@ -124,6 +124,7 @@
 				GCC_PREFIX_HEADER = AklogAuthPlugin_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = aklog;
 				WRAPPER_EXTENSION = bundle;
 			};
@@ -143,6 +144,7 @@
 				GCC_PREFIX_HEADER = AklogAuthPlugin_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = aklog;
 				WRAPPER_EXTENSION = bundle;
 			};
@@ -159,9 +161,9 @@
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				ONLY_ACTIVE_ARCH = NO;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
 			};
 			name = Debug;
 		};
@@ -175,9 +177,9 @@
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				ONLY_ACTIVE_ARCH = NO;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
 			};
 			name = Release;
 		};
diff --git a/src/platform/DARWIN/Makefile.in b/src/platform/DARWIN/Makefile.in
index 39af83b384..aa0eb93c13 100644
--- a/src/platform/DARWIN/Makefile.in
+++ b/src/platform/DARWIN/Makefile.in
@@ -10,42 +10,31 @@ include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 
-OSXSDK = @OSXSDK@
+XCODEBUILD_FLAGS = @XCODEBUILD_FLAGS@
+XCODEBUILD = xcodebuild $(XCODEBUILD_FLAGS)
 
 .PHONY: all afscell
 
-all: OpenAFS.prefPane afssettings afscell growlagent aklog.bundle
+all: OpenAFS.prefPane afssettings afscell growlagent aklog.bundle PrivilegedHelper
 
 AFSPreference/build/Release/OpenAFS.prefPane: OpenAFS.prefPane
 afscell/build/Release/afscell.bundle: afscell
 afscell/InstallerSections.plist: afscell
 
 OpenAFS.prefPane:
-	@case ${OSXSDK} in \
-	macosx* ) \
-		xcodebuild -sdk ${OSXSDK} -project ${srcdir}/AFSPreference/OpenAFS.xcodeproj SYMDIR=`pwd`/AFSPreference/build;; \
-	* ) \
-		echo Not building AFS prefPane for ${OSXSDK} ;; \
-	esac
+	$(XCODEBUILD) -project ${srcdir}/AFSPreference/OpenAFS.xcodeproj SYMDIR=`pwd`/AFSPreference/build
 
 aklog.bundle:
-	@case ${OSXSDK} in \
-	macosx* ) \
-		xcodebuild -sdk ${OSXSDK} -project ${srcdir}/AklogAuthPlugin/AklogAuthPlugin.xcodeproj SYMDIR=`pwd`/AklogAuthPlugin/build;; \
-	* ) \
-		echo Not building AklogAuthPlugin for ${OSXSDK} ;; \
-	esac
+	$(XCODEBUILD) -project ${srcdir}/AklogAuthPlugin/AklogAuthPlugin.xcodeproj SYMDIR=`pwd`/AklogAuthPlugin/build
 
 growlagent:
 	cd growlagent && $(MAKE) all
 
+PrivilegedHelper: OpenAFS.prefPane
+	cd PrivilegedHelper && $(MAKE) all
+
 afscell:
-	@case ${OSXSDK} in \
-	macosx* ) \
-		xcodebuild -sdk ${OSXSDK} -project ${srcdir}/afscell/afscell.xcodeproj SYMROOT=`pwd`/afscell/build;; \
-	* ) \
-		echo Not building afscell.bundle for ${OSXSDK} ;; \
-	esac
+	$(XCODEBUILD) -project ${srcdir}/afscell/afscell.xcodeproj SYMROOT=`pwd`/afscell/build
 
 afssettings: afssettings.m
 	${CC} ${AFS_CFLAGS} -o afssettings $? -framework Foundation
@@ -53,6 +42,7 @@ afssettings: afssettings.m
 install: \
 	${DESTDIR}${sbindir}/afssettings
 	cd growlagent && $(MAKE) install
+	cd PrivilegedHelper && $(MAKE) install
 
 dest: \
 	${DEST}/etc/afssettings \
@@ -61,6 +51,7 @@ dest: \
 	${DEST}/tools/OpenAFS.prefPane \
 	${DEST}/tools/aklog.bundle
 	cd growlagent && $(MAKE) dest
+	cd PrivilegedHelper && $(MAKE) dest
 
 ${DESTDIR}${sbindir}/afssettings: afssettings
 	${INSTALL} $? $@
@@ -93,3 +84,4 @@ clean:
 	$(RM) -rf afscell/build
 	$(RM) -f *.o core afssettings AFS_component_version_number.c
 	cd growlagent && $(MAKE) clean
+	cd PrivilegedHelper && $(MAKE) clean
diff --git a/src/platform/DARWIN/PrivilegedHelper/.gitignore b/src/platform/DARWIN/PrivilegedHelper/.gitignore
new file mode 100644
index 0000000000..c2a06e907d
--- /dev/null
+++ b/src/platform/DARWIN/PrivilegedHelper/.gitignore
@@ -0,0 +1,7 @@
+# After changing this file, please run
+#     git ls-files -i --exclude-standard
+# to check that you haven't inadvertently ignored any tracked files.
+
+/org.openafs.privhelper
+/privhelper-info.plist
+/privhelper.c
diff --git a/src/platform/DARWIN/PrivilegedHelper/Makefile.in b/src/platform/DARWIN/PrivilegedHelper/Makefile.in
new file mode 100644
index 0000000000..134f064486
--- /dev/null
+++ b/src/platform/DARWIN/PrivilegedHelper/Makefile.in
@@ -0,0 +1,29 @@
+srcdir=@srcdir@
+include @TOP_OBJDIR@/src/config/Makefile.config
+include @TOP_OBJDIR@/src/config/Makefile.pthread
+
+all: org.openafs.privhelper
+
+org.openafs.privhelper: privhelper.c
+	$(CC) -O2 -mmacosx-version-min=10.6 \
+		-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker privhelper-info.plist \
+		-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __launchd_plist -Xlinker privhelper-launchd.plist \
+		-o org.openafs.privhelper privhelper.c -framework Security -framework CoreFoundation
+
+clean:
+	$(RM) -f *.o org.openafs.privhelper
+
+PREFPANE_DIR = ${DEST}/tools/OpenAFS.prefPane
+LAUNCHSERVICES_DIR = $(PREFPANE_DIR)/Contents/Library/LaunchServices
+PRIVHELPER_TARGET = $(LAUNCHSERVICES_DIR)/org.openafs.privhelper
+
+install:
+
+dest: \
+	$(PRIVHELPER_TARGET)
+
+$(PRIVHELPER_TARGET): org.openafs.privhelper
+	-mkdir -p $(LAUNCHSERVICES_DIR)
+	${INSTALL} org.openafs.privhelper $(LAUNCHSERVICES_DIR)
+
+include ../../../config/Makefile.version
diff --git a/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in b/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in
new file mode 100644
index 0000000000..2552c152c5
--- /dev/null
+++ b/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleIdentifier</key>
+	<string>org.openafs.privhelper</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>privhelper</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>SMAuthorizedClients</key>
+	<array>
+	    <string>identifier "it.infn.lnf.network.openafs" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = @MACOS_TEAM_ID@</string>
+	</array>
+</dict>
+</plist>
diff --git a/src/platform/DARWIN/PrivilegedHelper/privhelper-launchd.plist b/src/platform/DARWIN/PrivilegedHelper/privhelper-launchd.plist
new file mode 100644
index 0000000000..eef495683f
--- /dev/null
+++ b/src/platform/DARWIN/PrivilegedHelper/privhelper-launchd.plist
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Label</key>
+	<string>org.openafs.privhelper</string>
+	<key>MachServices</key>
+	<dict>
+		<key>org.openafs.privhelper</key>
+		<true/>
+	</dict>
+</dict>
+</plist>
diff --git a/src/platform/DARWIN/PrivilegedHelper/privhelper.c.in b/src/platform/DARWIN/PrivilegedHelper/privhelper.c.in
new file mode 100644
index 0000000000..292d70227c
--- /dev/null
+++ b/src/platform/DARWIN/PrivilegedHelper/privhelper.c.in
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2022 Sine Nomine Associates. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Tool that performs privileged operations on behalf of Prefpane.
+ */
+
+#include <syslog.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <spawn.h>
+
+#include <xpc/xpc.h>
+#include <Security/Security.h>
+#include <Security/Authorization.h>
+
+#include <mach/message.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <xpc/xpc.h>
+
+#define LAUNCHCTL   "/bin/launchctl"
+
+#define PRIVHELPER_ID	"org.openafs.privhelper"
+#define AFS_ID		"org.openafs.filesystems.afs"
+#define AFS_PLIST	"/Library/LaunchDaemons/org.openafs.filesystems.afs.plist"
+#define AFS_RC		"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.rc"
+#define CONFIG_PREFIX	"/var/db/openafs"
+
+/*
+ * This is the code signing requirement imposed on anyone that connects to our
+ * XPC service.
+ *
+ * com.apple.systempreferences.legacyLoader.{arm64, arm64} and
+ * com.apple.systempreferences.legacyLoader refer to the "legacyloader"
+ * program that runs our prefpane code (signed by apple).
+ *
+ * it.infn.lnf.network.{openafs, AFSMenuExtra, AFSBackgrounder} refers to our
+ * AFSBackgrounder; the menubar provided by it may talk to privhelper.
+ *
+ * "certificate 1[field.1.2.840.113635.100.6.2.6]" means the code signature is
+ * signed by the Apple Developer ID cert authority.
+ *
+ * "certificate leaf[field.1.2.840.113635.100.6.1.13]" means the code is a
+ * Developer ID application.
+ *
+ * "certificate leaf[subject.OU] = @MACOS_TEAM_ID@" means the code was signed
+ * by us.
+ */
+#define CLI_SIGNATURES	"((identifier \"com.apple.systempreferences.legacyLoader.x86_64\" and anchor apple) or " \
+			 "(identifier \"com.apple.systempreferences.legacyLoader.arm64\" and anchor apple) or " \
+			 "(identifier \"com.apple.systempreferences.legacyLoader\" and anchor apple) or " \
+			 "(identifier \"it.infn.lnf.network.openafs\" and anchor apple generic and " \
+			  "certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and " \
+			  "certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and " \
+			  "certificate leaf[subject.OU] = @MACOS_TEAM_ID@) or " \
+			 "(identifier \"it.infn.lnf.network.AFSMenuExtra\" and anchor apple generic and " \
+			  "certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and " \
+			  "certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and " \
+			  "certificate leaf[subject.OU] = @MACOS_TEAM_ID@) or " \
+			 "(identifier \"it.infn.lnf.network.AFSBackgrounder\" and anchor apple generic and " \
+			  "certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and " \
+			  "certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and " \
+			  "certificate leaf[subject.OU] = @MACOS_TEAM_ID@))"
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+/* macOS 12.0 introduced xpc_connection_set_peer_code_signing_requirement(). */
+# define HAVE_XPC_CONNECTION_SET_PEER_CODE_SIGNING_REQUIREMENT
+#endif
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
+/* macOS 11.0 introduced SecCodeCreateWithXPCMessage(). */
+# define HAVE_SECCODECREATEWITHXPCMESSAGE
+#endif
+
+static void
+mem_error(void)
+{
+    syslog(LOG_ERR, "%s: Memory alloc failed", PRIVHELPER_ID);
+}
+
+#if !defined(HAVE_SECCODECREATEWITHXPCMESSAGE)
+/*
+ * We need xpc_dictionary_get_audit_token() to implement our own version of
+ * SecCodeCreateWithXPCMessage(). This isn't declared in public headers, but we
+ * can use it if we declare it ourselves.
+ */
+extern void xpc_dictionary_get_audit_token(xpc_object_t, audit_token_t *);
+
+/*
+ * Our own version of SecCodeCreateWithXPCMessage(), implemented in terms of
+ * xpc_dictionary_get_audit_token() and SecCodeCopyGuestWithAttributes().
+ *
+ * This gets the SecCodeRef of the peer that sent us the XPC message 'event',
+ * and returns it in *a_codeRef on success.
+ */
+static OSStatus
+SecCodeCreateWithXPCMessage(xpc_object_t event, SecCSFlags secflags, SecCodeRef *a_codeRef)
+{
+    OSStatus status;
+    audit_token_t auditToken;
+    CFDataRef tokenData = NULL;
+    CFDictionaryRef attr = NULL;
+
+    xpc_dictionary_get_audit_token(event, &auditToken);
+
+    tokenData = CFDataCreate(NULL, (const UInt8 *)&auditToken, sizeof(auditToken));
+    if (tokenData == NULL) {
+	mem_error();
+	status = errSecAllocate;
+	goto done;
+    }
+
+    const void *keys[] = {
+	kSecGuestAttributeAudit
+    };
+    const void *values[] = {
+	tokenData
+    };
+    attr = CFDictionaryCreate(NULL, keys, values, 1,
+			      &kCFTypeDictionaryKeyCallBacks,
+			      &kCFTypeDictionaryValueCallBacks);
+    if (attr == NULL) {
+	mem_error();
+	status = errSecAllocate;
+	goto done;
+    }
+
+    status = SecCodeCopyGuestWithAttributes(NULL, attr, secflags, a_codeRef);
+
+ done:
+    if (attr != NULL) {
+	CFRelease(attr);
+    }
+    if (tokenData != NULL) {
+	CFRelease(tokenData);
+    }
+
+    return status;
+}
+#endif /* !HAVE_SECCODECREATEWITHXPCMESSAGE */
+
+static int
+RunCommand(int log_failure, const char *arg1, const char *arg2,
+	   const char *arg3, const char *arg4)
+{
+    extern char **environ;
+    pid_t pid;
+    int code;
+    int status;
+    const char *argv[] = {
+	arg1, arg2, arg3, arg4, NULL
+    };
+
+    code = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
+    if (code != 0) {
+	syslog(LOG_ERR, "%s: Failed to execute %s, error %d", PRIVHELPER_ID,
+	       argv[0], code);
+	return -1;
+    }
+
+    code = waitpid(pid, &status, 0);
+    if (code <= 0) {
+	syslog(LOG_ERR, "%s: waitpid for %s failed, error %d/%d",
+	       PRIVHELPER_ID, argv[0], code, errno);
+	return -1;
+    }
+
+    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+	/* Command exited successfully. */
+	return 0;
+    }
+
+    if (log_failure) {
+	syslog(LOG_WARNING, "%s: Command %s failed, status %d",
+	       PRIVHELPER_ID, argv[0], status);
+    }
+
+    return status;
+}
+
+/*
+ * To make extra sure we don't accidentally write to some other file on the
+ * system, check any filename we're given against a specific list of files. If
+ * the filename we're given isn't one of these, refuse to do anything.
+ */
+static int
+check_filename(const char *filename)
+{
+    const char *allowlist[] = {
+	"/etc/cacheinfo",
+	"/etc/config/afs.conf",
+	"/etc/config/afsd.options",
+	"/etc/ThisCell",
+	"/etc/CellServDB",
+	"/etc/TheseCells",
+    };
+    int allowlist_len = sizeof(allowlist) / sizeof(allowlist[0]);
+    int fname_i;
+
+    for (fname_i = 0; fname_i < allowlist_len; fname_i++) {
+	if (strcmp(filename, allowlist[fname_i]) == 0) {
+	    return 0;
+	}
+    }
+
+    return -1;
+}
+
+/*
+ * Translate the given 'filename' (e.g., "/etc/ThisCell") into the full path to
+ * the file on disk.
+ */
+static char *
+GetFullPath(const char *task, const char *filename)
+{
+    int code;
+    char *path;
+
+    code = check_filename(filename);
+    if (code != 0) {
+	syslog(LOG_WARNING, "%s: Task '%s' got invalid filename '%s'",
+	       PRIVHELPER_ID, task, filename);
+	return NULL;
+    }
+
+    code = asprintf(&path, "%s%s", CONFIG_PREFIX, filename);
+    if (code < 0) {
+	mem_error();
+	return NULL;
+    }
+
+    return path;
+}
+
+/*
+ * Copies "filename" to "filename.afscommander_bk".
+ */
+static int
+BackupFile(const char *filename)
+{
+    int code;
+    char *src_path = NULL;
+    char *dest_path = NULL;
+
+    src_path = GetFullPath("backup", filename);
+    if (src_path == NULL) {
+	code = -1;
+	goto done;
+    }
+
+    code = asprintf(&dest_path, "%s.afscommander_bk", src_path);
+    if (code < 0) {
+	dest_path = NULL;
+	mem_error();
+	goto done;
+    }
+
+    code = RunCommand(1, "/bin/cp", "-n", src_path, dest_path);
+    if (code != 0) {
+	goto done;
+    }
+
+ done:
+    free(src_path);
+    free(dest_path);
+    return code;
+}
+
+/*
+ * Writes the given "data" into "filename".
+ */
+static int
+WriteFile(const char *filename, const char *data)
+{
+    int code;
+    char *path = NULL;
+    char *tmp_path = NULL;
+    FILE *fh = NULL;
+
+    path = GetFullPath("write", filename);
+    if (path == NULL) {
+	goto error;
+    }
+
+    code = asprintf(&tmp_path, "%s.tmp", path);
+    if (code < 0) {
+	tmp_path = NULL;
+	mem_error();
+	goto error;
+    }
+
+    fh = fopen(tmp_path, "w");
+    if (fh == NULL) {
+	code = errno;
+	syslog(LOG_WARNING, "%s: Cannot open %s for writing, errno %d",
+	       PRIVHELPER_ID, tmp_path, code);
+	goto error;
+    }
+
+    if (fputs(data, fh) == EOF) {
+	syslog(LOG_ERR, "%s: Error writing to %s", PRIVHELPER_ID, tmp_path);
+	goto error;
+    }
+
+    if (fclose(fh) == EOF) {
+	syslog(LOG_ERR, "%s: Error closing %s", PRIVHELPER_ID, tmp_path);
+	goto error;
+    }
+    fh = NULL;
+
+    code = RunCommand(1, "/usr/sbin/chown", "root:wheel", tmp_path, NULL);
+    if (code != 0) {
+	goto done;
+    }
+
+    code = RunCommand(1, "/bin/mv", "-f", tmp_path, path);
+
+ done:
+    free(path);
+    free(tmp_path);
+    if (fh != NULL) {
+	fclose(fh);
+    }
+    return code;
+
+ error:
+    code = -1;
+    goto done;
+}
+
+/**
+ * Run the requested privileged task.
+ *
+ * We implement the following tasks:
+ *
+ * - startup_enable: Run "launchctl load" to configure the OpenAFS client to
+ *   run at startup.
+ *
+ * - startup_disable: Run "launchctl unload" to configure the OpenAFS client to
+ *   not run at startup.
+ *
+ * - startup_check: Run "launchctl list" to check whether OpenAFS is configured
+ *   to run at startup. If it is, return 0; otherwise, return nonzero.
+ *
+ * - afsd_start: Run "afs.rc start" to start the OpenAFS client.
+ *
+ * - afsd_stop: Run "afs.rc stop" to stop the OpenAFS client.
+ *
+ * - backup: Make a backup copy of the configuration file named in the argument
+ *   "filename". This copies file "X" to "X.afscommander_bk".
+ *
+ * - write: Write data to a given file. The filename is given in the argument
+ *   "filename"; the data to write is in the argument "data".
+ *
+ * @param[in] task	The name of the requested task.
+ * @param[in] event	The XPC dictionary containing other task-specific
+ *			arguments.
+ *
+ * @returns Return status of the task
+ * @retval 0 success
+ * @retval -1 internal error
+ * @retval nonzero The return value of system() of a failed command for the
+ *                 task.
+ */
+static int
+ProcessRequest(const char *task, xpc_object_t event)
+{
+    if (strcmp(task, "startup_enable") == 0) {
+	return RunCommand(1, LAUNCHCTL, "load", "-w", AFS_PLIST);
+
+    } else if (strcmp(task, "startup_disable") == 0) {
+	return RunCommand(1, LAUNCHCTL, "unload", "-w", AFS_PLIST);
+
+    } else if (strcmp(task, "startup_check") == 0) {
+	return RunCommand(0, LAUNCHCTL, "list", AFS_ID, NULL);
+
+    } else if (strcmp(task, "afsd_start") == 0) {
+	return RunCommand(1, AFS_RC, "start", NULL, NULL);
+
+    } else if (strcmp(task, "afsd_stop") == 0) {
+	return RunCommand(1, AFS_RC, "stop", NULL, NULL);
+
+    } else if (strcmp(task, "backup") == 0) {
+	const char *filename = xpc_dictionary_get_string(event, "filename");
+	if (filename == NULL) {
+	    syslog(LOG_WARNING, "%s: Task backup missing filename", PRIVHELPER_ID);
+	    return -1;
+	}
+	return BackupFile(filename);
+
+    } else if (strcmp(task, "write") == 0) {
+	const char *filename;
+	const char *data;
+
+	filename = xpc_dictionary_get_string(event, "filename");
+	if (filename == NULL) {
+	    syslog(LOG_WARNING, "%s: Task 'write' missing filename", PRIVHELPER_ID);
+	    return -1;
+	}
+
+	data = xpc_dictionary_get_string(event, "data");
+	if (data == NULL) {
+	    syslog(LOG_WARNING, "%s: Task 'write' missing data", PRIVHELPER_ID);
+	    return -1;
+	}
+
+	return WriteFile(filename, data);
+    }
+
+    syslog(LOG_WARNING, "%s: Received unknown task '%s'", PRIVHELPER_ID, task);
+
+    return -1;
+}
+
+/*
+ * Is the task for the given event authorized to run commands as root? Check
+ * the AuthorizationExternalForm in event["auth"], and see if it is authorized
+ * for running commands as root.
+ *
+ * Returns 1 if the task is authorized, 0 otherwise.
+ */
+static int
+IsEventAuthorized(xpc_object_t event)
+{
+    OSStatus status;
+    int authorized = 0;
+
+    const void *auth_data;
+    size_t data_size = 0;
+
+    AuthorizationRef authRef;
+    AuthorizationExternalForm extForm;
+
+    /*
+     * Check that the given authRef has the kAuthorizationRightExecute right
+     * (the right to execute commands as root).
+     */
+    AuthorizationItem authItems[] = {
+	{ kAuthorizationRightExecute, 0, NULL, 0 }
+    };
+    AuthorizationRights rights = {
+	1, authItems
+    };
+
+    auth_data = xpc_dictionary_get_data(event, "auth", &data_size);
+    if (auth_data == NULL || data_size != sizeof(AuthorizationExternalForm)) {
+	syslog(LOG_WARNING, "%s: Authorization not found.", PRIVHELPER_ID);
+	return authorized;
+    }
+
+    memcpy(&extForm, auth_data, sizeof(extForm));
+
+    status = AuthorizationCreateFromExternalForm(&extForm, &authRef);
+    if (status != errAuthorizationSuccess) {
+	syslog(LOG_ERR, "%s: Deserialization failed.\n", PRIVHELPER_ID);
+	return authorized;
+    }
+
+    status = AuthorizationCopyRights(authRef, &rights,
+				     kAuthorizationEmptyEnvironment,
+				     kAuthorizationFlagDefaults, NULL);
+    AuthorizationFree(authRef, kAuthorizationFlagDefaults);
+    if (status == errAuthorizationSuccess) {
+	authorized = 1;
+    }
+    return authorized;
+}
+
+#if defined(HAVE_XPC_CONNECTION_SET_PEER_CODE_SIGNING_REQUIREMENT)
+
+/*
+ * Set the given code signing requirements for the given service.
+ *
+ * 'req_cf' is the requirement string as a CFStringRef.
+ */
+static int
+SetCodeReq(xpc_connection_t service, CFStringRef req_cf)
+{
+    const char *req_c = CFStringGetCStringPtr(req_cf, kCFStringEncodingUTF8);
+    if (req_c == NULL) {
+	syslog(LOG_ERR, "%s: Could not convert CFStringRef.", PRIVHELPER_ID);
+	return -1;
+    }
+    if (xpc_connection_set_peer_code_signing_requirement(service, req_c) != 0) {
+	syslog(LOG_ERR, "%s: Could not set peer code signing requirement.", PRIVHELPER_ID);
+	return -1;
+    }
+    return 0;
+}
+
+/*
+ * Is the xpc conn for the given event authorized to connect at all? This
+ * checks whether the peer satisfies the code signing requirements given in
+ * SetCodeReq().
+ *
+ * Returns 1 if the connection is authorized, 0 otherwise.
+ */
+static int
+IsConnAuthorized(xpc_object_t event)
+{
+    /*
+     * xpc_connection_set_peer_code_signing_requirement() ensures that all
+     * incoming connections and messages are validated against the given
+     * code-signing requirement. So we don't need to do any checks ourselves.
+     */
+    return 1;
+}
+
+#else /* HAVE_XPC_CONNECTION_SET_PEER_CODE_SIGNING_REQUIREMENT */
+
+/* Our compiled code security requirements, which we use to check every
+ * connection that comes in. */
+static SecRequirementRef secRequirementRef;
+
+static int
+SetCodeReq(xpc_connection_t service, CFStringRef req_cf)
+{
+    OSStatus code;
+    code = SecRequirementCreateWithString(req_cf,
+					  kSecCSDefaultFlags,
+					  &secRequirementRef);
+    if (code != errSecSuccess || secRequirementRef == NULL) {
+	syslog(LOG_ERR, "%s: Could not compile code sec requirement.", PRIVHELPER_ID);
+	return -1;
+    }
+    return 0;
+}
+
+static int
+IsConnAuthorized(xpc_object_t event)
+{
+    SecCodeRef codeRef = NULL;
+    OSStatus status;
+
+    status = SecCodeCreateWithXPCMessage(event, kSecCSDefaultFlags, &codeRef);
+    if (status != errSecSuccess || codeRef == NULL) {
+	return 0;
+    }
+
+    status = SecCodeCheckValidity(codeRef, kSecCSDefaultFlags, secRequirementRef);
+    CFRelease(codeRef);
+    if (status != errSecSuccess) {
+	return 0;
+    }
+
+    return 1;
+}
+
+#endif /* HAVE_XPC_CONNECTION_SET_PEER_CODE_SIGNING_REQUIREMENT */
+
+static void
+XPCEventHandler(xpc_connection_t conn, xpc_object_t event)
+{
+    int status;
+    xpc_type_t type;
+    xpc_object_t reply;
+    xpc_connection_t client;
+    const char *task;
+
+    type = xpc_get_type(event);
+    if (type == XPC_TYPE_ERROR) {
+	syslog(LOG_WARNING, "%s: Could not get event type.", PRIVHELPER_ID);
+	return;
+    }
+    if (!IsConnAuthorized(event)) {
+	syslog(LOG_WARNING, "%s: Connection not authorized.", PRIVHELPER_ID);
+	return;
+    }
+    if (!IsEventAuthorized(event)) {
+	syslog(LOG_WARNING, "%s: Event not authorized.", PRIVHELPER_ID);
+	return;
+    }
+
+    task = xpc_dictionary_get_string(event, "task");
+    if (task == NULL) {
+	syslog(LOG_WARNING, "%s: Could not get event task.", PRIVHELPER_ID);
+	return;
+    }
+
+    status = ProcessRequest(task, event);
+
+    reply = xpc_dictionary_create_reply(event);
+    if (reply == NULL) {
+	syslog(LOG_ERR, "%s: Could not create reply for event.", PRIVHELPER_ID);
+	return;
+    }
+
+    xpc_dictionary_set_int64(reply, "status", status);
+
+    client = xpc_dictionary_get_remote_connection(event);
+    if (client == NULL) {
+	syslog(LOG_ERR, "%s: No remote connection for event.", PRIVHELPER_ID);
+	xpc_release(reply);
+	return;
+    }
+
+    xpc_connection_send_message(client, reply);
+    xpc_release(reply);
+}
+
+static void
+XPCConnectionHandler(xpc_connection_t conn)
+{
+    xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
+	XPCEventHandler(conn, event);
+    });
+    xpc_connection_resume(conn);
+}
+
+int
+main(int argc, char *argv[])
+{
+    xpc_connection_t service;
+    dispatch_queue_t targetq = dispatch_get_main_queue();
+    uint64_t flags = XPC_CONNECTION_MACH_SERVICE_LISTENER;
+
+    service = xpc_connection_create_mach_service(PRIVHELPER_ID, targetq, flags);
+    if (service == NULL) {
+	syslog(LOG_ERR, "%s: Could not create service.", PRIVHELPER_ID);
+	exit(EXIT_FAILURE);
+    }
+
+    if (SetCodeReq(service, CFSTR(CLI_SIGNATURES)) != 0) {
+	xpc_release(service);
+	exit(EXIT_FAILURE);
+    }
+
+    xpc_connection_set_event_handler(service, ^(xpc_object_t conn) {
+	XPCConnectionHandler(conn);
+    });
+    xpc_connection_resume(service);
+
+    dispatch_main();
+    xpc_release(service);
+
+    return EXIT_SUCCESS;
+}
diff --git a/src/platform/DARWIN/afscell/afscell.xcodeproj/project.pbxproj b/src/platform/DARWIN/afscell/afscell.xcodeproj/project.pbxproj
index ffefcc228e..31aace9713 100644
--- a/src/platform/DARWIN/afscell/afscell.xcodeproj/project.pbxproj
+++ b/src/platform/DARWIN/afscell/afscell.xcodeproj/project.pbxproj
@@ -224,6 +224,7 @@
 				GCC_PREFIX_HEADER = afscell_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = afscell;
 				WRAPPER_EXTENSION = bundle;
 				ZERO_LINK = YES;
@@ -241,6 +242,7 @@
 				GCC_PREFIX_HEADER = afscell_Prefix.pch;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PRODUCT_NAME = afscell;
 				WRAPPER_EXTENSION = bundle;
 			};
@@ -251,6 +253,7 @@
 			buildSettings = {
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PREBINDING = NO;
 			};
 			name = Debug;
@@ -261,6 +264,7 @@
 				GCC_ENABLE_OBJC_GC = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				"OTHER_CFLAGS[arch=*]" = "-Werror=objc-method-access";
 				PREBINDING = NO;
 			};
 			name = Release;
diff --git a/src/ptserver/ptserver.c b/src/ptserver/ptserver.c
index 9cfd8fe4f6..a133ec8088 100644
--- a/src/ptserver/ptserver.c
+++ b/src/ptserver/ptserver.c
@@ -250,6 +250,7 @@ main(int argc, char **argv)
     afs_int32 numClasses;
     int lwps = 3;
     char clones[MAXHOSTSPERCELL];
+    char hoststr[16];
     afs_uint32 host = htonl(INADDR_ANY);
     struct cmd_syndesc *opts;
     struct cmd_item *list;
@@ -545,14 +546,17 @@ main(int argc, char **argv)
 	}
 	if (ccode == 1) {
 	    host = SHostAddrs[0];
-	    /* the following call is idempotent so if/when it gets called
-	     * again by the ubik init stuff, it doesn't really matter
-	     * -- klm
-	     */
-	    rx_InitHost(host, htons(AFSCONF_PROTPORT));
 	}
     }
 
+    ViceLog(0, ("ptserver binding rx to %s:%d\n",
+            afs_inet_ntoa_r(host, hoststr), AFSCONF_PROTPORT));
+    code = rx_InitHost(host, htons(AFSCONF_PROTPORT));
+    if (code < 0) {
+	ViceLog(0, ("ptserver: Rx init failed: %d\n", code));
+	PT_EXIT(1);
+    }
+
     /* Disable jumbograms */
     rx_SetNoJumbo();
 
diff --git a/src/roken/Makefile.in b/src/roken/Makefile.in
index e6daa6f5f5..c16206fa6f 100644
--- a/src/roken/Makefile.in
+++ b/src/roken/Makefile.in
@@ -22,23 +22,26 @@ HEADERS = ${TOP_INCDIR}/base64.h \
 
 UPSTREAM = $(TOP_SRCDIR)/external/heimdal/roken
 
+@SHARED_ONLY@SHARED_LIBS = librokenafs.la
+@SHARED_ONLY@SHARED_SHLIBS_TOP = $(TOP_LIBDIR)/librokenafs.$(SHLIB_SUFFIX)
+
 # TOP_LIBDIR is a convenient place where we can ensure that both the shared
 # and static versions of the library will end up (I'm looking at you, AIX).
 # Otherwise we could just use .libs directly, since only openafs-internal
 # tools will be linking roken from that directory.
-all: $(ROKEN_HEADERS) $(HEADERS) $(TOP_LIBDIR)/librokenafs.$(SHLIB_SUFFIX) \
+all: $(ROKEN_HEADERS) $(HEADERS) $(SHARED_SHLIBS_TOP) \
 	$(TOP_LIBDIR)/librokenafs.a
 
 buildtools: $(ROKEN_HEADERS) $(HEADERS)
 
-install: librokenafs.la librokenafs.a
-	$(LT_INSTALL_DATA) librokenafs.la $(DESTDIR)$(libdir)/librokenafs.la
-	$(RM) $(DESTDIR)$(libdir)/librokenafs.la
+install: $(SHARED_LIBS) librokenafs.a
+	@SHARED_ONLY@$(LT_INSTALL_DATA) librokenafs.la $(DESTDIR)$(libdir)/librokenafs.la
+	@SHARED_ONLY@$(RM) $(DESTDIR)$(libdir)/librokenafs.la
 	$(INSTALL_DATA) librokenafs.a $(DESTDIR)$(libdir)/librokenafs.a
 
-dest: librokenafs.la librokenafs.a
-	$(LT_INSTALL_DATA) librokenafs.la $(DEST)/lib/librokenafs.la
-	$(RM) $(DEST)/lib/librokenafs.la
+dest: $(SHARED_LIBS) librokenafs.a
+	@SHARED_ONLY@$(LT_INSTALL_DATA) librokenafs.la $(DEST)/lib/librokenafs.la
+	@SHARED_ONLY@$(RM) $(DEST)/lib/librokenafs.la
 	$(INSTALL_DATA) librokenafs.a $(DEST)/lib/librokenafs.a
 
 clean:
diff --git a/src/rx/FBSD/rx_knet.c b/src/rx/FBSD/rx_knet.c
index 47443eb593..5ea42a8be2 100644
--- a/src/rx/FBSD/rx_knet.c
+++ b/src/rx/FBSD/rx_knet.c
@@ -108,8 +108,7 @@ osi_StopListener(void)
     bzero(&taddr, sizeof(taddr));
     taddr.sin_len = sizeof(struct sockaddr_in);
     taddr.sin_family = AF_INET;
-    taddr.sin_port = rx_port;
-    taddr.sin_addr.s_addr = htonl(0x7f000001);	/* no place like localhost */
+    rxi_GetLocalAddr(&taddr);
     bzero(&dvec, sizeof(dvec));
     dvec.iov_base = &c;
     dvec.iov_len = 1;
diff --git a/src/rx/SOLARIS/rx_knet.c b/src/rx/SOLARIS/rx_knet.c
index 74339375fb..99280e278a 100644
--- a/src/rx/SOLARIS/rx_knet.c
+++ b/src/rx/SOLARIS/rx_knet.c
@@ -451,8 +451,7 @@ osi_FreeSocket(osi_socket asocket)
     AFS_STATCNT(osi_FreeSocket);
 
     taddr.sin_family = AF_INET;
-    taddr.sin_port = rx_port;
-    taddr.sin_addr.s_addr = htonl(0x7f000001);
+    rxi_GetLocalAddr(&taddr);
 
     dvec.iov_base = &c;
     dvec.iov_len = 1;
diff --git a/src/rx/rx.c b/src/rx/rx.c
index af717d8887..5048d02cb4 100644
--- a/src/rx/rx.c
+++ b/src/rx/rx.c
@@ -222,6 +222,9 @@ struct opr_queue rx_incomingCallQueue;
  * calls to process */
 struct opr_queue rx_idleServerQueue;
 
+/* Host address we're bound to, in NBO. */
+afs_uint32 rx_host;
+
 #if !defined(offsetof)
 #include <stddef.h>		/* for definition of offsetof() */
 #endif
@@ -591,6 +594,7 @@ rx_InitHost(u_int host, u_int port)
 #else
     osi_GetTime(&tv);
 #endif
+    rx_host = host;
     if (port) {
 	rx_port = port;
     } else {
@@ -2092,6 +2096,7 @@ rx_GetCall(int tno, struct rx_service *cur_service, osi_socket * socketp)
 	    opr_queue_Remove(&call->entry);
 	    MUTEX_EXIT(&rx_serverPool_lock);
 	    MUTEX_ENTER(&call->lock);
+	    CLEAR_CALL_QUEUE_LOCK(call);
 
 	    if (call->flags & RX_CALL_WAIT_PROC) {
 		call->flags &= ~RX_CALL_WAIT_PROC;
@@ -2110,7 +2115,6 @@ rx_GetCall(int tno, struct rx_service *cur_service, osi_socket * socketp)
 		|| opr_queue_First(&call->rq, struct rx_packet, entry)->header.seq != 1)
 		rxi_SendAck(call, 0, 0, RX_ACK_DELAY, 0);
 
-	    CLEAR_CALL_QUEUE_LOCK(call);
 	    break;
 	} else {
 	    /* If there are no eligible incoming calls, add this process
@@ -2260,6 +2264,7 @@ rx_GetCall(int tno, struct rx_service *cur_service, osi_socket * socketp)
 
     if (call) {
 	opr_queue_Remove(&call->entry);
+	CLEAR_CALL_QUEUE_LOCK(call);
 	/* we can't schedule a call if there's no data!!! */
 	/* send an ack if there's no data, if we're missing the
 	 * first packet, or we're missing something between first
@@ -3069,7 +3074,7 @@ rxi_FindPeer(afs_uint32 host, u_short port, int create)
     }
     if (!pp) {
 	if (create) {
-	    pp = rxi_AllocPeer();	/* This bzero's *pp */
+	    pp = rxi_AllocPeer();	/* This zeroes *pp */
 	    pp->host = host;	/* set here or in InitPeerParams is zero */
 	    pp->port = port;
 #ifdef AFS_RXERRQ_ENV
@@ -3161,7 +3166,7 @@ rxi_FindConnection(osi_socket socket, afs_uint32 host,
             *unknownService = 1;
 	    return (struct rx_connection *)0;
 	}
-	conn = rxi_AllocConnection();	/* This bzero's the connection */
+	conn = rxi_AllocConnection();	/* This zeroes the connection */
 	MUTEX_INIT(&conn->conn_call_lock, "conn call lock", MUTEX_DEFAULT, 0);
 	MUTEX_INIT(&conn->conn_data_lock, "conn data lock", MUTEX_DEFAULT, 0);
 	CV_INIT(&conn->conn_call_cv, "conn call cv", CV_DEFAULT, 0);
@@ -5008,6 +5013,7 @@ rxi_AttachServerProc(struct rx_call *call,
 	    if (opr_queue_IsOnQueue(&call->entry)) {
 		opr_queue_Remove(&call->entry);
 	    }
+	    CLEAR_CALL_QUEUE_LOCK(call);
 	}
 	call->state = RX_STATE_ACTIVE;
 	call->app.mode = RX_MODE_RECEIVING;
@@ -7335,21 +7341,70 @@ rxi_ReapConnections(struct rxevent *unused, void *unused1, void *unused2,
 }
 
 
-/* rxs_Release - This isn't strictly necessary but, since the macro name from
- * rx.h is sort of strange this is better.  This is called with a security
- * object before it is discarded.  Each connection using a security object has
- * its own refcount to the object so it won't actually be freed until the last
- * connection is destroyed.
- *
- * This is the only rxs module call.  A hold could also be written but no one
- * needs it. */
-
+/*
+ * rxs_Release - This is called with a security object before it is discarded.
+ * Each connection using a security object has its own refcount to the object
+ * so it won't actually be freed until the last connection is destroyed.
+ */
 int
 rxs_Release(struct rx_securityClass *aobj)
 {
     return RXS_Close(aobj);
 }
 
+static_inline rx_atomic_t *
+sc2refCount(struct rx_securityClass *aobj)
+{
+    opr_StaticAssert(sizeof(rx_atomic_t) <= sizeof(aobj->refCount_data));
+    return (rx_atomic_t *)&aobj->refCount_data;
+}
+
+/**
+ * Get a reference to a security object.
+ *
+ * @param[in] aobj  The security object.
+ * @returns The given security object.
+ */
+struct rx_securityClass *
+rxs_Ref(struct rx_securityClass *aobj)
+{
+    rx_atomic_t *refCount = sc2refCount(aobj);
+    rx_atomic_inc(refCount);
+    return aobj;
+}
+
+/**
+ * Puts a reference to a security object.
+ *
+ * This should only be used by securityClass implementations; users of a
+ * security class should use rxs_Release to release a reference to a security
+ * object.
+ *
+ * @param[in] aobj  The security object.
+ * @returns The refcount of the security object (post-decrement).
+ */
+int
+rxs_DecRef(struct rx_securityClass *aobj)
+{
+    rx_atomic_t *refCount = sc2refCount(aobj);
+    return rx_atomic_dec_and_read(refCount);
+}
+
+/**
+ * Set the reference count on a security object.
+ *
+ * This should only be used by securityClass implementations.
+ *
+ * @param[in] aobj  The security object.
+ * @param[in] refs  The refCount to set.
+ */
+void
+rxs_SetRefs(struct rx_securityClass *aobj, int refs)
+{
+    rx_atomic_t *refCount = sc2refCount(aobj);
+    rx_atomic_set(refCount, refs);
+}
+
 void
 rxi_DebugInit(void)
 {
@@ -7450,8 +7505,8 @@ rx_PrintTheseStats(FILE * file, struct rx_statistics *s, int size,
 		size, sizeof(struct rx_statistics));
     }
 
-    fprintf(file, "rx stats: free packets %d, allocs %d, ", (int)freePackets,
-	    s->packetRequests);
+    fprintf(file, "rx stats: free packets %u, allocs %u, ",
+	    (unsigned int)freePackets, s->packetRequests);
 
     if (version >= RX_DEBUGI_VERSION_W_NEWPACKETTYPES) {
 	fprintf(file, "alloc-failures(rcv %u/%u,send %u/%u,ack %u)\n",
@@ -9538,3 +9593,25 @@ rxi_NetSend(osi_socket socket, void *addr, struct iovec *dvec,
     return ESHUTDOWN;
 #endif
 }
+
+/*
+ * Get our local address (the address to use to send packets to ourselves). If
+ * rx_InitHost() was given a host to bind to, we use that host address;
+ * otherwise use 127.0.0.1. The port is the port we are actually bound to.
+ *
+ * @param[out] sin  host/port populated with the address to use
+ *
+ * @pre rx_InitHost() called successfully
+ */
+void
+rxi_GetLocalAddr(struct sockaddr_in *sin)
+{
+    if (rx_host != 0) {
+	/* If we're bound to an address, use that address as localhost. */
+	sin->sin_addr.s_addr = rx_host;
+    } else {
+	/* Otherwise, use 127.0.0.1. */
+	sin->sin_addr.s_addr = htonl(0x7f000001);
+    }
+    sin->sin_port = rx_port;
+}
diff --git a/src/rx/rx.h b/src/rx/rx.h
index f9a387db63..35ade63b41 100644
--- a/src/rx/rx.h
+++ b/src/rx/rx.h
@@ -603,7 +603,13 @@ struct rx_securityClass {
 	int (*op_Spare3) (void);
     } *ops;
     void *privateData;
-    int refCount;
+
+    /*
+     * Don't use this field directly. To manipulate the refcount, callers
+     * should use rxs_Ref()/rxs_Release(), and (for security class
+     * implementations only) rxs_DecRef()/rxs_SetRefs().
+     */
+    char refCount_data[8];
 };
 
 #define RXS_OP(obj,op,args) ((obj && (obj->ops->op_ ## op)) ? \
diff --git a/src/rx/rx_atomic.h b/src/rx/rx_atomic.h
index 29790411d6..789f7bb8e9 100644
--- a/src/rx/rx_atomic.h
+++ b/src/rx/rx_atomic.h
@@ -318,7 +318,7 @@ rx_atomic_add(rx_atomic_t *atomic, int change) {
 
 static_inline int
 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
-    return __sync_fetch_and_add(&atomic->var, change);
+    return __sync_add_and_fetch(&atomic->var, change);
 }
 
 static_inline void
diff --git a/src/rx/rx_internal.h b/src/rx/rx_internal.h
index 80d80a8ae6..3dacf3811d 100644
--- a/src/rx/rx_internal.h
+++ b/src/rx/rx_internal.h
@@ -17,6 +17,8 @@
 extern rx_atomic_t rx_nWaiting;
 extern rx_atomic_t rx_nWaited;
 
+extern afs_uint32 rx_host;
+
 /* How many times to retry sendmsg()-equivalent calls for AFS_RXERRQ_ENV. */
 #define RXI_SENDMSG_RETRY 8
 
@@ -68,6 +70,7 @@ extern void rxi_WaitforTQBusy(struct rx_call *call);
 #else
 # define rxi_WaitforTQBusy(call)
 #endif
+extern void rxi_GetLocalAddr(struct sockaddr_in *sin);
 
 /* rx_packet.h */
 
diff --git a/src/rx/rx_null.c b/src/rx/rx_null.c
index 809fc67b4b..cda3aa8cf5 100644
--- a/src/rx/rx_null.c
+++ b/src/rx/rx_null.c
@@ -25,7 +25,7 @@
 /* The null security object.  No authentication, no nothing. */
 
 static struct rx_securityOps null_ops;
-static struct rx_securityClass null_object = { &null_ops, 0, 0 };
+static struct rx_securityClass null_object = { &null_ops, 0, {0} };
 
 struct rx_securityClass *
 rxnull_NewServerSecurityObject(void)
diff --git a/src/rx/rx_packet.h b/src/rx/rx_packet.h
index 48736d3f8f..173762af7a 100644
--- a/src/rx/rx_packet.h
+++ b/src/rx/rx_packet.h
@@ -31,20 +31,6 @@
  * and that the offsets are as well.
  */
 
-
-#if !defined(AFS_NT40_ENV)
-# if !defined(AFS_DARWIN_ENV) && !defined(AFS_USR_DARWIN_ENV)   \
-    && !defined(AFS_XBSD_ENV) && !defined(AFS_USR_FBSD_ENV)     \
-    && !defined(AFS_USR_DFBSD_ENV) && !defined(AFS_LINUX_ENV)
-#  include <sys/sysmacros.h>	/* MIN, MAX on most commercial UNIX */
-# endif
-/* Linux 3.7 doesn't have sys/param.h in kernel space, and afs/param.h ensures
- * that MIN and MAX are available for kernel builds. */
-# if !(defined(AFS_LINUX_ENV) && defined(KERNEL))
-#  include <sys/param.h>	/* MIN, MAX elsewhere */
-# endif
-#endif /* !AFS_NT40_ENV */
-
 #define	IPv6_HDR_SIZE		40	/* IPv6 Header */
 #define IPv6_FRAG_HDR_SIZE	 8	/* IPv6 Fragment Header */
 #define UDP_HDR_SIZE             8	/* UDP Header */
diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h
index 6e1ae566c0..76c58d874b 100644
--- a/src/rx/rx_prototypes.h
+++ b/src/rx/rx_prototypes.h
@@ -85,6 +85,9 @@ extern void rxi_CallError(struct rx_call *call, afs_int32 error);
 extern void rx_SetConnSecondsUntilNatPing(struct rx_connection *conn,
 					  afs_int32 seconds);
 extern int rxs_Release(struct rx_securityClass *aobj);
+extern struct rx_securityClass *rxs_Ref(struct rx_securityClass *aobj);
+extern int rxs_DecRef(struct rx_securityClass *aobj);
+extern void rxs_SetRefs(struct rx_securityClass *aobj, int refs);
 #ifndef KERNEL
 extern void rx_PrintTheseStats(FILE * file, struct rx_statistics *s, int size,
 			       afs_int32 freePackets, char version);
diff --git a/src/rx/rx_trace.c b/src/rx/rx_trace.c
index 512491e7c4..9bd6a429ad 100644
--- a/src/rx/rx_trace.c
+++ b/src/rx/rx_trace.c
@@ -150,7 +150,11 @@ main(int argc, char **argv)
     argc--;
     while (argc && **argv == '-') {
 	if (strcmp(*argv, "-trace") == 0) {
-	    strcpy(rxi_tracename, *(++argv));
+	    if (strlcpy(rxi_tracename, *(++argv),
+			sizeof(rxi_tracename)) >= sizeof(rxi_tracename)) {
+		fprintf(stderr, "-trace argument too long\n");
+		exit(1);
+	    }
 	    argc--;
 	} else {
 	    err++;
diff --git a/src/rx/rx_user.c b/src/rx/rx_user.c
index 1effe0a198..619122b8d1 100644
--- a/src/rx/rx_user.c
+++ b/src/rx/rx_user.c
@@ -705,7 +705,7 @@ rxi_InitPeerParams(struct rx_peer *pp)
 
     pp->ifMTU = 0;
     rx_rto_setPeerTimeoutSecs(pp, 2);
-    /* I don't initialize these, because I presume they are bzero'd...
+    /* I don't initialize these, because I presume they are zeroed...
      * pp->burstSize pp->burst pp->burstWait.sec pp->burstWait.usec
      */
 
diff --git a/src/rx/test/testserver.c b/src/rx/test/testserver.c
index deead44641..db5bcf138c 100644
--- a/src/rx/test/testserver.c
+++ b/src/rx/test/testserver.c
@@ -94,8 +94,15 @@ main(argc, argv)
 	else if (strcmp(*argv, "-rxlog") == 0)
 	    rxlog = 1;
 #if defined(RXDEBUG) && !defined(AFS_NT40_ENV)
-	else if (strcmp(*argv, "-trace") == 0)
-	    strcpy(rxi_tracename, *(++argv)), argc--;
+	else if (strcmp(*argv, "-trace") == 0) {
+	    extern char rxi_tracename[80];
+	    argv++;
+	    argc--;
+	    if (strlcpy(rxi_tracename, *argv,
+			sizeof(rxi_tracename)) >= sizeof(rxi_tracename)) {
+		Quit("-trace argument too long");
+	    }
+	}
 #endif
 	else if (strcmp(*argv, "-logstdout") == 0)
 	    logstdout = 1;
diff --git a/src/rx/xdr_len.c b/src/rx/xdr_len.c
index 5de15d010d..9f9fe1ca92 100644
--- a/src/rx/xdr_len.c
+++ b/src/rx/xdr_len.c
@@ -84,26 +84,14 @@ xdrlen_inline(XDR *xdrs, u_int len)
 }
 
 static struct xdr_ops xdrlen_ops = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    /* Windows does not support labeled assigments */
-    xdrlen_getint32,    /* not supported */
-    xdrlen_putint32,    /* serialize an afs_int32 */
-    xdrlen_getbytes,    /* not supported */
-    xdrlen_putbytes,    /* serialize counted bytes */
-    xdrlen_getpos,      /* get offset in the stream */
-    xdrlen_setpos,      /* set offset in the stream */
-    xdrlen_inline,      /* not supported */
-    xdrlen_destroy,     /* destroy stream */
-#else
-    .x_getint32 = xdrlen_getint32,
-    .x_putint32 = xdrlen_putint32,
-    .x_getbytes = xdrlen_getbytes,
-    .x_putbytes = xdrlen_putbytes,
-    .x_getpostn = xdrlen_getpos,
-    .x_setpostn = xdrlen_setpos,
-    .x_inline = xdrlen_inline,
-    .x_destroy = xdrlen_destroy
-#endif
+    AFS_STRUCT_INIT(.x_getint32, xdrlen_getint32), /* not supported */
+    AFS_STRUCT_INIT(.x_putint32, xdrlen_putint32), /* serialize an afs_int32 */
+    AFS_STRUCT_INIT(.x_getbytes, xdrlen_getbytes), /* not supported */
+    AFS_STRUCT_INIT(.x_putbytes, xdrlen_putbytes), /* serialize counted bytes */
+    AFS_STRUCT_INIT(.x_getpostn, xdrlen_getpos),   /* get offset in the stream */
+    AFS_STRUCT_INIT(.x_setpostn, xdrlen_setpos),   /* set offset in the stream */
+    AFS_STRUCT_INIT(.x_inline,	 xdrlen_inline),   /* not supported */
+    AFS_STRUCT_INIT(.x_destroy,	 xdrlen_destroy),  /* destroy stream */
 };
 
 /**
diff --git a/src/rx/xdr_mem.c b/src/rx/xdr_mem.c
index ae849f521b..bd6720505e 100644
--- a/src/rx/xdr_mem.c
+++ b/src/rx/xdr_mem.c
@@ -59,26 +59,14 @@ static afs_int32 *xdrmem_inline(XDR *, u_int);
 static void xdrmem_destroy(XDR *);
 
 static struct xdr_ops xdrmem_ops = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    /* Windows does not support labeled assigments */
-    xdrmem_getint32,    /* deserialize an afs_int32 */
-    xdrmem_putint32,    /* serialize an afs_int32 */
-    xdrmem_getbytes,    /* deserialize counted bytes */
-    xdrmem_putbytes,    /* serialize counted bytes */
-    xdrmem_getpos,      /* get offset in the stream: not supported. */
-    xdrmem_setpos,      /* set offset in the stream: not supported. */
-    xdrmem_inline,      /* prime stream for inline macros */
-    xdrmem_destroy,     /* destroy stream */
-#else
-    .x_getint32 = xdrmem_getint32,
-    .x_putint32 = xdrmem_putint32,
-    .x_getbytes = xdrmem_getbytes,
-    .x_putbytes = xdrmem_putbytes,
-    .x_getpostn = xdrmem_getpos,
-    .x_setpostn = xdrmem_setpos,
-    .x_inline = xdrmem_inline,
-    .x_destroy = xdrmem_destroy
-#endif
+    AFS_STRUCT_INIT(.x_getint32, xdrmem_getint32), /* deserialize an afs_int32 */
+    AFS_STRUCT_INIT(.x_putint32, xdrmem_putint32), /* serialize an afs_int32 */
+    AFS_STRUCT_INIT(.x_getbytes, xdrmem_getbytes), /* deserialize counted bytes */
+    AFS_STRUCT_INIT(.x_putbytes, xdrmem_putbytes), /* serialize counted bytes */
+    AFS_STRUCT_INIT(.x_getpostn, xdrmem_getpos),   /* get offset in the stream: not supported. */
+    AFS_STRUCT_INIT(.x_setpostn, xdrmem_setpos),   /* set offset in the stream: not supported. */
+    AFS_STRUCT_INIT(.x_inline,	 xdrmem_inline),   /* prime stream for inline macros */
+    AFS_STRUCT_INIT(.x_destroy,	 xdrmem_destroy),  /* destroy stream */
 };
 
 /*
diff --git a/src/rx/xdr_rx.c b/src/rx/xdr_rx.c
index 62fbed331b..34e2b4d75e 100644
--- a/src/rx/xdr_rx.c
+++ b/src/rx/xdr_rx.c
@@ -49,26 +49,14 @@ static afs_int32 *xdrrx_inline(XDR *axdrs, u_int len);
  * Ops vector for stdio type XDR
  */
 static struct xdr_ops xdrrx_ops = {
-#ifndef HAVE_STRUCT_LABEL_SUPPORT
-    /* Windows does not support labeled assigments */
-    xdrrx_getint32,	/* deserialize an afs_int32 */
-    xdrrx_putint32,	/* serialize an afs_int32 */
-    xdrrx_getbytes,	/* deserialize counted bytes */
-    xdrrx_putbytes,	/* serialize counted bytes */
-    NULL,		/* get offset in the stream: not supported. */
-    NULL,		/* set offset in the stream: not supported. */
-    xdrrx_inline,	/* prime stream for inline macros */
-    NULL,		/* destroy stream */
-#else
-    .x_getint32 = xdrrx_getint32,	/* deserialize an afs_int32 */
-    .x_putint32 = xdrrx_putint32,	/* serialize an afs_int32 */
-    .x_getbytes = xdrrx_getbytes,	/* deserialize counted bytes */
-    .x_putbytes = xdrrx_putbytes,	/* serialize counted bytes */
-    .x_getpostn = NULL,		/* get offset in the stream: not supported. */
-    .x_setpostn = NULL,		/* set offset in the stream: not supported. */
-    .x_inline = xdrrx_inline,		/* prime stream for inline macros */
-    .x_destroy = NULL,			/* destroy stream */
-#endif
+    AFS_STRUCT_INIT(.x_getint32, xdrrx_getint32),	/* deserialize an afs_int32 */
+    AFS_STRUCT_INIT(.x_putint32, xdrrx_putint32),	/* serialize an afs_int32 */
+    AFS_STRUCT_INIT(.x_getbytes, xdrrx_getbytes),	/* deserialize counted bytes */
+    AFS_STRUCT_INIT(.x_putbytes, xdrrx_putbytes),	/* serialize counted bytes */
+    AFS_STRUCT_INIT(.x_getpostn, NULL),			/* get offset in the stream: not supported. */
+    AFS_STRUCT_INIT(.x_setpostn, NULL),			/* set offset in the stream: not supported. */
+    AFS_STRUCT_INIT(.x_inline,	 xdrrx_inline),		/* prime stream for inline macros */
+    AFS_STRUCT_INIT(.x_destroy,	 NULL),			/* destroy stream */
 };
 
 /*
diff --git a/src/rxkad/rxkad_client.c b/src/rxkad/rxkad_client.c
index 1f760b8c0e..7d48d010bf 100644
--- a/src/rxkad/rxkad_client.c
+++ b/src/rxkad/rxkad_client.c
@@ -50,21 +50,21 @@
 #endif /* max */
 
 static struct rx_securityOps rxkad_client_ops = {
-    rxkad_Close,
-    rxkad_NewConnection,	/* every new connection */
-    rxkad_PreparePacket,	/* once per packet creation */
-    0,				/* send packet (once per retrans.) */
-    0,
-    0,
-    0,
-    rxkad_GetResponse,		/* respond to challenge packet */
-    0,
-    rxkad_CheckPacket,		/* check data packet */
-    rxkad_DestroyConnection,
-    rxkad_GetStats,
-    0,
-    0,
-    0,
+    AFS_STRUCT_INIT(.op_Close,		   rxkad_Close),
+    AFS_STRUCT_INIT(.op_NewConnection,	   rxkad_NewConnection), /* every new connection */
+    AFS_STRUCT_INIT(.op_PreparePacket,	   rxkad_PreparePacket), /* once per packet creation */
+    AFS_STRUCT_INIT(.op_SendPacket,	   NULL),		 /* send packet (once per retrans.) */
+    AFS_STRUCT_INIT(.op_CheckAuthentication, NULL),
+    AFS_STRUCT_INIT(.op_CreateChallenge,   NULL),
+    AFS_STRUCT_INIT(.op_GetChallenge,	   NULL),
+    AFS_STRUCT_INIT(.op_GetResponse,	   rxkad_GetResponse),	 /* respond to challenge packet */
+    AFS_STRUCT_INIT(.op_CheckResponse,	   NULL),
+    AFS_STRUCT_INIT(.op_CheckPacket,	   rxkad_CheckPacket),	 /* check data packet */
+    AFS_STRUCT_INIT(.op_DestroyConnection, rxkad_DestroyConnection),
+    AFS_STRUCT_INIT(.op_GetStats,	   rxkad_GetStats),
+    AFS_STRUCT_INIT(.op_SetConfiguration,  NULL),
+    AFS_STRUCT_INIT(.op_Spare2,		   NULL),
+    AFS_STRUCT_INIT(.op_Spare3,		   NULL),
 };
 
 /* Allocate a new client security object.  Called with the encryption level,
@@ -86,7 +86,7 @@ rxkad_NewClientSecurityObject(rxkad_level level,
     size = sizeof(struct rx_securityClass);
     tsc = rxi_Alloc(size);
     memset((void *)tsc, 0, size);
-    tsc->refCount = 1;		/* caller gets one for free */
+    rxs_SetRefs(tsc, 1);		/* caller gets one for free */
     tsc->ops = &rxkad_client_ops;
 
     psize = PDATA_SIZE(ticketLen);
diff --git a/src/rxkad/rxkad_common.c b/src/rxkad/rxkad_common.c
index 6227e927f1..6b7783d6b5 100644
--- a/src/rxkad/rxkad_common.c
+++ b/src/rxkad/rxkad_common.c
@@ -192,7 +192,6 @@ rxkad_Init(void)
 /* static prototypes */
 static afs_int32 ComputeSum(struct rx_packet *apacket,
 			    fc_KeySchedule * aschedule, afs_int32 * aivec);
-static afs_int32 FreeObject(struct rx_securityClass *aobj);
 
 /* this call sets up an endpoint structure, leaving it in *network* byte
  * order so that it can be used quickly for encryption.
@@ -300,8 +299,6 @@ FreeObject(struct rx_securityClass *aobj)
 {
     struct rxkad_cprivate *tcp;	/* both structs start w/ type field */
 
-    if (aobj->refCount > 0)
-	return 0;		/* still in use */
     tcp = (struct rxkad_cprivate *)aobj->privateData;
     rxi_Free(aobj, sizeof(struct rx_securityClass));
     if (tcp->type & rxkad_client) {
@@ -322,10 +319,9 @@ FreeObject(struct rx_securityClass *aobj)
 int
 rxkad_Close(struct rx_securityClass *aobj)
 {
-    afs_int32 code;
-    aobj->refCount--;
-    code = FreeObject(aobj);
-    return code;
+    if (rxs_DecRef(aobj) > 0)
+	return 0;		/* still in use */
+    return FreeObject(aobj);
 }
 
 /* either: called to (re)create a new connection. */
@@ -358,7 +354,7 @@ rxkad_NewConnection(struct rx_securityClass *aobj,
 	INC_RXKAD_STATS(connections[rxkad_LevelIndex(tcp->level)]);
     }
 
-    aobj->refCount++;		/* attached connection */
+    rxs_Ref(aobj);		/* attached connection */
     return 0;
 }
 
@@ -398,10 +394,7 @@ rxkad_DestroyConnection(struct rx_securityClass *aobj,
 	}
 	INC_RXKAD_STATS(destroyClient);
     }
-    aobj->refCount--;		/* decrement connection counter */
-    if (aobj->refCount <= 0) {
-	(void)FreeObject(aobj);
-    }
+    (void)rxkad_Close(aobj);	/* decrement connection counter */
     return 0;
 }
 
diff --git a/src/rxkad/rxkad_server.c b/src/rxkad/rxkad_server.c
index 07e806bcdf..99964b3841 100644
--- a/src/rxkad/rxkad_server.c
+++ b/src/rxkad/rxkad_server.c
@@ -43,21 +43,21 @@ afs_int32(*rxkad_AlternateTicketDecoder) (afs_int32, char *, afs_int32,
 					  afs_uint32 *);
 
 static struct rx_securityOps rxkad_server_ops = {
-    rxkad_Close,
-    rxkad_NewConnection,
-    rxkad_PreparePacket,	/* once per packet creation */
-    0,				/* send packet (once per retrans) */
-    rxkad_CheckAuthentication,
-    rxkad_CreateChallenge,
-    rxkad_GetChallenge,
-    0,
-    rxkad_CheckResponse,
-    rxkad_CheckPacket,		/* check data packet */
-    rxkad_DestroyConnection,
-    rxkad_GetStats,
-    rxkad_SetConfiguration,
-    0,				/* spare 2 */
-    0,				/* spare 3 */
+    AFS_STRUCT_INIT(.op_Close,		rxkad_Close),
+    AFS_STRUCT_INIT(.op_NewConnection,	rxkad_NewConnection),
+    AFS_STRUCT_INIT(.op_PreparePacket,	rxkad_PreparePacket),	/* once per packet creation */
+    AFS_STRUCT_INIT(.op_SendPacket,	NULL),			/* send packet (once per retrans) */
+    AFS_STRUCT_INIT(.op_CheckAuthentication, rxkad_CheckAuthentication),
+    AFS_STRUCT_INIT(.op_CreateChallenge, rxkad_CreateChallenge),
+    AFS_STRUCT_INIT(.op_GetChallenge,	rxkad_GetChallenge),
+    AFS_STRUCT_INIT(.op_GetResponse,	NULL),
+    AFS_STRUCT_INIT(.op_CheckResponse,	rxkad_CheckResponse),
+    AFS_STRUCT_INIT(.op_CheckPacket,	rxkad_CheckPacket),	/* check data packet */
+    AFS_STRUCT_INIT(.op_DestroyConnection, rxkad_DestroyConnection),
+    AFS_STRUCT_INIT(.op_GetStats,	rxkad_GetStats),
+    AFS_STRUCT_INIT(.op_SetConfiguration, rxkad_SetConfiguration),
+    AFS_STRUCT_INIT(.op_Spare2,		NULL),			/* spare 2 */
+    AFS_STRUCT_INIT(.op_Spare3,		NULL),			/* spare 3 */
 };
 extern afs_uint32 rx_MyMaxSendSize;
 
@@ -147,7 +147,7 @@ rxkad_NewServerSecurityObject(rxkad_level level, void *get_key_rock,
     size = sizeof(struct rx_securityClass);
     tsc = rxi_Alloc(size);
     memset(tsc, 0, size);
-    tsc->refCount = 1;		/* caller has one reference */
+    rxs_SetRefs(tsc, 1);		/* caller has one reference */
     tsc->ops = &rxkad_server_ops;
     size = sizeof(struct rxkad_sprivate);
     tsp = rxi_Alloc(size);
diff --git a/src/rxkad/test/stress.c b/src/rxkad/test/stress.c
index 8c1c163c38..d652943e77 100644
--- a/src/rxkad/test/stress.c
+++ b/src/rxkad/test/stress.c
@@ -13,6 +13,7 @@
 #include <afs/param.h>
 
 
+#include <roken.h>
 #include <afs/stds.h>
 #include <sys/types.h>
 #ifdef AFS_NT40_ENV
@@ -144,8 +145,12 @@ CommandProc(struct cmd_syndesc *as, void *arock)
 
     if (startServer) {
 	if (as->parms[aTRACE].items) {
-	    extern char rxi_tracename[];
-	    strcpy(rxi_tracename, as->parms[aTRACE].items->data);
+	    extern char rxi_tracename[80];
+	    if (strlcpy(rxi_tracename, as->parms[aTRACE].items->data,
+			sizeof(rxi_tracename)) >= sizeof(rxi_tracename)) {
+		afs_com_err(whoami, 0, "-trace argument too long");
+		return ENAMETOOLONG;
+	    }
 	}
 
 	/* These options not compatible with -server */
diff --git a/src/sys/afssyscalls.h b/src/sys/afssyscalls.h
index ea74bcdd6b..0d46e3cd16 100644
--- a/src/sys/afssyscalls.h
+++ b/src/sys/afssyscalls.h
@@ -138,4 +138,19 @@ int     lpioctl(char *path, int cmd, void *cmarg, int follow);
 
 #endif /* AFS_NT40_ENV */
 
+#ifdef AFS_AIX_ENV
+/*
+ * Note that on AIX, syscall() is the confusing name of a system call exported
+ * by libafs defined in src/afs/afs_syscall.c, not a generic syscall-calling
+ * function like it is on other platforms (syscalls on AIX look like function
+ * calls due to some linker magic). This is just like lsetpag() and lpioctl(),
+ * so declare a prototype for it here.
+ *
+ * Ideally this prototype would match what's in src/afs/afs_syscall.c, but our
+ * callers call this with varying arguments, so we can't easily provide a real
+ * prototype with all arguments.
+ */
+int syscall();
+#endif
+
 #endif /* AFS_AFSSYSCALLS_H */
diff --git a/src/tests/fsx.c b/src/tests/fsx.c
index 2ce2ee0adb..479159cd5f 100644
--- a/src/tests/fsx.c
+++ b/src/tests/fsx.c
@@ -296,7 +296,7 @@ check_buffers(unsigned offset, unsigned size)
     unsigned op = 0;
     unsigned bad = 0;
 
-    if (bcmp(good_buf + offset, temp_buf, size) != 0) {
+    if (memcmp(good_buf + offset, temp_buf, size) != 0) {
 	prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n", offset, size);
 	prt("OFFSET\tGOOD\tBAD\tRANGE\n");
 	while (size > 0) {
@@ -500,7 +500,7 @@ dowrite(unsigned offset, unsigned size)
     gendata(original_buf, good_buf, offset, size);
     if (file_size < offset + size) {
 	if (file_size < offset)
-	    bzero(good_buf + file_size, offset - file_size);
+	    memset(good_buf + file_size, 0, offset - file_size);
 	file_size = offset + size;
 	if (lite) {
 	    warn("Lite file size bug in fsx!");
@@ -556,7 +556,7 @@ domapwrite(unsigned offset, unsigned size)
     gendata(original_buf, good_buf, offset, size);
     if (file_size < offset + size) {
 	if (file_size < offset)
-	    bzero(good_buf + file_size, offset - file_size);
+	    memset(good_buf + file_size, 0, offset - file_size);
 	file_size = offset + size;
 	if (lite) {
 	    warn("Lite file size bug in fsx!");
@@ -618,7 +618,7 @@ dotruncate(unsigned size)
     log4(OP_TRUNCATE, size, (unsigned)file_size, 0);
 
     if (size > file_size)
-	bzero(good_buf + file_size, size - file_size);
+	memset(good_buf + file_size, 0, size - file_size);
     file_size = size;
 
     if (testcalls <= simulatedopcount)
diff --git a/src/tools/dumpscan/afsdump_xsed.c b/src/tools/dumpscan/afsdump_xsed.c
index cd5208693c..877c29625c 100644
--- a/src/tools/dumpscan/afsdump_xsed.c
+++ b/src/tools/dumpscan/afsdump_xsed.c
@@ -339,7 +339,7 @@ main(int argc, char **argv)
 	exit(2);
     }
 
-    bzero(&dp, sizeof(dp));
+    memset(&dp, 0, sizeof(dp));
     dp.cb_error = my_error_cb;
     dp.repair_flags = repairflags;
     if (X->is_seekable)
@@ -365,7 +365,7 @@ main(int argc, char **argv)
 	dt_uint64 where;
 
 	dp.print_flags = printflags & DSPRINT_DEBUG;
-	bzero(&phi, sizeof(phi));
+	memset(&phi, 0, sizeof(phi));
 	phi.p = &dp;
 
 	if ((r = xftell(X, &where))
diff --git a/src/ubik/ubik.p.h b/src/ubik/ubik.p.h
index 6567961df1..60032884bd 100644
--- a/src/ubik/ubik.p.h
+++ b/src/ubik/ubik.p.h
@@ -591,13 +591,20 @@ extern int ubik_ClientInit(struct rx_connection **serverconns,
 extern afs_int32 ubik_ClientDestroy(struct ubik_client *aclient);
 extern struct rx_connection *ubik_RefreshConn(struct rx_connection *tc);
 #ifdef UBIK_LEGACY_CALLITER
-extern afs_int32 ubik_CallIter(int (*aproc) (), struct ubik_client *aclient,
+typedef int (*ubik_call_func)(struct rx_connection *,
+		      long p1, long p2, long p3, long p4,
+		      long p5, long p6, long p7, long p8,
+		      long p9, long p10, long p11, long p12,
+		      long p13, long p14, long p15, long p16);
+extern afs_int32 ubik_CallIter(ubik_call_func aproc,
+			       struct ubik_client *aclient,
 			       afs_int32 aflags, int *apos, long p1, long p2,
 			       long p3, long p4, long p5, long p6, long p7,
 			       long p8, long p9, long p10, long p11, long p12,
 			       long p13, long p14, long p15, long p16);
-extern afs_int32 ubik_Call_New(int (*aproc) (), struct ubik_client
-			       *aclient, afs_int32 aflags, long p1, long p2,
+extern afs_int32 ubik_Call_New(ubik_call_func aproc,
+			       struct ubik_client *aclient,
+			       afs_int32 aflags, long p1, long p2,
 			       long p3, long p4, long p5, long p6, long p7,
 			       long p8, long p9, long p10, long p11, long p12,
 			       long p13, long p14, long p15, long p16);
diff --git a/src/ubik/ubikclient.c b/src/ubik/ubikclient.c
index 450b1531e8..31ed5f991d 100644
--- a/src/ubik/ubikclient.c
+++ b/src/ubik/ubikclient.c
@@ -17,10 +17,6 @@
 # include <opr/lock.h>
 #endif
 
-#ifdef IGNORE_SOME_GCC_WARNINGS
-# pragma GCC diagnostic warning "-Wstrict-prototypes"
-#endif
-
 #include <afs/pthread_glock.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
@@ -411,7 +407,7 @@ try_GetSyncSite(struct ubik_client *aclient, afs_int32 apos)
  * been locked.
  */
 static afs_int32
-CallIter(int (*aproc) (), struct ubik_client *aclient,
+CallIter(ubik_call_func aproc, struct ubik_client *aclient,
 	 afs_int32 aflags, int *apos, long p1, long p2, long p3, long p4,
 	 long p5, long p6, long p7, long p8, long p9, long p10, long p11,
 	 long p12, long p13, long p14, long p15, long p16, int needlock)
@@ -474,7 +470,7 @@ errout:
  * \brief This is part of an iterator.  It doesn't handle finding sync sites.
  */
 afs_int32
-ubik_CallIter(int (*aproc) (), struct ubik_client *aclient,
+ubik_CallIter(ubik_call_func aproc, struct ubik_client *aclient,
 			       afs_int32 aflags, int *apos, long p1, long p2,
 			       long p3, long p4, long p5, long p6, long p7,
 			       long p8, long p9, long p10, long p11, long p12,
@@ -490,7 +486,7 @@ ubik_CallIter(int (*aproc) (), struct ubik_client *aclient,
  * \todo In the future, we should also put in a protocol to find the sync site.
  */
 afs_int32
-ubik_Call_New(int (*aproc) (), struct ubik_client *aclient,
+ubik_Call_New(ubik_call_func aproc, struct ubik_client *aclient,
 	      afs_int32 aflags, long p1, long p2, long p3, long p4, long p5,
 	      long p6, long p7, long p8, long p9, long p10, long p11,
 	      long p12, long p13, long p14, long p15, long p16)
@@ -551,7 +547,7 @@ ubik_Call_New(int (*aproc) (), struct ubik_client *aclient,
  * \todo In the future, we should also put in a protocol to find the sync site.
  */
 afs_int32
-ubik_Call(int (*aproc) (), struct ubik_client *aclient,
+ubik_Call(ubik_call_func aproc, struct ubik_client *aclient,
 	  afs_int32 aflags, long p1, long p2, long p3, long p4,
 	  long p5, long p6, long p7, long p8, long p9, long p10,
 	  long p11, long p12, long p13, long p14, long p15, long p16)
diff --git a/src/update/server.c b/src/update/server.c
index b4eb9f5b0c..29b939922a 100644
--- a/src/update/server.c
+++ b/src/update/server.c
@@ -199,6 +199,7 @@ main(int argc, char *argv[])
     struct rx_securityClass **securityClasses;
     afs_int32 numClasses;
     struct rx_service *service;
+    char hoststr[16];
     afs_uint32 host = htonl(INADDR_ANY);
 
     int a = 0;
@@ -312,6 +313,8 @@ main(int argc, char *argv[])
 
     /* Initialize Rx, telling it port number this server will use for its
      * single service */
+    fprintf(stderr, "upserver binding rx to %s:%d\n",
+            afs_inet_ntoa_r(host, hoststr), AFSCONF_UPDATEPORT);
     if (rx_InitHost(host, htons(AFSCONF_UPDATEPORT)) < 0)
 	Quit("rx_init");
 
diff --git a/src/util/ktime.c b/src/util/ktime.c
index ffdc2ccc5f..6976d32515 100644
--- a/src/util/ktime.c
+++ b/src/util/ktime.c
@@ -323,6 +323,7 @@ out:
 int
 ktime_DisplayString(struct ktime *aparm, char *astring)
 {
+    static const size_t ndays = sizeof(day) / sizeof(*day);
     char tempString[50];
 
     if (aparm->mask & KTIME_NEVER) {
@@ -335,6 +336,9 @@ ktime_DisplayString(struct ktime *aparm, char *astring)
 	strcpy(astring, "at");
 	if (aparm->mask & KTIME_DAY) {
 	    strcat(astring, " ");
+	    if (aparm->day < 0 || aparm->day >= ndays) {
+		return EINVAL;
+	    }
 	    strcat(astring, day[aparm->day]);
 	}
 	if (aparm->mask & KTIME_HOUR) {
diff --git a/src/venus/fs.c b/src/venus/fs.c
index fa914a4c42..a6e6d2e458 100644
--- a/src/venus/fs.c
+++ b/src/venus/fs.c
@@ -1017,7 +1017,12 @@ GetCell(char *fname, char *cellname)
     blob.out = cellname;
 
     code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1);
-    return code ? errno : 0;
+    if (code != 0) {
+	code = errno;
+	fprintf(stderr, "%s: Failed to get cell for '%s'\n", pn, fname);
+	Die(code, fname);
+    }
+    return code;
 }
 
 /* Check if a username is valid: If it contains only digits (or a
@@ -1738,6 +1743,7 @@ GetLastComponent(const char *data, char **outdir, char **outbase,
 
     *outbase = NULL;
     *outdir = NULL;
+    memset(&statbuff, 0, sizeof(statbuff));
 
     if (thru_symlink)
 	*thru_symlink = 0;
@@ -1745,7 +1751,7 @@ GetLastComponent(const char *data, char **outdir, char **outbase,
     snprintf(orig_name, sizeof(orig_name), "%s%s",
 	     (data[0] == '/') ? "" : "./", data);
 
-    if (lstat(orig_name, &statbuff) < 0) {
+    if (!literal && lstat(orig_name, &statbuff) < 0) {
 	/* if lstat fails, we should still try the pioctl, since it
 	 * may work (for example, lstat will fail, but pioctl will
 	 * work if the volume of offline (returning ENODEV). */
@@ -2676,10 +2682,6 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock)
     for (ti = as->parms[0].items; ti; ti = ti->next) {
 	code = GetCell(ti->data, cell);
 	if (code) {
-	    if (errno == ENOENT)
-		fprintf(stderr, "%s: no such cell as '%s'\n", pn, ti->data);
-	    else
-		Die(errno, ti->data);
 	    error = 1;
 	    continue;
 	}
@@ -4262,50 +4264,49 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
     }
     for (ti = as->parms[0].items; ti; ti = ti->next) {
         struct VenusFid vfid;
+	char *parent_dir = NULL;
+	char *last_component = NULL;
 
         blob.out_size = sizeof(struct VenusFid);
         blob.out = (char *) &vfid;
         blob.in_size = 0;
 
 	if (literal) {
-	    char *parent_dir = NULL;
-	    char *last_component = NULL;
-
 	    if (GetLastComponent(ti->data, &parent_dir,
 				 &last_component, NULL, literal) != 0) {
 		error = 1;
-		continue;
+		goto next_item;
 	    }
 
 	    blob.in = last_component;
 	    blob.in_size = strlen(last_component) + 1;
 	    code = pioctl(parent_dir, VIOC_GETLITERALFID, &blob, 1);
 
-	    free(parent_dir);
-	    free(last_component);
 	} else {
 	    code = pioctl(ti->data, VIOCGETFID, &blob, 1);
 	}
         if (code) {
             Die(errno,ti->data);
             error = 1;
-            continue;
+	    goto next_item;
         }
 
-        code = GetCell(ti->data, cell);
+	if (literal) {
+	    code = GetCell(parent_dir, cell);
+	} else {
+	    code = GetCell(ti->data, cell);
+	}
         if (code) {
-	    if (errno == ENOENT)
-		fprintf(stderr, "%s: no such cell as '%s'\n", pn, ti->data);
-	    else
-		Die(errno, ti->data);
-	    error = 1;
-	    continue;
+	    strlcpy(cell, "unknown-cell", sizeof(cell));
         }
 
         printf("File %s (%u.%u.%u) located in cell %s\n",
                ti->data, vfid.Fid.Volume, vfid.Fid.Vnode, vfid.Fid.Unique,
                cell);
 
+ next_item:
+	free(parent_dir);
+	free(last_component);
     }
 
     return error;
diff --git a/src/venus/fstrace.c b/src/venus/fstrace.c
index bce87dfa5b..2988bffde2 100644
--- a/src/venus/fstrace.c
+++ b/src/venus/fstrace.c
@@ -23,6 +23,7 @@
 #include <rx/rx.h>
 #include <afs/vice.h>
 #include <afs/sys_prototypes.h>
+#include <afs/afssyscalls.h>
 
 /* For SGI 6.2, this is changed to 1 if it's a 32 bit kernel. */
 int afs_icl_sizeofLong = ICL_LONG;
diff --git a/src/viced/NTMakefile b/src/viced/NTMakefile
index af621679f3..22b78934bc 100644
--- a/src/viced/NTMakefile
+++ b/src/viced/NTMakefile
@@ -100,6 +100,7 @@ $(EXEFILE): $(EXEOBJS) $(EXELIBS)
 CBD = $(DESTDIR)\root.server\usr\afs\bin\cbd.exe
 
 CBDLIBS =\
+	$(DESTDIR)\lib\opr.lib \
 	$(DESTDIR)\lib\afsroken.lib
 
 CBDRES = $(OUT)\cbd.res
diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c
index 5e6655fa26..8a91a7308b 100644
--- a/src/viced/afsfileprocs.c
+++ b/src/viced/afsfileprocs.c
@@ -3067,6 +3067,26 @@ SRXAFS_StoreData64(struct rx_call * acall, struct AFSFid * Fid,
     return code;
 }
 
+static char *
+printableACL(char *AccessList)
+{
+    char *s;
+    size_t i;
+    size_t len = strlen(AccessList);
+
+    s = calloc(1, len + 1);
+    if (s == NULL)
+	return NULL;
+
+    for (i = 0; i < len; i++) {
+	if (AccessList[i] == '\n')
+	    s[i] = ' ';
+	else
+	    s[i] = AccessList[i];
+    }
+    return s;
+}
+
 /**
  * Check if the given ACL blob is okay to use.
  *
@@ -3097,8 +3117,9 @@ check_acl(struct AFSOpaque *AccessList)
     return 0;
 }
 
-afs_int32
-SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
+static afs_int32
+common_StoreACL(afs_uint64 opcode,
+		struct rx_call * acall, struct AFSFid * Fid,
 		struct AFSOpaque *uncheckedACL,
 		struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
 {
@@ -3114,7 +3135,9 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     struct client *t_client = NULL;	/* tmp ptr to client data */
     struct in_addr logHostAddr;	/* host ip holder for inet_ntoa */
     struct fsstats fsstats;
+    char *displayACL = NULL;
     char *rawACL = NULL;
+    int newOpcode = (opcode == opcode_RXAFS_StoreACL);
 
     fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_STOREACL);
 
@@ -3130,9 +3153,12 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     /* Get ptr to client data for user Id for logging */
     t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
     logHostAddr.s_addr = rxr_HostOf(tcon);
-    ViceLog(1,
-	    ("SAFS_StoreACL, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
-	     Fid->Volume, Fid->Vnode, Fid->Unique, rawACL,
+    displayACL = printableACL(rawACL);
+    ViceLog(newOpcode ? 1 : 0,
+	    ("SAFS_StoreACL%s, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
+	     newOpcode ? "" : " CVE-2018-7168",
+	     Fid->Volume, Fid->Vnode, Fid->Unique,
+	     displayACL == NULL ? rawACL : displayACL,
 	     inet_ntoa(logHostAddr), ntohs(rxr_PortOf(tcon)), t_client->z.ViceId));
     FS_LOCK;
     AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
@@ -3160,6 +3186,12 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
 	goto Bad_StoreACL;
     }
 
+    if (opcode == opcode_RXAFS_OldStoreACL && !enable_old_store_acl) {
+	/* CVE-2018-7168 - administratively prohibited */
+	errorCode = EPERM;
+	goto Bad_StoreACL;
+    }
+
     /* Build and store the new Access List for the dir */
     if ((errorCode = RXStore_AccessList(targetptr, rawACL))) {
 	goto Bad_StoreACL;
@@ -3181,18 +3213,43 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     /* Update and store volume/vnode and parent vnodes back */
     PutVolumePackage(acall, parentwhentargetnotdir, targetptr, (Vnode *) 0,
 		     volptr, &client);
-    ViceLog(2, ("SAFS_StoreACL returns %d\n", errorCode));
+
+    ViceLog(2, ("%s returns %d\n",
+		opcode == opcode_RXAFS_StoreACL ? "SAFS_StoreACL"
+		 : "SAFS_OldStoreACL",
+		errorCode));
     errorCode = CallPostamble(tcon, errorCode, thost);
 
     fsstats_FinishOp(&fsstats, errorCode);
 
     osi_auditU(acall, StoreACLEvent, errorCode,
 	       AUD_ID, t_client ? t_client->z.ViceId : 0,
-	       AUD_FID, Fid, AUD_ACL, rawACL, AUD_END);
+	       AUD_FID, Fid, AUD_ACL,
+	       displayACL == NULL ? rawACL : displayACL,
+	       AUD_END);
+    free(displayACL);
     return errorCode;
 
 }				/*SRXAFS_StoreACL */
 
+/* SRXAFS_OldStoreACL (Deprecated - CVE-2018-7168 */
+afs_int32
+SRXAFS_OldStoreACL(struct rx_call *acall, struct AFSFid *Fid,
+		struct AFSOpaque *AccessList,
+		struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
+{
+    return common_StoreACL(opcode_RXAFS_OldStoreACL, acall, Fid, AccessList,
+			   OutStatus, Sync);
+}
+
+afs_int32
+SRXAFS_StoreACL(struct rx_call *acall, struct AFSFid *Fid,
+		struct AFSOpaque *AccessList,
+		struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
+{
+    return common_StoreACL(opcode_RXAFS_StoreACL, acall, Fid, AccessList,
+			   OutStatus, Sync);
+}
 
 /*
  * Note: This routine is called exclusively from SRXAFS_StoreStatus(), and
diff --git a/src/viced/callback.c b/src/viced/callback.c
index 11e405b129..79db1155cb 100644
--- a/src/viced/callback.c
+++ b/src/viced/callback.c
@@ -196,12 +196,16 @@ static int DumpCallBackState_r(void);
 #define FreeCB(cb) iFreeCB((struct CallBack *)cb, &cbstuff.nCBs)
 #define FreeFE(fe) iFreeFE((struct FileEntry *)fe, &cbstuff.nFEs)
 
+static afs_uint32 *HashTable;	/* File entry hash table */
+static afs_int32 FEhashsize;	/* number of buckets in HashTable */
+
+#define FEHASH_SIZE_OLD 512 /* Historical hard-coded FEhashsize */
+#define FE_CHAIN_TARGET 16  /* Target chain length for dynamic FEhashsize */
+#define FEHash(volume, unique) (((volume)+(unique))&(FEhashsize - 1))
 
 /* Other protos - move out sometime */
 void PrintCB(struct CallBack *cb, afs_uint32 now);
 
-static afs_uint32 HashTable[FEHASH_SIZE];	/* File entry hash table */
-
 static struct FileEntry *
 FindFE(AFSFid * fid)
 {
@@ -422,6 +426,8 @@ FDel(struct FileEntry *fe)
 int
 InitCallBack(int nblks)
 {
+    afs_int32 workingHashSize;
+
     opr_Assert(nblks > 0);
 
     H_LOCK;
@@ -444,6 +450,45 @@ InitCallBack(int nblks)
     cbstuff.nCBs = nblks;
     while (cbstuff.nCBs)
 	FreeCB(&CB[cbstuff.nCBs]);	/* This is correct */
+
+    if (nblks > 64000) {
+	/*
+	 * We may have a large number of callbacks to keep track of (more than
+	 * 64000, the default with the '-L' fileserver switch). Figure out a
+	 * hashtable size so our hash chains are around FE_CHAIN_TARGET long.
+	 * Start at the old historical hashtable size (FEHASH_SIZE_OLD), and
+	 * count up until we get a reasonable number.
+	 */
+	workingHashSize = FEHASH_SIZE_OLD;
+	while (nblks / workingHashSize > FE_CHAIN_TARGET) {
+	    opr_Assert(workingHashSize < MAX_AFS_INT32 / 2);
+	    workingHashSize *= 2;
+	}
+
+    } else {
+	/*
+	 * It looks like we're using one of the historical default values for
+	 * our callback limit (64000 is the amount given by '-L' in the
+	 * fileserver; all other defaults are smaller).
+	 *
+	 * In this case, we're not using a huge number of callbacks, so the
+	 * size of the hashtable is not a big concern. Use the old hard-coded
+	 * hashtable size of 512 (FEHASH_SIZE_OLD), so any fsstate.dat file we
+	 * may save to disk is understandable by old fileservers and other
+	 * tools.
+	 */
+	workingHashSize = FEHASH_SIZE_OLD;
+    }
+
+    /* hashtable size must be a power of 2 */
+    opr_Assert(workingHashSize > 0);
+    opr_Assert((workingHashSize & (workingHashSize - 1)) == 0);
+
+    HashTable = calloc(workingHashSize, sizeof(HashTable[0]));
+    if (HashTable == NULL) {
+	ViceLogThenPanic(0, ("Failed malloc in InitCallBack\n"));
+    }
+    FEhashsize = workingHashSize;
     cbstuff.nblks = nblks;
     cbstuff.nbreakers = 0;
     H_UNLOCK;
@@ -1230,7 +1275,7 @@ BreakVolumeCallBacksLater(VolumeId volume)
     ViceLog(25, ("Setting later on volume %" AFS_VOLID_FMT "\n",
 		 afs_printable_VolumeId_lu(volume)));
     H_LOCK;
-    for (hash = 0; hash < FEHASH_SIZE; hash++) {
+    for (hash = 0; hash < FEhashsize; hash++) {
 	for (feip = &HashTable[hash]; (fe = itofe(*feip)) != NULL; ) {
 	    if (fe->volid == volume) {
 		struct CallBack *cbnext;
@@ -1282,7 +1327,7 @@ BreakLaterCallBacks(void)
     /* Pick the first volume we see to clean up */
     fid.Volume = fid.Vnode = fid.Unique = 0;
 
-    for (hash = 0; hash < FEHASH_SIZE; hash++) {
+    for (hash = 0; hash < FEhashsize; hash++) {
 	for (feip = &HashTable[hash]; (fe = itofe(*feip)) != NULL; ) {
 	    if (fe && (fe->status & FE_LATER)
 		&& (fid.Volume == 0 || fid.Volume == fe->volid)) {
@@ -1686,17 +1731,19 @@ PrintCallBackStats(void)
 	    cbstuff.AddCallBacks, cbstuff.BreakCallBacks,
 	    cbstuff.DeleteCallBacks, cbstuff.DeleteFiles, cbstuff.CBsTimedOut,
 	    cbstuff.GotSomeSpaces, cbstuff.DeleteAllCallBacks);
-    fprintf(stderr, "%d CBs, %d FEs, (%d of total of %d 16-byte blocks)\n",
+    fprintf(stderr, "%d CBs, %d FEs, (%d of total of %d %d-byte blocks)\n",
 	    cbstuff.nCBs, cbstuff.nFEs, cbstuff.nCBs + cbstuff.nFEs,
-	    cbstuff.nblks);
+	    cbstuff.nblks, (int) sizeof(struct CallBack));
     fprintf(stderr, "%d GSS1, %d GSS2, %d GSS3, %d GSS4, %d GSS5 (internal counters)\n",
 	    cbstuff.GSS1, cbstuff.GSS2, cbstuff.GSS3, cbstuff.GSS4, cbstuff.GSS5);
-
+    fprintf(stderr, "%d FEhashsize\n",
+	    FEhashsize);
     return 0;
 }
 
 #define MAGIC 0x12345678	/* To check byte ordering of dump when it is read in */
 #define MAGICV2 0x12345679      /* To check byte ordering & version of dump when it is read in */
+#define MAGICV3 0x1234567A
 
 
 #ifndef INTERPRET_DUMP
@@ -1711,7 +1758,6 @@ static int cb_stateSaveFEHash(struct fs_dump_state * state);
 static int cb_stateSaveFEs(struct fs_dump_state * state);
 static int cb_stateSaveFE(struct fs_dump_state * state, struct FileEntry * fe);
 static int cb_stateRestoreTimeouts(struct fs_dump_state * state);
-static int cb_stateRestoreFEHash(struct fs_dump_state * state);
 static int cb_stateRestoreFEs(struct fs_dump_state * state);
 static int cb_stateRestoreFE(struct fs_dump_state * state);
 static int cb_stateRestoreCBs(struct fs_dump_state * state, struct FileEntry * fe,
@@ -1789,32 +1835,42 @@ cb_stateRestore(struct fs_dump_state * state)
 
     if (fs_stateReadHeader(state, &state->hdr->cb_offset, state->cb_hdr,
 			   sizeof(struct callback_state_header))) {
+	ViceLog(0, ("cb_stateRestore: failed to read cb_hdr\n"));
 	ret = 1;
 	goto done;
     }
 
     if (cb_stateCheckHeader(state->cb_hdr)) {
+	ViceLog(0, ("cb_stateRestore: failed check of cb_hdr\n"));
 	ret = 1;
 	goto done;
     }
 
     if (cb_stateAllocMap(state)) {
+	ViceLog(0, ("cb_stateRestore: failed to allocate map\n"));
 	ret = 1;
 	goto done;
     }
 
     if (cb_stateRestoreTimeouts(state)) {
+	ViceLog(0, ("cb_stateRestore: failed to restore timeouts\n"));
 	ret = 1;
 	goto done;
     }
 
-    if (cb_stateRestoreFEHash(state)) {
-	ret = 1;
-	goto done;
-    }
+    /*
+     * Note that we do not look at fehash_offset, and we skip reading in
+     * state->cb_fehash_hdr and all of the FE hash entries. Instead of loading
+     * the FE hashtable from disk, we'll just populate our hashtable ourselves
+     * as we load in the FEs. Loading the hashtable from disk currently isn't
+     * any faster (since we need to fixup the indices regardless), and
+     * populating the hashtable ourselves is a bit simpler and makes it easier
+     * to alter our hashing scheme.
+     */
 
     /* restore FEs and CBs from disk */
     if (cb_stateRestoreFEs(state)) {
+	ViceLog(0, ("cb_stateRestore: failed to restore FEs and CBs\n"));
 	ret = 1;
 	goto done;
     }
@@ -1838,12 +1894,6 @@ cb_stateRestoreIndices(struct fs_dump_state * state)
 	if (state->fe_map.entries[i].new_idx) {
 	    fe = itofe(state->fe_map.entries[i].new_idx);
 
-	    /* restore the fe->fnext entry */
-	    if (fe_OldToNew(state, fe->fnext, &fe->fnext)) {
-		ret = 1;
-		goto done;
-	    }
-
 	    /* restore the fe->firstcb entry */
 	    if (cb_OldToNew(state, fe->firstcb, &fe->firstcb)) {
 		ret = 1;
@@ -1909,14 +1959,6 @@ cb_stateRestoreIndices(struct fs_dump_state * state)
 	}
     }
 
-    /* restore the FE hash table queue heads */
-    for (i = 0; i < state->cb_fehash_hdr->records; i++) {
-	if (fe_OldToNew(state, HashTable[i], &HashTable[i])) {
-	    ret = 1;
-	    goto done;
-	}
-    }
-
  done:
     return ret;
 }
@@ -1942,9 +1984,11 @@ cb_stateVerifyFEHash(struct fs_dump_state * state)
 {
     int ret = 0, i;
     struct FileEntry * fe;
-    afs_uint32 fei, chain_len;
+    afs_uint32 fei, chain_len, max_FEs;
 
-    for (i = 0; i < FEHASH_SIZE; i++) {
+    max_FEs = cbstuff.nblks;
+
+    for (i = 0; i < FEhashsize; i++) {
 	chain_len = 0;
 	for (fei = HashTable[i], fe = itofe(fei);
 	     fe;
@@ -1957,9 +2001,9 @@ cb_stateVerifyFEHash(struct fs_dump_state * state)
 	    if (cb_stateVerifyFE(state, fe)) {
 		ret = 1;
 	    }
-	    if (chain_len > FS_STATE_FE_MAX_HASH_CHAIN_LEN) {
+	    if (chain_len > max_FEs) {
 		ViceLog(0, ("cb_stateVerifyFEHash: error: hash chain %d length exceeds %d; assuming there's a loop\n",
-			    i, FS_STATE_FE_MAX_HASH_CHAIN_LEN));
+			    i, max_FEs));
 		ret = 1;
 		break;
 	    }
@@ -1996,9 +2040,10 @@ static int
 cb_stateVerifyFCBList(struct fs_dump_state * state, struct FileEntry * fe)
 {
     int ret = 0;
-    afs_uint32 cbi, fei, chain_len = 0;
+    afs_uint32 cbi, fei, chain_len = 0, max_CBs;
     struct CallBack * cb;
 
+    max_CBs = cbstuff.nblks;
     fei = fetoi(fe);
 
     for (cbi = fe->firstcb, cb = itocb(cbi);
@@ -2015,9 +2060,9 @@ cb_stateVerifyFCBList(struct fs_dump_state * state, struct FileEntry * fe)
 			fei, cb->fhead));
 	    ret = 1;
 	}
-	if (chain_len > FS_STATE_FCB_MAX_LIST_LEN) {
+	if (chain_len > max_CBs) {
 	    ViceLog(0, ("cb_stateVerifyFCBList: error: list length exceeds %d (fei=%d); assuming there's a loop\n",
-			FS_STATE_FCB_MAX_LIST_LEN, fei));
+			max_CBs, fei));
 	    ret = 1;
 	    goto done;
 	}
@@ -2038,9 +2083,10 @@ int
 cb_stateVerifyHCBList(struct fs_dump_state * state, struct host * host)
 {
     int ret = 0;
-    afs_uint32 hi, chain_len, cbi;
+    afs_uint32 hi, chain_len, cbi, max_CBs;
     struct CallBack *cb, *ncb;
 
+    max_CBs = cbstuff.nblks;
     hi = h_htoi(host);
     chain_len = 0;
 
@@ -2076,9 +2122,10 @@ cb_stateVerifyHCBList(struct fs_dump_state * state, struct host * host)
 	    ret = 1;
 	    goto done;
 	}
-	if (chain_len > FS_STATE_HCB_MAX_LIST_LEN) {
-	    ViceLog(0, ("cb_stateVerifyFCBList: error: list length exceeds %d (h->index=%d); assuming there's a loop\n",
-			FS_STATE_HCB_MAX_LIST_LEN, hi));
+
+	if (chain_len > max_CBs) {
+	    ViceLog(0, ("cb_stateVerifyHCBList: error: list length exceeds %d (h->index=%d); assuming there's a loop\n",
+			max_CBs, hi));
 	    ret = 1;
 	    goto done;
 	}
@@ -2093,9 +2140,11 @@ static int
 cb_stateVerifyTimeoutQueues(struct fs_dump_state * state)
 {
     int ret = 0, i;
-    afs_uint32 cbi, chain_len;
+    afs_uint32 cbi, chain_len, max_CBs;
     struct CallBack *cb, *ncb;
 
+    max_CBs = cbstuff.nblks;
+
     for (i = 0; i < CB_NUM_TIMEOUT_QUEUES; i++) {
 	chain_len = 0;
 	for (cbi = timeout[i], cb = itocb(cbi);
@@ -2136,9 +2185,10 @@ cb_stateVerifyTimeoutQueues(struct fs_dump_state * state)
 		ret = 1;
 		break;
 	    }
-	    if (chain_len > FS_STATE_TCB_MAX_LIST_LEN) {
+
+	    if (chain_len > max_CBs) {
 		ViceLog(0, ("cb_stateVerifyTimeoutQueues: list length exceeds %d (tindex=%d); assuming there's a loop\n",
-			    FS_STATE_TCB_MAX_LIST_LEN, i));
+			    max_CBs, i));
 		ret = 1;
 		break;
 	    }
@@ -2157,7 +2207,6 @@ cb_stateSaveTimeouts(struct fs_dump_state * state)
 
     AssignInt64(state->eof_offset, &state->cb_hdr->timeout_offset);
 
-    memset(state->cb_timeout_hdr, 0, sizeof(struct callback_state_fehash_header));
     state->cb_timeout_hdr->magic = CALLBACK_STATE_TIMEOUT_MAGIC;
     state->cb_timeout_hdr->records = CB_NUM_TIMEOUT_QUEUES;
     state->cb_timeout_hdr->len = sizeof(struct callback_state_timeout_header) +
@@ -2192,15 +2241,20 @@ cb_stateRestoreTimeouts(struct fs_dump_state * state)
     if (fs_stateReadHeader(state, &state->cb_hdr->timeout_offset,
 			   state->cb_timeout_hdr,
 			   sizeof(struct callback_state_timeout_header))) {
+	ViceLog(0, ("cb_stateRestoreTimeouts: failed to read cb_timeout_hdr\n"));
 	ret = 1;
 	goto done;
     }
 
     if (state->cb_timeout_hdr->magic != CALLBACK_STATE_TIMEOUT_MAGIC) {
+	ViceLog(0, ("cb_stateRestoreTimeouts: bad header magic 0x%x != 0x%x\n",
+		state->cb_timeout_hdr->magic, CALLBACK_STATE_TIMEOUT_MAGIC));
 	ret = 1;
 	goto done;
     }
     if (state->cb_timeout_hdr->records != CB_NUM_TIMEOUT_QUEUES) {
+	ViceLog(0, ("cb_stateRestoreTimeouts: records %d != %d\n",
+		state->cb_timeout_hdr->records, CB_NUM_TIMEOUT_QUEUES));
 	ret = 1;
 	goto done;
     }
@@ -2209,11 +2263,16 @@ cb_stateRestoreTimeouts(struct fs_dump_state * state)
 
     if (state->cb_timeout_hdr->len !=
 	(sizeof(struct callback_state_timeout_header) + len)) {
+	ViceLog(0, ("cb_stateRestoreTimeouts: header len %d != %d + %d\n",
+		state->cb_timeout_hdr->len,
+		(int)sizeof(struct callback_state_timeout_header),
+		len));
 	ret = 1;
 	goto done;
     }
 
     if (fs_stateRead(state, timeout, len)) {
+	ViceLog(0, ("cb_stateRestoreTimeouts: failed read of timeout table\n"));
 	ret = 1;
 	goto done;
     }
@@ -2230,66 +2289,56 @@ cb_stateSaveFEHash(struct fs_dump_state * state)
 
     AssignInt64(state->eof_offset, &state->cb_hdr->fehash_offset);
 
-    memset(state->cb_fehash_hdr, 0, sizeof(struct callback_state_fehash_header));
     state->cb_fehash_hdr->magic = CALLBACK_STATE_FEHASH_MAGIC;
-    state->cb_fehash_hdr->records = FEHASH_SIZE;
-    state->cb_fehash_hdr->len = sizeof(struct callback_state_fehash_header) +
-	(state->cb_fehash_hdr->records * sizeof(afs_uint32));
-
-    iov[0].iov_base = (char *)state->cb_fehash_hdr;
-    iov[0].iov_len = sizeof(struct callback_state_fehash_header);
-    iov[1].iov_base = (char *)HashTable;
-    iov[1].iov_len = sizeof(HashTable);
-
-    if (fs_stateSeek(state, &state->cb_hdr->fehash_offset)) {
-	ret = 1;
-	goto done;
-    }
-
-    if (fs_stateWriteV(state, iov, 2)) {
-	ret = 1;
-	goto done;
-    }
-
-    fs_stateIncEOF(state, state->cb_fehash_hdr->len);
 
- done:
-    return ret;
-}
+    if (FEhashsize != FEHASH_SIZE_OLD) {
+	/*
+	 * If our hashtable size is not the historical FEHASH_SIZE_OLD, don't
+	 * write out the hashtable at all. The hashtable data on disk is not
+	 * very useful; we only write it out because older fileservers or other
+	 * utilities may need it for interpreting fsstate.dat. But if our
+	 * hashtable size is not FEHASH_SIZE_OLD, then they won't be able to
+	 * read it anwyay, since the hashtable size has changed. So just don't
+	 * write out the data; just write the header that says we have 0
+	 * hashtable buckets.
+	 */
+	state->cb_fehash_hdr->records = 0;
+	state->cb_fehash_hdr->len = sizeof(struct callback_state_fehash_header);
 
-static int
-cb_stateRestoreFEHash(struct fs_dump_state * state)
-{
-    int ret = 0, len;
+	if (fs_stateWriteHeader(state, &state->cb_hdr->fehash_offset,
+				state->cb_fehash_hdr,
+				sizeof(*state->cb_fehash_hdr))) {
+	    ret = 1;
+	    goto done;
+	}
 
-    if (fs_stateReadHeader(state, &state->cb_hdr->fehash_offset,
-			   state->cb_fehash_hdr,
-			   sizeof(struct callback_state_fehash_header))) {
-	ret = 1;
-	goto done;
-    }
+    } else {
+	/*
+	 * Write out our HashTable data. This information is not terribly
+	 * useful, but older fileservers and other utilities may need it.
+	 * Someday this can probably be removed.
+	 */
+	state->cb_fehash_hdr->records = FEhashsize;
+	state->cb_fehash_hdr->len = sizeof(struct callback_state_fehash_header) +
+	    (state->cb_fehash_hdr->records * sizeof(afs_uint32));
 
-    if (state->cb_fehash_hdr->magic != CALLBACK_STATE_FEHASH_MAGIC) {
-	ret = 1;
-	goto done;
-    }
-    if (state->cb_fehash_hdr->records != FEHASH_SIZE) {
-	ret = 1;
-	goto done;
-    }
+	iov[0].iov_base = (char *)state->cb_fehash_hdr;
+	iov[0].iov_len = sizeof(struct callback_state_fehash_header);
+	iov[1].iov_base = (char *)HashTable;
+	iov[1].iov_len = sizeof(HashTable[0]) * FEhashsize;
 
-    len = state->cb_fehash_hdr->records * sizeof(afs_uint32);
+	if (fs_stateSeek(state, &state->cb_hdr->fehash_offset)) {
+	    ret = 1;
+	    goto done;
+	}
 
-    if (state->cb_fehash_hdr->len !=
-	(sizeof(struct callback_state_fehash_header) + len)) {
-	ret = 1;
-	goto done;
+	if (fs_stateWriteV(state, iov, 2)) {
+	    ret = 1;
+	    goto done;
+	}
     }
 
-    if (fs_stateRead(state, HashTable, len)) {
-	ret = 1;
-	goto done;
-    }
+    fs_stateIncEOF(state, state->cb_fehash_hdr->len);
 
  done:
     return ret;
@@ -2304,7 +2353,7 @@ cb_stateSaveFEs(struct fs_dump_state * state)
 
     AssignInt64(state->eof_offset, &state->cb_hdr->fe_offset);
 
-    for (hash = 0; hash < FEHASH_SIZE ; hash++) {
+    for (hash = 0; hash < FEhashsize ; hash++) {
 	for (fei = HashTable[hash]; fei; fei = fe->fnext) {
 	    fe = itofe(fei);
 	    if (cb_stateSaveFE(state, fe)) {
@@ -2323,6 +2372,12 @@ cb_stateRestoreFEs(struct fs_dump_state * state)
 {
     int count, nFEs, ret = 0;
 
+    if (fs_stateSeek(state, &state->cb_hdr->fe_offset)) {
+	ViceLog(0, ("cb_stateRestoreFEs: error seeking to FE offset\n"));
+	ret = 1;
+	goto done;
+    }
+
     nFEs = state->cb_hdr->nFEs;
 
     for (count = 0; count < nFEs; count++) {
@@ -2443,6 +2498,8 @@ cb_stateRestoreFE(struct fs_dump_state * state)
     }
 
     if (hdr.magic != CALLBACK_STATE_ENTRY_MAGIC) {
+	ViceLog(0, ("cb_stateRestoreFE: magic 0x%x != 0x%x\n",
+		hdr.magic, CALLBACK_STATE_ENTRY_MAGIC));
 	ret = 1;
 	goto done;
     }
@@ -2532,11 +2589,17 @@ cb_stateCheckHeader(struct callback_state_header * hdr)
     int ret = 0;
 
     if (hdr->stamp.magic != CALLBACK_STATE_MAGIC) {
+	ViceLog(0, ("cb_stateCheckHeader: magic 0x%x != 0x%x\n",
+		hdr->stamp.magic, CALLBACK_STATE_MAGIC));
 	ret = 1;
     } else if (hdr->stamp.version != CALLBACK_STATE_VERSION) {
+	ViceLog(0, ("cb_stateCheckHeader: version %d != %d\n",
+		hdr->stamp.version, CALLBACK_STATE_VERSION));
 	ret = 1;
     } else if ((hdr->nFEs > cbstuff.nblks) || (hdr->nCBs > cbstuff.nblks)) {
-	ViceLog(0, ("cb_stateCheckHeader: saved callback state larger than callback memory allocation\n"));
+	ViceLog(0, ("cb_stateCheckHeader: saved callback state larger than "
+		"callback memory allocation (%d FEs, %d CBs > %d)\n",
+		hdr->nFEs, hdr->nCBs, cbstuff.nblks));
 	ret = 1;
     }
     return ret;
@@ -2556,12 +2619,13 @@ cb_stateDiskEntryToFE(struct fs_dump_state * state,
 		      struct FEDiskEntry * in, struct FileEntry * out)
 {
     int ret = 0;
+    int hash;
 
     memcpy(out, &in->fe, sizeof(struct FileEntry));
 
     /* setup FE map entry */
     if (!in->index || (in->index >= state->fe_map.len)) {
-	ViceLog(0, ("cb_stateDiskEntryToFE: index (%d) out of range",
+	ViceLog(0, ("cb_stateDiskEntryToFE: index (%d) out of range\n",
 		    in->index));
 	ret = 1;
 	goto done;
@@ -2570,6 +2634,11 @@ cb_stateDiskEntryToFE(struct fs_dump_state * state,
     state->fe_map.entries[in->index].old_idx = in->index;
     state->fe_map.entries[in->index].new_idx = fetoi(out);
 
+    /* Add this new FE to the HashTable. */
+    hash = FEHash(out->volid, out->unique);
+    out->fnext = HashTable[hash];
+    HashTable[hash] = fetoi(out);
+
  done:
     return ret;
 }
@@ -2677,7 +2746,7 @@ static int
 DumpCallBackState_r(void)
 {
     int fd, oflag;
-    afs_uint32 magic = MAGICV2, now = (afs_int32) time(NULL), freelisthead;
+    afs_uint32 magic = MAGICV3, now = (afs_int32) time(NULL), freelisthead;
 
     oflag = O_WRONLY | O_CREAT | O_TRUNC;
 #ifdef AFS_NT40_ENV
@@ -2697,6 +2766,7 @@ DumpCallBackState_r(void)
     DumpBytes(fd, &magic, sizeof(magic));
     DumpBytes(fd, &now, sizeof(now));
     DumpBytes(fd, &cbstuff, sizeof(cbstuff));
+    DumpBytes(fd, &FEhashsize, sizeof(FEhashsize));
     DumpBytes(fd, TimeOuts, sizeof(TimeOuts));
     DumpBytes(fd, timeout, sizeof(timeout));
     DumpBytes(fd, &tfirst, sizeof(tfirst));
@@ -2704,7 +2774,7 @@ DumpCallBackState_r(void)
     DumpBytes(fd, &freelisthead, sizeof(freelisthead));	/* This is a pointer */
     freelisthead = fetoi((struct FileEntry *)FEfree);
     DumpBytes(fd, &freelisthead, sizeof(freelisthead));	/* This is a pointer */
-    DumpBytes(fd, HashTable, sizeof(HashTable));
+    DumpBytes(fd, HashTable, sizeof(HashTable[0]) * FEhashsize);
     DumpBytes(fd, &CB[1], sizeof(CB[1]) * cbstuff.nblks);	/* CB stuff */
     DumpBytes(fd, &FE[1], sizeof(FE[1]) * cbstuff.nblks);	/* FE stuff */
     close(fd);
@@ -2763,17 +2833,22 @@ ReadDump(char *file, int timebits)
 	exit(1);
     }
     ReadBytes(fd, &magic, sizeof(magic));
-    if (magic == MAGICV2) {
+    if (magic == MAGICV3) {
+	/* V3 contains a new field for FEhashsize */
 	timebits = 32;
+	FEhashsize = 0;
+    } else if (magic == MAGICV2) {
+	timebits = 32;
+	FEhashsize = FEHASH_SIZE_OLD;
+    } else if (magic == MAGIC) {
+	FEhashsize = FEHASH_SIZE_OLD;
     } else {
-	if (magic != MAGIC) {
-	    fprintf(stderr,
-		    "Magic number of %s is invalid.  You might be trying to\n",
-		    file);
-	    fprintf(stderr,
-		    "run this program on a machine type with a different byte ordering.\n");
-	    exit(1);
-	}
+	fprintf(stderr,
+		"Magic number of %s is invalid (0x%x).  You might be trying to\n",
+		file, magic);
+	fprintf(stderr,
+		"run this program on a machine type with a different byte ordering.\n");
+	exit(1);
     }
     if (timebits == 64) {
 	ReadBytes(fd, &now64, sizeof(afs_int64));
@@ -2782,6 +2857,13 @@ ReadDump(char *file, int timebits)
 	ReadBytes(fd, &now, sizeof(afs_int32));
 
     ReadBytes(fd, &cbstuff, sizeof(cbstuff));
+    if (FEhashsize == 0) {
+	ReadBytes(fd, &FEhashsize, sizeof(FEhashsize));
+	if (FEhashsize == 0) {
+	    fprintf(stderr, "FEhashsize of 0 is not supported.\n");
+	    exit(1);
+	}
+    }
     ReadBytes(fd, TimeOuts, sizeof(TimeOuts));
     ReadBytes(fd, timeout, sizeof(timeout));
     ReadBytes(fd, &tfirst, sizeof(tfirst));
@@ -2793,7 +2875,9 @@ ReadDump(char *file, int timebits)
     CBfree = (struct CallBack *)itocb(freelisthead);
     ReadBytes(fd, &freelisthead, sizeof(freelisthead));
     FEfree = (struct FileEntry *)itofe(freelisthead);
-    ReadBytes(fd, HashTable, sizeof(HashTable));
+    HashTable = calloc(FEhashsize, sizeof(HashTable[0]));
+    opr_Assert(HashTable != NULL);
+    ReadBytes(fd, HashTable, sizeof(HashTable[0]) * FEhashsize);
     ReadBytes(fd, &CB[1], sizeof(CB[1]) * cbstuff.nblks);	/* CB stuff */
     ReadBytes(fd, &FE[1], sizeof(FE[1]) * cbstuff.nblks);	/* FE stuff */
     if (close(fd)) {
@@ -2900,7 +2984,7 @@ main(int argc, char **argv)
 	struct CallBack *cb;
 	struct FileEntry *fe;
 
-	for (hash = 0; hash < FEHASH_SIZE; hash++) {
+	for (hash = 0; hash < FEhashsize; hash++) {
 	    for (feip = &HashTable[hash]; (fe = itofe(*feip));) {
 		if (!vol || (fe->volid == vol)) {
 		    afs_uint32 fe_i = fetoi(fe);
diff --git a/src/viced/callback.h b/src/viced/callback.h
index 685e042375..f5c4804773 100644
--- a/src/viced/callback.h
+++ b/src/viced/callback.h
@@ -82,11 +82,6 @@ struct VCBParams {
 };
 
 
-/* callback hash macros */
-#define FEHASH_SIZE 512		/* Power of 2 */
-#define FEHASH_MASK (FEHASH_SIZE-1)
-#define FEHash(volume, unique) (((volume)+(unique))&(FEHASH_MASK))
-
 #define CB_NUM_TIMEOUT_QUEUES 128
 
 
diff --git a/src/viced/host.c b/src/viced/host.c
index 1adc7aa199..62a1b2ac33 100644
--- a/src/viced/host.c
+++ b/src/viced/host.c
@@ -3234,12 +3234,14 @@ h_stateRestore(struct fs_dump_state * state)
     /* seek to the right position and read in the host state header */
     if (fs_stateReadHeader(state, &state->hdr->h_offset, state->h_hdr,
 			   sizeof(struct host_state_header))) {
+	ViceLog(0, ("h_stateRestore: failed to read h_hdr\n"));
 	state->bail = 1;
 	goto done;
     }
 
     /* check the validity of the header */
     if (h_stateCheckHeader(state->h_hdr)) {
+	ViceLog(0, ("h_stateRestore: failed check of h_hdr\n"));
 	state->bail = 1;
 	goto done;
     }
@@ -3247,6 +3249,7 @@ h_stateRestore(struct fs_dump_state * state)
     records = state->h_hdr->records;
 
     if (h_stateAllocMap(state)) {
+	ViceLog(0, ("h_stateRestore: failed to allocate map\n"));
 	state->bail = 1;
 	goto done;
     }
@@ -3287,6 +3290,21 @@ h_stateVerify(struct fs_dump_state * state)
     return state->bail;
 }
 
+static int
+h_stateVerifyMaxHosts(struct fs_dump_state * state, int *a_maxHosts)
+{
+    if (state->mode == FS_STATE_DUMP_MODE) {
+	*a_maxHosts = hostCount;	/* state not fully populated yet */
+	return 0;
+    } else if (state->mode == FS_STATE_LOAD_MODE) {
+	*a_maxHosts = state->h_hdr->records;
+	return 0;
+    } else {
+	ViceLog(0, ("h_stateVerifyMaxHosts: bad state mode %d\n", state->mode));
+	return 1;
+    }
+}
+
 static int
 h_stateVerifyHost(struct host * h, void* rock)
 {
@@ -3347,7 +3365,13 @@ h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h,
     struct h_AddrHashChain *chain;
     int index = h_HashIndex(addr);
     char tmp[16];
-    int chain_len = 0;
+    int chain_len = 0, maxHosts;
+
+    ret = h_stateVerifyMaxHosts(state, &maxHosts);
+    if (ret != 0) {
+	ret = 1;
+	goto done;
+    }
 
     for (chain = hostAddrHashTable[index]; chain; chain = chain->next) {
 	host = chain->hostPtr;
@@ -3378,9 +3402,9 @@ h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h,
 	    found = 1;
 	    break;
 	}
-	if (chain_len > FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN) {
+	if (chain_len > maxHosts) {
 	    ViceLog(0, ("h_stateVerifyAddrHash: error: hash chain length exceeds %d; assuming there's a loop\n",
-			FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN));
+			maxHosts));
 	    ret = 1;
 	    goto done;
 	}
@@ -3394,10 +3418,15 @@ h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h,
 	                tmp, (unsigned)htons(port)));
 	    ret = 1;
 	    goto done;
-	} else {
+	} else if (state->mode == FS_STATE_DUMP_MODE) {
 	    ViceLog(0, ("h_stateVerifyAddrHash: warning: addr %s:%u not found in hash\n",
 	                tmp, (unsigned)htons(port)));
 	    state->flags.warnings_generated = 1;
+	} else {
+	    ViceLog(0, ("h_stateVerifyAddrHash: error: bad state mode %d\n",
+			state->mode));
+	    ret = 1;
+	    goto done;
 	}
     }
 
@@ -3414,7 +3443,13 @@ h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h)
     afsUUID * uuidp = &h->z.interface->uuid;
     int index = h_UuidHashIndex(uuidp);
     char tmp[40];
-    int chain_len = 0;
+    int chain_len = 0, maxHosts;
+
+    ret = h_stateVerifyMaxHosts(state, &maxHosts);
+    if (ret != 0) {
+	ret = 1;
+	goto done;
+    }
 
     for (chain = hostUuidHashTable[index]; chain; chain = chain->next) {
 	host = chain->hostPtr;
@@ -3433,9 +3468,9 @@ h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h)
 	    }
 	    goto done;
 	}
-	if (chain_len > FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN) {
+	if (chain_len > maxHosts) {
 	    ViceLog(0, ("h_stateVerifyUuidHash: error: hash chain length exceeds %d; assuming there's a loop\n",
-			FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN));
+			maxHosts));
 	    ret = 1;
 	    goto done;
 	}
@@ -3449,9 +3484,14 @@ h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h)
 	ViceLog(0, ("h_stateVerifyUuidHash: error: uuid %s not found in hash\n", tmp));
 	ret = 1;
 	goto done;
-    } else {
+    } else if (state->mode == FS_STATE_DUMP_MODE) {
 	ViceLog(0, ("h_stateVerifyUuidHash: warning: uuid %s not found in hash\n", tmp));
 	state->flags.warnings_generated = 1;
+    } else {
+	ViceLog(0, ("h_stateVerifyUuidHash: bad state mode %d\n",
+		    state->mode));
+	ret = 1;
+	goto done;
     }
 
  done:
@@ -3481,6 +3521,11 @@ h_stateCheckHeader(struct host_state_header * hdr)
 	ViceLog(0, ("check_host_state_header: unknown version number\n"));
 	ret = 1;
     }
+    else if (hdr->records > FS_STATE_H_MAX_LIST_LEN) {
+	ViceLog(0, ("check_host_state_header: saved host state too large "
+		"(%d > %d)\n", hdr->records, FS_STATE_H_MAX_LIST_LEN));
+	ret = 1;
+    }
     return ret;
 }
 
diff --git a/src/viced/serialize_state.c b/src/viced/serialize_state.c
index aaf4988295..a84d4f08ca 100644
--- a/src/viced/serialize_state.c
+++ b/src/viced/serialize_state.c
@@ -123,6 +123,8 @@ fs_stateSave(void)
 	goto done;
     }
 
+    state.mode = FS_STATE_DUMP_MODE;
+
     /* XXX
      * on busy servers, these checks will inevitably fail since stuff drops H_LOCK
      * all over the place (with structs left in inconsistent states) while RPCs to
@@ -221,12 +223,17 @@ fs_stateRestore(void)
 {
     int ret = 0;
     struct fs_dump_state state;
+    struct timeval now;
+    afs_int64 start_ms, end_ms, diff_ms;
 
     /* save and restore need to be atomic wrt other host package operations */
     H_LOCK;
 
     ViceLog(0, ("fs_stateRestore: commencing fileserver state restore\n"));
 
+    opr_Verify(gettimeofday(&now, NULL) == 0);
+    start_ms = now.tv_sec * 1000 + now.tv_usec / 1000;
+
     if (fs_stateAlloc(&state)) {
 	ViceLog(0, ("fs_stateRestore: memory allocation failed\n"));
 	ret = 1;
@@ -292,7 +299,13 @@ fs_stateRestore(void)
 	ViceLog(0, ("fs_stateRestore: fileserver state verification complete\n"));
     }
 
-    ViceLog(0, ("fs_stateRestore: restore was successful\n"));
+    opr_Verify(gettimeofday(&now, NULL) == 0);
+    end_ms = now.tv_sec * 1000 + now.tv_usec / 1000;
+    diff_ms = end_ms - start_ms;
+
+    ViceLog(0, ("fs_stateRestore: restore was successful in %lld ms "
+	    "(%d FEs, %d CBs)\n",
+	    diff_ms, state.cb_hdr->nFEs, state.cb_hdr->nCBs));
 
  done:
     if (state.fd >= 0) {
@@ -328,7 +341,6 @@ fs_stateCreateDump(struct fs_dump_state * state)
     }
 
     state->fd = fd;
-    state->mode = FS_STATE_DUMP_MODE;
     memset(state->hdr, 0, sizeof(struct fs_state_header));
     fs_stateIncEOF(state, sizeof(struct fs_state_header));
 
@@ -769,7 +781,7 @@ fs_stateMapFile(struct fs_dump_state * state, int preserve_flag )
 	flags = PROT_WRITE;
 	break;
     default:
-	ViceLog(0, ("fs_stateMapFile: invalid dump state mode\n"));
+	ViceLog(0, ("fs_stateMapFile: invalid dump state mode %d\n", state->mode));
 	return 1;
     }
 
@@ -1015,13 +1027,11 @@ fs_stateAlloc(struct fs_dump_state * state)
     memset(state, 0, sizeof(struct fs_dump_state));
     state->fd = -1;
     state->fn = (char *)AFSDIR_SERVER_FSSTATE_FILEPATH;
-    state->hdr = malloc(sizeof(struct fs_state_header));
-    state->h_hdr = malloc(sizeof(struct host_state_header));
-    state->cb_hdr = malloc(sizeof(struct callback_state_header));
-    state->cb_timeout_hdr =
-	malloc(sizeof(struct callback_state_timeout_header));
-    state->cb_fehash_hdr =
-	malloc(sizeof(struct callback_state_fehash_header));
+    state->hdr = calloc(1, sizeof(*state->hdr));
+    state->h_hdr = calloc(1, sizeof(*state->h_hdr));
+    state->cb_hdr = calloc(1, sizeof(*state->cb_hdr));
+    state->cb_timeout_hdr = calloc(1, sizeof(*state->cb_timeout_hdr));
+    state->cb_fehash_hdr = calloc(1, sizeof(*state->cb_fehash_hdr));
     if ((state->hdr == NULL) || (state->h_hdr == NULL) || (state->cb_hdr == NULL) ||
 	(state->cb_timeout_hdr == NULL) || (state->cb_fehash_hdr == NULL))
 	ret = 1;
diff --git a/src/viced/serialize_state.h b/src/viced/serialize_state.h
index c8e021b691..ad5d5a3d90 100644
--- a/src/viced/serialize_state.h
+++ b/src/viced/serialize_state.h
@@ -216,13 +216,7 @@ struct idx_map_entry_t {
  * make them fairly large so we don't get
  * false positives
  */
-#define FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN    100000     /* max elements in a host uuid-hash chain */
-#define FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN    2000000    /* max elements in a host ipv4-hash chain */
-#define FS_STATE_FE_MAX_HASH_CHAIN_LEN        100000     /* max elements in a FE fid-hash chain */
-#define FS_STATE_FCB_MAX_LIST_LEN             100000     /* max elements in a per-FE CB list */
-#define FS_STATE_HCB_MAX_LIST_LEN             100000     /* max elements in a per-host CB list */
-#define FS_STATE_TCB_MAX_LIST_LEN             100000     /* max elements in a per-timeout CB list */
-
+#define FS_STATE_H_MAX_LIST_LEN		    100000000	/* max number of hosts (100M) */
 
 /*
  * main state serialization state structure
@@ -230,8 +224,8 @@ struct idx_map_entry_t {
 
 struct fs_dump_state {
     enum {
-	FS_STATE_DUMP_MODE,
-	FS_STATE_LOAD_MODE
+	FS_STATE_DUMP_MODE = 0x1,
+	FS_STATE_LOAD_MODE = 0x2
     } mode;
     struct {
 	byte do_host_restore;              /* whether host restore should be done */
diff --git a/src/viced/viced.c b/src/viced/viced.c
index 0386864f44..36324e9e7a 100644
--- a/src/viced/viced.c
+++ b/src/viced/viced.c
@@ -164,6 +164,7 @@ int abort_threshold = 10;
 int udpBufSize = 0;		/* UDP buffer size for receive */
 int sendBufSize = 16384;	/* send buffer size */
 int saneacls = 0;		/* Sane ACLs Flag */
+int enable_old_store_acl = 1;	/* -cve-2018-7168-enforce */
 static int unsafe_attach = 0;   /* avoid inUse check on vol attach? */
 static int offline_timeout = -1; /* -offline-timeout option */
 static int offline_shutdown_timeout = -1; /* -offline-shutdown-timeout option */
@@ -894,6 +895,7 @@ enum optionsList {
     OPT_readonly,
     OPT_adminwrite,
     OPT_saneacls,
+    OPT_cve_2018_7168,
     OPT_buffers,
     OPT_callbacks,
     OPT_vcsize,
@@ -991,6 +993,8 @@ ParseArgs(int argc, char *argv[])
 			"from system:administrators");
     cmd_AddParmAtOffset(opts, OPT_saneacls, "-saneacls", CMD_FLAG,
 		        CMD_OPTIONAL, "set the saneacls capability bit");
+    cmd_AddParmAtOffset(opts, OPT_cve_2018_7168, "-cve-2018-7168-enforce", CMD_FLAG,
+			CMD_OPTIONAL, "disable (unreliable) old store acls rpc (opcode 134)");
 
     cmd_AddParmAtOffset(opts, OPT_buffers, "-b", CMD_SINGLE,
 			CMD_OPTIONAL, "buffers");
@@ -1192,6 +1196,10 @@ ParseArgs(int argc, char *argv[])
     cmd_OptionAsFlag(opts, OPT_readonly, &readonlyServer);
     cmd_OptionAsFlag(opts, OPT_adminwrite, &adminwriteServer);
     cmd_OptionAsFlag(opts, OPT_saneacls, &saneacls);
+    optval = 0;
+    cmd_OptionAsFlag(opts, OPT_cve_2018_7168, &optval);
+    if (optval != 0)
+	enable_old_store_acl = 0;
     cmd_OptionAsInt(opts, OPT_buffers, &buffs);
 
     if (cmd_OptionAsInt(opts, OPT_callbacks, &numberofcbs) == 0) {
@@ -1843,6 +1851,7 @@ main(int argc, char *argv[])
     int curLimit;
     time_t t;
     struct tm tm;
+    char hoststr[16];
     afs_uint32 rx_bindhost;
     VolumePackageOptions opts;
     struct afsconf_bsso_info bsso;
@@ -2011,6 +2020,8 @@ main(int argc, char *argv[])
 	rx_SetUdpBufSize(udpBufSize);	/* set the UDP buffer size for receive */
     rx_bindhost = SetupVL();
 
+    ViceLog(0, ("File server binding rx to %s:%d\n",
+            afs_inet_ntoa_r(rx_bindhost, hoststr), 7000));
     if (rx_InitHost(rx_bindhost, (int)htons(7000)) < 0) {
 	ViceLog(0, ("Cannot initialize RX\n"));
 	exit(1);
@@ -2217,7 +2228,6 @@ main(int argc, char *argv[])
     if (!he) {
 	ViceLog(0, ("Can't find address for FileServer '%s'\n", FS_HostName));
     } else {
-	char hoststr[16];
 	memcpy(&FS_HostAddr_NBO, he->h_addr, 4);
 	(void)afs_inet_ntoa_r(FS_HostAddr_NBO, hoststr);
 	FS_HostAddr_HBO = ntohl(FS_HostAddr_NBO);
diff --git a/src/viced/viced.h b/src/viced/viced.h
index d2f069932c..430817ec6e 100644
--- a/src/viced/viced.h
+++ b/src/viced/viced.h
@@ -182,6 +182,7 @@ struct AFSStatistics {
 
 extern int busyonrst;
 extern int saneacls;
+extern int enable_old_store_acl;
 
 #define RESTART_ORDINARY 1
 #define RESTART_FAST 2
diff --git a/src/vlserver/vlserver.c b/src/vlserver/vlserver.c
index 5feb05dca3..2685fd93a1 100644
--- a/src/vlserver/vlserver.c
+++ b/src/vlserver/vlserver.c
@@ -177,6 +177,7 @@ main(int argc, char **argv)
     char hostname[VL_MAXNAMELEN];
     int noAuth = 0;
     char clones[MAXHOSTSPERCELL];
+    char hoststr[16];
     afs_uint32 host = ntohl(INADDR_ANY);
     struct cmd_syndesc *opts;
     struct logOptions logopts;
@@ -299,7 +300,11 @@ main(int argc, char **argv)
     cmd_OptionAsFlag(opts, OPT_smallmem, &smallMem);
     if (cmd_OptionAsString(opts, OPT_trace, &optstring) == 0) {
 	extern char rxi_tracename[80];
-	strcpy(rxi_tracename, optstring);
+	if (strlcpy(rxi_tracename, optstring,
+		    sizeof(rxi_tracename)) >= sizeof(rxi_tracename)) {
+	    fprintf(stderr, "-trace argument too long\n");
+	    return -1;
+	}
 	free(optstring);
 	optstring = NULL;
     }
@@ -466,7 +471,6 @@ main(int argc, char **argv)
         }
         if (ccode == 1) {
             host = SHostAddrs[0];
-	    rx_InitHost(host, htons(AFSCONF_VLDBPORT));
 	}
     }
 
@@ -480,7 +484,9 @@ main(int argc, char **argv)
 	}
     }
 
-    code = rx_Init(htons(AFSCONF_VLDBPORT));
+    VLog(0, ("vlserver binding rx to %s:%d\n",
+         afs_inet_ntoa_r(host, hoststr), AFSCONF_VLDBPORT));
+    code = rx_InitHost(host, htons(AFSCONF_VLDBPORT));
     if (code < 0) {
         VLog(0, ("vlserver: Rx init failed: %d\n", code));
         exit(1);
diff --git a/src/vol/vol-salvage.c b/src/vol/vol-salvage.c
index 79a68c6bb6..6a8a948a89 100644
--- a/src/vol/vol-salvage.c
+++ b/src/vol/vol-salvage.c
@@ -2426,7 +2426,7 @@ SalvageVolumeHeaderFile(struct SalvInfo *salvinfo, struct InodeSummary *isp,
 
     for (i = 0; i < MAXINODETYPE; i++) {
 	if (stuff[i].inodeType == VI_LINKTABLE) {
-	    /* Gross hack: SalvageHeader does a bcmp on the volume header.
+	    /* Gross hack: SalvageHeader does a memcmp on the volume header.
 	     * And we may have recreated the link table earlier, so set the
 	     * RW header as well. The header magic was already checked.
 	     */
diff --git a/src/vol/volinfo-main.c b/src/vol/volinfo-main.c
index d630788eec..4b2ae986f1 100644
--- a/src/vol/volinfo-main.c
+++ b/src/vol/volinfo-main.c
@@ -90,6 +90,11 @@ VolInfo(struct cmd_syndesc *as, void *arock)
     }
     if ((ti = as->parms[P_VOLUMEID].items)) {
 	volumeId = strtoul(ti->data, NULL, 10);
+	if (volumeId == 0) {
+	    fprintf(stderr, "%s: Invalid -volumeid value: %s\n", progname,
+		    ti->data);
+	    return 1;
+	}
     }
     if (as->parms[P_HEADER].items) {
 	opt->dumpHeader = 1;
diff --git a/src/vol/volscan-main.c b/src/vol/volscan-main.c
index 79490df445..85ab03ddc2 100644
--- a/src/vol/volscan-main.c
+++ b/src/vol/volscan-main.c
@@ -104,6 +104,11 @@ VolScan(struct cmd_syndesc *as, void *arock)
     }
     if ((ti = as->parms[P_VOLUMEID].items)) {
 	volumeId = strtoul(ti->data, NULL, 10);
+	if (volumeId == 0) {
+	    fprintf(stderr, "%s: Invalid -volumeid value: %s\n", progname,
+		    ti->data);
+	    return 1;
+	}
     }
     if (as->parms[P_NOHEADING].items) {
 	opt->printHeading = 0;
diff --git a/src/vol/volume.c b/src/vol/volume.c
index 2fa05ca9ac..9bbf9fedfe 100644
--- a/src/vol/volume.c
+++ b/src/vol/volume.c
@@ -3242,7 +3242,7 @@ attach2(Error * ec, VolumeId volumeId, char *path, struct DiskPartition64 *partp
 
 	/*
 	 * We just read in the diskstuff part of the header.  If the detailed
-	 * volume stats area has not yet been initialized, we should bzero the
+	 * volume stats area has not yet been initialized, we should zero the
 	 * area and mark it as initialized.
 	 */
 	if (!(V_stat_initialized(vp))) {
@@ -6767,7 +6767,7 @@ VAdjustVolumeStatistics_r(Volume * vp)
 	V_dayUseDate(vp) = Midnight(now);
 
 	/*
-	 * All we need to do is bzero the entire VOL_STATS_BYTES of
+	 * All we need to do is zero the entire VOL_STATS_BYTES of
 	 * the detailed volume statistics area.
 	 */
 	memset((V_stat_area(vp)), 0, VOL_STATS_BYTES);
diff --git a/src/volser/volmain.c b/src/volser/volmain.c
index 872f3f0093..9ffc62996b 100644
--- a/src/volser/volmain.c
+++ b/src/volser/volmain.c
@@ -112,6 +112,38 @@ MyAfterProc(struct rx_call *acall, afs_int32 code)
     return;
 }
 
+#ifdef AFS_PTHREAD_ENV
+static void
+shutdown_signal(int sig)
+{
+    struct volser_trans *tt;
+    char part[16];
+
+    Log("Volserver shutting down on signal %d\n", sig);
+
+    VTRANS_LOCK;
+
+    for (tt = TransList(); tt != NULL; tt = tt->next) {
+	/*
+	 * We don't need to lock each individual 'tt', since we are only
+	 * accessing tt->tid, tt->volid and tt->partition, which never change
+	 * after the transaction is created.
+	 */
+	if (volutil_PartitionName2_r(tt->partition, part, sizeof(part)) != 0) {
+	    snprintf(part, sizeof(part), "[bad index %d]", tt->partition);
+	}
+	Log("Interrupting transaction %d for volume %u partition %s; volume may need salvage\n",
+	    tt->tid, tt->volid, part);
+    }
+
+    VTRANS_UNLOCK;
+
+    Log("Volserver shutdown complete\n");
+
+    exit(0);
+}
+#endif /* AFS_PTHREAD_ENV */
+
 /* Called every GCWAKEUP seconds to try to unlock all our partitions,
  * if we're idle and there are no active transactions
  */
@@ -443,6 +475,7 @@ main(int argc, char **argv)
     afs_int32 numClasses;
     struct rx_service *service;
     int rxpackets = 100;
+    char hoststr[16];
     afs_uint32 host = ntohl(INADDR_ANY);
     VolumePackageOptions opts;
     struct afsconf_bsso_info bsso;
@@ -544,6 +577,8 @@ main(int argc, char **argv)
             host = SHostAddrs[0];
     }
 
+    Log("Volserver binding rx to %s:%d\n",
+        afs_inet_ntoa_r(host, hoststr), AFSCONF_VOLUMEPORT);
     code = rx_InitHost(host, (int)htons(AFSCONF_VOLUMEPORT));
     if (code) {
 	fprintf(stderr, "rx init failed on socket AFSCONF_VOLUMEPORT %u\n",
@@ -567,6 +602,8 @@ main(int argc, char **argv)
 #ifdef AFS_PTHREAD_ENV
     opr_softsig_Init();
     SetupLogSoftSignals();
+    opr_softsig_Register(SIGINT, shutdown_signal);
+    opr_softsig_Register(SIGTERM, shutdown_signal);
 #else
     SetupLogSignals();
 #endif
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 69f709ddd2..29559ba302 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -22,7 +22,7 @@ runtests.o: $(srcdir)/runtests.c
 
 check test tests: runtests
 	@for A in $(SUBDIRS); do cd $$A && $(MAKE) $@ && cd .. || exit 1; done
-	MAKECHECK=1 ./libwrap @TOP_OBJDIR@/lib \
+	MAKECHECK=1 $(abs_top_srcdir)/tests/libwrap @TOP_OBJDIR@/lib \
 	    ./runtests -v -l $(abs_top_srcdir)/tests/TESTS
 
 install:
diff --git a/tests/auth/Makefile.in b/tests/auth/Makefile.in
index 781b652859..25964d95f7 100644
--- a/tests/auth/Makefile.in
+++ b/tests/auth/Makefile.in
@@ -6,7 +6,7 @@ include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 TESTS = authcon-t superuser-t keys-t realms-t
 
-MODULE_CFLAGS=-I$(srcdir)/../.. -I$(srcdir)/../common/
+MODULE_CFLAGS=-I$(TOP_OBJDIR) -I$(srcdir)/../common/
 
 all check test tests: $(TESTS)
 
diff --git a/tests/bozo/bos-man-t b/tests/bozo/bos-man-t
index b7a3d3222b..5226e9772d 100755
--- a/tests/bozo/bos-man-t
+++ b/tests/bozo/bos-man-t
@@ -2,24 +2,7 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'bos';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/bozo";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
-
+run_manpage_tests("src/bozo", "bos");
diff --git a/tests/bucoord/backup-man-t b/tests/bucoord/backup-man-t
index 162fd2cf90..8b126b4551 100755
--- a/tests/bucoord/backup-man-t
+++ b/tests/bucoord/backup-man-t
@@ -2,24 +2,7 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'backup';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/bucoord";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
-
+run_manpage_tests("src/bucoord", "backup");
diff --git a/tests/cmd/Makefile.in b/tests/cmd/Makefile.in
index 57dfe8fe2c..9c042ffeb0 100644
--- a/tests/cmd/Makefile.in
+++ b/tests/cmd/Makefile.in
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS = -I$(srcdir)/../..
+MODULE_CFLAGS = -I$(TOP_OBJDIR)
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/src/cmd/liboafs_cmd.la \
diff --git a/tests/common/Makefile.in b/tests/common/Makefile.in
index f71d9d37f9..3bc6096972 100644
--- a/tests/common/Makefile.in
+++ b/tests/common/Makefile.in
@@ -4,7 +4,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS=-I$(srcdir)/.. -I$(srcdir)/../..
+MODULE_CFLAGS=-I$(TOP_OBJDIR)
 
 all check test tests:	config.o servers.o ubik.o rxkad.o network.o
 
diff --git a/tests/common/common.h b/tests/common/common.h
index b97668391b..e1a407c9da 100644
--- a/tests/common/common.h
+++ b/tests/common/common.h
@@ -55,6 +55,7 @@ extern int afstest_GetUbikClient(struct afsconf_dir *dir, char *service,
 extern int afstest_IsLoopbackNetworkDefault(void);
 extern int afstest_SkipTestsIfLoopbackNetIsDefault(void);
 extern void afstest_SkipTestsIfBadHostname(void);
+extern void afstest_SkipTestsIfServerRunning(char *name);
 
 /* misc.c */
 extern char *afstest_GetProgname(char **argv);
diff --git a/tests/common/network.c b/tests/common/network.c
index 474fc61559..c664505c19 100644
--- a/tests/common/network.c
+++ b/tests/common/network.c
@@ -61,3 +61,44 @@ afstest_SkipTestsIfBadHostname(void)
     if (!host)
 	skip_all("Can't resolve hostname %s\n", hostname);
 }
+
+/*!
+ * Skips all TAP tests if a server is already running on this system.
+ *
+ * \param name[in]  IANA service name, e.g. "afs3-vlserver"
+ */
+void
+afstest_SkipTestsIfServerRunning(char *name)
+{
+    afs_int32 code;
+    osi_socket sock;
+    struct sockaddr_in addr;
+    afs_int32 service;
+
+    service = afsconf_FindService(name);
+    if (service == -1) {
+	fprintf(stderr, "Unknown service name: %s\n", name);
+	exit(1);
+    }
+    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (sock == OSI_NULLSOCKET) {
+	fprintf(stderr, "Failed to get socket file descriptor.\n");
+	exit(1);
+    }
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    addr.sin_port = service; /* Already in network byte order. */
+#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
+    addr.sin_len = sizeof(addr);
+#endif
+    code = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+    if (code < 0) {
+	if (errno == EADDRINUSE) {
+	    skip_all("Service %s is already running.\n", name);
+	} else {
+	    perror("bind");
+	    exit(1);
+	}
+    }
+    close(sock);
+}
diff --git a/tests/kauth/kas-man-t b/tests/kauth/kas-man-t
index 508dc47692..9ffb0ee883 100755
--- a/tests/kauth/kas-man-t
+++ b/tests/kauth/kas-man-t
@@ -2,24 +2,7 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'kas';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/kauth";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
-
+run_manpage_tests("src/kauth", "kas");
diff --git a/tests/opr/Makefile.in b/tests/opr/Makefile.in
index 96601775a9..d9a37f63df 100644
--- a/tests/opr/Makefile.in
+++ b/tests/opr/Makefile.in
@@ -3,7 +3,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS = -I$(srcdir)/../..
+MODULE_CFLAGS = -I$(TOP_OBJDIR)
 
 LIBS=../tap/libtap.a $(abs_top_builddir)/src/opr/liboafs_opr.la
 
diff --git a/tests/opr/softsig-t b/tests/opr/softsig-t
index d283c0f0b1..b9f650b5cb 100755
--- a/tests/opr/softsig-t
+++ b/tests/opr/softsig-t
@@ -32,7 +32,17 @@ use FindBin qw($Bin);
 
 # Start up our test process, and send it various signals. Check that these
 # signals make it to it correctly, and are reported on the command line.
-my $softsig_helper = $Bin . "/softsig-helper";
+
+my $softsig_helper;
+
+# Our softsig helper should be in $TOP_OBJDIR/tests/opr. To calculate that
+# path, use the BUILD env var if the test harness has set it; otherwise, our
+# next best guess is that it's in the same dir as this script.
+if (defined($ENV{C_TAP_BUILD})) {
+    $softsig_helper = $ENV{C_TAP_BUILD} . "/opr/softsig-helper";
+} else {
+    $softsig_helper = $Bin . "/softsig-helper";
+}
 
 # This -dummy argument prevents Perl from putting an intermediate sh
 # -c between us and softsig-helper in the case where the build
diff --git a/tests/ptserver/pts-man-t b/tests/ptserver/pts-man-t
index 288458702e..2991d5a675 100755
--- a/tests/ptserver/pts-man-t
+++ b/tests/ptserver/pts-man-t
@@ -2,24 +2,7 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'pts';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/ptserver";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
-
+run_manpage_tests("src/ptserver", "pts");
diff --git a/tests/rx/Makefile.in b/tests/rx/Makefile.in
index f5b4cf9244..373aac6efa 100644
--- a/tests/rx/Makefile.in
+++ b/tests/rx/Makefile.in
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS = -I$(srcdir)/../..
+MODULE_CFLAGS = -I$(TOP_OBJDIR)
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/src/rx/liboafs_rx.la
diff --git a/tests/tests-lib/perl5/mancheck_utils.pm b/tests/tests-lib/perl5/mancheck_utils.pm
index edfa8fc3da..62e1693cf6 100644
--- a/tests/tests-lib/perl5/mancheck_utils.pm
+++ b/tests/tests-lib/perl5/mancheck_utils.pm
@@ -52,7 +52,7 @@ sub lookup_sub_commands {
 #
 # Arguments:
 #
-#                builddir : A path to the OpenAFS build directory,
+#                  srcdir : A path to the OpenAFS source directory,
 #                           such as /tmp/1.4.14
 #
 #                 command : the name of the command (e.g. vos)
@@ -60,7 +60,7 @@ sub lookup_sub_commands {
 #             subcommlist : a list of sub-commands for command
 #
 sub test_command_man_pages {
-    my ($builddir, $command, @subcommlist) = @_;
+    my ($srcdir, $command, @subcommlist) = @_;
 
     # The following is because File::Find makes no sense to me
     # for this purpose, and actually seems totally misnamed
@@ -69,9 +69,9 @@ sub test_command_man_pages {
     my $frex = "";
     # Since we don't know what man section it might be in,
     # search all existing man page files for a filename match
-    my @mandirglob = glob("$builddir/doc/man-pages/man[1-8]/*");
+    my @mandirglob = glob("$srcdir/doc/man-pages/man[1-8]/*");
     # For every subcommand, see if command_subcommand.[1-8] exists
-    # in our man page build dir.
+    # in our man page source dir.
     foreach (@subcommlist) {
         my $subcommand = $_;
         $found = 0;
@@ -89,4 +89,28 @@ sub test_command_man_pages {
 	ok($found eq 1, "existence of man page for $command" . "_$subcommand");
     }
 }
+
+#
+# Setup the test plan and run all of the tests for the given command suite.
+#
+# Call like so:
+# run_manpage_tests("src/ptserver", "pts");
+#
+sub run_manpage_tests($$) {
+    my ($subdir, $command) = @_;
+
+    # When run from 'runtests', our cwd will be TOP_OBJDIR/tests. $C_TAP_SOURCE
+    # is set to TOP_SRCDIR/tests, and $C_TAP_BUILD is set to TOP_OBJDIR/tests.
+    # We want the top-level src and obj dirs, in order to find the relevant
+    # binaries and manpages.
+    my $srcdir = $ENV{C_TAP_SOURCE} . "/..";
+    my $objdir = $ENV{C_TAP_BUILD} . "/..";
+
+    my @sub_commands = lookup_sub_commands("$objdir/$subdir", $command);
+    die("No subcommands found in $objdir/$subdir/$command?") unless(@sub_commands);
+
+    plan tests => scalar @sub_commands;
+
+    test_command_man_pages($srcdir, $command, @sub_commands);
+}
 1;
diff --git a/tests/util/Makefile.in b/tests/util/Makefile.in
index 763ac89c95..267f0887b7 100644
--- a/tests/util/Makefile.in
+++ b/tests/util/Makefile.in
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.lwp
 
-MODULE_CFLAGS = -I$(srcdir)/../..
+MODULE_CFLAGS = -I$(TOP_OBJDIR)
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/lib/util.a \
diff --git a/tests/venus/fs-man-t b/tests/venus/fs-man-t
index cfbf6c0c89..55e9b0e34f 100755
--- a/tests/venus/fs-man-t
+++ b/tests/venus/fs-man-t
@@ -2,24 +2,7 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'fs';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/venus";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
-
+run_manpage_tests("src/venus", "fs");
diff --git a/tests/volser/Makefile.in b/tests/volser/Makefile.in
index 927edd6ec0..041480b7dc 100644
--- a/tests/volser/Makefile.in
+++ b/tests/volser/Makefile.in
@@ -6,7 +6,7 @@ include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 TESTS = vos-t
 
-MODULE_CFLAGS=-I$(srcdir)/../.. -I$(srcdir)/../common/
+MODULE_CFLAGS=-I$(TOP_OBJDIR) -I$(srcdir)/../common/
 
 all check test tests: $(TESTS)
 
diff --git a/tests/volser/vos-man-t b/tests/volser/vos-man-t
index 381f5ba7db..4ca4ef9e69 100755
--- a/tests/volser/vos-man-t
+++ b/tests/volser/vos-man-t
@@ -2,24 +2,8 @@
 
 use strict;
 use warnings;
-use File::Basename;
-use lib "./tests-lib/perl5";
+use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
 use mancheck_utils;
 
-# Set this to the bare command to test
-my $command = 'vos';
-my $builddir = $ENV{C_TAP_BUILD};
-if (!$builddir) {
-    $builddir = dirname($0) . "/..";
-}
-$builddir .= "/..";
-# Set this to the directory holding $command
-my $srcdir = "$builddir/src/volser";
-
-#---------------------------------------------------------------------
-
-my @sub_commands = lookup_sub_commands($srcdir, $command);
-plan tests => scalar @sub_commands;
-
-test_command_man_pages($builddir, $command, @sub_commands);
+run_manpage_tests("src/volser", "vos");
 
diff --git a/tests/volser/vos-t.c b/tests/volser/vos-t.c
index 41e74bdc5c..382fbed69b 100644
--- a/tests/volser/vos-t.c
+++ b/tests/volser/vos-t.c
@@ -106,6 +106,8 @@ main(int argc, char **argv)
     afstest_SkipTestsIfBadHostname();
     /* Skip all tests if the current hostname is on the loopback network */
     afstest_SkipTestsIfLoopbackNetIsDefault();
+    /* Skip all tests if a vlserver is already running on this system. */
+    afstest_SkipTestsIfServerRunning("afs3-vlserver");
 
     plan(6);
 
