summarylogtreecommitdiffstats
path: root/0004-Linux-6.3-Use-mnt_idmap-for-inode-op-functions.patch
blob: a343e55221a2ba5e395405097d6f59839f56a479 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
From 03583703045baa71f92be2bdf72a9d95ef0b5645 Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Wed, 29 Mar 2023 12:11:38 -0600
Subject: [PATCH 4/4] Linux 6.3: Use mnt_idmap for inode op functions

Through a series of Linux 6.3 commits starting with:
  'f2fs: project ids aren't idmapped' (64b4cdf22f) and ending with
  'fs: move mnt_idmap' (3707d84c13)
the inode operations functions were changed to take a mnt_idmap
structure instead of a user_namespace structure.  These were pulled in
via the the merge commit:
  'Pull vfs idmapping updates from Christian Brauner' (05e6295f7b)
The commit message for the merge contains background and overall
information for this conversion.

The above change simply changes the functions to use a different
structure (mnt_idmap instead of user_namespace).  For afs, it is a
simple change to swap the structures. But for some of the Linux calls
(generic_fillattr(), setattr_prepare(), and inode_op->setattr()) we
would like to use the Linux symbol nop_mnt_idmap, but that symbol is
exported as GPL only.  Instead, we will obtain its address from the
current task structure at libafs initialization (much the same way as
obtaining current user namespace for afs_ns).

Add autoconf tests to determine if inode_operations.create() uses the
mnt_idmap structure.  If so set a generic configure define for
"IOP_TAKES_MNT_IDMAP".

Update afs's inode operations functions to take and use a mnt_idmap
instead of a user_namespace.

At libafs initialization, obtain the mnt_idmap from the current task
and save it as an afs global variable, afs_mnt_idmap, to be used where
needed.

Reviewed-on: https://gerrit.openafs.org/15347
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 858ee34545e57acab1e4e5813cd1b9a011538b9e)

Change-Id: If89c6f401db04826ef45de83b91240f106cca616
Reviewed-on: https://gerrit.openafs.org/15389
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Kailas Zadbuke <kailashsz@in.ibm.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit f6fbb85c00411bf97e9855be73baf49bd6b061d7)
---
 src/afs/LINUX/osi_compat.h   |  8 ++++--
 src/afs/LINUX/osi_machdep.h  |  4 +++
 src/afs/LINUX/osi_module.c   | 22 ++++++++++++++++
 src/afs/LINUX/osi_vnodeops.c | 51 ++++++++++++++++++++++++++++++------
 src/cf/linux-kernel-sig.m4   | 13 +++++++++
 5 files changed, 88 insertions(+), 10 deletions(-)

diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index 808c608ad..bb4969ce8 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -534,7 +534,9 @@ afs_inode_setattr(struct osi_file *afile, struct iattr *newattrs) {
 
     int code = 0;
     struct inode *inode = OSIFILE_INODE(afile);
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+    code = inode->i_op->setattr(afs_mnt_idmap, afile->filp->f_dentry, newattrs);
+#elif defined(IOP_TAKES_USER_NAMESPACE)
     code = inode->i_op->setattr(afs_ns, afile->filp->f_dentry, newattrs);
 #elif !defined(HAVE_LINUX_INODE_SETATTR)
     code = inode->i_op->setattr(afile->filp->f_dentry, newattrs);
@@ -763,7 +765,9 @@ afs_d_path(struct dentry *dp, struct vfsmount *mnt, char *buf, int buflen)
 static inline int
 afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs)
 {
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+    return setattr_prepare(afs_mnt_idmap, dp, newattrs);
+#elif defined(IOP_TAKES_USER_NAMESPACE)
     return setattr_prepare(afs_ns, dp, newattrs);
 #elif defined(HAVE_LINUX_SETATTR_PREPARE)
     return setattr_prepare(dp, newattrs);
diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h
index 34940c60d..2220e0530 100644
--- a/src/afs/LINUX/osi_machdep.h
+++ b/src/afs/LINUX/osi_machdep.h
@@ -217,6 +217,10 @@ extern struct user_namespace *afs_ns;
 #  define afs_current_user_ns() ((struct user_namespace *)NULL)
 # endif
 
+#if defined(IOP_TAKES_MNT_IDMAP)
+extern struct mnt_idmap *afs_mnt_idmap;
+#endif
+
 static inline kuid_t afs_make_kuid(uid_t uid) {
     return make_kuid(afs_ns, uid);
 }
diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c
index 79ba57c4d..fdc347d2c 100644
--- a/src/afs/LINUX/osi_module.c
+++ b/src/afs/LINUX/osi_module.c
@@ -31,6 +31,10 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
+#if defined(IOP_TAKES_MNT_IDMAP)
+# include <linux/fs_struct.h>
+#endif
+
 #include "osi_pagecopy.h"
 
 extern struct file_system_type afs_fs_type;
@@ -46,6 +50,20 @@ int afs_global_owner = 0;
 struct user_namespace *afs_ns;
 #endif
 
+#if defined(IOP_TAKES_MNT_IDMAP)
+struct mnt_idmap *afs_mnt_idmap;
+
+static void
+afs_init_idmap(void)
+{
+    struct path fs_root;
+
+    get_fs_root(current->fs, &fs_root);
+    afs_mnt_idmap = mnt_idmap(fs_root.mnt);
+    path_put(&fs_root);
+}
+#endif
+
 int __init
 afs_init(void)
 {
@@ -55,6 +73,10 @@ afs_init(void)
     afs_ns = afs_current_user_ns();
 #endif
 
+#if defined(IOP_TAKES_MNT_IDMAP)
+    afs_init_idmap();
+#endif
+
     osi_Init();
 
     /* Initialize CellLRU since it is used while traversing CellServDB proc
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 06c00ac5b..fd54821bd 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1146,7 +1146,10 @@ vattr2inode(struct inode *ip, struct vattr *vp)
  * Linux version of setattr call. What to change is in the iattr struct.
  * We need to set bits in both the Linux inode as well as the vcache.
  */
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_notify_change(struct mnt_idmap *idmap, struct dentry *dp, struct iattr *iattrp)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_notify_change(struct user_namespace *mnt_userns, struct dentry *dp, struct iattr *iattrp)
 #else
@@ -1180,7 +1183,18 @@ out:
     return afs_convert_code(code);
 }
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat,
+		  u32 request_mask, unsigned int sync_mode)
+{
+	int err = afs_linux_revalidate(path->dentry);
+	if (!err) {
+		generic_fillattr(afs_mnt_idmap, path->dentry->d_inode, stat);
+	}
+	return err;
+}
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_getattr(struct user_namespace *mnt_userns, const struct path *path, struct kstat *stat,
 		  u32 request_mask, unsigned int sync_mode)
@@ -1661,7 +1675,11 @@ struct dentry_operations afs_dentry_operations = {
  * name is in kernel space at this point.
  */
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_create(struct mnt_idmap *idmap, struct inode *dip,
+		 struct dentry *dp, umode_t mode, bool excl)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_create(struct user_namespace *mnt_userns, struct inode *dip,
 		 struct dentry *dp, umode_t mode, bool excl)
@@ -1953,7 +1971,11 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
 }
 
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_symlink(struct mnt_idmap *idmap, struct inode *dip,
+		  struct dentry *dp, const char *target)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_symlink(struct user_namespace *mnt_userns, struct inode *dip,
 		  struct dentry *dp, const char *target)
@@ -1988,7 +2010,11 @@ out:
     return afs_convert_code(code);
 }
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_mkdir(struct mnt_idmap *idmap, struct inode *dip,
+		struct dentry *dp, umode_t mode)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_mkdir(struct user_namespace *mnt_userns, struct inode *dip,
 		struct dentry *dp, umode_t mode)
@@ -2068,7 +2094,13 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
 }
 
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_rename(struct mnt_idmap *idmap,
+		 struct inode *oldip, struct dentry *olddp,
+		 struct inode *newip, struct dentry *newdp,
+		 unsigned int flags)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_rename(struct user_namespace *mnt_userns,
 		 struct inode *oldip, struct dentry *olddp,
@@ -2092,7 +2124,7 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp,
     struct dentry *rehash = NULL;
 
 #if defined(HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS) || \
-    defined(IOP_TAKES_USER_NAMESPACE)
+    defined(IOP_TAKES_MNT_IDMAP) || defined(IOP_TAKES_USER_NAMESPACE)
     if (flags)
 	return -EINVAL;		/* no support for new flags yet */
 #endif
@@ -3388,7 +3420,10 @@ done:
  * Check access rights - returns error if can't check or permission denied.
  */
 
-#if defined(IOP_TAKES_USER_NAMESPACE)
+#if defined(IOP_TAKES_MNT_IDMAP)
+static int
+afs_linux_permission(struct mnt_idmap *idmap, struct inode *ip, int mode)
+#elif defined(IOP_TAKES_USER_NAMESPACE)
 static int
 afs_linux_permission(struct user_namespace *mnt_userns, struct inode *ip, int mode)
 #elif defined(IOP_PERMISSION_TAKES_FLAGS)
diff --git a/src/cf/linux-kernel-sig.m4 b/src/cf/linux-kernel-sig.m4
index e0cc9a2f3..5301f3503 100644
--- a/src/cf/linux-kernel-sig.m4
+++ b/src/cf/linux-kernel-sig.m4
@@ -28,4 +28,17 @@ dnl define.
 AS_IF([test AS_VAR_GET([ac_cv_linux_operation_inode_operations_create_user_namespace]) = yes],
       [AC_DEFINE([IOP_TAKES_USER_NAMESPACE], 1,
                  [define if inodeops require struct user_namespace])])
+dnl Linux 6.3 replaced the user_namespace parameter with mnt_idmap for
+dnl the inode operations functions.
+AC_CHECK_LINUX_OPERATION([inode_operations], [create], [mnt_idmap],
+                         [#include <linux/fs.h>],
+                         [int],
+                         [struct mnt_idmap *idmap,
+                         struct inode *inode, struct dentry *dentry,
+                         umode_t umode, bool flag])
+dnl if HAVE_LINUX_INODE_OPERATIONS_CREATE_MNT_IDMAP, create a more generic
+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])])
 ])
\ No newline at end of file
-- 
2.40.1