summarylogtreecommitdiffstats
path: root/0001-Linux-6.0-Replace-add_to_page_cache.patch
blob: d900953a13e45dcd1fbb0a4f075ffa0d6f46bd61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
From ea74bb05c9a36bcf77698008d340202959be8091 Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Thu, 22 Sep 2022 13:04:59 -0600
Subject: [PATCH] Linux-6.0: Replace add_to_page_cache

Linux 6.0 removed the add_to_page_cache function in the Linux commit:
    'filemap: Remove add_to_page_cache() and add_to_page_cache_locked()'
    (2bb876b58d593d7f2522ec0f41f20a74fde76822)

The replacement function, filemap_add_folio function is exported as GPL,
but a non-GPL wrapper was provided in the Linux 5.15 commit:
    'mm/filemap: Add filemap_add_folio()'
    (9dd3d069406cea073fc633e77bc59abbfde8c6c4)
which changed the GPL exported function add_to_page_cache_lru to a
non-GPL exported function.

The function add_to_page_cache_lru functionally combines the
add_to_page_cache with lru_cache_add.  Within afs, all the calls to
add_to_page_cache follow the pattern of calling the lru_cache_add
via the wrapper afs_lru_cache_add immediately after (except in one case
noted below).

Add an autoconf check to see if add_to_page_cache_lru is available.

Introduce a new wrapper function afs_add_to_page_cache_lru that handles
calling either add_to_page_cache/afs_lru_cache_add or
add_to_page_cache_lru.

As noted above there is one function, afs_linux_bypass_readpages, that
calls add_to_page_cache but does not immediately call afs_lru_cache_add.
This function is only used in Linux kernels prior to 5.18, see the
commit:
    'Linux-5.18: replace readpages with readahead' (7a181415db)
Since this code path is only built for a Linux kernel level where
add_to_page_cache should also exists, we do not replace this call.

NOTE:
The add_to_page_cache_lru was moved into mm/folio-compat.c which has a
comment indicating that callers of these functions should migrate to
folio calls.  However the replacement folio call that is needed by afs,
filemap_add_folio, is exported as GPL.

Change-Id: I10087ebeb8b08309e6c1bab4fc43f7e9f50bd105
---
 src/afs/LINUX/osi_vnodeops.c | 30 ++++++++++++++++++++++--------
 src/cf/linux-kernel-func.m4  | 10 ++++++++++
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 621e4da38..bec30bb4c 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -148,6 +148,23 @@ afs_lru_cache_finalize(struct afs_lru_pages *alrupages)
 }
 #endif /* !HAVE_LINUX_LRU_ADD_FILE */
 
+static inline int
+afs_add_to_page_cache_lru(struct afs_lru_pages *alrupages, struct page *page,
+			  struct address_space *mapping,
+			  pgoff_t index, gfp_t gfp)
+{
+#if defined(HAVE_LINUX_ADD_TO_PAGE_CACHE_LRU)
+    return add_to_page_cache_lru(page, mapping, index, gfp);
+#else
+    int code;
+    code = add_to_page_cache(page, mapping, index, gfp);
+    if (code == 0) {
+	afs_lru_cache_add(alrupages, page);
+    }
+    return code;
+#endif
+}
+
 /* This function converts a positive error code from AFS into a negative
  * code suitable for passing into the Linux VFS layer. It checks that the
  * error code is within the permissable bounds for the ERR_PTR mechanism.
@@ -2269,12 +2286,11 @@ afs_linux_read_cache(struct file *cachefp, struct page *page,
 		goto out;
 	    }
 
-	    code = add_to_page_cache(newpage, cachemapping,
-				     pageindex, GFP_KERNEL);
+	    code = afs_add_to_page_cache_lru(alrupages, newpage, cachemapping,
+					     pageindex, GFP_KERNEL);
 	    if (code == 0) {
 	        cachepage = newpage;
 	        newpage = NULL;
-		afs_lru_cache_add(alrupages, cachepage);
 	    } else {
 		put_page(newpage);
 		newpage = NULL;
@@ -3092,11 +3108,9 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
 	    goto out;
 	}
 
-	if (tdc && !add_to_page_cache(page, mapping, page->index,
-				      GFP_KERNEL)) {
-	    afs_lru_cache_add(&lrupages, page);
-
-	    /* Note that add_to_page_cache() locked 'page'.
+	if (tdc && !afs_add_to_page_cache_lru(&lrupages, page, mapping, page->index,
+					      GFP_KERNEL)) {
+	    /* Note that afs_add_to_page_cache_lru() locks the 'page'.
 	     * afs_linux_read_cache() is guaranteed to handle unlocking it. */
 	    afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupages, task);
 	}
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 27a1d4141..d3abdf9ff 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -189,6 +189,16 @@ AC_CHECK_LINUX_FUNC([kthread_complete_and_exit],
                      #include <linux/kthread.h>],
                     [kthread_complete_and_exit(0, 0);])
 
+dnl Linux 6.0 removed add_to_page_cache.  It's replacement, filemap_add_folio,
+dnl was added in 5.15 and is GPL-only, but has a NON-GPL wrapper called
+dnl add_to_page_cache_lru.
+dnl Note prior to 5.15, add_to_page_cache_lru was either not exported or
+dnl or exported as GPL-only.
+AC_CHECK_LINUX_FUNC([add_to_page_cache_lru],
+                    [#include <linux/kernel.h>
+                     #include <linux/pagemap.h>],
+                    [add_to_page_cache_lru(NULL, NULL, 0, 0);])
+
 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"],
-- 
2.37.3