summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Laß2022-06-01 19:28:25 +0200
committerMichael Laß2022-06-01 19:28:25 +0200
commit26972bfd6a0a08347f8f6da6f59d77a470c9bb1a (patch)
tree238a6e537c402230a5f34e62f57b1e8dff2e3e28
parent788bf8da53d27bbc92ac8c682b0930a7bf3b6a6d (diff)
downloadaur-26972bfd6a0a08347f8f6da6f59d77a470c9bb1a.tar.gz
Make compatible with Linux 5.18
This is a non-trivial set of backports from master to allow building against Linux 5.18. Use at your own risk.
-rw-r--r--.SRCINFO26
-rw-r--r--0001-Add-autoconf-archive-to-src-external.patch9
-rw-r--r--0002-Import-of-code-from-autoconf-archive.patch9
-rw-r--r--0003-Use-autoconf-archive-m4-from-src-external.patch9
-rw-r--r--0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch9
-rw-r--r--0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch9
-rw-r--r--0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch64
-rw-r--r--0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch125
-rw-r--r--0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch255
-rw-r--r--0009-LINUX-Don-t-panic-on-some-file-open-errors.patch127
-rw-r--r--0010-afs-Introduce-afs_IsDCacheFresh.patch371
-rw-r--r--0011-afs-introduce-get_dcache_readahead.patch146
-rw-r--r--0012-Linux-5.18-replace-readpages-with-readahead.patch304
-rw-r--r--PKGBUILD57
14 files changed, 1482 insertions, 38 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 399aa8a04f59..1efe2e851004 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = openafs-modules-dkms
pkgdesc = Kernel module for OpenAFS (dkms)
pkgver = 1.8.8.1
- pkgrel = 2
+ pkgrel = 3
url = http://www.openafs.org
arch = i686
arch = x86_64
@@ -22,12 +22,26 @@ pkgbase = openafs-modules-dkms
source = 0003-Use-autoconf-archive-m4-from-src-external.patch
source = 0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
source = 0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch
+ source = 0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch
+ source = 0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch
+ source = 0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch
+ source = 0009-LINUX-Don-t-panic-on-some-file-open-errors.patch
+ source = 0010-afs-Introduce-afs_IsDCacheFresh.patch
+ source = 0011-afs-introduce-get_dcache_readahead.patch
+ source = 0012-Linux-5.18-replace-readpages-with-readahead.patch
sha256sums = e7c4bed7075bcd6402e3f0c2d5b9dbe76ad2ee3c5fd5ddc3973a3356ca23ef44
sha256sums = 5ea5e184f9b44f5ed45817d2b5a10149d15c8c54f49e0b5b4b773652673cb9b0
- sha256sums = 67bad31f8a401f1fa4e851a1f8d2d772f6649573f81045cafae94c105bbff173
- sha256sums = 16ced06d3d4ffffa251e20aecd1ccb3fedb4585617b004b8ade0b4eab603b17d
- sha256sums = 3b2aa3343fe4b9401b272fcf0252f4c3f108f1a1e5039718de38b803690c9d74
- sha256sums = c9623eac1e8faf2be133d69c6146eb68be800de0c3226acd99848348b5bfd2f4
- sha256sums = 17c71196bf5f1fc1c62bab8f03a102d7ca75fec56de94390851b10bd27efa3e9
+ sha256sums = cbf078639b9b25d1e9ec191b9c340720f1fe5ebd1b7665c2ea762498fcf66fbf
+ sha256sums = f1feac79a69b9ecff4c7259842184e16ef1213e9fb5a2601c4963ea3dc12041c
+ sha256sums = 97410d4f5a7a09254ffa18411f242234aba483a0a7b989503ee831457c0ddb9f
+ sha256sums = 47faddb068dcbbea74c973c23aac7fe29b1482e984a37b5cfee283200da6b9e2
+ sha256sums = 45fa5eaa7b0e7e7bc6c9e0b7c5d97e5fefc54f60c084d5e7deddbe2c0c4697e9
+ sha256sums = d42fa0772193cd6a66e09ba9cdb81b77c636a266caaf0c465331ff7ca3925b1c
+ sha256sums = b47e4d5405961b7d40bd24e50c18740b9cd85a90e0e7f630101602efb2f12c2f
+ sha256sums = 9801be6de6399a2e0d899b0ed71bc5881ede5a926720d32377a24db31b035593
+ sha256sums = ce21b7ed721d685fb0f1ddf068003410b585e09be7a96daeb1e8bb10378cf4b3
+ sha256sums = 7a5410bce86f1471ae5d990b68f2b25fcff8d5f32d2b7fd9e29c098a91ef1cef
+ sha256sums = 4816b8502366995eb5e8e58e485db910269a118ea6ed67e8f16e6bc1aab53864
+ sha256sums = b51739e2670d13a46f0936fd50ef4bfadf40e83b22a53d46dd7b0eb490ebb700
pkgname = openafs-modules-dkms
diff --git a/0001-Add-autoconf-archive-to-src-external.patch b/0001-Add-autoconf-archive-to-src-external.patch
index 18a3fa55aaec..262ab43c4351 100644
--- a/0001-Add-autoconf-archive-to-src-external.patch
+++ b/0001-Add-autoconf-archive-to-src-external.patch
@@ -1,7 +1,7 @@
-From 26434fb4376a5db1f38fca8807825fbabc81be7b Mon Sep 17 00:00:00 2001
+From 006616bd8e88b2d386a5ddc23973cf3e625cb80d Mon Sep 17 00:00:00 2001
From: Andrew Deason <adeason@sinenomine.net>
Date: Sat, 4 Apr 2020 22:28:21 -0500
-Subject: [PATCH 1/5] Add autoconf-archive to src/external
+Subject: [PATCH 01/12] Add autoconf-archive to src/external
Add autoconf-archive to the src/external mechanism, so we can more
easily import and update the AX_* m4 macros we pull in from
@@ -13,12 +13,13 @@ include that in the list of files. While we're here, also include a
few more macros for checking compiler flags, which will be used in
subsequent commits.
-Change-Id: I8c6288fc1d48a47837ca08f8b9207e0ada921af8
Reviewed-on: https://gerrit.openafs.org/14133
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit a072c65bba86cbcd81157e354d3719ac41a2c97d)
+
+Change-Id: I785607be9abe85e43287c4880103a365e264473b
---
src/external/autoconf-archive-author | 1 +
src/external/autoconf-archive-files | 5 +++++
@@ -45,5 +46,5 @@ index 000000000..42c7c3852
+m4/ax_gcc_func_attribute.m4 m4/ax_gcc_func_attribute.m4
+m4/ax_require_defined.m4 m4/ax_require_defined.m4
--
-2.35.1
+2.36.1
diff --git a/0002-Import-of-code-from-autoconf-archive.patch b/0002-Import-of-code-from-autoconf-archive.patch
index 731fd0a3c25d..7d5062799ef0 100644
--- a/0002-Import-of-code-from-autoconf-archive.patch
+++ b/0002-Import-of-code-from-autoconf-archive.patch
@@ -1,7 +1,7 @@
-From 3dd58d1b0d417fcda3b7679aa0f0691f55740c93 Mon Sep 17 00:00:00 2001
+From d3782b1d4e6fd81c5432e95112eb44305f07f272 Mon Sep 17 00:00:00 2001
From: Autoconf Archive Maintainers <autoconf-archive-maintainers@gnu.org>
Date: Tue, 7 Apr 2020 10:23:16 -0500
-Subject: [PATCH 2/5] Import of code from autoconf-archive
+Subject: [PATCH 02/12] Import of code from autoconf-archive
This commit updates the code imported from autoconf-archive to
24358c8c5ca679949ef522964d94e4d1cd1f941a (v2019.01.06)
@@ -13,12 +13,13 @@ New files are:
m4/ax_gcc_func_attribute.m4
m4/ax_require_defined.m4
-Change-Id: I64e14d1b4d41ebfee82fa92da10239f73e28b4c9
Reviewed-on: https://gerrit.openafs.org/14138
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit d8205bbb482554812fbe66afa3c337d991a247b6)
+
+Change-Id: Ibc18f5ddef8b63ba258fa666ada60577a845aa8f
---
src/external/autoconf-archive-last | 1 +
.../m4/ax_append_compile_flags.m4 | 46 ++++
@@ -496,5 +497,5 @@ index 000000000..17c3eab7d
+ m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
--
-2.35.1
+2.36.1
diff --git a/0003-Use-autoconf-archive-m4-from-src-external.patch b/0003-Use-autoconf-archive-m4-from-src-external.patch
index b37a2977cb23..e4eeaed03e19 100644
--- a/0003-Use-autoconf-archive-m4-from-src-external.patch
+++ b/0003-Use-autoconf-archive-m4-from-src-external.patch
@@ -1,7 +1,7 @@
-From d82a2aa279ddf3ba36e753fe4f9d360ec3ee3206 Mon Sep 17 00:00:00 2001
+From ea2a0e128d71802f61b8da2e44de3c6325c5f328 Mon Sep 17 00:00:00 2001
From: Andrew Deason <adeason@sinenomine.net>
Date: Sat, 4 Apr 2020 22:35:07 -0500
-Subject: [PATCH 3/5] Use autoconf-archive m4 from src/external
+Subject: [PATCH 03/12] Use autoconf-archive m4 from src/external
Switch to using the m4 macros from autoconf-archive in our
src/external mechanism, instead of manually-copied versions in src/cf.
@@ -12,12 +12,13 @@ also a few new macros pulled in, but they are currently unused.
Increase our AC_PREREQ in configure.ac to 2.64, to match the AC_PREREQ
in some of the new files.
-Change-Id: I8acfe4df7b9a22d9b9e69004c3438034a2dacadb
Reviewed-on: https://gerrit.openafs.org/14135
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit ca847ddf35e336a8bc3159ce4b26f0162417bbd5)
+
+Change-Id: Ifa43b3869e426fada5bd925b0ae002a0f6436232
---
LICENSE | 15 +++++++++++++++
configure.ac | 2 +-
@@ -80,5 +81,5 @@ index 3ada36c6b..3ae1987f0 100755
echo "No aclocal found on your system (looked for aclocal & aclocal-1.10)"
exit 1
--
-2.35.1
+2.36.1
diff --git a/0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch b/0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
index 4c616e73cfd0..8abbb89b5bf0 100644
--- a/0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
+++ b/0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
@@ -1,7 +1,7 @@
-From 1f504c13f7203f7a2122f789ea1d70d8c3182e71 Mon Sep 17 00:00:00 2001
+From a714e865efe41aa1112f6f9c8479112660dacd6f Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Thu, 27 Jan 2022 20:19:17 -0700
-Subject: [PATCH 4/5] Linux-5.17: kernel func complete_and_exit renamed
+Subject: [PATCH 04/12] Linux-5.17: kernel func complete_and_exit renamed
Handle the Linux kernel function rename made in commit
"exit: Rename complete_and_exit to kthread_complete_and_exit"
@@ -13,12 +13,13 @@ complete_and_exit.
Replace calls to complete_and_exit with kthread_complete_and_exit.
-Change-Id: If8db2d0abb1de8b08f511e9ff67612ef605cd603
Reviewed-on: https://gerrit.openafs.org/14882
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit a651d4db7f86a24ea6784f6f27d5c8482667267b)
+
+Change-Id: Ibe96b92a84a8f876dda4019c221c37dabde93244
---
src/afs/LINUX/osi_compat.h | 4 ++++
src/afs/afs_call.c | 18 ++++++++++--------
@@ -136,5 +137,5 @@ index 0ca3e4463..cd4afe914 100644
dnl above tests
AS_IF([test "x$ac_cv_linux_func_d_alloc_anon" = "xno"],
--
-2.35.1
+2.36.1
diff --git a/0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch b/0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch
index 5565973657ca..1cc8503ed996 100644
--- a/0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch
+++ b/0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch
@@ -1,7 +1,7 @@
-From e71816dc640462aab0870fc46cf1d56b63575f45 Mon Sep 17 00:00:00 2001
+From 449d1faf87e2841e80be38cf2b4a5cf5ff4df2d8 Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri, 28 Jan 2022 14:10:46 -0700
-Subject: [PATCH 5/5] Linux-5.17: Kernel build uses -Wcast-function-type
+Subject: [PATCH 05/12] Linux-5.17: Kernel build uses -Wcast-function-type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -35,12 +35,13 @@ Note: upstream heimdal has committed a fix for this in:
hcrypto: Fix return type for null_Init, null_Update and null_Final
(fc4b3ce49b)
-Change-Id: I05b716867016a33ca02a791ed6bc5a7d846de608
Reviewed-on: https://gerrit.openafs.org/14881
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
(cherry picked from commit 6bdfa976731ce07f3236893ecf12abb9e169b882)
+
+Change-Id: Ibd354f663d5876c421a8b4e89b8943c9e3d59ebc
---
CODING | 12 +++++++++++-
src/cf/osconf.m4 | 4 ++++
@@ -123,5 +124,5 @@ index d98fa05ad..8e98afd56 100644
CFLAGS_rand-timer-kernel.o = -I$(TOP_SRCDIR)/external/heimdal/hcrypto
CFLAGS_rand-kernel.o = -I$(TOP_SRCDIR)/external/heimdal/hcrypto
--
-2.35.1
+2.36.1
diff --git a/0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch b/0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch
new file mode 100644
index 000000000000..631d2e4b9afe
--- /dev/null
+++ b/0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch
@@ -0,0 +1,64 @@
+From 081869eb8ba1733a044468203ab82affe258b359 Mon Sep 17 00:00:00 2001
+From: Cheyenne Wills <cwills@sinenomine.net>
+Date: Wed, 30 Mar 2022 11:09:45 -0600
+Subject: [PATCH 06/12] Linux-5.18 replace set_page_dirty with dirty_folio
+
+The commits going into Linux 5.18:
+
+ fs: Add aops->dirty_folio (6f31a5a261db)
+ fs: Convert __set_page_dirty_buffers to block_dirty_folio (e621900ad2)
+ fs: Remove aops ->set_page_dirty (3a3bae50af)
+
+replaces the address_space_operations structure member set_page_dirty
+which with dirty_folio. The linux function __set_page_dirty_buffers is
+replaced by block_dirty_folio.
+
+Nothing within afs uses or implements the set_page_dirty function,
+however the structure member is required to be initialized.
+
+Add an autoconf test for the dirty_folio member and if present, set the
+address_space_operations member dirty_folio to block_dirty_folio
+instead of setting the set_page_dirty member.
+
+Change-Id: Iad6783308989f4a1390c1c94d2c571048bd4e771
+Reviewed-on: https://gerrit.openafs.org/14939
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+(cherry picked from commit 6aa129e743e882cf30c35afd67eabf82274c5fca)
+---
+ src/afs/LINUX/osi_vnodeops.c | 4 ++++
+ src/cf/linux-kernel-struct.m4 | 2 ++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index 00103a538..a0c78c04d 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -3288,7 +3288,11 @@ static struct address_space_operations afs_file_aops = {
+ .readpage = afs_linux_readpage,
+ .readpages = afs_linux_readpages,
+ .writepage = afs_linux_writepage,
++#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_DIRTY_FOLIO)
++ .dirty_folio = block_dirty_folio,
++#else
+ .set_page_dirty = __set_page_dirty_buffers,
++#endif
+ #if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
+ .write_begin = afs_linux_write_begin,
+ .write_end = afs_linux_write_end,
+diff --git a/src/cf/linux-kernel-struct.m4 b/src/cf/linux-kernel-struct.m4
+index 003d34ab8..2d8cee655 100644
+--- a/src/cf/linux-kernel-struct.m4
++++ b/src/cf/linux-kernel-struct.m4
+@@ -3,6 +3,8 @@ dnl Check for structure elements
+ AC_CHECK_LINUX_STRUCT([address_space], [backing_dev_info], [fs.h])
+ AC_CHECK_LINUX_STRUCT([address_space_operations],
+ [write_begin], [fs.h])
++dnl linux 5.18 replaced set_page_dirty with dirty_folio
++AC_CHECK_LINUX_STRUCT([address_space_operations], [dirty_folio], [fs.h])
+ AC_CHECK_LINUX_STRUCT([backing_dev_info], [name],
+ [backing-dev.h])
+ AC_CHECK_LINUX_STRUCT([cred], [session_keyring], [cred.h])
+--
+2.36.1
+
diff --git a/0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch b/0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch
new file mode 100644
index 000000000000..231d7b477038
--- /dev/null
+++ b/0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch
@@ -0,0 +1,125 @@
+From 543eef55043a975c2ede3e8d9457c1456f9186e4 Mon Sep 17 00:00:00 2001
+From: Mark Vitale <mvitale@sinenomine.net>
+Date: Wed, 23 Sep 2020 17:02:52 -0400
+Subject: [PATCH 07/12] afs: remove vestigial externs for afs_xcbhash
+
+Commit 64cc7f0ca7a44bb214396c829268a541ab286c69 "afs: Create
+afs_StaleVCache" consolidated many references to afs_xcbhash into a new
+function afs_StaleVCache. However, this left many references to 'extern
+afs_wrlock_t afs_xcbhash' that are no longer needed.
+
+But actually, many of these have not been needed since
+src/afs/afs_prototypes.h gained 'extern afs_rwlock_t afs_xcbhash' with
+commit 8f2df21ffe59e9aa66219bf24656775b584c122d
+"pull-prototypes-to-head-20020821"
+
+Remove the vestigial extern references.
+
+No functional change is incurred by this commit.
+
+Change-Id: Ie6cfb6d90c52951795378d3b42e041567d207305
+Reviewed-on: https://gerrit.openafs.org/14405
+Reviewed-by: Andrew Deason <adeason@sinenomine.net>
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+(cherry picked from commit a3fc79633fb0601bf02508bd1e64652f403e4b7e)
+---
+ src/afs/VNOPS/afs_vnop_attrs.c | 1 -
+ src/afs/VNOPS/afs_vnop_dirops.c | 1 -
+ src/afs/VNOPS/afs_vnop_link.c | 2 --
+ src/afs/VNOPS/afs_vnop_remove.c | 1 -
+ src/afs/VNOPS/afs_vnop_rename.c | 2 --
+ src/afs/VNOPS/afs_vnop_symlink.c | 1 -
+ src/afs/afs_bypasscache.c | 2 --
+ 7 files changed, 10 deletions(-)
+
+diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c
+index 645cf3c0a..0c2620ed0 100644
+--- a/src/afs/VNOPS/afs_vnop_attrs.c
++++ b/src/afs/VNOPS/afs_vnop_attrs.c
+@@ -33,7 +33,6 @@
+ #include "afs/nfsclient.h"
+ #include "afs/afs_osidnlc.h"
+
+-extern afs_rwlock_t afs_xcbhash;
+ struct afs_exporter *afs_nfsexporter;
+ extern struct vcache *afs_globalVp;
+ #if defined(AFS_HPUX110_ENV)
+diff --git a/src/afs/VNOPS/afs_vnop_dirops.c b/src/afs/VNOPS/afs_vnop_dirops.c
+index 596651324..4c67c4be4 100644
+--- a/src/afs/VNOPS/afs_vnop_dirops.c
++++ b/src/afs/VNOPS/afs_vnop_dirops.c
+@@ -29,7 +29,6 @@
+ #include "afs/afs_osidnlc.h"
+
+ extern afs_rwlock_t afs_xvcache;
+-extern afs_rwlock_t afs_xcbhash;
+
+ /* don't set CDirty in here because RPC is called synchronously */
+
+diff --git a/src/afs/VNOPS/afs_vnop_link.c b/src/afs/VNOPS/afs_vnop_link.c
+index f57b7ad49..c74aa36e7 100644
+--- a/src/afs/VNOPS/afs_vnop_link.c
++++ b/src/afs/VNOPS/afs_vnop_link.c
+@@ -24,8 +24,6 @@
+ #include "afs/nfsclient.h"
+ #include "afs/afs_osidnlc.h"
+
+-extern afs_rwlock_t afs_xcbhash;
+-
+ /* Note that we don't set CDirty here, this is OK because the link
+ * RPC is called synchronously. */
+
+diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c
+index 33bc14218..eca9eed24 100644
+--- a/src/afs/VNOPS/afs_vnop_remove.c
++++ b/src/afs/VNOPS/afs_vnop_remove.c
+@@ -28,7 +28,6 @@
+
+
+ extern afs_rwlock_t afs_xvcache;
+-extern afs_rwlock_t afs_xcbhash;
+
+
+ static void
+diff --git a/src/afs/VNOPS/afs_vnop_rename.c b/src/afs/VNOPS/afs_vnop_rename.c
+index 2d4b9c185..59a1d5032 100644
+--- a/src/afs/VNOPS/afs_vnop_rename.c
++++ b/src/afs/VNOPS/afs_vnop_rename.c
+@@ -25,8 +25,6 @@
+ #include "afs/nfsclient.h"
+ #include "afs/afs_osidnlc.h"
+
+-extern afs_rwlock_t afs_xcbhash;
+-
+ /* Note that we don't set CDirty here, this is OK because the rename
+ * RPC is called synchronously. */
+
+diff --git a/src/afs/VNOPS/afs_vnop_symlink.c b/src/afs/VNOPS/afs_vnop_symlink.c
+index e88e09ecc..c9be5f6b7 100644
+--- a/src/afs/VNOPS/afs_vnop_symlink.c
++++ b/src/afs/VNOPS/afs_vnop_symlink.c
+@@ -30,7 +30,6 @@
+ #include "afs/afs_osidnlc.h"
+
+ extern afs_rwlock_t afs_xvcache;
+-extern afs_rwlock_t afs_xcbhash;
+
+ /* Note: There is the bare bones beginning of symlink hints in the now
+ * defunct afs/afs_lookup.c file. Since they are not in use, making the call
+diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c
+index 64da1ed19..c51bd25c7 100644
+--- a/src/afs/afs_bypasscache.c
++++ b/src/afs/afs_bypasscache.c
+@@ -112,8 +112,6 @@ int cache_bypass_strategy = NEVER_BYPASS_CACHE;
+ afs_size_t cache_bypass_threshold = AFS_CACHE_BYPASS_DISABLED; /* file size > threshold triggers bypass */
+ int cache_bypass_prefetch = 1; /* Should we do prefetching ? */
+
+-extern afs_rwlock_t afs_xcbhash;
+-
+ /*
+ * This is almost exactly like the PFlush() routine in afs_pioctl.c,
+ * but that routine is static. We are about to change a file from
+--
+2.36.1
+
diff --git a/0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch b/0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch
new file mode 100644
index 000000000000..c6289b54415f
--- /dev/null
+++ b/0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch
@@ -0,0 +1,255 @@
+From 3a0dbbb40e89ae0f0ec901c5fa831a2c1a5ca9a3 Mon Sep 17 00:00:00 2001
+From: Cheyenne Wills <cwills@sinenomine.net>
+Date: Wed, 1 Jun 2022 09:10:12 -0600
+Subject: [PATCH 08/12] afs: introduce afs_alloc_ncr/afs_free_ncr
+
+There is duplicated code for initializing a nocache_read_request
+and also freeing the associated storage in certain cases. Create a set
+of helper functions that allocates and frees a nocache_read_request and
+its associated structures.
+
+afs_alloc_ncr allocates a nocache_read_request structure and if not
+UKERNEL, will allocate and initialize the associated uio and iovec
+structures.
+
+afs_free_ncr releases a noncache_read_request structure and the
+associated uio and iovec structures if not UKERNEL.
+
+Update locations that allocate/free nocache_read_request structures to
+use the new functions.
+
+Change-Id: I80c0b4eb036bcb1223b73f4c1de2c12be362de42
+---
+ src/afs/LINUX/osi_vnodeops.c | 37 +++++++-----------
+ src/afs/UKERNEL/afs_usrops.c | 8 +++-
+ src/afs/afs_bypasscache.c | 73 +++++++++++++++++++++++++++++++-----
+ src/afs/afs_bypasscache.h | 3 +-
+ 4 files changed, 85 insertions(+), 36 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index a0c78c04d..9b5d05471 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -2537,7 +2537,6 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+ struct list_head *page_list, unsigned num_pages)
+ {
+ afs_int32 page_ix;
+- struct uio *auio;
+ afs_offs_t offset;
+ struct iovec* iovecp;
+ struct nocache_read_request *ancr;
+@@ -2552,20 +2551,10 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+ afs_int32 page_count = 0;
+ afs_int32 isize;
+
+- /* background thread must free: iovecp, auio, ancr */
+- iovecp = osi_Alloc(num_pages * sizeof(struct iovec));
+-
+- auio = osi_Alloc(sizeof(struct uio));
+- auio->uio_iov = iovecp;
+- auio->uio_iovcnt = num_pages;
+- auio->uio_flag = UIO_READ;
+- auio->uio_seg = AFS_UIOSYS;
+- auio->uio_resid = num_pages * PAGE_SIZE;
+-
+- ancr = osi_Alloc(sizeof(struct nocache_read_request));
+- ancr->auio = auio;
+- ancr->offset = auio->uio_offset;
+- ancr->length = auio->uio_resid;
++ ancr = afs_alloc_ncr(num_pages);
++ if (ancr == NULL)
++ return afs_convert_code(ENOMEM);
++ iovecp = ancr->auio->uio_iov;
+
+ afs_lru_cache_init(&lrupages);
+
+@@ -2587,7 +2576,7 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+
+ if(page_ix == 0) {
+ offset = page_offset(pp);
+- ancr->offset = auio->uio_offset = offset;
++ ancr->offset = ancr->auio->uio_offset = offset;
+ base_index = pp->index;
+ }
+ iovecp[page_ix].iov_len = PAGE_SIZE;
+@@ -2626,14 +2615,13 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+ if(page_count) {
+ afs_lru_cache_finalize(&lrupages);
+ credp = crref();
++ /* background thread frees the ancr */
+ code = afs_ReadNoCache(avc, ancr, credp);
+ crfree(credp);
+ } else {
+ /* If there is nothing for the background thread to handle,
+ * it won't be freeing the things that we never gave it */
+- osi_Free(iovecp, num_pages * sizeof(struct iovec));
+- osi_Free(auio, sizeof(struct uio));
+- osi_Free(ancr, sizeof(struct nocache_read_request));
++ afs_free_ncr(&ancr);
+ }
+ /* we do not flush, release, or unmap pages--that will be
+ * done for us by the background thread as each page comes in
+@@ -2665,8 +2653,13 @@ afs_linux_bypass_readpage(struct file *fp, struct page *pp)
+ ClearPageError(pp);
+
+ /* receiver frees */
+- auio = osi_Alloc(sizeof(struct uio));
+- iovecp = osi_Alloc(sizeof(struct iovec));
++ ancr = afs_alloc_ncr(1);
++ if (ancr == NULL) {
++ SetPageError(pp);
++ return afs_convert_code(ENOMEM);
++ }
++ auio = ancr->auio;
++ iovecp = auio->uio_iov;
+
+ /* address can be NULL, because we overwrite it with 'pp', below */
+ setup_uio(auio, iovecp, NULL, page_offset(pp),
+@@ -2676,8 +2669,6 @@ afs_linux_bypass_readpage(struct file *fp, struct page *pp)
+ get_page(pp); /* see above */
+ auio->uio_iov->iov_base = (void*) pp;
+ /* the background thread will free this */
+- ancr = osi_Alloc(sizeof(struct nocache_read_request));
+- ancr->auio = auio;
+ ancr->offset = page_offset(pp);
+ ancr->length = PAGE_SIZE;
+
+diff --git a/src/afs/UKERNEL/afs_usrops.c b/src/afs/UKERNEL/afs_usrops.c
+index 0e38fb84b..80403c5bd 100644
+--- a/src/afs/UKERNEL/afs_usrops.c
++++ b/src/afs/UKERNEL/afs_usrops.c
+@@ -2398,12 +2398,16 @@ uafs_pread_nocache_r(int fd, char *buf, int len, off_t offset)
+ }
+
+ /* these get freed in PrefetchNoCache, so... */
+- bparms = afs_osi_Alloc(sizeof(struct nocache_read_request));
++ bparms = afs_alloc_ncr(0);
++ if (bparms == NULL) {
++ errno = ENOMEM;
++ return -1;
++ }
+
+ code = afs_CreateReq(&bparms->areq, get_user_struct()->u_cred);
+ if (code) {
+ afs_DestroyReq(bparms->areq);
+- afs_osi_Free(bparms, sizeof(struct nocache_read_request));
++ afs_free_ncr(&bparms);
+ errno = code;
+ return -1;
+ }
+diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c
+index c51bd25c7..e13a32e9d 100644
+--- a/src/afs/afs_bypasscache.c
++++ b/src/afs/afs_bypasscache.c
+@@ -111,7 +111,68 @@
+ int cache_bypass_strategy = NEVER_BYPASS_CACHE;
+ afs_size_t cache_bypass_threshold = AFS_CACHE_BYPASS_DISABLED; /* file size > threshold triggers bypass */
+ int cache_bypass_prefetch = 1; /* Should we do prefetching ? */
++/*
++ * Allocate and initialize nocache_read_request/uid/iovec
++ * Returns NULL if memory allocation error.
++ */
++struct nocache_read_request *
++afs_alloc_ncr(unsigned num_pages)
++{
++ struct nocache_read_request *ancr = NULL;
++#if !defined(UKERNEL)
++ struct uio *auio = NULL;
++ struct iovec *iovecp = NULL;
++#endif
++
++ ancr = osi_Alloc(sizeof(*ancr));
++ if (ancr == NULL)
++ goto error;
+
++#if !defined(UKERNEL)
++ iovecp = osi_Alloc(num_pages * sizeof(*iovecp));
++ if (iovecp == NULL)
++ goto error;
++
++ auio = osi_Alloc(sizeof(*auio));
++ if (auio == NULL)
++ goto error;
++ auio->uio_iov = iovecp;
++ auio->uio_iovcnt = num_pages;
++ auio->uio_flag = UIO_READ;
++ auio->uio_seg = AFS_UIOSYS;
++ auio->uio_offset = 0;
++ auio->uio_resid = num_pages * PAGE_SIZE;
++
++ ancr->auio = auio;
++ ancr->offset = auio->uio_offset;
++ ancr->length = auio->uio_resid;
++#endif
++
++ return ancr;
++
++ error:
++#if !defined(UKERNEL)
++ osi_Free(iovecp, num_pages * sizeof(*iovecp));
++ osi_Free(auio, sizeof(*auio));
++#endif
++ osi_Free(ancr, sizeof(*ancr));
++ return NULL;
++}
++/*
++ * Free a nocache_read_request and associated structures
++ */
++void
++afs_free_ncr(struct nocache_read_request **ancr)
++{
++ if (*ancr == NULL)
++ return;
++#if !defined(UKERNEL)
++ osi_Free((*ancr)->auio->uio_iov, (*ancr)->auio->uio_iovcnt * sizeof(struct iovec));
++ osi_Free((*ancr)->auio, sizeof(struct uio));
++#endif
++ osi_Free(*ancr, sizeof(struct nocache_read_request));
++ *ancr = NULL;
++}
+ /*
+ * This is almost exactly like the PFlush() routine in afs_pioctl.c,
+ * but that routine is static. We are about to change a file from
+@@ -517,10 +578,7 @@ cleanup:
+ AFS_GLOCK();
+ afs_DestroyReq(areq);
+ AFS_GUNLOCK();
+- osi_Free(bparms->auio->uio_iov,
+- bparms->auio->uio_iovcnt * sizeof(struct iovec));
+- osi_Free(bparms->auio, sizeof(struct uio));
+- osi_Free(bparms, sizeof(struct nocache_read_request));
++ afs_free_ncr(&bparms);
+ return code;
+ }
+
+@@ -647,12 +705,7 @@ done:
+
+ afs_DestroyReq(areq);
+ osi_Free(tcallspec, sizeof(struct tlocal1));
+- osi_Free(bparms, sizeof(struct nocache_read_request));
+-#ifndef UKERNEL
+- /* in UKERNEL, the "pages" are passed in */
+- osi_Free(iovecp, auio->uio_iovcnt * sizeof(struct iovec));
+- osi_Free(auio, sizeof(struct uio));
+-#endif
++ afs_free_ncr(&bparms);
+ return code;
+ }
+ #endif
+diff --git a/src/afs/afs_bypasscache.h b/src/afs/afs_bypasscache.h
+index 37c5669b3..0c7542dd6 100644
+--- a/src/afs/afs_bypasscache.h
++++ b/src/afs/afs_bypasscache.h
+@@ -103,7 +103,8 @@ enum cache_bypass_strategies
+ extern int cache_bypass_prefetch;
+ extern int cache_bypass_strategy;
+ extern afs_size_t cache_bypass_threshold;
+-
++struct nocache_read_request *afs_alloc_ncr(unsigned num_pages);
++void afs_free_ncr(struct nocache_read_request **ancr);
+ void afs_TransitionToBypass(struct vcache *, afs_ucred_t *, int);
+ void afs_TransitionToCaching(struct vcache *, afs_ucred_t *, int);
+
+--
+2.36.1
+
diff --git a/0009-LINUX-Don-t-panic-on-some-file-open-errors.patch b/0009-LINUX-Don-t-panic-on-some-file-open-errors.patch
new file mode 100644
index 000000000000..9c2e2149ecfb
--- /dev/null
+++ b/0009-LINUX-Don-t-panic-on-some-file-open-errors.patch
@@ -0,0 +1,127 @@
+From 932347ddb95eca41ee4365b8ea32d282c692eaba Mon Sep 17 00:00:00 2001
+From: Cheyenne Wills <cwills@sinenomine.net>
+Date: Thu, 2 Jul 2020 13:39:27 -0600
+Subject: [PATCH 09/12] LINUX: Don't panic on some file open errors
+
+Commit 'LINUX: Return NULL for afs_linux_raw_open error' (f6af4a155)
+updated afs_linux_raw_open to return NULL on some errors, but still
+panics if obtaining the dentry fails.
+
+Commit 'afs: Verify osi_UFSOpen worked' (c6b61a451) updated callers of
+osi_UFSOpen to verify whether or not the open was successful. This
+meant osi_UFSOpen (and routines it calls) could pass back an error
+indication rather than panic when an error is encountered.
+
+Update afs_linux_raw_open to return a failure instead of panic if unable
+to obtain a dentry.
+
+Update osi_UFSOpen to return a NULL instead of panic if unable to obtain
+memory or fails to open the file. All callers of osi_UFSOpen handle a
+fail return, though some will still issue a panic.
+
+Update afs_linux_readpage_fastpath and afs_linux_readpages to not panic
+if afs_linux_raw_open fails. Instead of panic, return an error.
+
+For testing, an error can be forced by removing a file from the
+cache directory.
+
+Note this work is based on a commit by pruiter@sinenomine.net
+
+Change-Id: Ic47e4868b4f81d99fbe3b2e4958778508ae4851f
+Reviewed-on: https://gerrit.openafs.org/14242
+Reviewed-by: Andrew Deason <adeason@sinenomine.net>
+Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+(cherry picked from commit af73b9a3b1fc625694807287c0897391feaad52d)
+---
+ src/afs/LINUX/osi_file.c | 15 +++++++++++----
+ src/afs/LINUX/osi_vnodeops.c | 17 +++++++++++++----
+ 2 files changed, 24 insertions(+), 8 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c
+index 03777f563..004799c4c 100644
+--- a/src/afs/LINUX/osi_file.c
++++ b/src/afs/LINUX/osi_file.c
+@@ -65,8 +65,12 @@ afs_linux_raw_open(afs_dcache_id_t *ainode)
+
+ dp = afs_get_dentry_from_fh(afs_cacheSBp, ainode, cache_fh_len, cache_fh_type,
+ afs_fh_acceptable);
+- if ((!dp) || IS_ERR(dp))
+- osi_Panic("Can't get dentry\n");
++ if ((!dp) || IS_ERR(dp)) {
++ afs_warn("afs: Cannot get dentry for cache file (code %d). Trying to continue, "
++ "but AFS accesses may return errors or panic the system\n",
++ (int) PTR_ERR(dp));
++ return NULL;
++ }
+ tip = dp->d_inode;
+ tip->i_flags |= S_NOATIME; /* Disable updating access times. */
+
+@@ -115,8 +119,11 @@ osi_UFSOpen(afs_dcache_id_t *ainode)
+ AFS_GUNLOCK();
+ afile = kmalloc(sizeof(struct osi_file), GFP_NOFS);
+ if (!afile) {
+- osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
+- (int)sizeof(struct osi_file));
++ afs_warn("afs: Failed to allocate memory for opening a cache file. "
++ "Trying to continue, but AFS access may return errors or panic "
++ "the system\n");
++ AFS_GLOCK();
++ return NULL;
+ }
+ memset(afile, 0, sizeof(struct osi_file));
+
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index 9b5d05471..1631d3d3d 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -2398,7 +2398,11 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
+ /* XXX - I suspect we should be locking the inodes before we use them! */
+ AFS_GUNLOCK();
+ cacheFp = afs_linux_raw_open(&tdc->f.inode);
+- osi_Assert(cacheFp);
++ if (cacheFp == NULL) {
++ /* Problem getting the inode */
++ AFS_GLOCK();
++ goto out;
++ }
+ if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) {
+ cachefs_noreadpage = 1;
+ AFS_GLOCK();
+@@ -2785,8 +2789,10 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ afs_PutDCache(tdc);
+ AFS_GUNLOCK();
+ tdc = NULL;
+- if (cacheFp)
++ if (cacheFp) {
+ filp_close(cacheFp, NULL);
++ cacheFp = NULL;
++ }
+ }
+
+ if (!tdc) {
+@@ -2803,7 +2809,10 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ AFS_GUNLOCK();
+ if (tdc) {
+ cacheFp = afs_linux_raw_open(&tdc->f.inode);
+- osi_Assert(cacheFp);
++ if (cacheFp == NULL) {
++ /* Problem getting the inode */
++ goto out;
++ }
+ if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) {
+ cachefs_noreadpage = 1;
+ goto out;
+@@ -2824,7 +2833,7 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ afs_lru_cache_finalize(&lrupages);
+
+ out:
+- if (tdc)
++ if (cacheFp)
+ filp_close(cacheFp, NULL);
+
+ afs_pagecopy_put_task(task);
+--
+2.36.1
+
diff --git a/0010-afs-Introduce-afs_IsDCacheFresh.patch b/0010-afs-Introduce-afs_IsDCacheFresh.patch
new file mode 100644
index 000000000000..eb9a3669eae8
--- /dev/null
+++ b/0010-afs-Introduce-afs_IsDCacheFresh.patch
@@ -0,0 +1,371 @@
+From 2fcade1caea1e81f8b5b54c5c08e363649a4664c Mon Sep 17 00:00:00 2001
+From: Andrew Deason <adeason@sinenomine.net>
+Date: Thu, 17 Jan 2019 15:45:36 -0600
+Subject: [PATCH 10/12] afs: Introduce afs_IsDCacheFresh
+
+Numerous places in libafs check the DV of a dcache against the DV of
+the vcache for the same file, in order to check if the dcache is up to
+date and can be used. Consolidate all of these checks into a new
+function, afs_IsDCacheFresh, to make it easier for future commits to
+alter this logic.
+
+This commit should have no visible impact; it is just code
+reorganization.
+
+Change-Id: Iedc02b0f5d7d0542ab00ff1effdde03c2a851df4
+Reviewed-on: https://gerrit.openafs.org/13435
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+Tested-by: Andrew Deason <adeason@sinenomine.net>
+(cherry picked from commit 0d8ce846ab2e6c45166a61f04eb3af271cbd27db)
+---
+ src/afs/LINUX/osi_export.c | 8 ++++----
+ src/afs/LINUX/osi_vnodeops.c | 8 ++++----
+ src/afs/SOLARIS/osi_vnodeops.c | 6 +++---
+ src/afs/VNOPS/afs_vnop_create.c | 4 ++--
+ src/afs/VNOPS/afs_vnop_lookup.c | 8 ++++----
+ src/afs/VNOPS/afs_vnop_read.c | 4 ++--
+ src/afs/VNOPS/afs_vnop_readdir.c | 4 ++--
+ src/afs/VNOPS/afs_vnop_remove.c | 2 +-
+ src/afs/VNOPS/afs_vnop_rename.c | 2 +-
+ src/afs/afs_dcache.c | 30 ++++++++++++++++++++++++------
+ src/afs/afs_prototypes.h | 1 +
+ 11 files changed, 48 insertions(+), 29 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_export.c b/src/afs/LINUX/osi_export.c
+index a3175b5d5..926bd0df9 100644
+--- a/src/afs/LINUX/osi_export.c
++++ b/src/afs/LINUX/osi_export.c
+@@ -349,7 +349,7 @@ redo:
+ */
+ while ((adp->f.states & CStatd)
+ && (tdc->dflags & DFFetching)
+- && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
++ && afs_IsDCacheFresh(tdc, adp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseSharedLock(&adp->lock);
+ afs_osi_Sleep(&tdc->validPos);
+@@ -357,7 +357,7 @@ redo:
+ ObtainReadLock(&tdc->lock);
+ }
+ if (!(adp->f.states & CStatd)
+- || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, adp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseSharedLock(&adp->lock);
+ afs_PutDCache(tdc);
+@@ -770,7 +770,7 @@ redo:
+ */
+ while ((vcp->f.states & CStatd)
+ && (tdc->dflags & DFFetching)
+- && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
++ && afs_IsDCacheFresh(tdc, vcp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&vcp->lock);
+ afs_osi_Sleep(&tdc->validPos);
+@@ -778,7 +778,7 @@ redo:
+ ObtainReadLock(&tdc->lock);
+ }
+ if (!(vcp->f.states & CStatd)
+- || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, vcp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&vcp->lock);
+ afs_PutDCache(tdc);
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index 1631d3d3d..9f164f395 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -447,7 +447,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
+ */
+ while ((avc->f.states & CStatd)
+ && (tdc->dflags & DFFetching)
+- && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ && afs_IsDCacheFresh(tdc, avc)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseWriteLock(&avc->lock);
+ afs_osi_Sleep(&tdc->validPos);
+@@ -455,7 +455,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
+ ObtainReadLock(&tdc->lock);
+ }
+ if (!(avc->f.states & CStatd)
+- || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, avc)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseWriteLock(&avc->lock);
+ afs_PutDCache(tdc);
+@@ -2386,7 +2386,7 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
+ ObtainReadLock(&tdc->lock);
+
+ /* Is the dcache we've been given currently up to date */
+- if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) ||
++ if (!afs_IsDCacheFresh(tdc, avc) ||
+ (tdc->dflags & DFFetching))
+ goto out;
+
+@@ -2799,7 +2799,7 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ AFS_GLOCK();
+ if ((tdc = afs_FindDCache(avc, offset))) {
+ ObtainReadLock(&tdc->lock);
+- if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) ||
++ if (!afs_IsDCacheFresh(tdc, avc) ||
+ (tdc->dflags & DFFetching)) {
+ ReleaseReadLock(&tdc->lock);
+ afs_PutDCache(tdc);
+diff --git a/src/afs/SOLARIS/osi_vnodeops.c b/src/afs/SOLARIS/osi_vnodeops.c
+index fde268401..76b55b351 100644
+--- a/src/afs/SOLARIS/osi_vnodeops.c
++++ b/src/afs/SOLARIS/osi_vnodeops.c
+@@ -350,7 +350,7 @@ afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen, u_int *protp,
+
+ /* Check to see whether the cache entry is still valid */
+ if (!(avc->f.states & CStatd)
+- || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, avc)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&avc->lock);
+ afs_PutDCache(tdc);
+@@ -882,12 +882,12 @@ afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
+ AFS_GLOCK();
+ dcp_newpage = afs_FindDCache(avc, pageBase);
+ if (dcp_newpage
+- && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)) {
++ && afs_IsDCacheFresh(dcp_newpage, avc)) {
+ ObtainWriteLock(&avc->lock, 251);
+ ObtainWriteLock(&avc->vlock, 576);
+ ObtainReadLock(&dcp_newpage->lock);
+ if ((avc->activeV == 0)
+- && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)
++ && afs_IsDCacheFresh(dcp_newpage, avc)
+ && !(dcp_newpage->dflags & (DFFetching))) {
+ AFS_GUNLOCK();
+ segmap_pagecreate(segkmap, raddr, rsize, 1);
+diff --git a/src/afs/VNOPS/afs_vnop_create.c b/src/afs/VNOPS/afs_vnop_create.c
+index fe37eed36..70b531a6a 100644
+--- a/src/afs/VNOPS/afs_vnop_create.c
++++ b/src/afs/VNOPS/afs_vnop_create.c
+@@ -149,7 +149,7 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
+ * received a callback while we were waiting for the write lock.
+ */
+ if (!(adp->f.states & CStatd)
+- || (tdc && !hsame(adp->f.m.DataVersion, tdc->f.versionNo))) {
++ || (tdc && !afs_IsDCacheFresh(tdc, adp))) {
+ ReleaseWriteLock(&adp->lock);
+ if (tdc) {
+ ReleaseSharedLock(&tdc->lock);
+@@ -543,7 +543,7 @@ afs_LocalHero(struct vcache *avc, struct dcache *adc,
+ if (adc) {
+ /* does what's in the dcache *now* match what's in the vcache *now*,
+ * and do we have a valid callback? if not, our local copy is not "ok" */
+- ok = (hsame(avc->f.m.DataVersion, adc->f.versionNo) && avc->callback
++ ok = (afs_IsDCacheFresh(adc, avc) && avc->callback
+ && (avc->f.states & CStatd) && avc->cbExpires >= osi_Time());
+ } else {
+ ok = 0;
+diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c
+index b42d6db43..f47a505a7 100644
+--- a/src/afs/VNOPS/afs_vnop_lookup.c
++++ b/src/afs/VNOPS/afs_vnop_lookup.c
+@@ -752,7 +752,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
+ */
+ while ((adp->f.states & CStatd)
+ && (dcp->dflags & DFFetching)
+- && hsame(adp->f.m.DataVersion, dcp->f.versionNo)) {
++ && afs_IsDCacheFresh(dcp, adp)) {
+ afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
+ __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, dcp,
+ ICL_TYPE_INT32, dcp->dflags);
+@@ -763,7 +763,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
+ ObtainReadLock(&dcp->lock);
+ }
+ if (!(adp->f.states & CStatd)
+- || !hsame(adp->f.m.DataVersion, dcp->f.versionNo)) {
++ || !afs_IsDCacheFresh(dcp, adp)) {
+ ReleaseReadLock(&dcp->lock);
+ ReleaseReadLock(&adp->lock);
+ afs_PutDCache(dcp);
+@@ -1685,7 +1685,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
+ if (!afs_InReadDir(adp)) {
+ while ((adp->f.states & CStatd)
+ && (tdc->dflags & DFFetching)
+- && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
++ && afs_IsDCacheFresh(tdc, adp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&adp->lock);
+ afs_osi_Sleep(&tdc->validPos);
+@@ -1693,7 +1693,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
+ ObtainReadLock(&tdc->lock);
+ }
+ if (!(adp->f.states & CStatd)
+- || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, adp)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&adp->lock);
+ afs_PutDCache(tdc);
+diff --git a/src/afs/VNOPS/afs_vnop_read.c b/src/afs/VNOPS/afs_vnop_read.c
+index dba411715..e5c664207 100644
+--- a/src/afs/VNOPS/afs_vnop_read.c
++++ b/src/afs/VNOPS/afs_vnop_read.c
+@@ -190,7 +190,7 @@ afs_read(struct vcache *avc, struct uio *auio, afs_ucred_t *acred,
+ * 2 requests never return a null dcache entry, btw.
+ */
+ if (!(tdc->dflags & DFFetching)
+- && !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ && !afs_IsDCacheFresh(tdc, avc)) {
+ /* have cache entry, it is not coming in now,
+ * and we'll need new data */
+ tagain:
+@@ -270,7 +270,7 @@ afs_read(struct vcache *avc, struct uio *auio, afs_ucred_t *acred,
+ } else {
+ /* no longer fetching, verify data version
+ * (avoid new GetDCache call) */
+- if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)
++ if (afs_IsDCacheFresh(tdc, avc)
+ && ((len = tdc->validPos - filePos) > 0)) {
+ offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
+ } else {
+diff --git a/src/afs/VNOPS/afs_vnop_readdir.c b/src/afs/VNOPS/afs_vnop_readdir.c
+index cdc5af56d..8d41c3ef2 100644
+--- a/src/afs/VNOPS/afs_vnop_readdir.c
++++ b/src/afs/VNOPS/afs_vnop_readdir.c
+@@ -702,7 +702,7 @@ afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
+ */
+ while ((avc->f.states & CStatd)
+ && (tdc->dflags & DFFetching)
+- && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ && afs_IsDCacheFresh(tdc, avc)) {
+ afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
+ __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
+ ICL_TYPE_INT32, tdc->dflags);
+@@ -713,7 +713,7 @@ afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
+ ObtainReadLock(&tdc->lock);
+ }
+ if (!(avc->f.states & CStatd)
+- || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc, avc)) {
+ ReleaseReadLock(&tdc->lock);
+ ReleaseReadLock(&avc->lock);
+ afs_PutDCache(tdc);
+diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c
+index eca9eed24..06a84b060 100644
+--- a/src/afs/VNOPS/afs_vnop_remove.c
++++ b/src/afs/VNOPS/afs_vnop_remove.c
+@@ -234,7 +234,7 @@ afs_remove(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
+ * received a callback while we were waiting for the write lock.
+ */
+ if (!(adp->f.states & CStatd)
+- || (tdc && !hsame(adp->f.m.DataVersion, tdc->f.versionNo))) {
++ || (tdc && !afs_IsDCacheFresh(tdc, adp))) {
+ ReleaseWriteLock(&adp->lock);
+ if (tdc) {
+ ReleaseSharedLock(&tdc->lock);
+diff --git a/src/afs/VNOPS/afs_vnop_rename.c b/src/afs/VNOPS/afs_vnop_rename.c
+index 59a1d5032..d61c80e29 100644
+--- a/src/afs/VNOPS/afs_vnop_rename.c
++++ b/src/afs/VNOPS/afs_vnop_rename.c
+@@ -133,7 +133,7 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
+ */
+ if (tdc1) {
+ if (!(aodp->f.states & CStatd)
+- || !hsame(aodp->f.m.DataVersion, tdc1->f.versionNo)) {
++ || !afs_IsDCacheFresh(tdc1, aodp)) {
+
+ ReleaseWriteLock(&aodp->lock);
+ if (!oneDir) {
+diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c
+index 6a18f80d5..ac9e52269 100644
+--- a/src/afs/afs_dcache.c
++++ b/src/afs/afs_dcache.c
+@@ -1734,6 +1734,24 @@ afs_AllocDCache(struct vcache *avc, afs_int32 chunk, afs_int32 lock,
+ return tdc;
+ }
+
++/*!
++ * Check if a dcache is "fresh". That is, if the dcache's DV matches the DV of
++ * the vcache for that file.
++ *
++ * \param adc The dcache to check
++ * \param avc The vcache for adc
++ *
++ * \return 1 if the dcache does match avc's DV; 0 otherwise.
++ */
++int
++afs_IsDCacheFresh(struct dcache *adc, struct vcache *avc)
++{
++ if (!hsame(adc->f.versionNo, avc->f.m.DataVersion)) {
++ return 0;
++ }
++ return 1;
++}
++
+ /*
+ * afs_GetDCache
+ *
+@@ -1772,7 +1790,7 @@ void
+ updateV2DC(int lockVc, struct vcache *v, struct dcache *d, int src)
+ {
+ if (!lockVc || 0 == NBObtainWriteLock(&v->lock, src)) {
+- if (hsame(v->f.m.DataVersion, d->f.versionNo) && v->callback)
++ if (afs_IsDCacheFresh(d, v) && v->callback)
+ v->dchint = d;
+ if (lockVc)
+ ReleaseWriteLock(&v->lock);
+@@ -1882,7 +1900,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
+ ReleaseReadLock(&afs_xdcache);
+ shortcut = 1;
+
+- if (hsame(tdc->f.versionNo, avc->f.m.DataVersion)
++ if (afs_IsDCacheFresh(tdc, avc)
+ && !(tdc->dflags & DFFetching)) {
+
+ afs_stats_cmperf.dcacheHits++;
+@@ -2119,7 +2137,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
+ if (AFS_CHUNKTOBASE(chunk) >= avc->f.m.Length &&
+ #endif
+ #endif /* defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV) */
+- !hsame(avc->f.m.DataVersion, tdc->f.versionNo))
++ !afs_IsDCacheFresh(tdc, avc))
+ doReallyAdjustSize = 1;
+
+ if (doReallyAdjustSize || overWriteWholeChunk) {
+@@ -2183,7 +2201,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
+ * avc->lock(W) if !setLocks || slowPass
+ * tdc->lock(S)
+ */
+- if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) && !overWriteWholeChunk) {
++ if (!afs_IsDCacheFresh(tdc, avc) && !overWriteWholeChunk) {
+ /*
+ * Version number mismatch.
+ */
+@@ -2253,7 +2271,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
+ */
+
+ /* Watch for standard race condition around osi_FlushText */
+- if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
++ if (afs_IsDCacheFresh(tdc, avc)) {
+ updateV2DC(setLocks, avc, tdc, 569); /* set hint */
+ afs_stats_cmperf.dcacheHits++;
+ ConvertWToSLock(&tdc->lock);
+@@ -3592,7 +3610,7 @@ afs_ObtainDCacheForWriting(struct vcache *avc, afs_size_t filePos,
+ tdc = afs_FindDCache(avc, filePos);
+ if (tdc) {
+ ObtainWriteLock(&tdc->lock, 658);
+- if (!hsame(tdc->f.versionNo, avc->f.m.DataVersion)
++ if (!afs_IsDCacheFresh(tdc, avc)
+ || (tdc->dflags & DFFetching)) {
+ ReleaseWriteLock(&tdc->lock);
+ afs_PutDCache(tdc);
+diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
+index b9fd0782b..c8ed43fa7 100644
+--- a/src/afs/afs_prototypes.h
++++ b/src/afs/afs_prototypes.h
+@@ -288,6 +288,7 @@ extern struct dcache *afs_ObtainDCacheForWriting(struct vcache *avc,
+ int noLock);
+ extern void afs_PopulateDCache(struct vcache *avc, afs_size_t apos,
+ struct vrequest *areq);
++extern int afs_IsDCacheFresh(struct dcache *adc, struct vcache *avc);
+
+ /* afs_disconnected.c */
+
+--
+2.36.1
+
diff --git a/0011-afs-introduce-get_dcache_readahead.patch b/0011-afs-introduce-get_dcache_readahead.patch
new file mode 100644
index 000000000000..0b58ed1a1406
--- /dev/null
+++ b/0011-afs-introduce-get_dcache_readahead.patch
@@ -0,0 +1,146 @@
+From 61b3bebcb0cade613e92be738c726cd0fc264658 Mon Sep 17 00:00:00 2001
+From: Cheyenne Wills <cwills@sinenomine.net>
+Date: Wed, 1 Jun 2022 08:59:11 -0600
+Subject: [PATCH 11/12] afs: introduce get_dcache_readahead
+
+Relocate the block of code that obtains the dcache for a readahead
+operation from the afs_linux_readpages function into its own static
+function.
+
+Change-Id: Iaaf9523532e292a1f2426d5ced65ddfbceb5d060
+---
+ src/afs/LINUX/osi_vnodeops.c | 111 +++++++++++++++++++++++------------
+ 1 file changed, 75 insertions(+), 36 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index 9f164f395..893f8afff 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -2733,6 +2733,78 @@ afs_linux_readpage(struct file *fp, struct page *pp)
+
+ return code;
+ }
++/*
++ * Updates the tdc and cacheFp parameters
++ * Returns:
++ * 0 - success
++ * -1 - problem getting inode or no mapping function
++ */
++static int
++get_dcache_readahead(struct dcache **adc, struct file **acacheFp,
++ struct vcache *avc, loff_t offset)
++{
++ struct dcache *tdc = *adc;
++ struct file *cacheFp = *acacheFp;
++ int code = 0;
++
++ if (tdc != NULL && (tdc)->f.chunk != AFS_CHUNK(offset)) {
++ AFS_GLOCK();
++ ReleaseReadLock(&tdc->lock);
++ afs_PutDCache(tdc);
++ AFS_GUNLOCK();
++ tdc = NULL;
++ if (cacheFp != NULL) {
++ filp_close(cacheFp, NULL);
++ cacheFp = NULL;
++ }
++ }
++
++ if (tdc != NULL) {
++ AFS_GLOCK();
++ if ((tdc = afs_FindDCache(avc, offset))) {
++ ObtainReadLock(&tdc->lock);
++ if (!afs_IsDCacheFresh(tdc, avc) ||
++ ((tdc)->dflags & DFFetching)) {
++ ReleaseReadLock(&tdc->lock);
++ afs_PutDCache(tdc);
++ tdc = NULL;
++ }
++ }
++ AFS_GUNLOCK();
++ if (tdc != NULL) {
++ cacheFp = afs_linux_raw_open(&tdc->f.inode);
++ if (cacheFp == NULL) {
++ /* Problem getting the inode */
++ code = -1;
++ goto out;
++ }
++ if (!(cacheFp)->f_dentry->d_inode->i_mapping->a_ops->readpage) {
++ cachefs_noreadpage = 1;
++ /* No mapping function */
++ code = -1;
++ goto out;
++ }
++ }
++ }
++
++ out:
++ if (code) {
++ if (cacheFp != NULL) {
++ filp_close(cacheFp, NULL);
++ cacheFp = NULL;
++ }
++ if (tdc != NULL) {
++ AFS_GLOCK();
++ ReleaseReadLock(&tdc->lock);
++ afs_PutDCache(tdc);
++ AFS_GUNLOCK();
++ tdc = NULL;
++ }
++ }
++ *adc = tdc;
++ *acacheFp = cacheFp;
++ return code;
++}
+
+ /* Readpages reads a number of pages for a particular file. We use
+ * this to optimise the reading, by limiting the number of times upon which
+@@ -2783,42 +2855,9 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ list_del(&page->lru);
+ offset = page_offset(page);
+
+- if (tdc && tdc->f.chunk != AFS_CHUNK(offset)) {
+- AFS_GLOCK();
+- ReleaseReadLock(&tdc->lock);
+- afs_PutDCache(tdc);
+- AFS_GUNLOCK();
+- tdc = NULL;
+- if (cacheFp) {
+- filp_close(cacheFp, NULL);
+- cacheFp = NULL;
+- }
+- }
+-
+- if (!tdc) {
+- AFS_GLOCK();
+- if ((tdc = afs_FindDCache(avc, offset))) {
+- ObtainReadLock(&tdc->lock);
+- if (!afs_IsDCacheFresh(tdc, avc) ||
+- (tdc->dflags & DFFetching)) {
+- ReleaseReadLock(&tdc->lock);
+- afs_PutDCache(tdc);
+- tdc = NULL;
+- }
+- }
+- AFS_GUNLOCK();
+- if (tdc) {
+- cacheFp = afs_linux_raw_open(&tdc->f.inode);
+- if (cacheFp == NULL) {
+- /* Problem getting the inode */
+- goto out;
+- }
+- if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) {
+- cachefs_noreadpage = 1;
+- goto out;
+- }
+- }
+- }
++ code = get_dcache_readahead(&tdc, &cacheFp, avc, offset);
++ if (code)
++ goto out;
+
+ if (tdc && !add_to_page_cache(page, mapping, page->index,
+ GFP_KERNEL)) {
+--
+2.36.1
+
diff --git a/0012-Linux-5.18-replace-readpages-with-readahead.patch b/0012-Linux-5.18-replace-readpages-with-readahead.patch
new file mode 100644
index 000000000000..b7c474c6f2da
--- /dev/null
+++ b/0012-Linux-5.18-replace-readpages-with-readahead.patch
@@ -0,0 +1,304 @@
+From 7daef2e2bd350a1bee8bdbe6fdce3923c7867299 Mon Sep 17 00:00:00 2001
+From: Cheyenne Wills <cwills@sinenomine.net>
+Date: Tue, 31 May 2022 14:43:33 -0600
+Subject: [PATCH 12/12] Linux-5.18: replace readpages with readahead
+
+The linux 5.18 the commit 'fs: Remove ->readpages address space
+operation' (704528d8) removes the address_space_operations operation
+"readpages" which is replaced with the "readahead" operation
+that was introduced with the 5.8 commit 'mm: add readahead address
+space operation' (8151b4c8).
+
+The address_space_operation function, readahead is called by the VM
+to read pages. A filesystem provides an implementation to handle this
+operation.
+
+When readahead is called, the list of pages have already been added to
+the lru caches and are locked. The implementation of the readahead
+function needs to handle decrementing the reference count, unlocking the
+page and setting PageUptoDate when the IO has completed successfully. IO
+errors are ignored by the vfs during readahead (errors will be detected
+later in the vfs processing). We must simply unlock the page if an error
+occurs.
+ (See Linux Documentation/filesystems/vfs.rst)
+
+Add an autoconf test to detect the presence of 'readahead' in the
+address_space_operations structure.
+
+For the implementation of readahead (which is contained in Linux's
+osi_vnodeops.c):
+
+Add new functions 'afs_linux_bypass_readahead' and 'afs_linux_readahead'
+as replacements for 'afs_bypass_readpages' and 'afs_linux_readpages'
+when the linux kernel supports the readahead operation.
+
+Don't manage the LRU for pages for the readahead case (e.g. don't
+call the afs_lru_cache_* functions).
+
+Notes:
+ In afs_linux_bypass_readahead, the pages are already locked and are
+ already in the page cache, we just need to place the page into the
+ iovecp. The page's refcount will be decremented and will be unlocked
+ when processing the read request.
+
+ In afs_linux_readahead, the lrupages is needed in case a page is added
+ to the cachefp's mapping in afs_linux_read_cache (which also handles
+ unlocking the page). Failure to unlock the page if there was no tdc
+ results in the read process waiting on that page.
+
+Change-Id: I6960a2fc14df85869c373f3e3afbf3ee5eb7228f
+---
+ src/afs/LINUX/osi_vnodeops.c | 190 +++++++++++++++++++++++++++++++++-
+ src/cf/linux-kernel-struct.m4 | 2 +
+ 2 files changed, 190 insertions(+), 2 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
+index 893f8afff..1cc7cf8d6 100644
+--- a/src/afs/LINUX/osi_vnodeops.c
++++ b/src/afs/LINUX/osi_vnodeops.c
+@@ -2536,6 +2536,92 @@ afs_linux_prefetch(struct file *fp, struct page *pp)
+
+ }
+
++#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD)
++static void
++afs_linux_bypass_readahead(struct readahead_control *rac)
++{
++ struct file *fp = rac->file;
++ unsigned num_pages = readahead_count(rac);
++ afs_int32 page_ix;
++ afs_offs_t offset;
++ struct iovec* iovecp;
++ struct nocache_read_request *ancr;
++ struct page *pp;
++
++ afs_int32 code = 0;
++
++ cred_t *credp;
++ struct inode *ip = FILE_INODE(fp);
++ struct vcache *avc = VTOAFS(ip);
++ afs_int32 base_index = 0;
++ afs_int32 page_count = 0;
++ afs_int32 isize;
++
++ /* background thread must free: iovecp, auio, ancr */
++ ancr = afs_alloc_ncr(num_pages);
++ if (!ancr)
++ goto error;
++
++ iovecp = ancr->auio->uio_iov;
++
++ for (page_ix = 0; page_ix < num_pages; ++page_ix) {
++ pp = readahead_page(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);
++ continue;
++ }
++
++ if (page_ix == 0) {
++ offset = page_offset(pp);
++ ancr->offset = ancr->auio->uio_offset = offset;
++ base_index = pp->index;
++ }
++ iovecp[page_ix].iov_len = PAGE_SIZE;
++ if (base_index != pp->index) {
++ if (PageLocked(pp))
++ unlock_page(pp);
++ put_page(pp);
++ iovecp[page_ix].iov_base = NULL;
++ base_index++;
++ ancr->length -= PAGE_SIZE;
++ continue;
++ }
++ base_index++;
++ page_count++;
++ /* save the page for background map */
++ iovecp[page_ix].iov_base = pp;
++ }
++
++ /* If there were useful pages in the page list, schedule
++ * the read */
++ if (page_count) {
++ credp = crref();
++ code = afs_ReadNoCache(avc, ancr, credp);
++ crfree(credp);
++ } else {
++ /* If there is nothing for the background thread to handle,
++ * it won't be freeing the things that we never gave it */
++ afs_free_ncr(&ancr);
++ }
++ /* we do not flush, release, or unmap pages--that will be
++ * done for us by the background thread as each page comes in
++ * from the fileserver */
++ return;
++
++ error:
++ while ((pp = readahead_page(rac)) != NULL) {
++ if (PageLocked(pp)) {
++ unlock_page(pp);
++ }
++ }
++ return;
++}
++#else /* STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD */
+ static int
+ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+ struct list_head *page_list, unsigned num_pages)
+@@ -2632,7 +2718,7 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
+ * from the fileserver */
+ return afs_convert_code(code);
+ }
+-
++#endif /* STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD */
+
+ static int
+ afs_linux_bypass_readpage(struct file *fp, struct page *pp)
+@@ -2806,11 +2892,106 @@ get_dcache_readahead(struct dcache **adc, struct file **acacheFp,
+ return code;
+ }
+
+-/* Readpages reads a number of pages for a particular file. We use
++#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD)
++/*
++ * Readahead reads a number of pages for a particular file. We use
+ * this to optimise the reading, by limiting the number of times upon which
+ * we have to lookup, lock and open vcaches and dcaches
+ */
++static void
++afs_linux_readahead(struct readahead_control *rac)
++{
++ struct page *page;
++ struct address_space *mapping = rac->mapping;
++ struct inode *inode = mapping->host;
++ struct vcache *avc = VTOAFS(inode);
++ struct dcache *tdc;
++ struct file *cacheFp = NULL;
++ int code = 0;
++ loff_t offset;
++ struct afs_lru_pages lrupages;
++ struct afs_pagecopy_task *task;
++
++ if (afs_linux_bypass_check(inode)) {
++ afs_linux_bypass_readahead(rac);
++ return;
++ }
++ if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
++ return;
++
++ /* No readpage (ex: tmpfs) , skip */
++ if (cachefs_noreadpage)
++ return;
++
++ AFS_GLOCK();
++ if ((code = afs_linux_VerifyVCache(avc, NULL))) {
++ AFS_GUNLOCK();
++ return;
++ }
++
++ ObtainWriteLock(&avc->lock, 912);
++ AFS_GUNLOCK();
++
++ task = afs_pagecopy_init_task();
+
++ tdc = NULL;
++
++ afs_lru_cache_init(&lrupages);
++
++ while ((page = readahead_page(rac)) != NULL) {
++ offset = page_offset(page);
++
++ code = get_dcache_readahead(&tdc, &cacheFp, avc, offset);
++ if (code)
++ goto error;
++
++ if (tdc != NULL) {
++ /* Note that add_to_page_cache() locked 'page'.
++ * afs_linux_read_cache() is guaranteed to handle unlocking it. */
++ afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupages, task);
++ } else if (PageLocked(page)) {
++ unlock_page(page);
++ }
++ put_page(page);
++ }
++ afs_lru_cache_finalize(&lrupages);
++
++ done:
++ if (cacheFp)
++ filp_close(cacheFp, NULL);
++
++ afs_pagecopy_put_task(task);
++
++ AFS_GLOCK();
++ if (tdc != NULL) {
++ ReleaseReadLock(&tdc->lock);
++ afs_PutDCache(tdc);
++ }
++
++ ReleaseWriteLock(&avc->lock);
++ AFS_GUNLOCK();
++ return;
++
++ error:
++ /*
++ * Any error detected during readahead are ignored by the vfs.
++ * Simply unlock the page(s).
++ */
++ if (PageLocked(page)) {
++ unlock_page(page);
++ }
++ while ((page = readahead_page(rac)) != NULL) {
++ if (PageLocked(page)) {
++ unlock_page(page);
++ }
++ }
++ goto done;
++}
++#else /* STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD */
++/* Readpages reads a number of pages for a particular file. We use
++ * this to optimise the reading, by limiting the number of times upon which
++ * we have to lookup, lock and open vcaches and dcaches
++ */
+ static int
+ afs_linux_readpages(struct file *fp, struct address_space *mapping,
+ struct list_head *page_list, unsigned int num_pages)
+@@ -2887,6 +3068,7 @@ out:
+ AFS_GUNLOCK();
+ return 0;
+ }
++#endif /* STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD */
+
+ /* Prepare an AFS vcache for writeback. Should be called with the vcache
+ * locked */
+@@ -3325,7 +3507,11 @@ static struct inode_operations afs_file_iops = {
+
+ static struct address_space_operations afs_file_aops = {
+ .readpage = afs_linux_readpage,
++#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_READAHEAD)
++ .readahead = afs_linux_readahead,
++#else
+ .readpages = afs_linux_readpages,
++#endif
+ .writepage = afs_linux_writepage,
+ #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_DIRTY_FOLIO)
+ .dirty_folio = block_dirty_folio,
+diff --git a/src/cf/linux-kernel-struct.m4 b/src/cf/linux-kernel-struct.m4
+index 2d8cee655..597289bc8 100644
+--- a/src/cf/linux-kernel-struct.m4
++++ b/src/cf/linux-kernel-struct.m4
+@@ -5,6 +5,8 @@ AC_CHECK_LINUX_STRUCT([address_space_operations],
+ [write_begin], [fs.h])
+ dnl linux 5.18 replaced set_page_dirty with dirty_folio
+ AC_CHECK_LINUX_STRUCT([address_space_operations], [dirty_folio], [fs.h])
++dnl linux 5.18 replaced readpages with readahead (introduced in 5.8)
++AC_CHECK_LINUX_STRUCT([address_space_operations], [readahead], [fs.h])
+ AC_CHECK_LINUX_STRUCT([backing_dev_info], [name],
+ [backing-dev.h])
+ AC_CHECK_LINUX_STRUCT([cred], [session_keyring], [cred.h])
+--
+2.36.1
+
diff --git a/PKGBUILD b/PKGBUILD
index 6035ac353de9..894e439edc41 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -7,7 +7,7 @@
pkgname=openafs-modules-dkms
_srcname=openafs
pkgver=1.8.8.1
-pkgrel=2
+pkgrel=3
pkgdesc="Kernel module for OpenAFS (dkms)"
arch=('i686' 'x86_64' 'armv7h')
url="http://www.openafs.org"
@@ -17,19 +17,33 @@ provides=("openafs-modules=$pkgver")
conflicts=('openafs-features-libafs' 'openafs-modules' 'openafs<1.6.6-2')
options=(!emptydirs)
source=("http://openafs.org/dl/openafs/${pkgver}/${_srcname}-${pkgver}-src.tar.bz2"
- "dkms.conf"
- 0001-Add-autoconf-archive-to-src-external.patch
- 0002-Import-of-code-from-autoconf-archive.patch
- 0003-Use-autoconf-archive-m4-from-src-external.patch
- 0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
- 0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch)
+ "dkms.conf"
+ 0001-Add-autoconf-archive-to-src-external.patch
+ 0002-Import-of-code-from-autoconf-archive.patch
+ 0003-Use-autoconf-archive-m4-from-src-external.patch
+ 0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch
+ 0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch
+ 0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch
+ 0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch
+ 0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch
+ 0009-LINUX-Don-t-panic-on-some-file-open-errors.patch
+ 0010-afs-Introduce-afs_IsDCacheFresh.patch
+ 0011-afs-introduce-get_dcache_readahead.patch
+ 0012-Linux-5.18-replace-readpages-with-readahead.patch)
sha256sums=('e7c4bed7075bcd6402e3f0c2d5b9dbe76ad2ee3c5fd5ddc3973a3356ca23ef44'
'5ea5e184f9b44f5ed45817d2b5a10149d15c8c54f49e0b5b4b773652673cb9b0'
- '67bad31f8a401f1fa4e851a1f8d2d772f6649573f81045cafae94c105bbff173'
- '16ced06d3d4ffffa251e20aecd1ccb3fedb4585617b004b8ade0b4eab603b17d'
- '3b2aa3343fe4b9401b272fcf0252f4c3f108f1a1e5039718de38b803690c9d74'
- 'c9623eac1e8faf2be133d69c6146eb68be800de0c3226acd99848348b5bfd2f4'
- '17c71196bf5f1fc1c62bab8f03a102d7ca75fec56de94390851b10bd27efa3e9')
+ 'cbf078639b9b25d1e9ec191b9c340720f1fe5ebd1b7665c2ea762498fcf66fbf'
+ 'f1feac79a69b9ecff4c7259842184e16ef1213e9fb5a2601c4963ea3dc12041c'
+ '97410d4f5a7a09254ffa18411f242234aba483a0a7b989503ee831457c0ddb9f'
+ '47faddb068dcbbea74c973c23aac7fe29b1482e984a37b5cfee283200da6b9e2'
+ '45fa5eaa7b0e7e7bc6c9e0b7c5d97e5fefc54f60c084d5e7deddbe2c0c4697e9'
+ 'd42fa0772193cd6a66e09ba9cdb81b77c636a266caaf0c465331ff7ca3925b1c'
+ 'b47e4d5405961b7d40bd24e50c18740b9cd85a90e0e7f630101602efb2f12c2f'
+ '9801be6de6399a2e0d899b0ed71bc5881ede5a926720d32377a24db31b035593'
+ 'ce21b7ed721d685fb0f1ddf068003410b585e09be7a96daeb1e8bb10378cf4b3'
+ '7a5410bce86f1471ae5d990b68f2b25fcff8d5f32d2b7fd9e29c098a91ef1cef'
+ '4816b8502366995eb5e8e58e485db910269a118ea6ed67e8f16e6bc1aab53864'
+ 'b51739e2670d13a46f0936fd50ef4bfadf40e83b22a53d46dd7b0eb490ebb700')
prepare() {
cd "${srcdir}/${_srcname}-${pkgver}"
@@ -43,6 +57,25 @@ prepare() {
patch -p1 < "${srcdir}/0004-Linux-5.17-kernel-func-complete_and_exit-renamed.patch"
patch -p1 < "${srcdir}/0005-Linux-5.17-Kernel-build-uses-Wcast-function-type.patch"
+ # Linux 5.18 (14939)
+ patch -p1 < "${srcdir}/0006-Linux-5.18-replace-set_page_dirty-with-dirty_folio.patch"
+
+ # Backport from master to make later patches apply cleanly
+ patch -p1 < "${srcdir}/0007-afs-remove-vestigial-externs-for-afs_xcbhash.patch"
+
+ # Prep. for Linux 5.18 patch (14954)
+ patch -p1 < "${srcdir}/0008-afs-introduce-afs_alloc_ncr-afs_free_ncr.patch"
+
+ # Backports from master to make later patches apply cleanly
+ patch -p1 < "${srcdir}/0009-LINUX-Don-t-panic-on-some-file-open-errors.patch"
+ patch -p1 < "${srcdir}/0010-afs-Introduce-afs_IsDCacheFresh.patch"
+
+ # Prep. for Linux 5.18 patch (14962)
+ patch -p1 < "${srcdir}/0011-afs-introduce-get_dcache_readahead.patch"
+
+ # Linux 5.18 (14953)
+ patch -p1 < "${srcdir}/0012-Linux-5.18-replace-readpages-with-readahead.patch"
+
# Only needed when changes to configure were made
./regen.sh -q
}