]> git.pld-linux.org Git - packages/zfs.git/blob - kernel-5.12.patch
- fixes for building with kernel 5.12, rel 2
[packages/zfs.git] / kernel-5.12.patch
1 From e2a8296131e94ad785f5564156ed2db1fdb2e080 Mon Sep 17 00:00:00 2001
2 From: Coleman Kane <ckane@colemankane.org>
3 Date: Sat, 20 Mar 2021 00:00:59 -0400
4 Subject: [PATCH] Linux 5.12 compat: idmapped mounts
5
6 In Linux 5.12, the filesystem API was modified to support ipmapped
7 mounts by adding a "struct user_namespace *" parameter to a number
8 functions and VFS handlers. This change adds the needed autoconf
9 macros to detect the new interfaces and updates the code appropriately.
10 This change does not add support for idmapped mounts, instead it
11 preserves the existing behavior by passing the initial user namespace
12 where needed.  A subsequent commit will be required to add support
13 for idmapped mounted.
14
15 Reviewed-by: Tony Hutter <hutter2@llnl.gov>
16 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
17 Co-authored-by: Brian Behlendorf <behlendorf1@llnl.gov>
18 Signed-off-by: Coleman Kane <ckane@colemankane.org>
19 Closes #11712
20 ---
21  config/kernel-generic_fillattr.m4            | 28 +++++++
22  config/kernel-inode-create.m4                | 43 +++++++++--
23  config/kernel-inode-getattr.m4               | 63 +++++++++++++---
24  config/kernel-is_owner_or_cap.m4             | 23 +++++-
25  config/kernel-mkdir-umode-t.m4               | 32 --------
26  config/kernel-mkdir.m4                       | 65 ++++++++++++++++
27  config/kernel-mknod.m4                       | 30 ++++++++
28  config/kernel-rename.m4                      | 50 ++++++++++---
29  config/kernel-setattr-prepare.m4             | 45 ++++++++---
30  config/kernel-symlink.m4                     | 30 ++++++++
31  config/kernel-xattr-handler.m4               | 78 +++++++++++++-------
32  config/kernel.m4                             | 18 +++--
33  include/os/linux/kernel/linux/vfs_compat.h   | 24 +++++-
34  include/os/linux/kernel/linux/xattr_compat.h | 17 ++++-
35  include/os/linux/zfs/sys/zfs_vnops_os.h      |  3 +-
36  include/os/linux/zfs/sys/zpl.h               | 18 +++++
37  module/os/linux/zfs/policy.c                 |  2 +-
38  module/os/linux/zfs/zfs_vnops_os.c           |  5 +-
39  module/os/linux/zfs/zpl_ctldir.c             | 51 ++++++++++++-
40  module/os/linux/zfs/zpl_file.c               |  2 +-
41  module/os/linux/zfs/zpl_inode.c              | 49 +++++++++++-
42  module/os/linux/zfs/zpl_xattr.c              |  4 +-
43  22 files changed, 557 insertions(+), 123 deletions(-)
44  create mode 100644 config/kernel-generic_fillattr.m4
45  delete mode 100644 config/kernel-mkdir-umode-t.m4
46  create mode 100644 config/kernel-mkdir.m4
47  create mode 100644 config/kernel-mknod.m4
48  create mode 100644 config/kernel-symlink.m4
49
50 diff --git a/config/kernel-generic_fillattr.m4 b/config/kernel-generic_fillattr.m4
51 new file mode 100644
52 index 00000000000..50c8031305b
53 --- /dev/null
54 +++ b/config/kernel-generic_fillattr.m4
55 @@ -0,0 +1,28 @@
56 +dnl #
57 +dnl # 5.12 API
58 +dnl #
59 +dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace*
60 +dnl # as the first arg, to support idmapped mounts.
61 +dnl #
62 +AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [
63 +       ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [
64 +               #include <linux/fs.h>
65 +       ],[
66 +               struct user_namespace *userns = NULL;
67 +               struct inode *in = NULL;
68 +               struct kstat *k = NULL;
69 +               generic_fillattr(userns, in, k);
70 +       ])
71 +])
72 +
73 +AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [
74 +       AC_MSG_CHECKING([whether generic_fillattr requres struct user_namespace*])
75 +       ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [
76 +               AC_MSG_RESULT([yes])
77 +               AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1,
78 +                   [generic_fillattr requires struct user_namespace*])
79 +       ],[
80 +               AC_MSG_RESULT([no])
81 +       ])
82 +])
83 +
84 diff --git a/config/kernel-inode-create.m4 b/config/kernel-inode-create.m4
85 index 9f28bcbd4f7..a6ea11fb61b 100644
86 --- a/config/kernel-inode-create.m4
87 +++ b/config/kernel-inode-create.m4
88 @@ -1,7 +1,25 @@
89 -dnl #
90 -dnl # 3.6 API change
91 -dnl #
92 -AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [
93 +AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
94 +       dnl #
95 +       dnl # 5.12 API change that added the struct user_namespace* arg
96 +       dnl # to the front of this function type's arg list.
97 +       dnl #
98 +       ZFS_LINUX_TEST_SRC([create_userns], [
99 +               #include <linux/fs.h>
100 +               #include <linux/sched.h>
101 +
102 +               int inode_create(struct user_namespace *userns,
103 +                   struct inode *inode ,struct dentry *dentry,
104 +                   umode_t umode, bool flag) { return 0; }
105 +
106 +               static const struct inode_operations
107 +                       iops __attribute__ ((unused)) = {
108 +                       .create         = inode_create,
109 +               };
110 +       ],[])
111 +
112 +       dnl #
113 +       dnl # 3.6 API change
114 +       dnl #
115         ZFS_LINUX_TEST_SRC([create_flags], [
116                 #include <linux/fs.h>
117                 #include <linux/sched.h>
118 @@ -16,11 +34,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [
119         ],[])
120  ])
121  
122 -AC_DEFUN([ZFS_AC_KERNEL_CREATE_FLAGS], [
123 -       AC_MSG_CHECKING([whether iops->create() passes flags])
124 -       ZFS_LINUX_TEST_RESULT([create_flags], [
125 +AC_DEFUN([ZFS_AC_KERNEL_CREATE], [
126 +       AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*])
127 +       ZFS_LINUX_TEST_RESULT([create_userns], [
128                 AC_MSG_RESULT(yes)
129 +               AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1,
130 +                  [iops->create() takes struct user_namespace*])
131         ],[
132 -               ZFS_LINUX_TEST_ERROR([iops->create()])
133 +               AC_MSG_RESULT(no)
134 +
135 +               AC_MSG_CHECKING([whether iops->create() passes flags])
136 +               ZFS_LINUX_TEST_RESULT([create_flags], [
137 +                       AC_MSG_RESULT(yes)
138 +               ],[
139 +                       ZFS_LINUX_TEST_ERROR([iops->create()])
140 +               ])
141         ])
142  ])
143 diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4
144 index 48391d66f8b..f62e82f5230 100644
145 --- a/config/kernel-inode-getattr.m4
146 +++ b/config/kernel-inode-getattr.m4
147 @@ -1,8 +1,29 @@
148 -dnl #
149 -dnl # Linux 4.11 API
150 -dnl # See torvalds/linux@a528d35
151 -dnl #
152  AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
153 +       dnl #
154 +       dnl # Linux 5.12 API
155 +       dnl # The getattr I/O operations handler type was extended to require
156 +       dnl # a struct user_namespace* as its first arg, to support idmapped
157 +       dnl # mounts.
158 +       dnl #
159 +       ZFS_LINUX_TEST_SRC([inode_operations_getattr_userns], [
160 +               #include <linux/fs.h>
161 +
162 +               int test_getattr(
163 +                       struct user_namespace *userns,
164 +                   const struct path *p, struct kstat *k,
165 +                   u32 request_mask, unsigned int query_flags)
166 +                   { return 0; }
167 +
168 +               static const struct inode_operations
169 +                   iops __attribute__ ((unused)) = {
170 +                       .getattr = test_getattr,
171 +               };
172 +       ],[])
173 +
174 +       dnl #
175 +       dnl # Linux 4.11 API
176 +       dnl # See torvalds/linux@a528d35
177 +       dnl #
178         ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [
179                 #include <linux/fs.h>
180  
181 @@ -33,21 +54,39 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
182  ])
183  
184  AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [
185 -       AC_MSG_CHECKING([whether iops->getattr() takes a path])
186 -       ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
187 +       dnl #
188 +       dnl # Kernel 5.12 test
189 +       dnl #
190 +       AC_MSG_CHECKING([whether iops->getattr() takes user_namespace])
191 +       ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [
192                 AC_MSG_RESULT(yes)
193 -               AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
194 -                   [iops->getattr() takes a path])
195 +               AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1,
196 +                   [iops->getattr() takes struct user_namespace*])
197         ],[
198                 AC_MSG_RESULT(no)
199  
200 -               AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
201 -               ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
202 +               dnl #
203 +               dnl # Kernel 4.11 test
204 +               dnl #
205 +               AC_MSG_CHECKING([whether iops->getattr() takes a path])
206 +               ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
207                         AC_MSG_RESULT(yes)
208 -                       AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
209 -                           [iops->getattr() takes a vfsmount])
210 +                       AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
211 +                               [iops->getattr() takes a path])
212                 ],[
213                         AC_MSG_RESULT(no)
214 +
215 +                       dnl #
216 +                       dnl # Kernel < 4.11 test
217 +                       dnl #
218 +                       AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
219 +                       ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
220 +                               AC_MSG_RESULT(yes)
221 +                               AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
222 +                                       [iops->getattr() takes a vfsmount])
223 +                       ],[
224 +                               AC_MSG_RESULT(no)
225 +                       ])
226                 ])
227         ])
228  ])
229 diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4
230 index 3df6163da27..3c3c6ad2240 100644
231 --- a/config/kernel-is_owner_or_cap.m4
232 +++ b/config/kernel-is_owner_or_cap.m4
233 @@ -11,13 +11,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [
234                 struct inode *ip = NULL;
235                 (void) inode_owner_or_capable(ip);
236         ])
237 +
238 +       ZFS_LINUX_TEST_SRC([inode_owner_or_capable_idmapped], [
239 +               #include <linux/fs.h>
240 +       ],[
241 +               struct inode *ip = NULL;
242 +               (void) inode_owner_or_capable(&init_user_ns, ip);
243 +       ])
244  ])
245  
246  AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
247         AC_MSG_CHECKING([whether inode_owner_or_capable() exists])
248         ZFS_LINUX_TEST_RESULT([inode_owner_or_capable], [
249                 AC_MSG_RESULT(yes)
250 -       ],[
251 -               ZFS_LINUX_TEST_ERROR([capability])
252 +               AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE, 1,
253 +                   [inode_owner_or_capable() exists])
254 +       ], [
255 +               AC_MSG_RESULT(no)
256 +
257 +               AC_MSG_CHECKING(
258 +                   [whether inode_owner_or_capable() takes user_ns])
259 +               ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_idmapped], [
260 +                       AC_MSG_RESULT(yes)
261 +                       AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED, 1,
262 +                           [inode_owner_or_capable() takes user_ns])
263 +               ],[
264 +                       ZFS_LINUX_TEST_ERROR([capability])
265 +               ])
266         ])
267  ])
268 diff --git a/config/kernel-mkdir-umode-t.m4 b/config/kernel-mkdir-umode-t.m4
269 deleted file mode 100644
270 index 19599670df3..00000000000
271 --- a/config/kernel-mkdir-umode-t.m4
272 +++ /dev/null
273 @@ -1,32 +0,0 @@
274 -dnl #
275 -dnl # 3.3 API change
276 -dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a
277 -dnl # umode_t type rather than an int.  The expectation is that any backport
278 -dnl # would also change all three prototypes.  However, if it turns out that
279 -dnl # some distribution doesn't backport the whole thing this could be
280 -dnl # broken apart into three separate checks.
281 -dnl #
282 -AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T], [
283 -       ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [
284 -               #include <linux/fs.h>
285 -
286 -               int mkdir(struct inode *inode, struct dentry *dentry,
287 -                   umode_t umode) { return 0; }
288 -
289 -               static const struct inode_operations
290 -                   iops __attribute__ ((unused)) = {
291 -                       .mkdir = mkdir,
292 -               };
293 -       ],[])
294 -])
295 -
296 -AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
297 -       AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t])
298 -       ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
299 -               AC_MSG_RESULT(yes)
300 -               AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
301 -                   [iops->create()/mkdir()/mknod() take umode_t])
302 -       ],[
303 -               ZFS_LINUX_TEST_ERROR([mkdir()])
304 -       ])
305 -])
306 diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4
307 new file mode 100644
308 index 00000000000..a162bcd880f
309 --- /dev/null
310 +++ b/config/kernel-mkdir.m4
311 @@ -0,0 +1,65 @@
312 +dnl #
313 +dnl # Supported mkdir() interfaces checked newest to oldest.
314 +dnl #
315 +AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [
316 +       dnl #
317 +       dnl # 5.12 API change
318 +       dnl # The struct user_namespace arg was added as the first argument to
319 +       dnl # mkdir()
320 +       dnl #
321 +       ZFS_LINUX_TEST_SRC([mkdir_user_namespace], [
322 +               #include <linux/fs.h>
323 +
324 +               int mkdir(struct user_namespace *userns,
325 +                       struct inode *inode, struct dentry *dentry,
326 +                   umode_t umode) { return 0; }
327 +
328 +               static const struct inode_operations
329 +                   iops __attribute__ ((unused)) = {
330 +                       .mkdir = mkdir,
331 +               };
332 +       ],[])
333 +
334 +       dnl #
335 +       dnl # 3.3 API change
336 +       dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a
337 +       dnl # umode_t type rather than an int.  The expectation is that any backport
338 +       dnl # would also change all three prototypes.  However, if it turns out that
339 +       dnl # some distribution doesn't backport the whole thing this could be
340 +       dnl # broken apart into three separate checks.
341 +       dnl #
342 +       ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [
343 +               #include <linux/fs.h>
344 +
345 +               int mkdir(struct inode *inode, struct dentry *dentry,
346 +                   umode_t umode) { return 0; }
347 +
348 +               static const struct inode_operations
349 +                   iops __attribute__ ((unused)) = {
350 +                       .mkdir = mkdir,
351 +               };
352 +       ],[])
353 +])
354 +
355 +AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [
356 +       dnl #
357 +       dnl # 5.12 API change
358 +       dnl # The struct user_namespace arg was added as the first argument to
359 +       dnl # mkdir() of the iops structure.
360 +       dnl #
361 +       AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*])
362 +       ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [
363 +               AC_MSG_RESULT(yes)
364 +               AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
365 +                   [iops->mkdir() takes struct user_namespace*])
366 +       ],[
367 +               AC_MSG_CHECKING([whether iops->mkdir() takes umode_t])
368 +               ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
369 +                       AC_MSG_RESULT(yes)
370 +                       AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
371 +                           [iops->mkdir() takes umode_t])
372 +               ],[
373 +                       ZFS_LINUX_TEST_ERROR([mkdir()])
374 +               ])
375 +       ])
376 +])
377 diff --git a/config/kernel-mknod.m4 b/config/kernel-mknod.m4
378 new file mode 100644
379 index 00000000000..ffe45106003
380 --- /dev/null
381 +++ b/config/kernel-mknod.m4
382 @@ -0,0 +1,30 @@
383 +AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [
384 +       dnl #
385 +       dnl # 5.12 API change that added the struct user_namespace* arg
386 +       dnl # to the front of this function type's arg list.
387 +       dnl #
388 +       ZFS_LINUX_TEST_SRC([mknod_userns], [
389 +               #include <linux/fs.h>
390 +               #include <linux/sched.h>
391 +
392 +               int tmp_mknod(struct user_namespace *userns,
393 +                   struct inode *inode ,struct dentry *dentry,
394 +                   umode_t u, dev_t d) { return 0; }
395 +
396 +               static const struct inode_operations
397 +                       iops __attribute__ ((unused)) = {
398 +                       .mknod          = tmp_mknod,
399 +               };
400 +       ],[])
401 +])
402 +
403 +AC_DEFUN([ZFS_AC_KERNEL_MKNOD], [
404 +       AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*])
405 +       ZFS_LINUX_TEST_RESULT([mknod_userns], [
406 +               AC_MSG_RESULT(yes)
407 +               AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1,
408 +                   [iops->mknod() takes struct user_namespace*])
409 +       ],[
410 +               AC_MSG_RESULT(no)
411 +       ])
412 +])
413 diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4
414 index f707391539d..31d199f33bb 100644
415 --- a/config/kernel-rename.m4
416 +++ b/config/kernel-rename.m4
417 @@ -1,10 +1,10 @@
418 -dnl #
419 -dnl # 4.9 API change,
420 -dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants
421 -dnl # flags.
422 -dnl #
423 -AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [
424 -       ZFS_LINUX_TEST_SRC([inode_operations_rename], [
425 +AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
426 +       dnl #
427 +       dnl # 4.9 API change,
428 +       dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants
429 +       dnl # flags.
430 +       dnl #
431 +       ZFS_LINUX_TEST_SRC([inode_operations_rename_flags], [
432                 #include <linux/fs.h>
433                 int rename_fn(struct inode *sip, struct dentry *sdp,
434                         struct inode *tip, struct dentry *tdp,
435 @@ -15,15 +15,41 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [
436                         .rename = rename_fn,
437                 };
438         ],[])
439 +
440 +       dnl #
441 +       dnl # 5.12 API change,
442 +       dnl #
443 +       dnl # Linux 5.12 introduced passing struct user_namespace* as the first argument
444 +       dnl # of the rename() and other inode_operations members.
445 +       dnl #
446 +       ZFS_LINUX_TEST_SRC([inode_operations_rename_userns], [
447 +               #include <linux/fs.h>
448 +               int rename_fn(struct user_namespace *user_ns, struct inode *sip,
449 +                       struct dentry *sdp, struct inode *tip, struct dentry *tdp,
450 +                       unsigned int flags) { return 0; }
451 +
452 +               static const struct inode_operations
453 +                   iops __attribute__ ((unused)) = {
454 +                       .rename = rename_fn,
455 +               };
456 +       ],[])
457  ])
458  
459 -AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
460 -       AC_MSG_CHECKING([whether iops->rename() wants flags])
461 -       ZFS_LINUX_TEST_RESULT([inode_operations_rename], [
462 +AC_DEFUN([ZFS_AC_KERNEL_RENAME], [
463 +       AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*])
464 +       ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [
465                 AC_MSG_RESULT(yes)
466 -               AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
467 -                   [iops->rename() wants flags])
468 +               AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1,
469 +                   [iops->rename() takes struct user_namespace*])
470         ],[
471                 AC_MSG_RESULT(no)
472 +
473 +               ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [
474 +                       AC_MSG_RESULT(yes)
475 +                       AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
476 +                               [iops->rename() wants flags])
477 +               ],[
478 +                       AC_MSG_RESULT(no)
479 +               ])
480         ])
481  ])
482 diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4
483 index 45408c45c69..24245aa5344 100644
484 --- a/config/kernel-setattr-prepare.m4
485 +++ b/config/kernel-setattr-prepare.m4
486 @@ -1,27 +1,52 @@
487 -dnl #
488 -dnl # 4.9 API change
489 -dnl # The inode_change_ok() function has been renamed setattr_prepare()
490 -dnl # and updated to take a dentry rather than an inode.
491 -dnl #
492  AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
493 +       dnl #
494 +       dnl # 4.9 API change
495 +       dnl # The inode_change_ok() function has been renamed setattr_prepare()
496 +       dnl # and updated to take a dentry rather than an inode.
497 +       dnl #
498         ZFS_LINUX_TEST_SRC([setattr_prepare], [
499                 #include <linux/fs.h>
500         ], [
501                 struct dentry *dentry = NULL;
502                 struct iattr *attr = NULL;
503                 int error __attribute__ ((unused)) =
504 -                   setattr_prepare(dentry, attr);
505 +                       setattr_prepare(dentry, attr);
506 +       ])
507 +
508 +       dnl #
509 +       dnl # 5.12 API change
510 +       dnl # The setattr_prepare() function has been changed to accept a new argument
511 +       dnl # for struct user_namespace*
512 +       dnl #
513 +       ZFS_LINUX_TEST_SRC([setattr_prepare_userns], [
514 +               #include <linux/fs.h>
515 +       ], [
516 +               struct dentry *dentry = NULL;
517 +               struct iattr *attr = NULL;
518 +               struct user_namespace *userns = NULL;
519 +               int error __attribute__ ((unused)) =
520 +                       setattr_prepare(userns, dentry, attr);
521         ])
522  ])
523  
524  AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [
525 -       AC_MSG_CHECKING([whether setattr_prepare() is available])
526 -       ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
527 +       AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*])
528 +       ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns],
529             [setattr_prepare], [fs/attr.c], [
530                 AC_MSG_RESULT(yes)
531 -               AC_DEFINE(HAVE_SETATTR_PREPARE, 1,
532 -                   [setattr_prepare() is available])
533 +               AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1,
534 +                   [setattr_prepare() accepts user_namespace])
535         ], [
536                 AC_MSG_RESULT(no)
537 +
538 +               AC_MSG_CHECKING([whether setattr_prepare() is available, doesn't accept user_namespace])
539 +               ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
540 +                       [setattr_prepare], [fs/attr.c], [
541 +                       AC_MSG_RESULT(yes)
542 +                       AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1,
543 +                               [setattr_prepare() is available, doesn't accept user_namespace])
544 +               ], [
545 +                       AC_MSG_RESULT(no)
546 +               ])
547         ])
548  ])
549 diff --git a/config/kernel-symlink.m4 b/config/kernel-symlink.m4
550 new file mode 100644
551 index 00000000000..d90366d04b7
552 --- /dev/null
553 +++ b/config/kernel-symlink.m4
554 @@ -0,0 +1,30 @@
555 +AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [
556 +       dnl #
557 +       dnl # 5.12 API change that added the struct user_namespace* arg
558 +       dnl # to the front of this function type's arg list.
559 +       dnl #
560 +       ZFS_LINUX_TEST_SRC([symlink_userns], [
561 +               #include <linux/fs.h>
562 +               #include <linux/sched.h>
563 +
564 +               int tmp_symlink(struct user_namespace *userns,
565 +                   struct inode *inode ,struct dentry *dentry,
566 +                   const char *path) { return 0; }
567 +
568 +               static const struct inode_operations
569 +                       iops __attribute__ ((unused)) = {
570 +                       .symlink                = tmp_symlink,
571 +               };
572 +       ],[])
573 +])
574 +
575 +AC_DEFUN([ZFS_AC_KERNEL_SYMLINK], [
576 +       AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*])
577 +       ZFS_LINUX_TEST_RESULT([symlink_userns], [
578 +               AC_MSG_RESULT(yes)
579 +               AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1,
580 +                   [iops->symlink() takes struct user_namespace*])
581 +       ],[
582 +               AC_MSG_RESULT(no)
583 +       ])
584 +])
585 diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
586 index 137bf4a8aff..00b1e74a9cc 100644
587 --- a/config/kernel-xattr-handler.m4
588 +++ b/config/kernel-xattr-handler.m4
589 @@ -152,6 +152,21 @@ dnl #
590  dnl # Supported xattr handler set() interfaces checked newest to oldest.
591  dnl #
592  AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
593 +       ZFS_LINUX_TEST_SRC([xattr_handler_set_userns], [
594 +               #include <linux/xattr.h>
595 +
596 +               int set(const struct xattr_handler *handler,
597 +                       struct user_namespace *mnt_userns,
598 +                       struct dentry *dentry, struct inode *inode,
599 +                       const char *name, const void *buffer,
600 +                       size_t size, int flags)
601 +                       { return 0; }
602 +               static const struct xattr_handler
603 +                       xops __attribute__ ((unused)) = {
604 +                       .set = set,
605 +               };
606 +       ],[])
607 +
608         ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [
609                 #include <linux/xattr.h>
610  
611 @@ -194,45 +209,58 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
612  
613  AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
614         dnl #
615 -       dnl # 4.7 API change,
616 -       dnl # The xattr_handler->set() callback was changed to take both
617 -       dnl # dentry and inode.
618 +       dnl # 5.12 API change,
619 +       dnl # The xattr_handler->set() callback was changed to 8 arguments, and
620 +       dnl # struct user_namespace* was inserted as arg #2
621         dnl #
622 -       AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
623 -       ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
624 +       AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace])
625 +       ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [
626                 AC_MSG_RESULT(yes)
627 -               AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
628 -                   [xattr_handler->set() wants both dentry and inode])
629 +               AC_DEFINE(HAVE_XATTR_SET_USERNS, 1,
630 +                   [xattr_handler->set() takes user_namespace])
631         ],[
632                 dnl #
633 -               dnl # 4.4 API change,
634 -               dnl # The xattr_handler->set() callback was changed to take a
635 -               dnl # xattr_handler, and handler_flags argument was removed and
636 -               dnl # should be accessed by handler->flags.
637 +               dnl # 4.7 API change,
638 +               dnl # The xattr_handler->set() callback was changed to take both
639 +               dnl # dentry and inode.
640                 dnl #
641                 AC_MSG_RESULT(no)
642 -               AC_MSG_CHECKING(
643 -                   [whether xattr_handler->set() wants xattr_handler])
644 -               ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
645 +               AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
646 +               ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
647                         AC_MSG_RESULT(yes)
648 -                       AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
649 -                           [xattr_handler->set() wants xattr_handler])
650 +                       AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
651 +                           [xattr_handler->set() wants both dentry and inode])
652                 ],[
653                         dnl #
654 -                       dnl # 2.6.33 API change,
655 -                       dnl # The xattr_handler->set() callback was changed
656 -                       dnl # to take a dentry instead of an inode, and a
657 -                       dnl # handler_flags argument was added.
658 +                       dnl # 4.4 API change,
659 +                       dnl # The xattr_handler->set() callback was changed to take a
660 +                       dnl # xattr_handler, and handler_flags argument was removed and
661 +                       dnl # should be accessed by handler->flags.
662                         dnl #
663                         AC_MSG_RESULT(no)
664                         AC_MSG_CHECKING(
665 -                           [whether xattr_handler->set() wants dentry])
666 -                       ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
667 +                           [whether xattr_handler->set() wants xattr_handler])
668 +                       ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
669                                 AC_MSG_RESULT(yes)
670 -                               AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
671 -                                   [xattr_handler->set() wants dentry])
672 +                               AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
673 +                                   [xattr_handler->set() wants xattr_handler])
674                         ],[
675 -                               ZFS_LINUX_TEST_ERROR([xattr set()])
676 +                               dnl #
677 +                               dnl # 2.6.33 API change,
678 +                               dnl # The xattr_handler->set() callback was changed
679 +                               dnl # to take a dentry instead of an inode, and a
680 +                               dnl # handler_flags argument was added.
681 +                               dnl #
682 +                               AC_MSG_RESULT(no)
683 +                               AC_MSG_CHECKING(
684 +                                   [whether xattr_handler->set() wants dentry])
685 +                               ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
686 +                                       AC_MSG_RESULT(yes)
687 +                                       AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
688 +                                           [xattr_handler->set() wants dentry])
689 +                               ],[
690 +                                       ZFS_LINUX_TEST_ERROR([xattr set()])
691 +                               ])
692                         ])
693                 ])
694         ])
695 diff --git a/config/kernel.m4 b/config/kernel.m4
696 index f31be845f5d..24db38f09f4 100644
697 --- a/config/kernel.m4
698 +++ b/config/kernel.m4
699 @@ -79,9 +79,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
700         ZFS_AC_KERNEL_SRC_EVICT_INODE
701         ZFS_AC_KERNEL_SRC_DIRTY_INODE
702         ZFS_AC_KERNEL_SRC_SHRINKER
703 -       ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T
704 +       ZFS_AC_KERNEL_SRC_MKDIR
705         ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS
706 -       ZFS_AC_KERNEL_SRC_CREATE_FLAGS
707 +       ZFS_AC_KERNEL_SRC_CREATE
708         ZFS_AC_KERNEL_SRC_GET_LINK
709         ZFS_AC_KERNEL_SRC_PUT_LINK
710         ZFS_AC_KERNEL_SRC_TMPFILE
711 @@ -115,7 +115,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
712         ZFS_AC_KERNEL_SRC_KUIDGID_T
713         ZFS_AC_KERNEL_SRC_KUID_HELPERS
714         ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST
715 -       ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS
716 +       ZFS_AC_KERNEL_SRC_RENAME
717         ZFS_AC_KERNEL_SRC_CURRENT_TIME
718         ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES
719         ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL
720 @@ -125,6 +125,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
721         ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES
722         ZFS_AC_KERNEL_SRC_KSTRTOUL
723         ZFS_AC_KERNEL_SRC_PERCPU
724 +       ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS
725 +       ZFS_AC_KERNEL_SRC_MKNOD
726 +       ZFS_AC_KERNEL_SRC_SYMLINK
727  
728         AC_MSG_CHECKING([for available kernel interfaces])
729         ZFS_LINUX_TEST_COMPILE_ALL([kabi])
730 @@ -177,9 +180,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
731         ZFS_AC_KERNEL_EVICT_INODE
732         ZFS_AC_KERNEL_DIRTY_INODE
733         ZFS_AC_KERNEL_SHRINKER
734 -       ZFS_AC_KERNEL_MKDIR_UMODE_T
735 +       ZFS_AC_KERNEL_MKDIR
736         ZFS_AC_KERNEL_LOOKUP_FLAGS
737 -       ZFS_AC_KERNEL_CREATE_FLAGS
738 +       ZFS_AC_KERNEL_CREATE
739         ZFS_AC_KERNEL_GET_LINK
740         ZFS_AC_KERNEL_PUT_LINK
741         ZFS_AC_KERNEL_TMPFILE
742 @@ -213,7 +216,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
743         ZFS_AC_KERNEL_KUIDGID_T
744         ZFS_AC_KERNEL_KUID_HELPERS
745         ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST
746 -       ZFS_AC_KERNEL_RENAME_WANTS_FLAGS
747 +       ZFS_AC_KERNEL_RENAME
748         ZFS_AC_KERNEL_CURRENT_TIME
749         ZFS_AC_KERNEL_USERNS_CAPABILITIES
750         ZFS_AC_KERNEL_IN_COMPAT_SYSCALL
751 @@ -223,6 +226,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
752         ZFS_AC_KERNEL_TOTALHIGH_PAGES
753         ZFS_AC_KERNEL_KSTRTOUL
754         ZFS_AC_KERNEL_PERCPU
755 +       ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS
756 +       ZFS_AC_KERNEL_MKNOD
757 +       ZFS_AC_KERNEL_SYMLINK
758  ])
759  
760  dnl #
761 diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h
762 index c35e80d31cd..91e908598fb 100644
763 --- a/include/os/linux/kernel/linux/vfs_compat.h
764 +++ b/include/os/linux/kernel/linux/vfs_compat.h
765 @@ -343,7 +343,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid)
766  /*
767   * 4.9 API change
768   */
769 -#ifndef HAVE_SETATTR_PREPARE
770 +#if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \
771 +    defined(HAVE_SETATTR_PREPARE_USERNS))
772  static inline int
773  setattr_prepare(struct dentry *dentry, struct iattr *ia)
774  {
775 @@ -389,6 +390,15 @@ func(const struct path *path, struct kstat *stat, u32 request_mask,        \
776  {                                                                      \
777         return (func##_impl(path, stat, request_mask, query_flags));    \
778  }
779 +#elif defined(HAVE_USERNS_IOPS_GETATTR)
780 +#define        ZPL_GETATTR_WRAPPER(func)                                       \
781 +static int                                                             \
782 +func(struct user_namespace *user_ns, const struct path *path,  \
783 +    struct kstat *stat, u32 request_mask, unsigned int query_flags)    \
784 +{                                                                      \
785 +       return (func##_impl(user_ns, path, stat, request_mask, \
786 +           query_flags));      \
787 +}
788  #else
789  #error
790  #endif
791 @@ -436,4 +446,16 @@ zpl_is_32bit_api(void)
792  #endif
793  }
794  
795 +/*
796 + * 5.12 API change
797 + * To support id-mapped mounts, generic_fillattr() was modified to
798 + * accept a new struct user_namespace* as its first arg.
799 + */
800 +#ifdef HAVE_GENERIC_FILLATTR_USERNS
801 +#define        zpl_generic_fillattr(user_ns, ip, sp)   \
802 +    generic_fillattr(user_ns, ip, sp)
803 +#else
804 +#define        zpl_generic_fillattr(user_ns, ip, sp)   generic_fillattr(ip, sp)
805 +#endif
806 +
807  #endif /* _ZFS_VFS_H */
808 diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h
809 index 8348e99198a..54690727eab 100644
810 --- a/include/os/linux/kernel/linux/xattr_compat.h
811 +++ b/include/os/linux/kernel/linux/xattr_compat.h
812 @@ -119,12 +119,27 @@ fn(struct dentry *dentry, const char *name, void *buffer, size_t size,    \
813  #error "Unsupported kernel"
814  #endif
815  
816 +/*
817 + * 5.12 API change,
818 + * The xattr_handler->set() callback was changed to take the
819 + * struct user_namespace* as the first arg, to support idmapped
820 + * mounts.
821 + */
822 +#if defined(HAVE_XATTR_SET_USERNS)
823 +#define        ZPL_XATTR_SET_WRAPPER(fn)                                       \
824 +static int                                                             \
825 +fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \
826 +    struct dentry *dentry, struct inode *inode, const char *name,      \
827 +    const void *buffer, size_t size, int flags)        \
828 +{                                                                      \
829 +       return (__ ## fn(inode, name, buffer, size, flags));            \
830 +}
831  /*
832   * 4.7 API change,
833   * The xattr_handler->set() callback was changed to take a both dentry and
834   * inode, because the dentry might not be attached to an inode yet.
835   */
836 -#if defined(HAVE_XATTR_SET_DENTRY_INODE)
837 +#elif defined(HAVE_XATTR_SET_DENTRY_INODE)
838  #define        ZPL_XATTR_SET_WRAPPER(fn)                                       \
839  static int                                                             \
840  fn(const struct xattr_handler *handler, struct dentry *dentry,         \
841 diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h
842 index ef76de3e298..47f91e4a6cf 100644
843 --- a/include/os/linux/zfs/sys/zfs_vnops_os.h
844 +++ b/include/os/linux/zfs/sys/zfs_vnops_os.h
845 @@ -54,7 +54,8 @@ extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap,
846  extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd,
847      cred_t *cr, int flags);
848  extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr);
849 -extern int zfs_getattr_fast(struct inode *ip, struct kstat *sp);
850 +extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip,
851 +       struct kstat *sp);
852  extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr);
853  extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp,
854      char *tnm, cred_t *cr, int flags);
855 diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
856 index b0bb9c29c0b..21825d1f378 100644
857 --- a/include/os/linux/zfs/sys/zpl.h
858 +++ b/include/os/linux/zfs/sys/zpl.h
859 @@ -171,4 +171,22 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
860         timespec_trunc(ts, (ip)->i_sb->s_time_gran)
861  #endif
862  
863 +#if defined(HAVE_INODE_OWNER_OR_CAPABLE)
864 +#define        zpl_inode_owner_or_capable(ns, ip)      inode_owner_or_capable(ip)
865 +#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED)
866 +#define        zpl_inode_owner_or_capable(ns, ip)      inode_owner_or_capable(ns, ip)
867 +#else
868 +#error "Unsupported kernel"
869 +#endif
870 +
871 +#ifdef HAVE_SETATTR_PREPARE_USERNS
872 +#define        zpl_setattr_prepare(ns, dentry, ia)     setattr_prepare(ns, dentry, ia)
873 +#else
874 +/*
875 + * Use kernel-provided version, or our own from
876 + * linux/vfs_compat.h
877 + */
878 +#define        zpl_setattr_prepare(ns, dentry, ia)     setattr_prepare(dentry, ia)
879 +#endif
880 +
881  #endif /* _SYS_ZPL_H */
882 diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c
883 index 8780d7f6c70..bbccb2e572d 100644
884 --- a/module/os/linux/zfs/policy.c
885 +++ b/module/os/linux/zfs/policy.c
886 @@ -124,7 +124,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
887         if (crgetfsuid(cr) == owner)
888                 return (0);
889  
890 -       if (inode_owner_or_capable(ip))
891 +       if (zpl_inode_owner_or_capable(kcred->user_ns, ip))
892                 return (0);
893  
894  #if defined(CONFIG_USER_NS)
895 diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
896 index 84c33b541ea..8aeed6f568c 100644
897 --- a/module/os/linux/zfs/zfs_vnops_os.c
898 +++ b/module/os/linux/zfs/zfs_vnops_os.c
899 @@ -1656,7 +1656,8 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
900   */
901  /* ARGSUSED */
902  int
903 -zfs_getattr_fast(struct inode *ip, struct kstat *sp)
904 +zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip,
905 +    struct kstat *sp)
906  {
907         znode_t *zp = ITOZ(ip);
908         zfsvfs_t *zfsvfs = ITOZSB(ip);
909 @@ -1668,7 +1669,7 @@ zfs_getattr_fast(struct inode *ip, struct kstat *sp)
910  
911         mutex_enter(&zp->z_lock);
912  
913 -       generic_fillattr(ip, sp);
914 +       zpl_generic_fillattr(user_ns, ip, sp);
915         /*
916          * +1 link count for root inode with visible '.zfs' directory.
917          */
918 diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c
919 index e6420f19ed8..9b526afd000 100644
920 --- a/module/os/linux/zfs/zpl_ctldir.c
921 +++ b/module/os/linux/zfs/zpl_ctldir.c
922 @@ -101,12 +101,22 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
923   */
924  /* ARGSUSED */
925  static int
926 +#ifdef HAVE_USERNS_IOPS_GETATTR
927 +zpl_root_getattr_impl(struct user_namespace *user_ns,
928 +    const struct path *path, struct kstat *stat, u32 request_mask,
929 +    unsigned int query_flags)
930 +#else
931  zpl_root_getattr_impl(const struct path *path, struct kstat *stat,
932      u32 request_mask, unsigned int query_flags)
933 +#endif
934  {
935         struct inode *ip = path->dentry->d_inode;
936  
937 +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR)
938 +       generic_fillattr(user_ns, ip, stat);
939 +#else
940         generic_fillattr(ip, stat);
941 +#endif
942         stat->atime = current_time(ip);
943  
944         return (0);
945 @@ -290,8 +300,14 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
946  #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
947  
948  static int
949 +#ifdef HAVE_IOPS_RENAME_USERNS
950 +zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip,
951 +    struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
952 +    unsigned int flags)
953 +#else
954  zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
955      struct inode *tdip, struct dentry *tdentry, unsigned int flags)
956 +#endif
957  {
958         cred_t *cr = CRED();
959         int error;
960 @@ -309,7 +325,7 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
961         return (error);
962  }
963  
964 -#ifndef HAVE_RENAME_WANTS_FLAGS
965 +#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS)
966  static int
967  zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
968      struct inode *tdip, struct dentry *tdentry)
969 @@ -333,7 +349,12 @@ zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry)
970  }
971  
972  static int
973 +#ifdef HAVE_IOPS_MKDIR_USERNS
974 +zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip,
975 +    struct dentry *dentry, umode_t mode)
976 +#else
977  zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
978 +#endif
979  {
980         cred_t *cr = CRED();
981         vattr_t *vap;
982 @@ -363,14 +384,24 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
983   */
984  /* ARGSUSED */
985  static int
986 +#ifdef HAVE_USERNS_IOPS_GETATTR
987 +zpl_snapdir_getattr_impl(struct user_namespace *user_ns,
988 +    const struct path *path, struct kstat *stat, u32 request_mask,
989 +    unsigned int query_flags)
990 +#else
991  zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
992      u32 request_mask, unsigned int query_flags)
993 +#endif
994  {
995         struct inode *ip = path->dentry->d_inode;
996         zfsvfs_t *zfsvfs = ITOZSB(ip);
997  
998         ZPL_ENTER(zfsvfs);
999 +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR)
1000 +       generic_fillattr(user_ns, ip, stat);
1001 +#else
1002         generic_fillattr(ip, stat);
1003 +#endif
1004  
1005         stat->nlink = stat->size = 2;
1006         stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
1007 @@ -408,7 +439,7 @@ const struct file_operations zpl_fops_snapdir = {
1008  const struct inode_operations zpl_ops_snapdir = {
1009         .lookup         = zpl_snapdir_lookup,
1010         .getattr        = zpl_snapdir_getattr,
1011 -#ifdef HAVE_RENAME_WANTS_FLAGS
1012 +#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
1013         .rename         = zpl_snapdir_rename2,
1014  #else
1015         .rename         = zpl_snapdir_rename,
1016 @@ -495,8 +526,14 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
1017  
1018  /* ARGSUSED */
1019  static int
1020 +#ifdef HAVE_USERNS_IOPS_GETATTR
1021 +zpl_shares_getattr_impl(struct user_namespace *user_ns,
1022 +    const struct path *path, struct kstat *stat, u32 request_mask,
1023 +    unsigned int query_flags)
1024 +#else
1025  zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
1026      u32 request_mask, unsigned int query_flags)
1027 +#endif
1028  {
1029         struct inode *ip = path->dentry->d_inode;
1030         zfsvfs_t *zfsvfs = ITOZSB(ip);
1031 @@ -506,7 +543,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
1032         ZPL_ENTER(zfsvfs);
1033  
1034         if (zfsvfs->z_shares_dir == 0) {
1035 +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR)
1036 +               generic_fillattr(user_ns, path->dentry->d_inode, stat);
1037 +#else
1038                 generic_fillattr(path->dentry->d_inode, stat);
1039 +#endif
1040                 stat->nlink = stat->size = 2;
1041                 stat->atime = current_time(ip);
1042                 ZPL_EXIT(zfsvfs);
1043 @@ -515,7 +556,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
1044  
1045         error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
1046         if (error == 0) {
1047 -               error = -zfs_getattr_fast(ZTOI(dzp), stat);
1048 +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR)
1049 +               error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat);
1050 +#else
1051 +               error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat);
1052 +#endif
1053                 iput(ZTOI(dzp));
1054         }
1055  
1056 diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c
1057 index 970db4a8b73..ea6993ffa4b 100644
1058 --- a/module/os/linux/zfs/zpl_file.c
1059 +++ b/module/os/linux/zfs/zpl_file.c
1060 @@ -869,7 +869,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
1061             !capable(CAP_LINUX_IMMUTABLE))
1062                 return (-EACCES);
1063  
1064 -       if (!inode_owner_or_capable(ip))
1065 +       if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
1066                 return (-EACCES);
1067  
1068         xva_init(xva);
1069 diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c
1070 index 117963f44af..cf0eab3e8c9 100644
1071 --- a/module/os/linux/zfs/zpl_inode.c
1072 +++ b/module/os/linux/zfs/zpl_inode.c
1073 @@ -128,7 +128,12 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr)
1074  }
1075  
1076  static int
1077 +#ifdef HAVE_IOPS_CREATE_USERNS
1078 +zpl_create(struct user_namespace *user_ns, struct inode *dir,
1079 +    struct dentry *dentry, umode_t mode, bool flag)
1080 +#else
1081  zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)
1082 +#endif
1083  {
1084         cred_t *cr = CRED();
1085         znode_t *zp;
1086 @@ -163,7 +168,12 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)
1087  }
1088  
1089  static int
1090 +#ifdef HAVE_IOPS_MKNOD_USERNS
1091 +zpl_mknod(struct user_namespace *user_ns, struct inode *dir,
1092 +    struct dentry *dentry, umode_t mode,
1093 +#else
1094  zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
1095 +#endif
1096      dev_t rdev)
1097  {
1098         cred_t *cr = CRED();
1099 @@ -278,7 +288,12 @@ zpl_unlink(struct inode *dir, struct dentry *dentry)
1100  }
1101  
1102  static int
1103 +#ifdef HAVE_IOPS_MKDIR_USERNS
1104 +zpl_mkdir(struct user_namespace *user_ns, struct inode *dir,
1105 +    struct dentry *dentry, umode_t mode)
1106 +#else
1107  zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1108 +#endif
1109  {
1110         cred_t *cr = CRED();
1111         vattr_t *vap;
1112 @@ -338,8 +353,14 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry)
1113  }
1114  
1115  static int
1116 +#ifdef HAVE_USERNS_IOPS_GETATTR
1117 +zpl_getattr_impl(struct user_namespace *user_ns,
1118 +    const struct path *path, struct kstat *stat, u32 request_mask,
1119 +    unsigned int query_flags)
1120 +#else
1121  zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
1122      unsigned int query_flags)
1123 +#endif
1124  {
1125         int error;
1126         fstrans_cookie_t cookie;
1127 @@ -350,7 +371,11 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
1128          * XXX request_mask and query_flags currently ignored.
1129          */
1130  
1131 -       error = -zfs_getattr_fast(path->dentry->d_inode, stat);
1132 +#ifdef HAVE_USERNS_IOPS_GETATTR
1133 +       error = -zfs_getattr_fast(user_ns, path->dentry->d_inode, stat);
1134 +#else
1135 +       error = -zfs_getattr_fast(kcred->user_ns, path->dentry->d_inode, stat);
1136 +#endif
1137         spl_fstrans_unmark(cookie);
1138         ASSERT3S(error, <=, 0);
1139  
1140 @@ -359,7 +384,12 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
1141  ZPL_GETATTR_WRAPPER(zpl_getattr);
1142  
1143  static int
1144 +#ifdef HAVE_SETATTR_PREPARE_USERNS
1145 +zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry,
1146 +    struct iattr *ia)
1147 +#else
1148  zpl_setattr(struct dentry *dentry, struct iattr *ia)
1149 +#endif
1150  {
1151         struct inode *ip = dentry->d_inode;
1152         cred_t *cr = CRED();
1153 @@ -367,7 +397,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
1154         int error;
1155         fstrans_cookie_t cookie;
1156  
1157 -       error = setattr_prepare(dentry, ia);
1158 +       error = zpl_setattr_prepare(kcred->user_ns, dentry, ia);
1159         if (error)
1160                 return (error);
1161  
1162 @@ -399,8 +429,14 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
1163  }
1164  
1165  static int
1166 +#ifdef HAVE_IOPS_RENAME_USERNS
1167 +zpl_rename2(struct user_namespace *user_ns, struct inode *sdip,
1168 +    struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
1169 +    unsigned int flags)
1170 +#else
1171  zpl_rename2(struct inode *sdip, struct dentry *sdentry,
1172      struct inode *tdip, struct dentry *tdentry, unsigned int flags)
1173 +#endif
1174  {
1175         cred_t *cr = CRED();
1176         int error;
1177 @@ -421,7 +457,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry,
1178         return (error);
1179  }
1180  
1181 -#ifndef HAVE_RENAME_WANTS_FLAGS
1182 +#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS)
1183  static int
1184  zpl_rename(struct inode *sdip, struct dentry *sdentry,
1185      struct inode *tdip, struct dentry *tdentry)
1186 @@ -431,7 +467,12 @@ zpl_rename(struct inode *sdip, struct dentry *sdentry,
1187  #endif
1188  
1189  static int
1190 +#ifdef HAVE_IOPS_SYMLINK_USERNS
1191 +zpl_symlink(struct user_namespace *user_ns, struct inode *dir,
1192 +    struct dentry *dentry, const char *name)
1193 +#else
1194  zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
1195 +#endif
1196  {
1197         cred_t *cr = CRED();
1198         vattr_t *vap;
1199 @@ -678,7 +719,7 @@ const struct inode_operations zpl_dir_inode_operations = {
1200         .mkdir          = zpl_mkdir,
1201         .rmdir          = zpl_rmdir,
1202         .mknod          = zpl_mknod,
1203 -#ifdef HAVE_RENAME_WANTS_FLAGS
1204 +#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
1205         .rename         = zpl_rename2,
1206  #else
1207         .rename         = zpl_rename,
1208 diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c
1209 index 83812f2dcba..971cd6ad031 100644
1210 --- a/module/os/linux/zfs/zpl_xattr.c
1211 +++ b/module/os/linux/zfs/zpl_xattr.c
1212 @@ -1233,7 +1233,7 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
1213         if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1214                 return (-EOPNOTSUPP);
1215  
1216 -       if (!inode_owner_or_capable(ip))
1217 +       if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
1218                 return (-EPERM);
1219  
1220         if (value) {
1221 @@ -1273,7 +1273,7 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name,
1222         if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1223                 return (-EOPNOTSUPP);
1224  
1225 -       if (!inode_owner_or_capable(ip))
1226 +       if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
1227                 return (-EPERM);
1228  
1229         if (value) {
1230 From ffd6978ef59cfe2773e984bf03de2f0b93b03f5c Mon Sep 17 00:00:00 2001
1231 From: Coleman Kane <ckane@colemankane.org>
1232 Date: Sat, 20 Mar 2021 01:33:42 -0400
1233 Subject: [PATCH] Linux 5.12 update: bio_max_segs() replaces BIO_MAX_PAGES
1234
1235 The BIO_MAX_PAGES macro is being retired in favor of a bio_max_segs()
1236 function that implements the typical MIN(x,y) logic used throughout the
1237 kernel for bounding the allocation, and also the new implementation is
1238 intended to be signed-safe (which the former was not).
1239
1240 Reviewed-by: Tony Hutter <hutter2@llnl.gov>
1241 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
1242 Signed-off-by: Coleman Kane <ckane@colemankane.org>
1243 Closes #11765
1244 ---
1245  config/kernel-bio_max_segs.m4   | 23 +++++++++++++++++++++++
1246  config/kernel.m4                |  2 ++
1247  module/os/linux/zfs/vdev_disk.c |  5 +++++
1248  3 files changed, 30 insertions(+)
1249  create mode 100644 config/kernel-bio_max_segs.m4
1250
1251 diff --git a/config/kernel-bio_max_segs.m4 b/config/kernel-bio_max_segs.m4
1252 new file mode 100644
1253 index 00000000000..a90d75455c1
1254 --- /dev/null
1255 +++ b/config/kernel-bio_max_segs.m4
1256 @@ -0,0 +1,23 @@
1257 +dnl #
1258 +dnl # 5.12 API change removes BIO_MAX_PAGES in favor of bio_max_segs()
1259 +dnl # which will handle the logic of setting the upper-bound to a
1260 +dnl # BIO_MAX_PAGES, internally.
1261 +dnl #
1262 +AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS], [
1263 +       ZFS_LINUX_TEST_SRC([bio_max_segs], [
1264 +               #include <linux/bio.h>
1265 +       ],[
1266 +               bio_max_segs(1);
1267 +       ])
1268 +])
1269 +
1270 +AC_DEFUN([ZFS_AC_KERNEL_BIO_MAX_SEGS], [
1271 +       AC_MSG_CHECKING([whether bio_max_segs() exists])
1272 +       ZFS_LINUX_TEST_RESULT([bio_max_segs], [
1273 +               AC_MSG_RESULT(yes)
1274 +
1275 +               AC_DEFINE([HAVE_BIO_MAX_SEGS], 1, [bio_max_segs() is implemented])
1276 +       ],[
1277 +               AC_MSG_RESULT(no)
1278 +       ])
1279 +])
1280 diff --git a/config/kernel.m4 b/config/kernel.m4
1281 index 24db38f09f4..dfb6165d879 100644
1282 --- a/config/kernel.m4
1283 +++ b/config/kernel.m4
1284 @@ -128,6 +128,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
1285         ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS
1286         ZFS_AC_KERNEL_SRC_MKNOD
1287         ZFS_AC_KERNEL_SRC_SYMLINK
1288 +       ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
1289  
1290         AC_MSG_CHECKING([for available kernel interfaces])
1291         ZFS_LINUX_TEST_COMPILE_ALL([kabi])
1292 @@ -229,6 +230,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
1293         ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS
1294         ZFS_AC_KERNEL_MKNOD
1295         ZFS_AC_KERNEL_SYMLINK
1296 +       ZFS_AC_KERNEL_BIO_MAX_SEGS
1297  ])
1298  
1299  dnl #
1300 diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c
1301 index ff71ef4cd06..c56fd3a6ff2 100644
1302 --- a/module/os/linux/zfs/vdev_disk.c
1303 +++ b/module/os/linux/zfs/vdev_disk.c
1304 @@ -589,9 +589,14 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
1305                 }
1306  
1307                 /* bio_alloc() with __GFP_WAIT never returns NULL */
1308 +#ifdef HAVE_BIO_MAX_SEGS
1309 +               dr->dr_bio[i] = bio_alloc(GFP_NOIO, bio_max_segs(
1310 +                   abd_nr_pages_off(zio->io_abd, bio_size, abd_offset)));
1311 +#else
1312                 dr->dr_bio[i] = bio_alloc(GFP_NOIO,
1313                     MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset),
1314                     BIO_MAX_PAGES));
1315 +#endif
1316                 if (unlikely(dr->dr_bio[i] == NULL)) {
1317                         vdev_disk_dio_free(dr);
1318                         return (SET_ERROR(ENOMEM));
This page took 0.195056 seconds and 3 git commands to generate.