diff options
author | Georgy Yakovlev <gyakovlev@gentoo.org> | 2021-06-03 18:20:37 -0700 |
---|---|---|
committer | Georgy Yakovlev <gyakovlev@gentoo.org> | 2021-06-03 18:25:13 -0700 |
commit | 919f0c385d58501b3b1aa32543ff3772aea483ee (patch) | |
tree | 5342c0528bfccaf39ac0fa945ca3a069eeb9a32e /sys-fs | |
parent | net-news/liferea: add ~ppc64 keyword (diff) | |
download | gentoo-919f0c385d58501b3b1aa32543ff3772aea483ee.tar.gz gentoo-919f0c385d58501b3b1aa32543ff3772aea483ee.tar.bz2 gentoo-919f0c385d58501b3b1aa32543ff3772aea483ee.zip |
sys-fs/zfs-kmod: revbump 2.0.4, add 5.12 support and fixes
run eautoreconf, as a lot of m4 files changed
Bug: https://bugs.gentoo.org/792627
Bug: https://bugs.gentoo.org/790686
Signed-off-by: Georgy Yakovlev <gyakovlev@gentoo.org>
Diffstat (limited to 'sys-fs')
8 files changed, 1902 insertions, 0 deletions
diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_bio_max_segs.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_bio_max_segs.patch new file mode 100644 index 000000000000..33f9a344e2f2 --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_bio_max_segs.patch @@ -0,0 +1,91 @@ +From 77352db228c07ce8ba50478b9029820ca69c6c1b Mon Sep 17 00:00:00 2001 +From: Coleman Kane <ckane@colemankane.org> +Date: Sat, 20 Mar 2021 01:33:42 -0400 +Subject: [PATCH] Linux 5.12 update: bio_max_segs() replaces BIO_MAX_PAGES + +The BIO_MAX_PAGES macro is being retired in favor of a bio_max_segs() +function that implements the typical MIN(x,y) logic used throughout the +kernel for bounding the allocation, and also the new implementation is +intended to be signed-safe (which the former was not). + +Reviewed-by: Tony Hutter <hutter2@llnl.gov> +Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> +Signed-off-by: Coleman Kane <ckane@colemankane.org> +Closes #11765 +(cherry picked from commit ffd6978ef59cfe2773e984bf03de2f0b93b03f5c) +Signed-off-by: Jonathon Fernyhough <jonathon@m2x.dev> +--- + config/kernel-bio_max_segs.m4 | 23 +++++++++++++++++++++++ + config/kernel.m4 | 2 ++ + module/os/linux/zfs/vdev_disk.c | 5 +++++ + 3 files changed, 30 insertions(+) + create mode 100644 config/kernel-bio_max_segs.m4 + +diff --git a/config/kernel-bio_max_segs.m4 b/config/kernel-bio_max_segs.m4 +new file mode 100644 +index 00000000000..a90d75455c1 +--- /dev/null ++++ b/config/kernel-bio_max_segs.m4 +@@ -0,0 +1,23 @@ ++dnl # ++dnl # 5.12 API change removes BIO_MAX_PAGES in favor of bio_max_segs() ++dnl # which will handle the logic of setting the upper-bound to a ++dnl # BIO_MAX_PAGES, internally. ++dnl # ++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS], [ ++ ZFS_LINUX_TEST_SRC([bio_max_segs], [ ++ #include <linux/bio.h> ++ ],[ ++ bio_max_segs(1); ++ ]) ++]) ++ ++AC_DEFUN([ZFS_AC_KERNEL_BIO_MAX_SEGS], [ ++ AC_MSG_CHECKING([whether bio_max_segs() exists]) ++ ZFS_LINUX_TEST_RESULT([bio_max_segs], [ ++ AC_MSG_RESULT(yes) ++ ++ AC_DEFINE([HAVE_BIO_MAX_SEGS], 1, [bio_max_segs() is implemented]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) ++]) +diff --git a/config/kernel.m4 b/config/kernel.m4 +index 51c7fb926ec..b8d53490a4a 100644 +--- a/config/kernel.m4 ++++ b/config/kernel.m4 +@@ -127,6 +127,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ + ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS + ZFS_AC_KERNEL_SRC_MKNOD + ZFS_AC_KERNEL_SRC_SYMLINK ++ ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS + + AC_MSG_CHECKING([for available kernel interfaces]) + ZFS_LINUX_TEST_COMPILE_ALL([kabi]) +@@ -227,6 +228,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS + ZFS_AC_KERNEL_MKNOD + ZFS_AC_KERNEL_SYMLINK ++ ZFS_AC_KERNEL_BIO_MAX_SEGS + ]) + + dnl # +diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c +index 08c33313407..aaaf4105979 100644 +--- a/module/os/linux/zfs/vdev_disk.c ++++ b/module/os/linux/zfs/vdev_disk.c +@@ -593,9 +593,14 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, + } + + /* bio_alloc() with __GFP_WAIT never returns NULL */ ++#ifdef HAVE_BIO_MAX_SEGS ++ dr->dr_bio[i] = bio_alloc(GFP_NOIO, bio_max_segs( ++ abd_nr_pages_off(zio->io_abd, bio_size, abd_offset))); ++#else + dr->dr_bio[i] = bio_alloc(GFP_NOIO, + MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset), + BIO_MAX_PAGES)); ++#endif + if (unlikely(dr->dr_bio[i] == NULL)) { + vdev_disk_dio_free(dr); + return (SET_ERROR(ENOMEM)); diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_idmapped_mounts.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_idmapped_mounts.patch new file mode 100644 index 000000000000..fd8b025a8fd7 --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_idmapped_mounts.patch @@ -0,0 +1,1231 @@ +From f315d9a3ff3cc0b81c99dd9be5878a55d2e98d8e Mon Sep 17 00:00:00 2001 +From: Coleman Kane <ckane@colemankane.org> +Date: Sat, 20 Mar 2021 00:00:59 -0400 +Subject: [PATCH] Linux 5.12 compat: idmapped mounts + +In Linux 5.12, the filesystem API was modified to support ipmapped +mounts by adding a "struct user_namespace *" parameter to a number +functions and VFS handlers. This change adds the needed autoconf +macros to detect the new interfaces and updates the code appropriately. +This change does not add support for idmapped mounts, instead it +preserves the existing behavior by passing the initial user namespace +where needed. A subsequent commit will be required to add support +for idmapped mounted. + +Reviewed-by: Tony Hutter <hutter2@llnl.gov> +Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> +Co-authored-by: Brian Behlendorf <behlendorf1@llnl.gov> +Signed-off-by: Coleman Kane <ckane@colemankane.org> +Closes #11712 +(cherry picked from commit e2a8296131e94ad785f5564156ed2db1fdb2e080) +Signed-off-by: Jonathon Fernyhough <jonathon@m2x.dev> +--- + config/kernel-generic_fillattr.m4 | 28 +++++++ + config/kernel-inode-create.m4 | 43 +++++++++-- + config/kernel-inode-getattr.m4 | 63 +++++++++++++--- + config/kernel-is_owner_or_cap.m4 | 23 +++++- + config/kernel-mkdir-umode-t.m4 | 32 -------- + config/kernel-mkdir.m4 | 65 ++++++++++++++++ + config/kernel-mknod.m4 | 30 ++++++++ + config/kernel-rename.m4 | 50 ++++++++++--- + config/kernel-setattr-prepare.m4 | 45 ++++++++--- + config/kernel-symlink.m4 | 30 ++++++++ + config/kernel-xattr-handler.m4 | 78 +++++++++++++------- + config/kernel.m4 | 18 +++-- + include/os/linux/kernel/linux/vfs_compat.h | 24 +++++- + include/os/linux/kernel/linux/xattr_compat.h | 17 ++++- + include/os/linux/zfs/sys/zfs_vnops_os.h | 3 +- + include/os/linux/zfs/sys/zpl.h | 18 +++++ + module/os/linux/zfs/policy.c | 2 +- + module/os/linux/zfs/zfs_vnops_os.c | 5 +- + module/os/linux/zfs/zpl_ctldir.c | 51 ++++++++++++- + module/os/linux/zfs/zpl_file.c | 2 +- + module/os/linux/zfs/zpl_inode.c | 49 +++++++++++- + module/os/linux/zfs/zpl_xattr.c | 4 +- + 22 files changed, 557 insertions(+), 123 deletions(-) + create mode 100644 config/kernel-generic_fillattr.m4 + delete mode 100644 config/kernel-mkdir-umode-t.m4 + create mode 100644 config/kernel-mkdir.m4 + create mode 100644 config/kernel-mknod.m4 + create mode 100644 config/kernel-symlink.m4 + +diff --git a/config/kernel-generic_fillattr.m4 b/config/kernel-generic_fillattr.m4 +new file mode 100644 +index 00000000000..50c8031305b +--- /dev/null ++++ b/config/kernel-generic_fillattr.m4 +@@ -0,0 +1,28 @@ ++dnl # ++dnl # 5.12 API ++dnl # ++dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace* ++dnl # as the first arg, to support idmapped mounts. ++dnl # ++AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [ ++ ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [ ++ #include <linux/fs.h> ++ ],[ ++ struct user_namespace *userns = NULL; ++ struct inode *in = NULL; ++ struct kstat *k = NULL; ++ generic_fillattr(userns, in, k); ++ ]) ++]) ++ ++AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [ ++ AC_MSG_CHECKING([whether generic_fillattr requres struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [ ++ AC_MSG_RESULT([yes]) ++ AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1, ++ [generic_fillattr requires struct user_namespace*]) ++ ],[ ++ AC_MSG_RESULT([no]) ++ ]) ++]) ++ +diff --git a/config/kernel-inode-create.m4 b/config/kernel-inode-create.m4 +index 9f28bcbd4f7..a6ea11fb61b 100644 +--- a/config/kernel-inode-create.m4 ++++ b/config/kernel-inode-create.m4 +@@ -1,7 +1,25 @@ +-dnl # +-dnl # 3.6 API change +-dnl # +-AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [ ++AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [ ++ dnl # ++ dnl # 5.12 API change that added the struct user_namespace* arg ++ dnl # to the front of this function type's arg list. ++ dnl # ++ ZFS_LINUX_TEST_SRC([create_userns], [ ++ #include <linux/fs.h> ++ #include <linux/sched.h> ++ ++ int inode_create(struct user_namespace *userns, ++ struct inode *inode ,struct dentry *dentry, ++ umode_t umode, bool flag) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .create = inode_create, ++ }; ++ ],[]) ++ ++ dnl # ++ dnl # 3.6 API change ++ dnl # + ZFS_LINUX_TEST_SRC([create_flags], [ + #include <linux/fs.h> + #include <linux/sched.h> +@@ -16,11 +34,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [ + ],[]) + ]) + +-AC_DEFUN([ZFS_AC_KERNEL_CREATE_FLAGS], [ +- AC_MSG_CHECKING([whether iops->create() passes flags]) +- ZFS_LINUX_TEST_RESULT([create_flags], [ ++AC_DEFUN([ZFS_AC_KERNEL_CREATE], [ ++ AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([create_userns], [ + AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1, ++ [iops->create() takes struct user_namespace*]) + ],[ +- ZFS_LINUX_TEST_ERROR([iops->create()]) ++ AC_MSG_RESULT(no) ++ ++ AC_MSG_CHECKING([whether iops->create() passes flags]) ++ ZFS_LINUX_TEST_RESULT([create_flags], [ ++ AC_MSG_RESULT(yes) ++ ],[ ++ ZFS_LINUX_TEST_ERROR([iops->create()]) ++ ]) + ]) + ]) +diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4 +index 48391d66f8b..f62e82f5230 100644 +--- a/config/kernel-inode-getattr.m4 ++++ b/config/kernel-inode-getattr.m4 +@@ -1,8 +1,29 @@ +-dnl # +-dnl # Linux 4.11 API +-dnl # See torvalds/linux@a528d35 +-dnl # + AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ ++ dnl # ++ dnl # Linux 5.12 API ++ dnl # The getattr I/O operations handler type was extended to require ++ dnl # a struct user_namespace* as its first arg, to support idmapped ++ dnl # mounts. ++ dnl # ++ ZFS_LINUX_TEST_SRC([inode_operations_getattr_userns], [ ++ #include <linux/fs.h> ++ ++ int test_getattr( ++ struct user_namespace *userns, ++ const struct path *p, struct kstat *k, ++ u32 request_mask, unsigned int query_flags) ++ { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .getattr = test_getattr, ++ }; ++ ],[]) ++ ++ dnl # ++ dnl # Linux 4.11 API ++ dnl # See torvalds/linux@a528d35 ++ dnl # + ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [ + #include <linux/fs.h> + +@@ -33,21 +54,39 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ + ]) + + AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [ +- AC_MSG_CHECKING([whether iops->getattr() takes a path]) +- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ ++ dnl # ++ dnl # Kernel 5.12 test ++ dnl # ++ AC_MSG_CHECKING([whether iops->getattr() takes user_namespace]) ++ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, +- [iops->getattr() takes a path]) ++ AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1, ++ [iops->getattr() takes struct user_namespace*]) + ],[ + AC_MSG_RESULT(no) + +- AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) +- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [ ++ dnl # ++ dnl # Kernel 4.11 test ++ dnl # ++ AC_MSG_CHECKING([whether iops->getattr() takes a path]) ++ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, +- [iops->getattr() takes a vfsmount]) ++ AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, ++ [iops->getattr() takes a path]) + ],[ + AC_MSG_RESULT(no) ++ ++ dnl # ++ dnl # Kernel < 4.11 test ++ dnl # ++ AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) ++ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, ++ [iops->getattr() takes a vfsmount]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) + ]) + ]) + ]) +diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4 +index 3df6163da27..3c3c6ad2240 100644 +--- a/config/kernel-is_owner_or_cap.m4 ++++ b/config/kernel-is_owner_or_cap.m4 +@@ -11,13 +11,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [ + struct inode *ip = NULL; + (void) inode_owner_or_capable(ip); + ]) ++ ++ ZFS_LINUX_TEST_SRC([inode_owner_or_capable_idmapped], [ ++ #include <linux/fs.h> ++ ],[ ++ struct inode *ip = NULL; ++ (void) inode_owner_or_capable(&init_user_ns, ip); ++ ]) + ]) + + AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [ + AC_MSG_CHECKING([whether inode_owner_or_capable() exists]) + ZFS_LINUX_TEST_RESULT([inode_owner_or_capable], [ + AC_MSG_RESULT(yes) +- ],[ +- ZFS_LINUX_TEST_ERROR([capability]) ++ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE, 1, ++ [inode_owner_or_capable() exists]) ++ ], [ ++ AC_MSG_RESULT(no) ++ ++ AC_MSG_CHECKING( ++ [whether inode_owner_or_capable() takes user_ns]) ++ ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_idmapped], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED, 1, ++ [inode_owner_or_capable() takes user_ns]) ++ ],[ ++ ZFS_LINUX_TEST_ERROR([capability]) ++ ]) + ]) + ]) +diff --git a/config/kernel-mkdir-umode-t.m4 b/config/kernel-mkdir-umode-t.m4 +deleted file mode 100644 +index 19599670df3..00000000000 +--- a/config/kernel-mkdir-umode-t.m4 ++++ /dev/null +@@ -1,32 +0,0 @@ +-dnl # +-dnl # 3.3 API change +-dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a +-dnl # umode_t type rather than an int. The expectation is that any backport +-dnl # would also change all three prototypes. However, if it turns out that +-dnl # some distribution doesn't backport the whole thing this could be +-dnl # broken apart into three separate checks. +-dnl # +-AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T], [ +- ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [ +- #include <linux/fs.h> +- +- int mkdir(struct inode *inode, struct dentry *dentry, +- umode_t umode) { return 0; } +- +- static const struct inode_operations +- iops __attribute__ ((unused)) = { +- .mkdir = mkdir, +- }; +- ],[]) +-]) +- +-AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [ +- AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t]) +- ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [ +- AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_MKDIR_UMODE_T, 1, +- [iops->create()/mkdir()/mknod() take umode_t]) +- ],[ +- ZFS_LINUX_TEST_ERROR([mkdir()]) +- ]) +-]) +diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4 +new file mode 100644 +index 00000000000..a162bcd880f +--- /dev/null ++++ b/config/kernel-mkdir.m4 +@@ -0,0 +1,65 @@ ++dnl # ++dnl # Supported mkdir() interfaces checked newest to oldest. ++dnl # ++AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [ ++ dnl # ++ dnl # 5.12 API change ++ dnl # The struct user_namespace arg was added as the first argument to ++ dnl # mkdir() ++ dnl # ++ ZFS_LINUX_TEST_SRC([mkdir_user_namespace], [ ++ #include <linux/fs.h> ++ ++ int mkdir(struct user_namespace *userns, ++ struct inode *inode, struct dentry *dentry, ++ umode_t umode) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .mkdir = mkdir, ++ }; ++ ],[]) ++ ++ dnl # ++ dnl # 3.3 API change ++ dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a ++ dnl # umode_t type rather than an int. The expectation is that any backport ++ dnl # would also change all three prototypes. However, if it turns out that ++ dnl # some distribution doesn't backport the whole thing this could be ++ dnl # broken apart into three separate checks. ++ dnl # ++ ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [ ++ #include <linux/fs.h> ++ ++ int mkdir(struct inode *inode, struct dentry *dentry, ++ umode_t umode) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .mkdir = mkdir, ++ }; ++ ],[]) ++]) ++ ++AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [ ++ dnl # ++ dnl # 5.12 API change ++ dnl # The struct user_namespace arg was added as the first argument to ++ dnl # mkdir() of the iops structure. ++ dnl # ++ AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1, ++ [iops->mkdir() takes struct user_namespace*]) ++ ],[ ++ AC_MSG_CHECKING([whether iops->mkdir() takes umode_t]) ++ ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_MKDIR_UMODE_T, 1, ++ [iops->mkdir() takes umode_t]) ++ ],[ ++ ZFS_LINUX_TEST_ERROR([mkdir()]) ++ ]) ++ ]) ++]) +diff --git a/config/kernel-mknod.m4 b/config/kernel-mknod.m4 +new file mode 100644 +index 00000000000..ffe45106003 +--- /dev/null ++++ b/config/kernel-mknod.m4 +@@ -0,0 +1,30 @@ ++AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [ ++ dnl # ++ dnl # 5.12 API change that added the struct user_namespace* arg ++ dnl # to the front of this function type's arg list. ++ dnl # ++ ZFS_LINUX_TEST_SRC([mknod_userns], [ ++ #include <linux/fs.h> ++ #include <linux/sched.h> ++ ++ int tmp_mknod(struct user_namespace *userns, ++ struct inode *inode ,struct dentry *dentry, ++ umode_t u, dev_t d) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .mknod = tmp_mknod, ++ }; ++ ],[]) ++]) ++ ++AC_DEFUN([ZFS_AC_KERNEL_MKNOD], [ ++ AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([mknod_userns], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1, ++ [iops->mknod() takes struct user_namespace*]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) ++]) +diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4 +index f707391539d..31d199f33bb 100644 +--- a/config/kernel-rename.m4 ++++ b/config/kernel-rename.m4 +@@ -1,10 +1,10 @@ +-dnl # +-dnl # 4.9 API change, +-dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants +-dnl # flags. +-dnl # +-AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [ +- ZFS_LINUX_TEST_SRC([inode_operations_rename], [ ++AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [ ++ dnl # ++ dnl # 4.9 API change, ++ dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants ++ dnl # flags. ++ dnl # ++ ZFS_LINUX_TEST_SRC([inode_operations_rename_flags], [ + #include <linux/fs.h> + int rename_fn(struct inode *sip, struct dentry *sdp, + struct inode *tip, struct dentry *tdp, +@@ -15,15 +15,41 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [ + .rename = rename_fn, + }; + ],[]) ++ ++ dnl # ++ dnl # 5.12 API change, ++ dnl # ++ dnl # Linux 5.12 introduced passing struct user_namespace* as the first argument ++ dnl # of the rename() and other inode_operations members. ++ dnl # ++ ZFS_LINUX_TEST_SRC([inode_operations_rename_userns], [ ++ #include <linux/fs.h> ++ int rename_fn(struct user_namespace *user_ns, struct inode *sip, ++ struct dentry *sdp, struct inode *tip, struct dentry *tdp, ++ unsigned int flags) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .rename = rename_fn, ++ }; ++ ],[]) + ]) + +-AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [ +- AC_MSG_CHECKING([whether iops->rename() wants flags]) +- ZFS_LINUX_TEST_RESULT([inode_operations_rename], [ ++AC_DEFUN([ZFS_AC_KERNEL_RENAME], [ ++ AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, +- [iops->rename() wants flags]) ++ AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1, ++ [iops->rename() takes struct user_namespace*]) + ],[ + AC_MSG_RESULT(no) ++ ++ ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, ++ [iops->rename() wants flags]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) + ]) + ]) +diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4 +index 45408c45c69..24245aa5344 100644 +--- a/config/kernel-setattr-prepare.m4 ++++ b/config/kernel-setattr-prepare.m4 +@@ -1,27 +1,52 @@ +-dnl # +-dnl # 4.9 API change +-dnl # The inode_change_ok() function has been renamed setattr_prepare() +-dnl # and updated to take a dentry rather than an inode. +-dnl # + AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [ ++ dnl # ++ dnl # 4.9 API change ++ dnl # The inode_change_ok() function has been renamed setattr_prepare() ++ dnl # and updated to take a dentry rather than an inode. ++ dnl # + ZFS_LINUX_TEST_SRC([setattr_prepare], [ + #include <linux/fs.h> + ], [ + struct dentry *dentry = NULL; + struct iattr *attr = NULL; + int error __attribute__ ((unused)) = +- setattr_prepare(dentry, attr); ++ setattr_prepare(dentry, attr); ++ ]) ++ ++ dnl # ++ dnl # 5.12 API change ++ dnl # The setattr_prepare() function has been changed to accept a new argument ++ dnl # for struct user_namespace* ++ dnl # ++ ZFS_LINUX_TEST_SRC([setattr_prepare_userns], [ ++ #include <linux/fs.h> ++ ], [ ++ struct dentry *dentry = NULL; ++ struct iattr *attr = NULL; ++ struct user_namespace *userns = NULL; ++ int error __attribute__ ((unused)) = ++ setattr_prepare(userns, dentry, attr); + ]) + ]) + + AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [ +- AC_MSG_CHECKING([whether setattr_prepare() is available]) +- ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare], ++ AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns], + [setattr_prepare], [fs/attr.c], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_SETATTR_PREPARE, 1, +- [setattr_prepare() is available]) ++ AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1, ++ [setattr_prepare() accepts user_namespace]) + ], [ + AC_MSG_RESULT(no) ++ ++ AC_MSG_CHECKING([whether setattr_prepare() is available, doesn't accept user_namespace]) ++ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare], ++ [setattr_prepare], [fs/attr.c], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1, ++ [setattr_prepare() is available, doesn't accept user_namespace]) ++ ], [ ++ AC_MSG_RESULT(no) ++ ]) + ]) + ]) +diff --git a/config/kernel-symlink.m4 b/config/kernel-symlink.m4 +new file mode 100644 +index 00000000000..d90366d04b7 +--- /dev/null ++++ b/config/kernel-symlink.m4 +@@ -0,0 +1,30 @@ ++AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [ ++ dnl # ++ dnl # 5.12 API change that added the struct user_namespace* arg ++ dnl # to the front of this function type's arg list. ++ dnl # ++ ZFS_LINUX_TEST_SRC([symlink_userns], [ ++ #include <linux/fs.h> ++ #include <linux/sched.h> ++ ++ int tmp_symlink(struct user_namespace *userns, ++ struct inode *inode ,struct dentry *dentry, ++ const char *path) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .symlink = tmp_symlink, ++ }; ++ ],[]) ++]) ++ ++AC_DEFUN([ZFS_AC_KERNEL_SYMLINK], [ ++ AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*]) ++ ZFS_LINUX_TEST_RESULT([symlink_userns], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1, ++ [iops->symlink() takes struct user_namespace*]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) ++]) +diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4 +index 137bf4a8aff..00b1e74a9cc 100644 +--- a/config/kernel-xattr-handler.m4 ++++ b/config/kernel-xattr-handler.m4 +@@ -152,6 +152,21 @@ dnl # + dnl # Supported xattr handler set() interfaces checked newest to oldest. + dnl # + AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [ ++ ZFS_LINUX_TEST_SRC([xattr_handler_set_userns], [ ++ #include <linux/xattr.h> ++ ++ int set(const struct xattr_handler *handler, ++ struct user_namespace *mnt_userns, ++ struct dentry *dentry, struct inode *inode, ++ const char *name, const void *buffer, ++ size_t size, int flags) ++ { return 0; } ++ static const struct xattr_handler ++ xops __attribute__ ((unused)) = { ++ .set = set, ++ }; ++ ],[]) ++ + ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [ + #include <linux/xattr.h> + +@@ -194,45 +209,58 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [ + + AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [ + dnl # +- dnl # 4.7 API change, +- dnl # The xattr_handler->set() callback was changed to take both +- dnl # dentry and inode. ++ dnl # 5.12 API change, ++ dnl # The xattr_handler->set() callback was changed to 8 arguments, and ++ dnl # struct user_namespace* was inserted as arg #2 + dnl # +- AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode]) +- ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [ ++ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace]) ++ ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1, +- [xattr_handler->set() wants both dentry and inode]) ++ AC_DEFINE(HAVE_XATTR_SET_USERNS, 1, ++ [xattr_handler->set() takes user_namespace]) + ],[ + dnl # +- dnl # 4.4 API change, +- dnl # The xattr_handler->set() callback was changed to take a +- dnl # xattr_handler, and handler_flags argument was removed and +- dnl # should be accessed by handler->flags. ++ dnl # 4.7 API change, ++ dnl # The xattr_handler->set() callback was changed to take both ++ dnl # dentry and inode. + dnl # + AC_MSG_RESULT(no) +- AC_MSG_CHECKING( +- [whether xattr_handler->set() wants xattr_handler]) +- ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [ ++ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode]) ++ ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1, +- [xattr_handler->set() wants xattr_handler]) ++ AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1, ++ [xattr_handler->set() wants both dentry and inode]) + ],[ + dnl # +- dnl # 2.6.33 API change, +- dnl # The xattr_handler->set() callback was changed +- dnl # to take a dentry instead of an inode, and a +- dnl # handler_flags argument was added. ++ dnl # 4.4 API change, ++ dnl # The xattr_handler->set() callback was changed to take a ++ dnl # xattr_handler, and handler_flags argument was removed and ++ dnl # should be accessed by handler->flags. + dnl # + AC_MSG_RESULT(no) + AC_MSG_CHECKING( +- [whether xattr_handler->set() wants dentry]) +- ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [ ++ [whether xattr_handler->set() wants xattr_handler]) ++ ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [ + AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1, +- [xattr_handler->set() wants dentry]) ++ AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1, ++ [xattr_handler->set() wants xattr_handler]) + ],[ +- ZFS_LINUX_TEST_ERROR([xattr set()]) ++ dnl # ++ dnl # 2.6.33 API change, ++ dnl # The xattr_handler->set() callback was changed ++ dnl # to take a dentry instead of an inode, and a ++ dnl # handler_flags argument was added. ++ dnl # ++ AC_MSG_RESULT(no) ++ AC_MSG_CHECKING( ++ [whether xattr_handler->set() wants dentry]) ++ ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1, ++ [xattr_handler->set() wants dentry]) ++ ],[ ++ ZFS_LINUX_TEST_ERROR([xattr set()]) ++ ]) + ]) + ]) + ]) +diff --git a/config/kernel.m4 b/config/kernel.m4 +index 55620b3daa8..51c7fb926ec 100644 +--- a/config/kernel.m4 ++++ b/config/kernel.m4 +@@ -79,9 +79,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ + ZFS_AC_KERNEL_SRC_EVICT_INODE + ZFS_AC_KERNEL_SRC_DIRTY_INODE + ZFS_AC_KERNEL_SRC_SHRINKER +- ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T ++ ZFS_AC_KERNEL_SRC_MKDIR + ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS +- ZFS_AC_KERNEL_SRC_CREATE_FLAGS ++ ZFS_AC_KERNEL_SRC_CREATE + ZFS_AC_KERNEL_SRC_GET_LINK + ZFS_AC_KERNEL_SRC_PUT_LINK + ZFS_AC_KERNEL_SRC_TMPFILE +@@ -115,7 +115,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ + ZFS_AC_KERNEL_SRC_KUIDGID_T + ZFS_AC_KERNEL_SRC_KUID_HELPERS + ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST +- ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS ++ ZFS_AC_KERNEL_SRC_RENAME + ZFS_AC_KERNEL_SRC_CURRENT_TIME + ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES + ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL +@@ -124,6 +124,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ + ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES + ZFS_AC_KERNEL_SRC_KSTRTOUL + ZFS_AC_KERNEL_SRC_PERCPU ++ ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS ++ ZFS_AC_KERNEL_SRC_MKNOD ++ ZFS_AC_KERNEL_SRC_SYMLINK + + AC_MSG_CHECKING([for available kernel interfaces]) + ZFS_LINUX_TEST_COMPILE_ALL([kabi]) +@@ -176,9 +179,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_EVICT_INODE + ZFS_AC_KERNEL_DIRTY_INODE + ZFS_AC_KERNEL_SHRINKER +- ZFS_AC_KERNEL_MKDIR_UMODE_T ++ ZFS_AC_KERNEL_MKDIR + ZFS_AC_KERNEL_LOOKUP_FLAGS +- ZFS_AC_KERNEL_CREATE_FLAGS ++ ZFS_AC_KERNEL_CREATE + ZFS_AC_KERNEL_GET_LINK + ZFS_AC_KERNEL_PUT_LINK + ZFS_AC_KERNEL_TMPFILE +@@ -212,7 +215,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_KUIDGID_T + ZFS_AC_KERNEL_KUID_HELPERS + ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST +- ZFS_AC_KERNEL_RENAME_WANTS_FLAGS ++ ZFS_AC_KERNEL_RENAME + ZFS_AC_KERNEL_CURRENT_TIME + ZFS_AC_KERNEL_USERNS_CAPABILITIES + ZFS_AC_KERNEL_IN_COMPAT_SYSCALL +@@ -221,6 +224,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_TOTALHIGH_PAGES + ZFS_AC_KERNEL_KSTRTOUL + ZFS_AC_KERNEL_PERCPU ++ ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS ++ ZFS_AC_KERNEL_MKNOD ++ ZFS_AC_KERNEL_SYMLINK + ]) + + dnl # +diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h +index c35e80d31cd..91e908598fb 100644 +--- a/include/os/linux/kernel/linux/vfs_compat.h ++++ b/include/os/linux/kernel/linux/vfs_compat.h +@@ -343,7 +343,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid) + /* + * 4.9 API change + */ +-#ifndef HAVE_SETATTR_PREPARE ++#if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \ ++ defined(HAVE_SETATTR_PREPARE_USERNS)) + static inline int + setattr_prepare(struct dentry *dentry, struct iattr *ia) + { +@@ -389,6 +390,15 @@ func(const struct path *path, struct kstat *stat, u32 request_mask, \ + { \ + return (func##_impl(path, stat, request_mask, query_flags)); \ + } ++#elif defined(HAVE_USERNS_IOPS_GETATTR) ++#define ZPL_GETATTR_WRAPPER(func) \ ++static int \ ++func(struct user_namespace *user_ns, const struct path *path, \ ++ struct kstat *stat, u32 request_mask, unsigned int query_flags) \ ++{ \ ++ return (func##_impl(user_ns, path, stat, request_mask, \ ++ query_flags)); \ ++} + #else + #error + #endif +@@ -436,4 +446,16 @@ zpl_is_32bit_api(void) + #endif + } + ++/* ++ * 5.12 API change ++ * To support id-mapped mounts, generic_fillattr() was modified to ++ * accept a new struct user_namespace* as its first arg. ++ */ ++#ifdef HAVE_GENERIC_FILLATTR_USERNS ++#define zpl_generic_fillattr(user_ns, ip, sp) \ ++ generic_fillattr(user_ns, ip, sp) ++#else ++#define zpl_generic_fillattr(user_ns, ip, sp) generic_fillattr(ip, sp) ++#endif ++ + #endif /* _ZFS_VFS_H */ +diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h +index 8348e99198a..54690727eab 100644 +--- a/include/os/linux/kernel/linux/xattr_compat.h ++++ b/include/os/linux/kernel/linux/xattr_compat.h +@@ -119,12 +119,27 @@ fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \ + #error "Unsupported kernel" + #endif + ++/* ++ * 5.12 API change, ++ * The xattr_handler->set() callback was changed to take the ++ * struct user_namespace* as the first arg, to support idmapped ++ * mounts. ++ */ ++#if defined(HAVE_XATTR_SET_USERNS) ++#define ZPL_XATTR_SET_WRAPPER(fn) \ ++static int \ ++fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \ ++ struct dentry *dentry, struct inode *inode, const char *name, \ ++ const void *buffer, size_t size, int flags) \ ++{ \ ++ return (__ ## fn(inode, name, buffer, size, flags)); \ ++} + /* + * 4.7 API change, + * The xattr_handler->set() callback was changed to take a both dentry and + * inode, because the dentry might not be attached to an inode yet. + */ +-#if defined(HAVE_XATTR_SET_DENTRY_INODE) ++#elif defined(HAVE_XATTR_SET_DENTRY_INODE) + #define ZPL_XATTR_SET_WRAPPER(fn) \ + static int \ + fn(const struct xattr_handler *handler, struct dentry *dentry, \ +diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h +index 1c9cdf7bf8f..ba83f5dd83d 100644 +--- a/include/os/linux/zfs/sys/zfs_vnops_os.h ++++ b/include/os/linux/zfs/sys/zfs_vnops_os.h +@@ -56,7 +56,8 @@ extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, + extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, + cred_t *cr, int flags); + extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr); +-extern int zfs_getattr_fast(struct inode *ip, struct kstat *sp); ++extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip, ++ struct kstat *sp); + extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); + extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, + char *tnm, cred_t *cr, int flags); +diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h +index b0bb9c29c0b..21825d1f378 100644 +--- a/include/os/linux/zfs/sys/zpl.h ++++ b/include/os/linux/zfs/sys/zpl.h +@@ -171,4 +171,22 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx) + timespec_trunc(ts, (ip)->i_sb->s_time_gran) + #endif + ++#if defined(HAVE_INODE_OWNER_OR_CAPABLE) ++#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ip) ++#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED) ++#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ns, ip) ++#else ++#error "Unsupported kernel" ++#endif ++ ++#ifdef HAVE_SETATTR_PREPARE_USERNS ++#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia) ++#else ++/* ++ * Use kernel-provided version, or our own from ++ * linux/vfs_compat.h ++ */ ++#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(dentry, ia) ++#endif ++ + #endif /* _SYS_ZPL_H */ +diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c +index 8780d7f6c70..bbccb2e572d 100644 +--- a/module/os/linux/zfs/policy.c ++++ b/module/os/linux/zfs/policy.c +@@ -124,7 +124,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner) + if (crgetfsuid(cr) == owner) + return (0); + +- if (inode_owner_or_capable(ip)) ++ if (zpl_inode_owner_or_capable(kcred->user_ns, ip)) + return (0); + + #if defined(CONFIG_USER_NS) +diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c +index 7484d651c1f..ce0701763fd 100644 +--- a/module/os/linux/zfs/zfs_vnops_os.c ++++ b/module/os/linux/zfs/zfs_vnops_os.c +@@ -1907,7 +1907,8 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr) + */ + /* ARGSUSED */ + int +-zfs_getattr_fast(struct inode *ip, struct kstat *sp) ++zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip, ++ struct kstat *sp) + { + znode_t *zp = ITOZ(ip); + zfsvfs_t *zfsvfs = ITOZSB(ip); +@@ -1919,7 +1920,7 @@ zfs_getattr_fast(struct inode *ip, struct kstat *sp) + + mutex_enter(&zp->z_lock); + +- generic_fillattr(ip, sp); ++ zpl_generic_fillattr(user_ns, ip, sp); + /* + * +1 link count for root inode with visible '.zfs' directory. + */ +diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c +index e6420f19ed8..9b526afd000 100644 +--- a/module/os/linux/zfs/zpl_ctldir.c ++++ b/module/os/linux/zfs/zpl_ctldir.c +@@ -101,12 +101,22 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) + */ + /* ARGSUSED */ + static int ++#ifdef HAVE_USERNS_IOPS_GETATTR ++zpl_root_getattr_impl(struct user_namespace *user_ns, ++ const struct path *path, struct kstat *stat, u32 request_mask, ++ unsigned int query_flags) ++#else + zpl_root_getattr_impl(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags) ++#endif + { + struct inode *ip = path->dentry->d_inode; + ++#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) ++ generic_fillattr(user_ns, ip, stat); ++#else + generic_fillattr(ip, stat); ++#endif + stat->atime = current_time(ip); + + return (0); +@@ -290,8 +300,14 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir) + #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */ + + static int ++#ifdef HAVE_IOPS_RENAME_USERNS ++zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip, ++ struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, ++ unsigned int flags) ++#else + zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry, unsigned int flags) ++#endif + { + cred_t *cr = CRED(); + int error; +@@ -309,7 +325,7 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, + return (error); + } + +-#ifndef HAVE_RENAME_WANTS_FLAGS ++#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) + static int + zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry) +@@ -333,7 +349,12 @@ zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry) + } + + static int ++#ifdef HAVE_IOPS_MKDIR_USERNS ++zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip, ++ struct dentry *dentry, umode_t mode) ++#else + zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) ++#endif + { + cred_t *cr = CRED(); + vattr_t *vap; +@@ -363,14 +384,24 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) + */ + /* ARGSUSED */ + static int ++#ifdef HAVE_USERNS_IOPS_GETATTR ++zpl_snapdir_getattr_impl(struct user_namespace *user_ns, ++ const struct path *path, struct kstat *stat, u32 request_mask, ++ unsigned int query_flags) ++#else + zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags) ++#endif + { + struct inode *ip = path->dentry->d_inode; + zfsvfs_t *zfsvfs = ITOZSB(ip); + + ZPL_ENTER(zfsvfs); ++#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) ++ generic_fillattr(user_ns, ip, stat); ++#else + generic_fillattr(ip, stat); ++#endif + + stat->nlink = stat->size = 2; + stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); +@@ -408,7 +439,7 @@ const struct file_operations zpl_fops_snapdir = { + const struct inode_operations zpl_ops_snapdir = { + .lookup = zpl_snapdir_lookup, + .getattr = zpl_snapdir_getattr, +-#ifdef HAVE_RENAME_WANTS_FLAGS ++#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) + .rename = zpl_snapdir_rename2, + #else + .rename = zpl_snapdir_rename, +@@ -495,8 +526,14 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) + + /* ARGSUSED */ + static int ++#ifdef HAVE_USERNS_IOPS_GETATTR ++zpl_shares_getattr_impl(struct user_namespace *user_ns, ++ const struct path *path, struct kstat *stat, u32 request_mask, ++ unsigned int query_flags) ++#else + zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags) ++#endif + { + struct inode *ip = path->dentry->d_inode; + zfsvfs_t *zfsvfs = ITOZSB(ip); +@@ -506,7 +543,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, + ZPL_ENTER(zfsvfs); + + if (zfsvfs->z_shares_dir == 0) { ++#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) ++ generic_fillattr(user_ns, path->dentry->d_inode, stat); ++#else + generic_fillattr(path->dentry->d_inode, stat); ++#endif + stat->nlink = stat->size = 2; + stat->atime = current_time(ip); + ZPL_EXIT(zfsvfs); +@@ -515,7 +556,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, + + error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); + if (error == 0) { +- error = -zfs_getattr_fast(ZTOI(dzp), stat); ++#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) ++ error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat); ++#else ++ error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat); ++#endif + iput(ZTOI(dzp)); + } + +diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c +index 80762f9669b..08bf97ff338 100644 +--- a/module/os/linux/zfs/zpl_file.c ++++ b/module/os/linux/zfs/zpl_file.c +@@ -869,7 +869,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva) + !capable(CAP_LINUX_IMMUTABLE)) + return (-EACCES); + +- if (!inode_owner_or_capable(ip)) ++ if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) + return (-EACCES); + + xva_init(xva); +diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c +index f336fbb1272..364b9fbef24 100644 +--- a/module/os/linux/zfs/zpl_inode.c ++++ b/module/os/linux/zfs/zpl_inode.c +@@ -128,7 +128,12 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr) + } + + static int ++#ifdef HAVE_IOPS_CREATE_USERNS ++zpl_create(struct user_namespace *user_ns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, bool flag) ++#else + zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) ++#endif + { + cred_t *cr = CRED(); + znode_t *zp; +@@ -163,7 +168,12 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) + } + + static int ++#ifdef HAVE_IOPS_MKNOD_USERNS ++zpl_mknod(struct user_namespace *user_ns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, ++#else + zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++#endif + dev_t rdev) + { + cred_t *cr = CRED(); +@@ -278,7 +288,12 @@ zpl_unlink(struct inode *dir, struct dentry *dentry) + } + + static int ++#ifdef HAVE_IOPS_MKDIR_USERNS ++zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, ++ struct dentry *dentry, umode_t mode) ++#else + zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++#endif + { + cred_t *cr = CRED(); + vattr_t *vap; +@@ -338,8 +353,14 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry) + } + + static int ++#ifdef HAVE_USERNS_IOPS_GETATTR ++zpl_getattr_impl(struct user_namespace *user_ns, ++ const struct path *path, struct kstat *stat, u32 request_mask, ++ unsigned int query_flags) ++#else + zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, + unsigned int query_flags) ++#endif + { + int error; + fstrans_cookie_t cookie; +@@ -350,7 +371,11 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, + * XXX request_mask and query_flags currently ignored. + */ + +- error = -zfs_getattr_fast(path->dentry->d_inode, stat); ++#ifdef HAVE_USERNS_IOPS_GETATTR ++ error = -zfs_getattr_fast(user_ns, path->dentry->d_inode, stat); ++#else ++ error = -zfs_getattr_fast(kcred->user_ns, path->dentry->d_inode, stat); ++#endif + spl_fstrans_unmark(cookie); + ASSERT3S(error, <=, 0); + +@@ -359,7 +384,12 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, + ZPL_GETATTR_WRAPPER(zpl_getattr); + + static int ++#ifdef HAVE_SETATTR_PREPARE_USERNS ++zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, ++ struct iattr *ia) ++#else + zpl_setattr(struct dentry *dentry, struct iattr *ia) ++#endif + { + struct inode *ip = dentry->d_inode; + cred_t *cr = CRED(); +@@ -367,7 +397,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) + int error; + fstrans_cookie_t cookie; + +- error = setattr_prepare(dentry, ia); ++ error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); + if (error) + return (error); + +@@ -399,8 +429,14 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) + } + + static int ++#ifdef HAVE_IOPS_RENAME_USERNS ++zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, ++ struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, ++ unsigned int flags) ++#else + zpl_rename2(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry, unsigned int flags) ++#endif + { + cred_t *cr = CRED(); + int error; +@@ -421,7 +457,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, + return (error); + } + +-#ifndef HAVE_RENAME_WANTS_FLAGS ++#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) + static int + zpl_rename(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry) +@@ -431,7 +467,12 @@ zpl_rename(struct inode *sdip, struct dentry *sdentry, + #endif + + static int ++#ifdef HAVE_IOPS_SYMLINK_USERNS ++zpl_symlink(struct user_namespace *user_ns, struct inode *dir, ++ struct dentry *dentry, const char *name) ++#else + zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) ++#endif + { + cred_t *cr = CRED(); + vattr_t *vap; +@@ -677,7 +718,7 @@ const struct inode_operations zpl_dir_inode_operations = { + .mkdir = zpl_mkdir, + .rmdir = zpl_rmdir, + .mknod = zpl_mknod, +-#ifdef HAVE_RENAME_WANTS_FLAGS ++#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) + .rename = zpl_rename2, + #else + .rename = zpl_rename, +diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c +index 1ec3dae2bb8..5e35f90df85 100644 +--- a/module/os/linux/zfs/zpl_xattr.c ++++ b/module/os/linux/zfs/zpl_xattr.c +@@ -1233,7 +1233,7 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, + if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) + return (-EOPNOTSUPP); + +- if (!inode_owner_or_capable(ip)) ++ if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) + return (-EPERM); + + if (value) { +@@ -1273,7 +1273,7 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name, + if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) + return (-EOPNOTSUPP); + +- if (!inode_owner_or_capable(ip)) ++ if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) + return (-EPERM); + + if (value) { diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_iov_iter_advance.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_iov_iter_advance.patch new file mode 100644 index 000000000000..95ecda34652c --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_iov_iter_advance.patch @@ -0,0 +1,40 @@ +From 3e0bc63e1b0ca03493b936e92e871ca7ae451a0a Mon Sep 17 00:00:00 2001 +From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> +Date: Tue, 1 Jun 2021 14:58:08 -0400 +Subject: [PATCH] Remove iov_iter_advance() for iter_write + +The additional iter advance is incorrect, as copy_from_iter() has +already done the right thing. This will result in the following +warning being printed to the console as of the 5.12 kernel. + + Attempted to advance past end of bvec iter + +This change should have been included with #11378 when a +similar change was made on the read side. + +Suggested-by: @siebenmann +Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> +Signed-off-by: Rich Ercolani <rincebrain@gmail.com> +Issue #11378 +Closes #12041 +Closes #12155 +(cherry picked from commit 3f81aba7668143c6ca6fc44983d4c880606dea8f) +Signed-off-by: Jonathon Fernyhough <jonathon@m2x.dev> +--- + module/os/linux/zfs/zpl_file.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c +index 08bf97ff338..e20c1dd413c 100644 +--- a/module/os/linux/zfs/zpl_file.c ++++ b/module/os/linux/zfs/zpl_file.c +@@ -342,9 +342,6 @@ zpl_iter_write(struct kiocb *kiocb, struct iov_iter *from) + ssize_t wrote = count - uio.uio_resid; + kiocb->ki_pos += wrote; + +- if (wrote > 0) +- iov_iter_advance(from, wrote); +- + return (wrote); + } + diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_tmpfile.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_tmpfile.patch new file mode 100644 index 000000000000..08acee821489 --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_tmpfile.patch @@ -0,0 +1,89 @@ +From 6eced028dbbc2a44e32c4c0a76234ac2da9a365a Mon Sep 17 00:00:00 2001 +From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> +Date: Thu, 20 May 2021 19:02:36 -0400 +Subject: [PATCH] Update tmpfile() existence detection + +Linux changed the tmpfile() signature again in torvalds/linux@6521f89, +which in turn broke our HAVE_TMPFILE detection in configure. + +Update that macro to include the new case, and change the signature of +zpl_tmpfile as appropriate. + +Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> +Signed-off-by: Rich Ercolani <rincebrain@gmail.com> +Closes: #12060 +Closes: #12087 +--- + config/kernel-tmpfile.m4 | 28 ++++++++++++++++++++++++---- + module/os/linux/zfs/zpl_inode.c | 5 +++++ + 2 files changed, 29 insertions(+), 4 deletions(-) + +diff --git a/config/kernel-tmpfile.m4 b/config/kernel-tmpfile.m4 +index f510bfe6ba0..45c2e6ceea5 100644 +--- a/config/kernel-tmpfile.m4 ++++ b/config/kernel-tmpfile.m4 +@@ -3,23 +3,43 @@ dnl # 3.11 API change + dnl # Add support for i_op->tmpfile + dnl # + AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [ +- ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [ ++ dnl # ++ dnl # 5.11 API change ++ dnl # add support for userns parameter to tmpfile ++ dnl # ++ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_userns], [ + #include <linux/fs.h> +- int tmpfile(struct inode *inode, struct dentry *dentry, ++ int tmpfile(struct user_namespace *userns, ++ struct inode *inode, struct dentry *dentry, + umode_t mode) { return 0; } + static struct inode_operations + iops __attribute__ ((unused)) = { + .tmpfile = tmpfile, + }; + ],[]) ++ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [ ++ #include <linux/fs.h> ++ int tmpfile(struct inode *inode, struct dentry *dentry, ++ umode_t mode) { return 0; } ++ static struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .tmpfile = tmpfile, ++ }; ++ ],[]) + ]) + + AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [ + AC_MSG_CHECKING([whether i_op->tmpfile() exists]) +- ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [ ++ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_userns], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) ++ AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns]) + ],[ +- AC_MSG_RESULT(no) ++ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) + ]) + ]) +diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c +index 364b9fbef24..ab0373ef9ba 100644 +--- a/module/os/linux/zfs/zpl_inode.c ++++ b/module/os/linux/zfs/zpl_inode.c +@@ -218,7 +218,12 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, + + #ifdef HAVE_TMPFILE + static int ++#ifdef HAVE_TMPFILE_USERNS ++zpl_tmpfile(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode) ++#else + zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) ++#endif + { + cred_t *cr = CRED(); + struct inode *ip; diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_userns.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_userns.patch new file mode 100644 index 000000000000..1d8530ec8c6c --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_5.12_compat_userns.patch @@ -0,0 +1,173 @@ +From b3f8b103cb3a4bbb7ad41f6faf630be7baa4f585 Mon Sep 17 00:00:00 2001 +From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> +Date: Thu, 27 May 2021 11:55:49 -0400 +Subject: [PATCH] Bend zpl_set_acl to permit the new userns* parameter + +Just like #12087, the set_acl signature changed with all the bolted-on +*userns parameters, which disabled set_acl usage, and caused #12076. + +Turn zpl_set_acl into zpl_set_acl and zpl_set_acl_impl, and add a +new configure test for the new version. + +Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> +Signed-off-by: Rich Ercolani <rincebrain@gmail.com> +Closes #12076 +Closes #12093 +--- + config/kernel-acl.m4 | 25 +++++++++++++++++++++-- + include/os/linux/zfs/sys/zpl.h | 5 +++++ + module/os/linux/zfs/zpl_xattr.c | 35 ++++++++++++++++++++++----------- + 3 files changed, 51 insertions(+), 14 deletions(-) + +diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4 +index e02ce665323..c6da4df24eb 100644 +--- a/config/kernel-acl.m4 ++++ b/config/kernel-acl.m4 +@@ -189,7 +189,22 @@ dnl # + dnl # 3.14 API change, + dnl # Check if inode_operations contains the function set_acl + dnl # ++dnl # 5.12 API change, ++dnl # set_acl() added a user_namespace* parameter first ++dnl # + AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [ ++ ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns], [ ++ #include <linux/fs.h> ++ ++ int set_acl_fn(struct user_namespace *userns, ++ struct inode *inode, struct posix_acl *acl, ++ int type) { return 0; } ++ ++ static const struct inode_operations ++ iops __attribute__ ((unused)) = { ++ .set_acl = set_acl_fn, ++ }; ++ ],[]) + ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [ + #include <linux/fs.h> + +@@ -205,11 +220,17 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [ + + AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [ + AC_MSG_CHECKING([whether iops->set_acl() exists]) +- ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [ ++ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) ++ AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args]) + ],[ +- AC_MSG_RESULT(no) ++ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ]) + ]) + ]) + +diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h +index 21825d1f378..54f3fa0fdb0 100644 +--- a/include/os/linux/zfs/sys/zpl.h ++++ b/include/os/linux/zfs/sys/zpl.h +@@ -63,7 +63,12 @@ extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip, + const struct qstr *qstr); + #if defined(CONFIG_FS_POSIX_ACL) + #if defined(HAVE_SET_ACL) ++#if defined(HAVE_SET_ACL_USERNS) ++extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip, ++ struct posix_acl *acl, int type); ++#else + extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type); ++#endif /* HAVE_SET_ACL_USERNS */ + #endif /* HAVE_SET_ACL */ + extern struct posix_acl *zpl_get_acl(struct inode *ip, int type); + extern int zpl_init_acl(struct inode *ip, struct inode *dir); +diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c +index 5e35f90df85..89ba9de14f6 100644 +--- a/module/os/linux/zfs/zpl_xattr.c ++++ b/module/os/linux/zfs/zpl_xattr.c +@@ -926,11 +926,8 @@ xattr_handler_t zpl_xattr_security_handler = { + * attribute implemented by filesystems in the kernel." - xattr(7) + */ + #ifdef CONFIG_FS_POSIX_ACL +-#ifndef HAVE_SET_ACL +-static +-#endif +-int +-zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type) ++static int ++zpl_set_acl_impl(struct inode *ip, struct posix_acl *acl, int type) + { + char *name, *value = NULL; + int error = 0; +@@ -1002,6 +999,19 @@ zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type) + return (error); + } + ++#ifdef HAVE_SET_ACL ++int ++#ifdef HAVE_SET_ACL_USERNS ++zpl_set_acl(struct user_namespace *userns, struct inode *ip, ++ struct posix_acl *acl, int type) ++#else ++zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type) ++#endif /* HAVE_SET_ACL_USERNS */ ++{ ++ return (zpl_set_acl_impl(ip, acl, type)); ++} ++#endif /* HAVE_SET_ACL */ ++ + struct posix_acl * + zpl_get_acl(struct inode *ip, int type) + { +@@ -1083,7 +1093,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir) + umode_t mode; + + if (S_ISDIR(ip->i_mode)) { +- error = zpl_set_acl(ip, acl, ACL_TYPE_DEFAULT); ++ error = zpl_set_acl_impl(ip, acl, ACL_TYPE_DEFAULT); + if (error) + goto out; + } +@@ -1093,8 +1103,10 @@ zpl_init_acl(struct inode *ip, struct inode *dir) + if (error >= 0) { + ip->i_mode = mode; + zfs_mark_inode_dirty(ip); +- if (error > 0) +- error = zpl_set_acl(ip, acl, ACL_TYPE_ACCESS); ++ if (error > 0) { ++ error = zpl_set_acl_impl(ip, acl, ++ ACL_TYPE_ACCESS); ++ } + } + } + out: +@@ -1121,7 +1133,7 @@ zpl_chmod_acl(struct inode *ip) + + error = __posix_acl_chmod(&acl, GFP_KERNEL, ip->i_mode); + if (!error) +- error = zpl_set_acl(ip, acl, ACL_TYPE_ACCESS); ++ error = zpl_set_acl_impl(ip, acl, ACL_TYPE_ACCESS); + + zpl_posix_acl_release(acl); + +@@ -1250,8 +1262,7 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, + } else { + acl = NULL; + } +- +- error = zpl_set_acl(ip, acl, type); ++ error = zpl_set_acl_impl(ip, acl, type); + zpl_posix_acl_release(acl); + + return (error); +@@ -1291,7 +1302,7 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name, + acl = NULL; + } + +- error = zpl_set_acl(ip, acl, type); ++ error = zpl_set_acl_impl(ip, acl, type); + zpl_posix_acl_release(acl); + + return (error); diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_spl_kmem_cache_slab_limit_16K.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_spl_kmem_cache_slab_limit_16K.patch new file mode 100644 index 000000000000..3448f76a8012 --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_spl_kmem_cache_slab_limit_16K.patch @@ -0,0 +1,59 @@ +From 783784582225e8ddfbf07993d9fc278bf08025c5 Mon Sep 17 00:00:00 2001 +From: Brian Behlendorf <behlendorf1@llnl.gov> +Date: Thu, 3 Jun 2021 13:37:45 -0700 +Subject: [PATCH] Linux: Set spl_kmem_cache_slab_limit when page size !4K + +For small objects the kernel's slab implementation is very fast and +space efficient. However, as the allocation size increases to +require multiple pages performance suffers. The SPL kmem cache +allocator was designed to better handle these large allocation +sizes. Therefore, on Linux the kmem_cache_* compatibility wrappers +prefer to use the kernel's slab allocator for small objects and +the custom SPL kmem cache allocator for larger objects. + +This logic was effectively disabled for all architectures using +a non-4K page size which caused all kmem caches to only use the +SPL implementation. Functionally this is fine, but the SPL code +which calculates the target number of objects per-slab does not +take in to account that __vmalloc() always returns page-aligned +memory. This can result in a massive amount of wasted space when +allocating tiny objects on a platform using large pages (64k). + +To resolve this issue we set the spl_kmem_cache_slab_limit cutoff +to 16K for all architectures. + +This particular change does not attempt to update the logic used +to calculate the optimal number of pages per slab. This remains +an issue which should be addressed in a future change. + +Reviewed-by: Matthew Ahrens <mahrens@delphix.com> +Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com> +Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> +Closes #12152 +Closes #11429 +Closes #11574 +Closes #12150 +--- + module/os/linux/spl/spl-kmem-cache.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/module/os/linux/spl/spl-kmem-cache.c b/module/os/linux/spl/spl-kmem-cache.c +index 3699b6a159a..2151ef008fd 100644 +--- a/module/os/linux/spl/spl-kmem-cache.c ++++ b/module/os/linux/spl/spl-kmem-cache.c +@@ -100,13 +100,10 @@ MODULE_PARM_DESC(spl_kmem_cache_max_size, "Maximum size of slab in MB"); + * For small objects the Linux slab allocator should be used to make the most + * efficient use of the memory. However, large objects are not supported by + * the Linux slab and therefore the SPL implementation is preferred. A cutoff +- * of 16K was determined to be optimal for architectures using 4K pages. ++ * of 16K was determined to be optimal for architectures using 4K pages and ++ * to also work well on architecutres using larger 64K page sizes. + */ +-#if PAGE_SIZE == 4096 + unsigned int spl_kmem_cache_slab_limit = 16384; +-#else +-unsigned int spl_kmem_cache_slab_limit = 0; +-#endif + module_param(spl_kmem_cache_slab_limit, uint, 0644); + MODULE_PARM_DESC(spl_kmem_cache_slab_limit, + "Objects less than N bytes use the Linux slab"); diff --git a/sys-fs/zfs-kmod/files/zfs-8.0.4_stream_resume.patch b/sys-fs/zfs-kmod/files/zfs-8.0.4_stream_resume.patch new file mode 100644 index 000000000000..196fab65f4ab --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-8.0.4_stream_resume.patch @@ -0,0 +1,33 @@ +From ee2a9d2c771657168652e058477b81389c662b5e Mon Sep 17 00:00:00 2001 +From: Paul Zuchowski <31706010+PaulZ-98@users.noreply.github.com> +Date: Fri, 14 May 2021 00:46:14 -0400 +Subject: [PATCH] Fix dmu_recv_stream test for resumable + +Use dsl_dataset_has_resume_receive_state() +not dsl_dataset_is_zapified() to check if +stream is resumable. + +Reviewed-by: Matthew Ahrens <mahrens@delphix.com> +Reviewed-by: Alek Pinchuk <apinchuk@axcient.com> +Reviewed-by: Ryan Moeller <ryan@ixsystems.com> +Signed-off-by: Paul Zuchowski <pzuchowski@datto.com> +Closes #12034 +--- + module/zfs/dmu_recv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c +index b5414749f7f..f44b397853f 100644 +--- a/module/zfs/dmu_recv.c ++++ b/module/zfs/dmu_recv.c +@@ -2878,8 +2878,8 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp) + int err = 0; + struct receive_writer_arg *rwa = kmem_zalloc(sizeof (*rwa), KM_SLEEP); + +- if (dsl_dataset_is_zapified(drc->drc_ds)) { +- uint64_t bytes; ++ if (dsl_dataset_has_resume_receive_state(drc->drc_ds)) { ++ uint64_t bytes = 0; + (void) zap_lookup(drc->drc_ds->ds_dir->dd_pool->dp_meta_objset, + drc->drc_ds->ds_object, DS_FIELD_RESUME_BYTES, + sizeof (bytes), 1, &bytes); diff --git a/sys-fs/zfs-kmod/zfs-kmod-2.0.4-r1.ebuild b/sys-fs/zfs-kmod/zfs-kmod-2.0.4-r1.ebuild new file mode 100644 index 000000000000..505ae6384ef8 --- /dev/null +++ b/sys-fs/zfs-kmod/zfs-kmod-2.0.4-r1.ebuild @@ -0,0 +1,186 @@ +# Copyright 1999-2021 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +inherit autotools dist-kernel-utils flag-o-matic linux-mod toolchain-funcs + +DESCRIPTION="Linux ZFS kernel module for sys-fs/zfs" +HOMEPAGE="https://github.com/openzfs/zfs" + +if [[ ${PV} == "9999" ]]; then + inherit git-r3 + EGIT_REPO_URI="https://github.com/openzfs/zfs.git" +else + MY_PV="${PV/_rc/-rc}" + SRC_URI="https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz" + KEYWORDS="~amd64 ~arm64 ~ppc64" + S="${WORKDIR}/zfs-${PV%_rc?}" + ZFS_KERNEL_COMPAT="5.12" +fi + +LICENSE="CDDL MIT debug? ( GPL-2+ )" +SLOT="0" +IUSE="custom-cflags debug +rootfs" + +DEPEND="" + +RDEPEND="${DEPEND} + !sys-kernel/spl +" + +BDEPEND=" + dev-lang/perl + virtual/awk +" + +RESTRICT="debug? ( strip ) test" + +DOCS=( AUTHORS COPYRIGHT META README.md ) + +PATCHES=( + "${FILESDIR}"/zfs-8.0.4_5.12_compat_idmapped_mounts.patch + "${FILESDIR}"/zfs-8.0.4_5.12_compat_bio_max_segs.patch + "${FILESDIR}"/zfs-8.0.4_5.12_compat_tmpfile.patch + "${FILESDIR}"/zfs-8.0.4_5.12_compat_userns.patch + "${FILESDIR}"/zfs-8.0.4_5.12_compat_iov_iter_advance.patch + "${FILESDIR}"/zfs-8.0.4_stream_resume.patch + "${FILESDIR}"/zfs-8.0.4_spl_kmem_cache_slab_limit_16K.patch +) + +pkg_setup() { + CONFIG_CHECK=" + !DEBUG_LOCK_ALLOC + EFI_PARTITION + MODULES + !PAX_KERNEXEC_PLUGIN_METHOD_OR + !TRIM_UNUSED_KSYMS + ZLIB_DEFLATE + ZLIB_INFLATE + " + + use debug && CONFIG_CHECK="${CONFIG_CHECK} + FRAME_POINTER + DEBUG_INFO + !DEBUG_INFO_REDUCED + " + + use rootfs && \ + CONFIG_CHECK="${CONFIG_CHECK} + BLK_DEV_INITRD + DEVTMPFS + " + + kernel_is -lt 5 && CONFIG_CHECK="${CONFIG_CHECK} IOSCHED_NOOP" + + if [[ ${PV} != "9999" ]]; then + local kv_major_max kv_minor_max zcompat + zcompat="${ZFS_KERNEL_COMPAT_OVERRIDE:-${ZFS_KERNEL_COMPAT}}" + kv_major_max="${zcompat%%.*}" + zcompat="${zcompat#*.}" + kv_minor_max="${zcompat%%.*}" + kernel_is -le "${kv_major_max}" "${kv_minor_max}" || die \ + "Linux ${kv_major_max}.${kv_minor_max} is the latest supported version" + + fi + + kernel_is -ge 3 10 || die "Linux 3.10 or newer required" + + linux-mod_pkg_setup +} + +src_prepare() { + default + eautoreconf + # Set module revision number + sed -i "s/\(Release:\)\(.*\)1/\1\2${PR}-gentoo/" META || die "Could not set Gentoo release" +} + +src_configure() { + set_arch_to_kernel + + use custom-cflags || strip-flags + + filter-ldflags -Wl,* + + local myconf=( + CROSS_COMPILE="${CHOST}-" + HOSTCC="$(tc-getBUILD_CC)" + --bindir="${EPREFIX}/bin" + --sbindir="${EPREFIX}/sbin" + --with-config=kernel + --with-linux="${KV_DIR}" + --with-linux-obj="${KV_OUT_DIR}" + $(use_enable debug) + ) + + econf "${myconf[@]}" +} + +src_compile() { + set_arch_to_kernel + + myemakeargs=( + CROSS_COMPILE="${CHOST}-" + HOSTCC="$(tc-getBUILD_CC)" + V=1 + ) + + emake "${myemakeargs[@]}" +} + +src_install() { + set_arch_to_kernel + + myemakeargs+=( + DEPMOD=: + DESTDIR="${D}" + INSTALL_MOD_PATH="${EPREFIX:-/}" # lib/modules/<kver> added by KBUILD + ) + + emake "${myemakeargs[@]}" install + + einstalldocs +} + +pkg_postinst() { + linux-mod_pkg_postinst + + # Remove old modules + if [[ -d "${EROOT}/lib/modules/${KV_FULL}/addon/zfs" ]]; then + ewarn "${PN} now installs modules in ${EROOT}/lib/modules/${KV_FULL}/extra/zfs" + ewarn "Old modules were detected in ${EROOT}/lib/modules/${KV_FULL}/addon/zfs" + ewarn "Automatically removing old modules to avoid problems." + rm -r "${EROOT}/lib/modules/${KV_FULL}/addon/zfs" || die "Cannot remove modules" + rmdir --ignore-fail-on-non-empty "${EROOT}/lib/modules/${KV_FULL}/addon" + fi + + if [[ -z ${ROOT} ]] && use dist-kernel; then + set_arch_to_portage + dist-kernel_reinstall_initramfs "${KV_DIR}" "${KV_FULL}" + fi + + if use x86 || use arm; then + ewarn "32-bit kernels will likely require increasing vmalloc to" + ewarn "at least 256M and decreasing zfs_arc_max to some value less than that." + fi + + ewarn "This version of OpenZFS includes support for new feature flags" + ewarn "that are incompatible with previous versions. GRUB2 support for" + ewarn "/boot with the new feature flags is not yet available." + ewarn "Do *NOT* upgrade root pools to use the new feature flags." + ewarn "Any new pools will be created with the new feature flags by default" + ewarn "and will not be compatible with older versions of ZFSOnLinux. To" + ewarn "create a newpool that is backward compatible wih GRUB2, use " + ewarn + ewarn "zpool create -d -o feature@async_destroy=enabled " + ewarn " -o feature@empty_bpobj=enabled -o feature@lz4_compress=enabled" + ewarn " -o feature@spacemap_histogram=enabled" + ewarn " -o feature@enabled_txg=enabled " + ewarn " -o feature@extensible_dataset=enabled -o feature@bookmarks=enabled" + ewarn " ..." + ewarn + ewarn "GRUB2 support will be updated as soon as either the GRUB2" + ewarn "developers do a tag or the Gentoo developers find time to backport" + ewarn "support from GRUB2 HEAD." +} |