diff --git a/sys-fs/zfs-kmod/Manifest b/sys-fs/zfs-kmod/Manifest index 6a83a98b5e73b216705e06bf210394a398815d7d..61929f1efb6265752018e019baef414942da334a 100644 --- a/sys-fs/zfs-kmod/Manifest +++ b/sys-fs/zfs-kmod/Manifest @@ -1,14 +1,9 @@ AUX 2.1.10-Revert-ZFS_IOC_COUNT_FILLED-does-unnecessary-txg_wai.patch 1932 BLAKE2B 761f1ed4a17c946fb08aa46c3b9defb0672897311dc61225f28298af7569f6350b264cb917696c091ebbf2a95aec8e2005385d27d3f996b99cc424ae0b503082 SHA512 ebdb7c6562eba403397b17dc0830f5c10a80b339ff62f52b569b4ddc28660e8ba353f2e54927e546812fe17539249ba6d1757d5cc150d3a2a75f41e702bcd239 -AUX 2.1.11-6.3-compat-idmapped-mount-api-changes.patch 95219 BLAKE2B bac74774b10ab4d0a06aa3e0d425c6e76566ff385ed3995a91bda3282ad62d80113df02f638fbfae24042b7bf8387d731554c7689f5c8280c68359cc6a21faf4 SHA512 47516410204e28540a8c29d3cf451fcfb6a7139561a036a46800ad7a402c20c6af7fa269302f8affa7b0e964b26a6b9bcdbd807fa648ed34d07a579ebeef951b -AUX 2.1.11-6.3-compat-writepage_t-typedef-change.patch 5498 BLAKE2B 70a6a5589e14bd5de689d4d50956f3b2ae6820a36b8d84c872c36ce9042e067cea2022bba291c9711823fb8e6d2e1c3aa1d7935e3f4bf429c15bc7f2499ae23a SHA512 2b55930c10acb50f744362a9dcc29ce0132f55453258e907e5cb85f3205c25fafd4e76e986819650e6b7a8a64f442ba4dce78ff1d2d38e961aed9342bd9a7ddd -AUX 2.1.11-expose-additional-attributes.patch 41613 BLAKE2B 495e656bffab4e282dd260f9d080d3543ebcb88eed79e3f1bb3dccdd303543dcb921e7cc5b5a3b2357ae7fd2343909e7184540df4b0b76a76530543610f7c5ba SHA512 17eaceeb490e0094b54d7c4e37bf653eb5cea2846316bdda0319a9c10c802084561a48aa7b1d72a4b6b08e09bf6ea688b93daa912a7c42feddad02c11749a399 -AUX 2.1.11-optimize-access-checks.patch 6850 BLAKE2B f4b5f05fd197668b23bcffcab661ab641cc9eedd84e23e39229e630fbc34441b2838f457739759df56e5ac80eb539b311f7e8f3f7abd4601a0ae169a1d464e9a SHA512 2876721ae59e918ced2ac439b32c350f3c6d4b9e23c6a830f81b69b63a05b55e0a15b774b03aeb85ded515825ccf29c783e19d7b52d6e09441ca3ba9e658427e -AUX 2.1.11-support-idmapped-mount-in-user-ns.patch 69463 BLAKE2B e599d28bab727b800c5f654b1902c0001dd411ee24bbeb04957fce7eeb6d9d1f3e152058dc0d0a430e3422fb7bb4cadaf09460cd48fe1e7a2374954c8cfe66e7 SHA512 b8109a18c012f69be7cd5dfadf6fdf0d349ec5248316414acca92b40065c8d60d08fa8ed0c2214bf40ae0351443abf3897baef48065688fa408528877e2ae759 -AUX 2.1.11-support-idmapped-mount.patch 104745 BLAKE2B bc6611d64e5b296025aab9a42202f44ba6c14a629128dec6b5bc3eb5a244809f1c04a466d118cf5e41d5af8977bf84aca5edbb5930301ded060920796f8a7bb7 SHA512 fcf4380c49cf1066b68942de5ffac0e052a72bea4095af7dd27ab2b36e7629a245050f1c480c1267957b18f3429579f04f570cdd8209fcfd1a72b819a0b4534c AUX 2.1.7-ppc64-ieee128-compat.patch 6889 BLAKE2B 9214915ed5b1d149927d46f749903fbb9b4d243d993041b8c6db039dcb7a3968a315f211e010ef9373b721336d45daef264d951e7ea1e0aed01818ebccae9d02 SHA512 4e3edbe396d0c1fdb7b286417b2bf7fe114b392e09158b3f5d3e3d1c4844bf0d59263309883363175dacd63194fd0d6a120ace35c83989d0546dae825bbb91bd +AUX zfs-kmod-2.1.11-gentoo.patch 1076 BLAKE2B d2b0fe2ff1ac31c2a2a184141f107010dae61d2de465462b8177db1a07918be2bd2fc4d4570ad8758da87ef14cf3878db062fe9eb5b53fa3156e7db5c06073d4 SHA512 9e103aae75036e52f89e79c4d4ed3cffe670ef423cda7c2f936533b9329e994c7a02d241289f6565e9d086e5b0bdd6865ab3677c3ad84eaadf3abe310977b6a8 AUX zfs-kmod-2.1.6-fgrep.patch 2183 BLAKE2B b8c9b58cc6d94e9ddeacbe3c5eca9d040f1c6fba84b814c8c553d5c1e15334765d3190286a4ad2298762bc54f66a8b89ef69d115cfbd5a25d928170a1d46a770 SHA512 f65e7ffa8cfd00da7ad6d1fcbf5d61172c52e55ea2630f719b49750692c1c046e8baed0e04cadc841adbd804cf861ec712b0d07dbbcae7c1c3b475326045ae8c -DIST zfs-2.1.11.tar.gz 35100716 BLAKE2B 991ac2347bcd452812e247358e2c44a04a88e700d25878b5b95f86939e6114e1205e7afabfd2a1ea9220947876511374d7224aa587d3d66184838d705f71a89a SHA512 335a543644d2dbba919213a28cc5922bf6a118fc19069db84562ce056449a2d6ca4ba827e54f304ab7d9be22260aa9b255134f1b12e2bc98890f757f35e48bd7 -DIST zfs-2.1.11.tar.gz.asc 836 BLAKE2B 0b904d8e1de2dd08a377efc94e32862192d6b9ccb8628af058a71b3ea51f5e483e0cf527906cd222fe9b41b28ca0b30b0efa07d97c480e5546f6e2bed8cbcb01 SHA512 7329e62012ba64288345d8959611de82502ef1da4020e215462fbb2ed209413ec8638d211a31dd6e70be71c998f1da1d8a0d19e5df1f2778782ebb988c94aa41 -EBUILD zfs-kmod-2.1.11.ebuild 6588 BLAKE2B 59815b0bc24c8f84e3a4362c3df66cc7e08b0e16e7ef7a7fdb098003c5465905cce095df7315b2ad0cadbb7f7a81c4bdbeeea4cd48a400caff1c7fa8e7507551 SHA512 241c3977cb69c6e5266690acc3ec73007a08ea27db44756dedfa20c32ff0f0942e964ad226b8e252eaba3b312f1a73e53500b2f97819d29d0b5e6d9502d8abe0 -EBUILD zfs-kmod-9999.ebuild 6569 BLAKE2B 2bf117650742e0044bf78d4838c0f8b1a2895d4bac31df742be78ce93aa321074840233d825b8844d01a2de0d1923d0f42bacb53109b7c034592babdb5c4dde9 SHA512 f0342de93072653647992b0b1c22c81f026697446b721fb44cde9808beea93651d58323ebdefb783adfc9eb3b2d8ff02fb267fdf6e4109e1b2355e1867ffedba -MISC metadata.xml 651 BLAKE2B 477c5d768a2eddab7bc0c14d0845801e25bfd9298fe229a132d7ff11a8560988d0230ec5d4b1447df32f58b9754df0cbe989f2a5600cd3fa99124ea4edc45cdd SHA512 d9bf0598c87bcdaab7d81dd5502caf1400f3c8d3834a6770630d85ed365cd4ebb3beeebae72d2d4d49bcdd0aa6cd709aa57cb2af4195dfc04a9c0cef89cfd724 +DIST zfs-2.1.12.tar.gz 35155013 BLAKE2B 652780e6bf7b63f45909110726d53795fada034f6044c8393fa3980e30217ada6931e3c2bb57210719e3c78c16f973f69287b7e2b475601f4ce12d701d9d96ae SHA512 f48493a21883e441cda705fb085353bed033f1620a1d0f93069c345c76cf2c0759a2e6f7a80c47c9398e9878abfe1d90d931fe5ceaf2588770a71491a434631e +DIST zfs-2.1.12.tar.gz.asc 836 BLAKE2B 9215e732981a82254115cd17ec3c9810d4e9e5d5f7bb848778848f911478fc2e4bdbfc563e9835a2e876c26d9e0e8755724a0995baf9ad24e9265123e10cfddf SHA512 69c8b618947fd966eba0bba1c7326ddd463861f051a6cf1d06e23bd6d840fe7503f02adec2c3cbb203fa7b1cced51500f3689c224b653d13d227edd51b5a44f6 +EBUILD zfs-kmod-2.1.12.ebuild 4614 BLAKE2B 74e78e5d5c0b097fbdbd02e31c4f655fed10e7a03baa5fa73c5f5e2fbff8a3a0f09f6851f1e4ca13878be7467e7cec7aad28fce2614cbafc3c8953fd4a05ec9a SHA512 781b4644912840c323f17981d96e309b0275c50995c42cf5646007a60ee8d21e827071ebb58d7e66689b41310b89d1fb183d3d7d5af36c9cd5e5abe6d3d3cb99 +EBUILD zfs-kmod-9999.ebuild 5944 BLAKE2B a107234585e66c308e467490a31b1505dada4c12cb0d8f891949d9b123fbad9fc1de35da3aa0f211e998af5c57d688888abfcdccf2cbdb65368b45609971b9ed SHA512 143123c0daaca21087f55c652f8c1816fddc905bf4135f17dbfdd610fa85d9a3b2d0a3f8142502bfd20c94b53220c26b106ed43aed23b846a76a0e4212068d22 +MISC metadata.xml 776 BLAKE2B 4c48182f7ceee679b4d947a70cb232980969b59bdc425463a929b6ae8be5f79450a3869bf3cc4d00069b65cda8a06f42eba29a7974c5e1b34a2998992901bcbe SHA512 f3f0af7dcdd26a01fc1b00af46ff64e7e6d7bb83a2225ea4cbff5c1a56651ddfdf3e7f59af914833f52828b9d059c6a8cb7f32037319abed129c40987349745f diff --git a/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-idmapped-mount-api-changes.patch b/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-idmapped-mount-api-changes.patch deleted file mode 100644 index 83185f488b09985d71b87f18bed0430d7b2ef90d..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-idmapped-mount-api-changes.patch +++ /dev/null @@ -1,2573 +0,0 @@ -From ecd3ef2b3171e7ce507fd0ad653597d00eab0228 Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:56:38 -0500 -Subject: [PATCH] Backport "Support idmapped mount for kernel 6.3" - ---- - config/kernel-acl.m4 | 34 ++++++-- - config/kernel-generic_fillattr.m4 | 33 +++++-- - config/kernel-inode-create.m4 | 41 +++++++-- - config/kernel-inode-getattr.m4 | 63 ++++++++++---- - config/kernel-inode-permission.m4 | 35 ++++++-- - config/kernel-inode-setattr.m4 | 87 +++++++++++++++++++ - config/kernel-is_owner_or_cap.m4 | 25 +++++- - config/kernel-mkdir.m4 | 55 +++++++++--- - config/kernel-mknod.m4 | 34 +++++++- - config/kernel-rename.m4 | 59 ++++++++++--- - config/kernel-setattr-prepare.m4 | 44 +++++++--- - config/kernel-symlink.m4 | 33 +++++-- - config/kernel-tmpfile.m4 | 33 +++++-- - config/kernel-xattr-handler.m4 | 91 +++++++++++++------- - config/kernel.m4 | 6 +- - include/os/freebsd/spl/sys/types.h | 2 +- - include/os/freebsd/zfs/sys/zfs_vnops_os.h | 10 +-- - include/os/linux/kernel/linux/vfs_compat.h | 21 ++++- - include/os/linux/kernel/linux/xattr_compat.h | 17 +++- - include/os/linux/spl/sys/cred.h | 30 ++++--- - include/os/linux/spl/sys/types.h | 15 +++- - include/os/linux/zfs/sys/policy.h | 6 +- - include/os/linux/zfs/sys/zfs_vnops_os.h | 15 ++-- - include/os/linux/zfs/sys/zpl.h | 13 ++- - include/sys/zfs_acl.h | 12 +-- - module/os/freebsd/zfs/zfs_acl.c | 10 +-- - module/os/freebsd/zfs/zfs_vnops_os.c | 10 +-- - module/os/linux/spl/spl-cred.c | 12 +++ - module/os/linux/zfs/policy.c | 13 +-- - module/os/linux/zfs/zfs_acl.c | 37 ++++---- - module/os/linux/zfs/zfs_dir.c | 4 +- - module/os/linux/zfs/zfs_ioctl_os.c | 4 + - module/os/linux/zfs/zfs_vnops_os.c | 35 ++++---- - module/os/linux/zfs/zfs_znode.c | 2 +- - module/os/linux/zfs/zpl_ctldir.c | 61 ++++++++++--- - module/os/linux/zfs/zpl_file.c | 10 +-- - module/os/linux/zfs/zpl_inode.c | 79 ++++++++++++----- - module/os/linux/zfs/zpl_xattr.c | 25 +++--- - module/zfs/zfs_replay.c | 14 +-- - module/zfs/zfs_vnops.c | 4 +- - 40 files changed, 848 insertions(+), 286 deletions(-) - create mode 100644 config/kernel-inode-setattr.m4 - -diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4 -index 6e92da97d0f..be08c3c6072 100644 ---- a/config/kernel-acl.m4 -+++ b/config/kernel-acl.m4 -@@ -236,7 +236,22 @@ dnl # - dnl # 6.2 API change, - dnl # set_acl() second paramter changed to a struct dentry * - dnl # -+dnl # 6.3 API change, -+dnl # set_acl() first parameter changed to struct mnt_idmap * -+dnl # - AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [ -+ ZFS_LINUX_TEST_SRC([inode_operations_set_acl_mnt_idmap_dentry], [ -+ #include <linux/fs.h> -+ -+ int set_acl_fn(struct mnt_idmap *idmap, -+ struct dentry *dent, 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_userns_dentry], [ - #include <linux/fs.h> - -@@ -281,17 +296,24 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [ - AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) - AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args]) - ],[ -- ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns_dentry], [ -+ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_mnt_idmap_dentry], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) -- AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1, -- [iops->set_acl() takes 4 args, arg2 is struct dentry *]) -+ AC_DEFINE(HAVE_SET_ACL_IDMAP_DENTRY, 1, -+ [iops->set_acl() takes 4 args, arg1 is struct mnt_idmap *]) - ],[ -- ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [ -+ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns_dentry], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args]) -+ AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) -+ AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1, -+ [iops->set_acl() takes 4 args, arg2 is struct dentry *]) - ],[ -- ZFS_LINUX_REQUIRE_API([i_op->set_acl()], [3.14]) -+ 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]) -+ ],[ -+ ZFS_LINUX_REQUIRE_API([i_op->set_acl()], [3.14]) -+ ]) - ]) - ]) - ]) -diff --git a/config/kernel-generic_fillattr.m4 b/config/kernel-generic_fillattr.m4 -index 0acd5d53103..02dee4d4c00 100644 ---- a/config/kernel-generic_fillattr.m4 -+++ b/config/kernel-generic_fillattr.m4 -@@ -4,7 +4,10 @@ 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], [ -+dnl # 6.3 API -+dnl # generic_fillattr() now takes struct mnt_idmap* as the first argument -+dnl # -+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR], [ - ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [ - #include <linux/fs.h> - ],[ -@@ -13,16 +16,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [ - struct kstat *k = NULL; - generic_fillattr(userns, in, k); - ]) -+ -+ ZFS_LINUX_TEST_SRC([generic_fillattr_mnt_idmap], [ -+ #include <linux/fs.h> -+ ],[ -+ struct mnt_idmap *idmap = NULL; -+ struct inode *in = NULL; -+ struct kstat *k = NULL; -+ generic_fillattr(idmap, in, k); -+ ]) - ]) - --AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [ -- AC_MSG_CHECKING([whether generic_fillattr requires struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [ -+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR], [ -+ AC_MSG_CHECKING([whether generic_fillattr requires struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([generic_fillattr_mnt_idmap], [ - AC_MSG_RESULT([yes]) -- AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1, -- [generic_fillattr requires struct user_namespace*]) -+ AC_DEFINE(HAVE_GENERIC_FILLATTR_IDMAP, 1, -+ [generic_fillattr requires struct mnt_idmap*]) - ],[ -- AC_MSG_RESULT([no]) -+ AC_MSG_CHECKING([whether generic_fillattr requires 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 a6ea11fb61b..9e9e4318097 100644 ---- a/config/kernel-inode-create.m4 -+++ b/config/kernel-inode-create.m4 -@@ -1,4 +1,22 @@ - AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [ -+ dnl # -+ dnl # 6.3 API change -+ dnl # The first arg is changed to struct mnt_idmap * -+ dnl # -+ ZFS_LINUX_TEST_SRC([create_mnt_idmap], [ -+ #include <linux/fs.h> -+ #include <linux/sched.h> -+ -+ int inode_create(struct mnt_idmap *idmap, -+ 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 # 5.12 API change that added the struct user_namespace* arg - dnl # to the front of this function type's arg list. -@@ -35,19 +53,28 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [ - ]) - - AC_DEFUN([ZFS_AC_KERNEL_CREATE], [ -- AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT([create_userns], [ -+ AC_MSG_CHECKING([whether iops->create() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([create_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1, -- [iops->create() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_CREATE_IDMAP, 1, -+ [iops->create() takes struct mnt_idmap*]) - ],[ - AC_MSG_RESULT(no) - -- AC_MSG_CHECKING([whether iops->create() passes flags]) -- ZFS_LINUX_TEST_RESULT([create_flags], [ -+ 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 f62e82f5230..c8bfb07862a 100644 ---- a/config/kernel-inode-getattr.m4 -+++ b/config/kernel-inode-getattr.m4 -@@ -1,4 +1,24 @@ - AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ -+ dnl # -+ dnl # Linux 6.3 API -+ dnl # The first arg of getattr I/O operations handler type -+ dnl # is changed to struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([inode_operations_getattr_mnt_idmap], [ -+ #include <linux/fs.h> -+ -+ int test_getattr( -+ struct mnt_idmap *idmap, -+ 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 5.12 API - dnl # The getattr I/O operations handler type was extended to require -@@ -55,37 +75,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ - - AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [ - dnl # -- dnl # Kernel 5.12 test -+ dnl # Kernel 6.3 test - dnl # -- AC_MSG_CHECKING([whether iops->getattr() takes user_namespace]) -- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [ -+ AC_MSG_CHECKING([whether iops->getattr() takes mnt_idmap]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1, -- [iops->getattr() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IDMAP_IOPS_GETATTR, 1, -+ [iops->getattr() takes struct mnt_idmap*]) - ],[ - AC_MSG_RESULT(no) -- - dnl # -- dnl # Kernel 4.11 test -+ dnl # Kernel 5.12 test - dnl # -- AC_MSG_CHECKING([whether iops->getattr() takes a path]) -- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ -+ 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) - - dnl # -- dnl # Kernel < 4.11 test -+ 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_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-inode-permission.m4 b/config/kernel-inode-permission.m4 -index ba9ff5d43d4..01d23635b0c 100644 ---- a/config/kernel-inode-permission.m4 -+++ b/config/kernel-inode-permission.m4 -@@ -1,4 +1,22 @@ - AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [ -+ dnl # -+ dnl # 6.3 API change -+ dnl # iops->permission() now takes struct mnt_idmap* -+ dnl # as its first arg -+ dnl # -+ ZFS_LINUX_TEST_SRC([permission_mnt_idmap], [ -+ #include <linux/fs.h> -+ #include <linux/sched.h> -+ -+ int inode_permission(struct mnt_idmap *idmap, -+ struct inode *inode, int mask) { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .permission = inode_permission, -+ }; -+ ],[]) -+ - dnl # - dnl # 5.12 API change that added the struct user_namespace* arg - dnl # to the front of this function type's arg list. -@@ -18,12 +36,19 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [ - ]) - - AC_DEFUN([ZFS_AC_KERNEL_PERMISSION], [ -- AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT([permission_userns], [ -+ AC_MSG_CHECKING([whether iops->permission() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([permission_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1, -- [iops->permission() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_PERMISSION_IDMAP, 1, -+ [iops->permission() takes struct mnt_idmap*]) - ],[ -- AC_MSG_RESULT(no) -+ AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*]) -+ ZFS_LINUX_TEST_RESULT([permission_userns], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1, -+ [iops->permission() takes struct user_namespace*]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) - ]) - ]) -diff --git a/config/kernel-inode-setattr.m4 b/config/kernel-inode-setattr.m4 -new file mode 100644 -index 00000000000..45755b4eb27 ---- /dev/null -+++ b/config/kernel-inode-setattr.m4 -@@ -0,0 +1,87 @@ -+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SETATTR], [ -+ dnl # -+ dnl # Linux 6.3 API -+ dnl # The first arg of setattr I/O operations handler type -+ dnl # is changed to struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([inode_operations_setattr_mnt_idmap], [ -+ #include <linux/fs.h> -+ -+ int test_setattr( -+ struct mnt_idmap *idmap, -+ struct dentry *de, struct iattr *ia) -+ { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .setattr = test_setattr, -+ }; -+ ],[]) -+ -+ dnl # -+ dnl # Linux 5.12 API -+ dnl # The setattr 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_setattr_userns], [ -+ #include <linux/fs.h> -+ -+ int test_setattr( -+ struct user_namespace *userns, -+ struct dentry *de, struct iattr *ia) -+ { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .setattr = test_setattr, -+ }; -+ ],[]) -+ -+ ZFS_LINUX_TEST_SRC([inode_operations_setattr], [ -+ #include <linux/fs.h> -+ -+ int test_setattr( -+ struct dentry *de, struct iattr *ia) -+ { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .setattr = test_setattr, -+ }; -+ ],[]) -+]) -+ -+AC_DEFUN([ZFS_AC_KERNEL_INODE_SETATTR], [ -+ dnl # -+ dnl # Kernel 6.3 test -+ dnl # -+ AC_MSG_CHECKING([whether iops->setattr() takes mnt_idmap]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr_mnt_idmap], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_IDMAP_IOPS_SETATTR, 1, -+ [iops->setattr() takes struct mnt_idmap*]) -+ ],[ -+ AC_MSG_RESULT(no) -+ dnl # -+ dnl # Kernel 5.12 test -+ dnl # -+ AC_MSG_CHECKING([whether iops->setattr() takes user_namespace]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr_userns], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_USERNS_IOPS_SETATTR, 1, -+ [iops->setattr() takes struct user_namespace*]) -+ ],[ -+ AC_MSG_RESULT(no) -+ -+ AC_MSG_CHECKING([whether iops->setattr() exists]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_IOPS_SETATTR, 1, -+ [iops->setattr() exists]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) -+ ]) -+ ]) -+]) -diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4 -index a90cf3da641..4e9c002b77f 100644 ---- a/config/kernel-is_owner_or_cap.m4 -+++ b/config/kernel-is_owner_or_cap.m4 -@@ -16,12 +16,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [ - (void) inode_owner_or_capable(ip); - ]) - -- ZFS_LINUX_TEST_SRC([inode_owner_or_capable_idmapped], [ -+ ZFS_LINUX_TEST_SRC([inode_owner_or_capable_userns], [ - #include <linux/fs.h> - ],[ - struct inode *ip = NULL; - (void) inode_owner_or_capable(&init_user_ns, ip); - ]) -+ -+ ZFS_LINUX_TEST_SRC([inode_owner_or_capable_mnt_idmap], [ -+ #include <linux/fs.h> -+ #include <linux/mnt_idmapping.h> -+ ],[ -+ struct inode *ip = NULL; -+ (void) inode_owner_or_capable(&nop_mnt_idmap, ip); -+ ]) - ]) - - AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [ -@@ -35,12 +43,21 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [ - - AC_MSG_CHECKING( - [whether inode_owner_or_capable() takes user_ns]) -- ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_idmapped], [ -+ ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_userns], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED, 1, -+ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_USERNS, 1, - [inode_owner_or_capable() takes user_ns]) - ],[ -- ZFS_LINUX_TEST_ERROR([capability]) -+ AC_MSG_RESULT(no) -+ AC_MSG_CHECKING( -+ [whether inode_owner_or_capable() takes mnt_idmap]) -+ ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_mnt_idmap], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAP, 1, -+ [inode_owner_or_capable() takes mnt_idmap]) -+ ], [ -+ ZFS_LINUX_TEST_ERROR([capability]) -+ ]) - ]) - ]) - ]) -diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4 -index 6667ed04fa4..7407a791b84 100644 ---- a/config/kernel-mkdir.m4 -+++ b/config/kernel-mkdir.m4 -@@ -2,6 +2,22 @@ dnl # - dnl # Supported mkdir() interfaces checked newest to oldest. - dnl # - AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [ -+ dnl # -+ dnl # 6.3 API change -+ dnl # mkdir() takes struct mnt_idmap * as the first arg -+ dnl # -+ ZFS_LINUX_TEST_SRC([mkdir_mnt_idmap], [ -+ #include <linux/fs.h> -+ -+ int mkdir(struct mnt_idmap *idmap, -+ struct inode *inode, struct dentry *dentry, -+ umode_t umode) { return 0; } -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .mkdir = mkdir, -+ }; -+ ],[]) -+ - dnl # - dnl # 5.12 API change - dnl # The struct user_namespace arg was added as the first argument to -@@ -43,25 +59,36 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_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 # 6.3 API change -+ dnl # mkdir() takes struct mnt_idmap * as the first arg - dnl # -- AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [ -+ AC_MSG_CHECKING([whether iops->mkdir() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([mkdir_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1, -- [iops->mkdir() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_MKDIR_IDMAP, 1, -+ [iops->mkdir() takes struct mnt_idmap*]) - ],[ -- AC_MSG_RESULT(no) -- -- AC_MSG_CHECKING([whether iops->mkdir() takes umode_t]) -- ZFS_LINUX_TEST_RESULT([inode_operations_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_MKDIR_UMODE_T, 1, -- [iops->mkdir() takes umode_t]) -+ AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1, -+ [iops->mkdir() takes struct user_namespace*]) - ],[ -- ZFS_LINUX_TEST_ERROR([mkdir()]) -+ AC_MSG_RESULT(no) -+ -+ 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 -index ffe45106003..1494ec1ae4d 100644 ---- a/config/kernel-mknod.m4 -+++ b/config/kernel-mknod.m4 -@@ -1,4 +1,22 @@ - AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [ -+ dnl # -+ dnl # 6.3 API change -+ dnl # The first arg is now struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([mknod_mnt_idmap], [ -+ #include <linux/fs.h> -+ #include <linux/sched.h> -+ -+ int tmp_mknod(struct mnt_idmap *idmap, -+ 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, -+ }; -+ ],[]) -+ - dnl # - dnl # 5.12 API change that added the struct user_namespace* arg - dnl # to the front of this function type's arg list. -@@ -19,12 +37,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_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_CHECKING([whether iops->mknod() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([mknod_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1, -- [iops->mknod() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_MKNOD_IDMAP, 1, -+ [iops->mknod() takes struct mnt_idmap*]) - ],[ - AC_MSG_RESULT(no) -+ 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 302db43f574..06a9791bc8d 100644 ---- a/config/kernel-rename.m4 -+++ b/config/kernel-rename.m4 -@@ -33,24 +33,63 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [ - .rename = rename_fn, - }; - ],[]) -+ -+ dnl # -+ dnl # 6.3 API change - the first arg is now struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([inode_operations_rename_mnt_idmap], [ -+ #include <linux/fs.h> -+ int rename_fn(struct mnt_idmap *idmap, 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], [ -- AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [ -+ AC_MSG_CHECKING([whether iops->rename() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_rename_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1, -- [iops->rename() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_RENAME_IDMAP, 1, -+ [iops->rename() takes struct mnt_idmap*]) - ],[ -- AC_MSG_RESULT(no) -- -- AC_MSG_CHECKING([whether iop->rename() wants flags]) -- ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [ -+ 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) -+ -+ AC_MSG_CHECKING([whether iops->rename2() exists]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_rename2], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_RENAME2, 1, [iops->rename2() exists]) -+ ],[ -+ AC_MSG_RESULT(no) -+ -+ AC_MSG_CHECKING([whether iops->rename() wants flags]) -+ 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) -+ -+ AC_MSG_CHECKING([whether struct inode_operations_wrapper takes .rename2()]) -+ ZFS_LINUX_TEST_RESULT([dir_inode_operations_wrapper_rename2], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_RENAME2_OPERATIONS_WRAPPER, 1, -+ [struct inode_operations_wrapper takes .rename2()]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) -+ ]) -+ ]) - ]) - ]) - ]) -diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4 -index 24245aa5344..e02d6263e9c 100644 ---- a/config/kernel-setattr-prepare.m4 -+++ b/config/kernel-setattr-prepare.m4 -@@ -27,26 +27,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [ - int error __attribute__ ((unused)) = - setattr_prepare(userns, dentry, attr); - ]) -+ -+ dnl # -+ dnl # 6.3 API change -+ dnl # The first arg of setattr_prepare() is changed to struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([setattr_prepare_mnt_idmap], [ -+ #include <linux/fs.h> -+ ], [ -+ struct dentry *dentry = NULL; -+ struct iattr *attr = NULL; -+ struct mnt_idmap *idmap = NULL; -+ int error __attribute__ ((unused)) = -+ setattr_prepare(idmap, dentry, attr); -+ ]) - ]) - - AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [ -- AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*]) -- ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns], -+ AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_mnt_idmap], - [setattr_prepare], [fs/attr.c], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1, -- [setattr_prepare() accepts user_namespace]) -+ AC_DEFINE(HAVE_SETATTR_PREPARE_IDMAP, 1, -+ [setattr_prepare() accepts mnt_idmap]) - ], [ -- 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_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_NO_USERNS, 1, -- [setattr_prepare() is available, doesn't accept user_namespace]) -+ 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 -index d90366d04b7..a0333ed66a7 100644 ---- a/config/kernel-symlink.m4 -+++ b/config/kernel-symlink.m4 -@@ -1,4 +1,20 @@ - AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [ -+ dnl # -+ dnl # 6.3 API change that changed the first arg -+ dnl # to struct mnt_idmap* -+ dnl # -+ ZFS_LINUX_TEST_SRC([symlink_mnt_idmap], [ -+ #include <linux/fs.h> -+ #include <linux/sched.h> -+ int tmp_symlink(struct mnt_idmap *idmap, -+ struct inode *inode ,struct dentry *dentry, -+ const char *path) { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .symlink = tmp_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. -@@ -19,12 +35,19 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_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_CHECKING([whether iops->symlink() takes struct mnt_idmap*]) -+ ZFS_LINUX_TEST_RESULT([symlink_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1, -- [iops->symlink() takes struct user_namespace*]) -+ AC_DEFINE(HAVE_IOPS_SYMLINK_IDMAP, 1, -+ [iops->symlink() takes struct mnt_idmap*]) - ],[ -- AC_MSG_RESULT(no) -+ 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-tmpfile.m4 b/config/kernel-tmpfile.m4 -index 0e1deb3612f..cc18b8f65a8 100644 ---- a/config/kernel-tmpfile.m4 -+++ b/config/kernel-tmpfile.m4 -@@ -4,6 +4,19 @@ dnl # Add support for i_op->tmpfile - dnl # - AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [ - dnl # -+ dnl # 6.3 API change -+ dnl # The first arg is now struct mnt_idmap * -+ dnl # -+ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_mnt_idmap], [ -+ #include <linux/fs.h> -+ int tmpfile(struct mnt_idmap *idmap, -+ struct inode *inode, struct file *file, -+ umode_t mode) { return 0; } -+ static struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .tmpfile = tmpfile, -+ }; -+ ],[]) - dnl # 6.1 API change - dnl # use struct file instead of struct dentry - dnl # -@@ -44,23 +57,29 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_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_mnt_idmap], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) -- AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns]) -- ],[ -- ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry_userns], [ -+ AC_DEFINE(HAVE_TMPFILE_IDMAP, 1, [i_op->tmpfile() has mnt_idmap]) -+ ], [ -+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [ - 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_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature]) - ],[ -- ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry], [ -+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry_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_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature]) - ],[ -- ZFS_LINUX_REQUIRE_API([i_op->tmpfile()], [3.11]) -+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) -+ AC_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature]) -+ ],[ -+ ZFS_LINUX_REQUIRE_API([i_op->tmpfile()], [3.11]) -+ ]) - ]) - ]) - ]) -diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4 -index b6cbfa15500..6b8a08dbcc8 100644 ---- a/config/kernel-xattr-handler.m4 -+++ b/config/kernel-xattr-handler.m4 -@@ -179,6 +179,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_mnt_idmap], [ -+ #include <linux/xattr.h> -+ -+ int set(const struct xattr_handler *handler, -+ struct mnt_idmap *idmap, -+ 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_userns], [ - #include <linux/xattr.h> - -@@ -240,53 +255,63 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [ - 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, inode, and user_namespace]) -- ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [ -+ dnl # 6.3 API change, -+ dnl # The xattr_handler->set() callback 2nd arg is now struct mnt_idmap * -+ dnl # -+ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and mnt_idmap]) -+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_mnt_idmap], [ - AC_MSG_RESULT(yes) -- AC_DEFINE(HAVE_XATTR_SET_USERNS, 1, -- [xattr_handler->set() takes user_namespace]) -- ],[ -- dnl # -- 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 dentry and inode]) -- ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [ -+ AC_DEFINE(HAVE_XATTR_SET_IDMAP, 1, -+ [xattr_handler->set() takes mnt_idmap]) -+ ], [ -+ 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 1998b831e96..b376a151694 100644 ---- a/config/kernel.m4 -+++ b/config/kernel.m4 -@@ -69,6 +69,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE - ZFS_AC_KERNEL_SRC_XATTR - ZFS_AC_KERNEL_SRC_ACL -+ ZFS_AC_KERNEL_SRC_INODE_SETATTR - ZFS_AC_KERNEL_SRC_INODE_GETATTR - ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS - ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION -@@ -131,7 +132,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC_KSTRTOUL - ZFS_AC_KERNEL_SRC_PERCPU - ZFS_AC_KERNEL_SRC_CPU_HOTPLUG -- ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS -+ ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR - ZFS_AC_KERNEL_SRC_MKNOD - ZFS_AC_KERNEL_SRC_SYMLINK - ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS -@@ -189,6 +190,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE - ZFS_AC_KERNEL_XATTR - ZFS_AC_KERNEL_ACL -+ ZFS_AC_KERNEL_INODE_SETATTR - ZFS_AC_KERNEL_INODE_GETATTR - ZFS_AC_KERNEL_INODE_SET_FLAGS - ZFS_AC_KERNEL_INODE_SET_IVERSION -@@ -251,7 +253,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL_KSTRTOUL - ZFS_AC_KERNEL_PERCPU - ZFS_AC_KERNEL_CPU_HOTPLUG -- ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS -+ ZFS_AC_KERNEL_GENERIC_FILLATTR - ZFS_AC_KERNEL_MKNOD - ZFS_AC_KERNEL_SYMLINK - ZFS_AC_KERNEL_BIO_MAX_SEGS -diff --git a/include/os/freebsd/spl/sys/types.h b/include/os/freebsd/spl/sys/types.h -index 6557c840feb..bbb81f9f840 100644 ---- a/include/os/freebsd/spl/sys/types.h -+++ b/include/os/freebsd/spl/sys/types.h -@@ -104,7 +104,7 @@ typedef u_longlong_t len_t; - - typedef longlong_t diskaddr_t; - --typedef void zuserns_t; -+typedef void zidmap_t; - - #include <sys/debug.h> - #endif /* !_OPENSOLARIS_SYS_TYPES_H_ */ -diff --git a/include/os/freebsd/zfs/sys/zfs_vnops_os.h b/include/os/freebsd/zfs/sys/zfs_vnops_os.h -index 460aecd2e70..b79cccfcf35 100644 ---- a/include/os/freebsd/zfs/sys/zfs_vnops_os.h -+++ b/include/os/freebsd/zfs/sys/zfs_vnops_os.h -@@ -35,22 +35,22 @@ int dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count, - int *rbehind, int *rahead, int last_size); - extern int zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags); - extern int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, -- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); -+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns); - extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd, - cred_t *cr, int flags); - extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, -- zuserns_t *mnt_ns); -+ zidmap_t *mnt_ns); - extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp, -- const char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); -+ const char *tnm, cred_t *cr, int flags, zidmap_t *mnt_ns); - extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, -- const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); -+ const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns); - extern int zfs_link(znode_t *tdzp, znode_t *sp, - const char *name, cred_t *cr, int flags); - extern int zfs_space(znode_t *zp, int cmd, struct flock *bfp, int flag, - offset_t offset, cred_t *cr); - extern int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -- zuserns_t *mnt_ns); -+ zidmap_t *mnt_ns); - extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, - cred_t *cr); - extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, -diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h -index 91e908598fb..e82bbf755d5 100644 ---- a/include/os/linux/kernel/linux/vfs_compat.h -+++ b/include/os/linux/kernel/linux/vfs_compat.h -@@ -344,7 +344,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid) - * 4.9 API change - */ - #if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \ -- defined(HAVE_SETATTR_PREPARE_USERNS)) -+ defined(HAVE_SETATTR_PREPARE_USERNS) || \ -+ defined(HAVE_SETATTR_PREPARE_IDMAP)) - static inline int - setattr_prepare(struct dentry *dentry, struct iattr *ia) - { -@@ -399,6 +400,15 @@ func(struct user_namespace *user_ns, const struct path *path, \ - return (func##_impl(user_ns, path, stat, request_mask, \ - query_flags)); \ - } -+#elif defined(HAVE_IDMAP_IOPS_GETATTR) -+#define ZPL_GETATTR_WRAPPER(func) \ -+static int \ -+func(struct mnt_idmap *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 -@@ -450,8 +460,15 @@ zpl_is_32bit_api(void) - * 5.12 API change - * To support id-mapped mounts, generic_fillattr() was modified to - * accept a new struct user_namespace* as its first arg. -+ * -+ * 6.3 API change -+ * generic_fillattr() first arg is changed to struct mnt_idmap * -+ * - */ --#ifdef HAVE_GENERIC_FILLATTR_USERNS -+#ifdef HAVE_GENERIC_FILLATTR_IDMAP -+#define zpl_generic_fillattr(idmap, ip, sp) \ -+ generic_fillattr(idmap, ip, sp) -+#elif defined(HAVE_GENERIC_FILLATTR_USERNS) - #define zpl_generic_fillattr(user_ns, ip, sp) \ - generic_fillattr(user_ns, ip, sp) - #else -diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h -index 83763c64a14..700454c26de 100644 ---- a/include/os/linux/kernel/linux/xattr_compat.h -+++ b/include/os/linux/kernel/linux/xattr_compat.h -@@ -133,13 +133,28 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \ - #error "Unsupported kernel" - #endif - -+/* -+ * 6.3 API change, -+ * The xattr_handler->set() callback was changed to take the -+ * struct mnt_idmap* as the first arg, to support idmapped -+ * mounts. -+ */ -+#if defined(HAVE_XATTR_SET_IDMAP) -+#define ZPL_XATTR_SET_WRAPPER(fn) \ -+static int \ -+fn(const struct xattr_handler *handler, struct mnt_idmap *user_ns, \ -+ struct dentry *dentry, struct inode *inode, const char *name, \ -+ const void *buffer, size_t size, int flags) \ -+{ \ -+ return (__ ## fn(user_ns, inode, name, buffer, size, flags)); \ -+} - /* - * 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) -+#elif defined(HAVE_XATTR_SET_USERNS) - #define ZPL_XATTR_SET_WRAPPER(fn) \ - static int \ - fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \ -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index 75ad400d312..7fd5f644863 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -48,6 +48,8 @@ extern struct task_struct init_task; - #define SGID_TO_KGID(x) (KGIDT_INIT(x)) - #define KGIDP_TO_SGIDP(x) (&(x)->val) - -+extern zidmap_t *zfs_get_init_idmap(void); -+ - /* Check if the user ns is the initial one */ - static inline boolean_t - zfs_is_init_userns(struct user_namespace *user_ns) -@@ -74,36 +76,39 @@ static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns, - return (zfs_is_init_userns(mnt_userns) || mnt_userns == fs_userns); - } - --static inline uid_t zfs_uid_to_vfsuid(struct user_namespace *mnt_userns, -+static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns, - struct user_namespace *fs_userns, uid_t uid) - { -- if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ struct user_namespace *owner = idmap_owner(mnt_userns); -+ if (zfs_no_idmapping(owner, fs_userns)) - return (uid); - if (!zfs_is_init_userns(fs_userns)) - uid = from_kuid(fs_userns, KUIDT_INIT(uid)); - if (uid == (uid_t)-1) - return (uid); -- return (__kuid_val(make_kuid(mnt_userns, uid))); -+ return (__kuid_val(make_kuid(owner, uid))); - } - --static inline gid_t zfs_gid_to_vfsgid(struct user_namespace *mnt_userns, -+static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns, - struct user_namespace *fs_userns, gid_t gid) - { -- if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ struct user_namespace *owner = idmap_owner(mnt_userns); -+ if (zfs_no_idmapping(owner, fs_userns)) - return (gid); - if (!zfs_is_init_userns(fs_userns)) - gid = from_kgid(fs_userns, KGIDT_INIT(gid)); - if (gid == (gid_t)-1) - return (gid); -- return (__kgid_val(make_kgid(mnt_userns, gid))); -+ return (__kgid_val(make_kgid(owner, gid))); - } - --static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns, -+static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns, - struct user_namespace *fs_userns, uid_t uid) - { -- if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ struct user_namespace *owner = idmap_owner(mnt_userns); -+ if (zfs_no_idmapping(owner, fs_userns)) - return (uid); -- uid = from_kuid(mnt_userns, KUIDT_INIT(uid)); -+ uid = from_kuid(owner, KUIDT_INIT(uid)); - if (uid == (uid_t)-1) - return (uid); - if (zfs_is_init_userns(fs_userns)) -@@ -111,12 +116,13 @@ static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns, - return (__kuid_val(make_kuid(fs_userns, uid))); - } - --static inline gid_t zfs_vfsgid_to_gid(struct user_namespace *mnt_userns, -+static inline gid_t zfs_vfsgid_to_gid(zidmap_t *mnt_userns, - struct user_namespace *fs_userns, gid_t gid) - { -- if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ struct user_namespace *owner = idmap_owner(mnt_userns); -+ if (zfs_no_idmapping(owner, fs_userns)) - return (gid); -- gid = from_kgid(mnt_userns, KGIDT_INIT(gid)); -+ gid = from_kgid(owner, KGIDT_INIT(gid)); - if (gid == (gid_t)-1) - return (gid); - if (zfs_is_init_userns(fs_userns)) -diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h -index cae1bbddf10..a7666187ec2 100644 ---- a/include/os/linux/spl/sys/types.h -+++ b/include/os/linux/spl/sys/types.h -@@ -55,6 +55,19 @@ typedef int major_t; - typedef int minor_t; - - struct user_namespace; --typedef struct user_namespace zuserns_t; -+#ifdef HAVE_IOPS_CREATE_IDMAP -+#include <linux/refcount.h> -+struct mnt_idmap { -+ struct user_namespace *owner; -+ refcount_t count; -+}; -+typedef struct mnt_idmap zidmap_t; -+#define idmap_owner(p) (((struct mnt_idmap *)p)->owner) -+#else -+typedef struct user_namespace zidmap_t; -+#define idmap_owner(p) ((struct user_namespace *)p) -+#endif -+ -+extern zidmap_t *zfs_init_idmap; - - #endif /* _SPL_TYPES_H */ -diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h -index 7548804b9ee..ab352fd30cb 100644 ---- a/include/os/linux/zfs/sys/policy.h -+++ b/include/os/linux/zfs/sys/policy.h -@@ -47,14 +47,14 @@ int secpolicy_vnode_create_gid(const cred_t *); - int secpolicy_vnode_remove(const cred_t *); - int secpolicy_vnode_setdac(const cred_t *, uid_t); - int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t); --int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *, -- zuserns_t *); -+int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zidmap_t *, -+ struct user_namespace *); - int secpolicy_zinject(const cred_t *); - int secpolicy_zfs(const cred_t *); - int secpolicy_zfs_proc(const cred_t *, proc_t *); - void secpolicy_setid_clear(vattr_t *, cred_t *); - int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *, -- const vattr_t *, cred_t *, zuserns_t *, zuserns_t *); -+ const vattr_t *, cred_t *, zidmap_t *, struct user_namespace *); - int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t); - int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *, - const struct vattr *, int, int (void *, int, cred_t *), void *); -diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h -index fcb32308562..941eb93e97f 100644 ---- a/include/os/linux/zfs/sys/zfs_vnops_os.h -+++ b/include/os/linux/zfs/sys/zfs_vnops_os.h -@@ -46,24 +46,23 @@ extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags, - cred_t *cr, int *direntflags, pathname_t *realpnp); - extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -- zuserns_t *mnt_ns); -+ zidmap_t *mnt_ns); - extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl, - int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, -- zuserns_t *mnt_ns); -+ zidmap_t *mnt_ns); - extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags); - extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, -- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); -+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns); - 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 user_namespace *, struct inode *ip, -- struct kstat *sp); -+extern int zfs_getattr_fast(zidmap_t *, struct inode *ip, struct kstat *sp); - extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, -- zuserns_t *mnt_ns); -+ zidmap_t *mnt_ns); - extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, -- char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); -+ char *tnm, cred_t *cr, int flags, zidmap_t *mnt_ns); - extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, -- char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); -+ char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns); - extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr); - extern int zfs_link(znode_t *tdzp, znode_t *szp, - char *name, cred_t *cr, int flags); -diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h -index 703e335c28a..795b9b4f4ce 100644 ---- a/include/os/linux/zfs/sys/zpl.h -+++ b/include/os/linux/zfs/sys/zpl.h -@@ -39,7 +39,7 @@ - - /* zpl_inode.c */ - extern void zpl_vap_init(vattr_t *vap, struct inode *dir, -- umode_t mode, cred_t *cr, zuserns_t *mnt_ns); -+ umode_t mode, cred_t *cr, zidmap_t *mnt_ns); - - extern const struct inode_operations zpl_inode_operations; - extern const struct inode_operations zpl_dir_inode_operations; -@@ -64,7 +64,10 @@ 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) -+#if defined(HAVE_SET_ACL_IDMAP_DENTRY) -+extern int zpl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, -+ struct posix_acl *acl, int type); -+#elif defined(HAVE_SET_ACL_USERNS) - extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip, - struct posix_acl *acl, int type); - #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2) -@@ -186,13 +189,15 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx) - - #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) -+#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_USERNS) - #define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ns, ip) -+#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAP) -+#define zpl_inode_owner_or_capable(idmap, ip) inode_owner_or_capable(idmap, ip) - #else - #error "Unsupported kernel" - #endif - --#ifdef HAVE_SETATTR_PREPARE_USERNS -+#if defined(HAVE_SETATTR_PREPARE_USERNS) || defined(HAVE_SETATTR_PREPARE_IDMAP) - #define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia) - #else - /* -diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h -index 93a1f7f6172..55af29cc000 100644 ---- a/include/sys/zfs_acl.h -+++ b/include/sys/zfs_acl.h -@@ -206,7 +206,7 @@ struct zfsvfs; - - #ifdef _KERNEL - int zfs_acl_ids_create(struct znode *, int, vattr_t *, -- cred_t *, vsecattr_t *, zfs_acl_ids_t *, zuserns_t *); -+ cred_t *, vsecattr_t *, zfs_acl_ids_t *, zidmap_t *); - void zfs_acl_ids_free(zfs_acl_ids_t *); - boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t); - int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *); -@@ -216,15 +216,15 @@ void zfs_oldace_byteswap(ace_t *, int); - void zfs_ace_byteswap(void *, size_t, boolean_t); - extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr); - extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *, -- zuserns_t *); -+ zidmap_t *); - int zfs_fastaccesschk_execute(struct znode *, cred_t *); --extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zuserns_t *); --extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *); -+extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zidmap_t *); -+extern int zfs_zaccess_unix(void *, int, cred_t *); - extern int zfs_acl_access(struct znode *, int, cred_t *); - int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t); --int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zuserns_t *); -+int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zidmap_t *); - int zfs_zaccess_rename(struct znode *, struct znode *, -- struct znode *, struct znode *, cred_t *cr, zuserns_t *mnt_ns); -+ struct znode *, struct znode *, cred_t *cr, zidmap_t *mnt_ns); - void zfs_acl_free(zfs_acl_t *); - int zfs_vsec_2_aclp(struct zfsvfs *, umode_t, vsecattr_t *, cred_t *, - struct zfs_fuid_info **, zfs_acl_t **); -diff --git a/module/os/freebsd/zfs/zfs_acl.c b/module/os/freebsd/zfs/zfs_acl.c -index ca50f442a07..060bf143136 100644 ---- a/module/os/freebsd/zfs/zfs_acl.c -+++ b/module/os/freebsd/zfs/zfs_acl.c -@@ -1618,7 +1618,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, - */ - int - zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, -- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) -+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns) - { - int error; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -2341,7 +2341,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - */ - int - zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - uint32_t working_mode; - int error; -@@ -2472,7 +2472,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, - */ - int - zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, - mnt_ns)); -@@ -2542,7 +2542,7 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp, - * - */ - int --zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) -+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns) - { - uint32_t dzp_working_mode = 0; - uint32_t zp_working_mode = 0; -@@ -2629,7 +2629,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) - - int - zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, -- znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) -+ znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns) - { - int add_perm; - int error; -diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c -index 0b7bbbdc52b..145ad4680b2 100644 ---- a/module/os/freebsd/zfs/zfs_vnops_os.c -+++ b/module/os/freebsd/zfs/zfs_vnops_os.c -@@ -1062,7 +1062,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, - /* ARGSUSED */ - int - zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, -- znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, zuserns_t *mnt_ns) -+ znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, zidmap_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -1413,7 +1413,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags) - /*ARGSUSED*/ - int - zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, -- cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) -+ cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -2224,7 +2224,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) - */ - /* ARGSUSED */ - int --zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) -+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns) - { - vnode_t *vp = ZTOV(zp); - zfsvfs_t *zfsvfs = zp->z_zfsvfs; -@@ -3478,7 +3478,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, - - int - zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, -- cred_t *cr, int flags, zuserns_t *mnt_ns) -+ cred_t *cr, int flags, zidmap_t *mnt_ns) - { - struct componentname scn, tcn; - vnode_t *sdvp, *tdvp; -@@ -3533,7 +3533,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, - /*ARGSUSED*/ - int - zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, -- const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) -+ const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns) - { - znode_t *zp; - dmu_tx_t *tx; -diff --git a/module/os/linux/spl/spl-cred.c b/module/os/linux/spl/spl-cred.c -index f81b9540a63..d407fc66b2d 100644 ---- a/module/os/linux/spl/spl-cred.c -+++ b/module/os/linux/spl/spl-cred.c -@@ -145,6 +145,18 @@ crgetgid(const cred_t *cr) - return (KGID_TO_SGID(cr->fsgid)); - } - -+/* Return the initial user ns or nop_mnt_idmap */ -+zidmap_t * -+zfs_get_init_idmap(void) -+{ -+#ifdef HAVE_IOPS_CREATE_IDMAP -+ return ((zidmap_t *)&nop_mnt_idmap); -+#else -+ return ((zidmap_t *)&init_user_ns); -+#endif -+} -+ -+EXPORT_SYMBOL(zfs_get_init_idmap); - EXPORT_SYMBOL(crhold); - EXPORT_SYMBOL(crfree); - EXPORT_SYMBOL(crgetuid); -diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c -index e879ec32c20..cc831bbb339 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 (crgetuid(cr) == owner) - return (0); - -- if (zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ if (zpl_inode_owner_or_capable(zfs_init_idmap, ip)) - return (0); - - #if defined(CONFIG_USER_NS) -@@ -214,8 +214,8 @@ secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr, - * Determine that subject can set the file setgid flag. - */ - int --secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns, -- zuserns_t *fs_ns) -+secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zidmap_t *mnt_ns, -+ struct user_namespace *fs_ns) - { - gid = zfs_gid_to_vfsgid(mnt_ns, fs_ns, gid); - #if defined(CONFIG_USER_NS) -@@ -286,8 +286,8 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr) - * Determine that subject can set the file setid flags. - */ - static int --secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns, -- zuserns_t *fs_ns) -+secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zidmap_t *mnt_ns, -+ struct user_namespace *fs_ns) - { - owner = zfs_uid_to_vfsuid(mnt_ns, fs_ns, owner); - -@@ -315,7 +315,8 @@ secpolicy_vnode_stky_modify(const cred_t *cr) - - int - secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, -- const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns, zuserns_t *fs_ns) -+ const vattr_t *ovap, cred_t *cr, zidmap_t *mnt_ns, -+ struct user_namespace *fs_ns) - { - int error; - -diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c -index 3d31da6e35b..7014ccd22a3 100644 ---- a/module/os/linux/zfs/zfs_acl.c -+++ b/module/os/linux/zfs/zfs_acl.c -@@ -1801,7 +1801,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp, - */ - int - zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, -- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) -+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns) - { - int error; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -1980,7 +1980,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - return (SET_ERROR(ENOSYS)); - - if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, -- kcred->user_ns))) -+ zfs_init_idmap))) - return (error); - - mutex_enter(&zp->z_acl_lock); -@@ -2140,7 +2140,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - return (SET_ERROR(EPERM)); - - if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, -- kcred->user_ns))) -+ zfs_init_idmap))) - return (error); - - error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, -@@ -2286,7 +2286,7 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) - */ - static int - zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, -- boolean_t anyaccess, cred_t *cr, zuserns_t *mnt_ns) -+ boolean_t anyaccess, cred_t *cr, zidmap_t *mnt_ns) - { - zfsvfs_t *zfsvfs = ZTOZSB(zp); - zfs_acl_t *aclp; -@@ -2420,7 +2420,7 @@ zfs_has_access(znode_t *zp, cred_t *cr) - uint32_t have = ACE_ALL_PERMS; - - if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, -- kcred->user_ns) != 0) { -+ zfs_init_idmap) != 0) { - uid_t owner; - - owner = zfs_fuid_map_id(ZTOZSB(zp), -@@ -2451,9 +2451,9 @@ zfs_has_access(znode_t *zp, cred_t *cr) - */ - static int - zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { -- int err, mask; -+ int err, mask = 0; - int unmapped = 0; - - ASSERT(zp->z_pflags & ZFS_ACL_TRIVIAL); -@@ -2464,11 +2464,10 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, - return (unmapped ? SET_ERROR(EPERM) : 0); - } - --#if defined(HAVE_IOPS_PERMISSION_USERNS) -+#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \ -+ defined(HAVE_IOPS_PERMISSION_IDMAP)) - if (mnt_ns) - err = generic_permission(mnt_ns, ZTOI(zp), mask); -- else -- err = generic_permission(cr->user_ns, ZTOI(zp), mask); - #else - err = generic_permission(ZTOI(zp), mask); - #endif -@@ -2483,7 +2482,7 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, - - static int - zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, -- boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zuserns_t *mnt_ns) -+ boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zidmap_t *mnt_ns) - { - zfsvfs_t *zfsvfs = ZTOZSB(zp); - int err; -@@ -2540,7 +2539,7 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, - - static int - zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, -- cred_t *cr, zuserns_t *mnt_ns) -+ cred_t *cr, zidmap_t *mnt_ns) - { - if (*working_mode != ACE_WRITE_DATA) - return (SET_ERROR(EACCES)); -@@ -2613,7 +2612,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - DTRACE_PROBE(zfs__fastpath__execute__access__miss); - ZFS_ENTER(ZTOZSB(zdp)); - error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -- kcred->user_ns); -+ zfs_init_idmap); - ZFS_EXIT(ZTOZSB(zdp)); - return (error); - } -@@ -2626,7 +2625,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - */ - int - zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - uint32_t working_mode; - int error; -@@ -2776,7 +2775,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, - */ - int - zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, - mnt_ns)); -@@ -2786,11 +2785,11 @@ zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, - * Access function for secpolicy_vnode_setattr - */ - int --zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) -+zfs_zaccess_unix(void *zp, int mode, cred_t *cr) - { - int v4_mode = zfs_unix_to_v4(mode >> 6); - -- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, kcred->user_ns)); -+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_idmap)); - } - - /* See zfs_zaccess_delete() */ -@@ -2867,7 +2866,7 @@ int zfs_write_implies_delete_child = 1; - * zfs_write_implies_delete_child - */ - int --zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) -+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns) - { - uint32_t wanted_dirperms; - uint32_t dzp_working_mode = 0; -@@ -2998,7 +2997,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) - - int - zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, -- znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) -+ znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns) - { - int add_perm; - int error; -diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c -index 8c65c33628d..353e8805a8c 100644 ---- a/module/os/linux/zfs/zfs_dir.c -+++ b/module/os/linux/zfs/zfs_dir.c -@@ -1067,7 +1067,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr) - *xzpp = NULL; - - if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, -- &acl_ids, kcred->user_ns)) != 0) -+ &acl_ids, zfs_init_idmap)) != 0) - return (error); - if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { - zfs_acl_ids_free(&acl_ids); -@@ -1216,7 +1216,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) - - if ((uid = crgetuid(cr)) == downer || uid == fowner || - zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -- kcred->user_ns) == 0) -+ zfs_init_idmap) == 0) - return (0); - else - return (secpolicy_vnode_remove(cr)); -diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c -index d70b31f9f10..5634a2514ae 100644 ---- a/module/os/linux/zfs/zfs_ioctl_os.c -+++ b/module/os/linux/zfs/zfs_ioctl_os.c -@@ -290,6 +290,8 @@ zfsdev_detach(void) - #define ZFS_DEBUG_STR "" - #endif - -+zidmap_t *zfs_init_idmap; -+ - static int __init - openzfs_init(void) - { -@@ -313,6 +315,8 @@ openzfs_init(void) - printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); - #endif /* CONFIG_FS_POSIX_ACL */ - -+ zfs_init_idmap = (zidmap_t *)zfs_get_init_idmap(); -+ - return (0); - } - -diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c -index 23f3d140cf5..f8240ab7682 100644 ---- a/module/os/linux/zfs/zfs_vnops_os.c -+++ b/module/os/linux/zfs/zfs_vnops_os.c -@@ -501,7 +501,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, -- B_TRUE, cr, kcred->user_ns))) { -+ B_TRUE, cr, zfs_init_idmap))) { - zrele(*zpp); - *zpp = NULL; - } -@@ -520,7 +520,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -- kcred->user_ns))) { -+ zfs_init_idmap))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -567,7 +567,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - int - zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -817,7 +817,7 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - int - zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl, - int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - znode_t *zp = NULL, *dzp = ITOZ(dip); - zfsvfs_t *zfsvfs = ITOZSB(dip); -@@ -1002,7 +1002,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_idmap))) { - goto out; - } - -@@ -1196,7 +1196,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - /*ARGSUSED*/ - int - zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, -- cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) -+ cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -1418,7 +1418,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_idmap))) { - goto out; - } - -@@ -1671,8 +1671,7 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr) - */ - /* ARGSUSED */ - int --zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip, -- struct kstat *sp) -+zfs_getattr_fast(zidmap_t *user_ns, struct inode *ip, struct kstat *sp) - { - znode_t *zp = ITOZ(ip); - zfsvfs_t *zfsvfs = ITOZSB(ip); -@@ -1860,7 +1859,7 @@ zfs_setattr_dir(znode_t *dzp) - */ - /* ARGSUSED */ - int --zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) -+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns) - { - struct inode *ip; - zfsvfs_t *zfsvfs = ZTOZSB(zp); -@@ -2057,10 +2056,10 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) - * Take ownership or chgrp to group we are a member of - */ - -- uid = zfs_uid_to_vfsuid((struct user_namespace *)mnt_ns, -- zfs_i_user_ns(ip), vap->va_uid); -- gid = zfs_gid_to_vfsgid((struct user_namespace *)mnt_ns, -- zfs_i_user_ns(ip), vap->va_gid); -+ uid = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ip), -+ vap->va_uid); -+ gid = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ip), -+ vap->va_gid); - take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr)); - take_group = (mask & ATTR_GID) && - zfs_groupmember(zfsvfs, gid, cr); -@@ -2698,7 +2697,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) - /*ARGSUSED*/ - int - zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, -- cred_t *cr, int flags, zuserns_t *mnt_ns) -+ cred_t *cr, int flags, zidmap_t *mnt_ns) - { - znode_t *szp, *tzp; - zfsvfs_t *zfsvfs = ZTOZSB(sdzp); -@@ -3067,7 +3066,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, - /*ARGSUSED*/ - int - zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, -- znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) -+ znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns) - { - znode_t *zp; - zfs_dirlock_t *dl; -@@ -3373,7 +3372,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, - } - - if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, -- kcred->user_ns))) { -+ zfs_init_idmap))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3962,7 +3961,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, - * operates directly on inodes, so we need to check access rights. - */ - if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -- kcred->user_ns))) { -+ zfs_init_idmap))) { - ZFS_EXIT(zfsvfs); - return (error); - } -diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c -index 5e820587388..4a1c6525aca 100644 ---- a/module/os/linux/zfs/zfs_znode.c -+++ b/module/os/linux/zfs/zfs_znode.c -@@ -1947,7 +1947,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) - } - - VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, -- cr, NULL, &acl_ids, kcred->user_ns)); -+ cr, NULL, &acl_ids, zfs_init_idmap)); - zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, rootzp); - error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); -diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c -index e4f191ba051..1e1c35ed157 100644 ---- a/module/os/linux/zfs/zpl_ctldir.c -+++ b/module/os/linux/zfs/zpl_ctldir.c -@@ -101,7 +101,11 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) - */ - /* ARGSUSED */ - static int --#ifdef HAVE_USERNS_IOPS_GETATTR -+#ifdef HAVE_IDMAP_IOPS_GETATTR -+zpl_root_getattr_impl(struct mnt_idmap *user_ns, -+ const struct path *path, struct kstat *stat, u32 request_mask, -+ unsigned int query_flags) -+#elif defined(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) -@@ -112,8 +116,14 @@ zpl_root_getattr_impl(const struct path *path, struct kstat *stat, - { - struct inode *ip = path->dentry->d_inode; - --#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) -+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) -+#ifdef HAVE_GENERIC_FILLATTR_USERNS - generic_fillattr(user_ns, ip, stat); -+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP) -+ generic_fillattr(user_ns, ip, stat); -+#else -+ (void) user_ns; -+#endif - #else - generic_fillattr(ip, stat); - #endif -@@ -304,6 +314,10 @@ static int - zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip, - struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, - unsigned int flags) -+#elif defined(HAVE_IOPS_RENAME_IDMAP) -+zpl_snapdir_rename2(struct mnt_idmap *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) -@@ -325,7 +339,9 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, - return (error); - } - --#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) -+#if (!defined(HAVE_RENAME_WANTS_FLAGS) && \ -+ !defined(HAVE_IOPS_RENAME_USERNS) && \ -+ !defined(HAVE_IOPS_RENAME_IDMAP)) - static int - zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, - struct inode *tdip, struct dentry *tdentry) -@@ -352,6 +368,9 @@ static int - #ifdef HAVE_IOPS_MKDIR_USERNS - zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip, - struct dentry *dentry, umode_t mode) -+#elif defined(HAVE_IOPS_MKDIR_IDMAP) -+zpl_snapdir_mkdir(struct mnt_idmap *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 -@@ -363,10 +382,10 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); --#ifdef HAVE_IOPS_MKDIR_USERNS -+#if (defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP)) - zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); - #else -- zpl_vap_init(vap, dip, mode | S_IFDIR, cr, kcred->user_ns); -+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_idmap); - #endif - - error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); -@@ -388,7 +407,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) - */ - /* ARGSUSED */ - static int --#ifdef HAVE_USERNS_IOPS_GETATTR -+#ifdef HAVE_IDMAP_IOPS_GETATTR -+zpl_snapdir_getattr_impl(struct mnt_idmap *user_ns, -+ const struct path *path, struct kstat *stat, u32 request_mask, -+ unsigned int query_flags) -+#elif defined(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) -@@ -401,8 +424,14 @@ zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, - zfsvfs_t *zfsvfs = ITOZSB(ip); - - ZPL_ENTER(zfsvfs); --#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) -+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) -+#ifdef HAVE_GENERIC_FILLATTR_USERNS -+ generic_fillattr(user_ns, ip, stat); -+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP) - generic_fillattr(user_ns, ip, stat); -+#else -+ (void) user_ns; -+#endif - #else - generic_fillattr(ip, stat); - #endif -@@ -443,7 +472,9 @@ const struct file_operations zpl_fops_snapdir = { - const struct inode_operations zpl_ops_snapdir = { - .lookup = zpl_snapdir_lookup, - .getattr = zpl_snapdir_getattr, --#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) -+#if (defined(HAVE_RENAME_WANTS_FLAGS) || \ -+ defined(HAVE_IOPS_RENAME_USERNS) || \ -+ defined(HAVE_IOPS_RENAME_IDMAP)) - .rename = zpl_snapdir_rename2, - #else - .rename = zpl_snapdir_rename, -@@ -534,6 +565,10 @@ static int - zpl_shares_getattr_impl(struct user_namespace *user_ns, - const struct path *path, struct kstat *stat, u32 request_mask, - unsigned int query_flags) -+#elif defined(HAVE_IDMAP_IOPS_GETATTR) -+zpl_shares_getattr_impl(struct mnt_idmap *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) -@@ -547,8 +582,14 @@ 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) -+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) -+#ifdef HAVE_GENERIC_FILLATTR_USERNS -+ generic_fillattr(user_ns, path->dentry->d_inode, stat); -+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP) - generic_fillattr(user_ns, path->dentry->d_inode, stat); -+#else -+ (void) user_ns; -+#endif - #else - generic_fillattr(path->dentry->d_inode, stat); - #endif -@@ -560,7 +601,7 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, - - error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); - if (error == 0) { --#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) -+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) - error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat); - #else - error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat); -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index 4ad30efd3ec..f124599393f 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -924,7 +924,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva) - !capable(CAP_LINUX_IMMUTABLE)) - return (-EPERM); - -- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) - return (-EACCES); - - xva_init(xva); -@@ -971,7 +971,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1019,7 +1019,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1054,7 +1054,7 @@ __zpl_ioctl_setdosflags(struct inode *ip, uint64_t ioctl_flags, xvattr_t *xva) - !capable(CAP_LINUX_IMMUTABLE)) - return (-EPERM); - -- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) - return (-EACCES); - - xva_init(xva); -@@ -1107,7 +1107,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap); - spl_fstrans_unmark(cookie); - crfree(cr); - -diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c -index ea659d9618a..01bcfc19f2b 100644 ---- a/module/os/linux/zfs/zpl_inode.c -+++ b/module/os/linux/zfs/zpl_inode.c -@@ -112,12 +112,12 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) - - void - zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, -- zuserns_t *mnt_ns) -+ zidmap_t *mnt_ns) - { - vap->va_mask = ATTR_MODE; - vap->va_mode = mode; - -- vap->va_uid = zfs_vfsuid_to_uid((struct user_namespace *)mnt_ns, -+ vap->va_uid = zfs_vfsuid_to_uid(mnt_ns, - zfs_i_user_ns(dir), crgetuid(cr)); - - if (dir && dir->i_mode & S_ISGID) { -@@ -125,7 +125,7 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, - if (S_ISDIR(mode)) - vap->va_mode |= S_ISGID; - } else { -- vap->va_gid = zfs_vfsgid_to_gid((struct user_namespace *)mnt_ns, -+ vap->va_gid = zfs_vfsgid_to_gid(mnt_ns, - zfs_i_user_ns(dir), crgetgid(cr)); - } - } -@@ -134,6 +134,9 @@ 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) -+#elif defined(HAVE_IOPS_CREATE_IDMAP) -+zpl_create(struct mnt_idmap *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 -@@ -143,8 +146,8 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) - vattr_t *vap; - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_IOPS_CREATE_USERNS -- zuserns_t *user_ns = kcred->user_ns; -+#if !(defined(HAVE_IOPS_CREATE_USERNS) || defined(HAVE_IOPS_CREATE_IDMAP)) -+ zidmap_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -@@ -180,6 +183,9 @@ static int - #ifdef HAVE_IOPS_MKNOD_USERNS - zpl_mknod(struct user_namespace *user_ns, struct inode *dir, - struct dentry *dentry, umode_t mode, -+#elif defined(HAVE_IOPS_MKNOD_IDMAP) -+zpl_mknod(struct mnt_idmap *user_ns, struct inode *dir, -+ struct dentry *dentry, umode_t mode, - #else - zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - #endif -@@ -190,8 +196,8 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - vattr_t *vap; - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_IOPS_MKNOD_USERNS -- zuserns_t *user_ns = kcred->user_ns; -+#if !(defined(HAVE_IOPS_MKNOD_USERNS) || defined(HAVE_IOPS_MKNOD_IDMAP)) -+ zidmap_t *user_ns = kcred->user_ns; - #endif - - /* -@@ -233,7 +239,10 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - - #ifdef HAVE_TMPFILE - static int --#ifndef HAVE_TMPFILE_DENTRY -+#ifdef HAVE_TMPFILE_IDMAP -+zpl_tmpfile(struct mnt_idmap *userns, struct inode *dir, -+ struct file *file, umode_t mode) -+#elif !defined(HAVE_TMPFILE_DENTRY) - zpl_tmpfile(struct user_namespace *userns, struct inode *dir, - struct file *file, umode_t mode) - #else -@@ -250,8 +259,8 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) - vattr_t *vap; - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_TMPFILE_USERNS -- zuserns_t *userns = kcred->user_ns; -+#if !(defined(HAVE_TMPFILE_USERNS) || defined(HAVE_TMPFILE_IDMAP)) -+ zidmap_t *userns = kcred->user_ns; - #endif - - crhold(cr); -@@ -329,6 +338,9 @@ static int - #ifdef HAVE_IOPS_MKDIR_USERNS - zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, - struct dentry *dentry, umode_t mode) -+#elif defined(HAVE_IOPS_MKDIR_IDMAP) -+zpl_mkdir(struct mnt_idmap *user_ns, struct inode *dir, -+ struct dentry *dentry, umode_t mode) - #else - zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - #endif -@@ -338,8 +350,8 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - znode_t *zp; - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_IOPS_MKDIR_USERNS -- zuserns_t *user_ns = kcred->user_ns; -+#if !(defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP)) -+ zidmap_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -@@ -402,6 +414,10 @@ static int - zpl_getattr_impl(struct user_namespace *user_ns, - const struct path *path, struct kstat *stat, u32 request_mask, - unsigned int query_flags) -+#elif defined(HAVE_IDMAP_IOPS_GETATTR) -+zpl_getattr_impl(struct mnt_idmap *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) -@@ -418,7 +434,7 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, - * XXX query_flags currently ignored. - */ - --#ifdef HAVE_USERNS_IOPS_GETATTR -+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) - error = -zfs_getattr_fast(user_ns, ip, stat); - #else - error = -zfs_getattr_fast(kcred->user_ns, ip, stat); -@@ -457,9 +473,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 -+#ifdef HAVE_USERNS_IOPS_SETATTR - zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, - struct iattr *ia) -+#elif defined(HAVE_IDMAP_IOPS_SETATTR) -+zpl_setattr(struct mnt_idmap *user_ns, struct dentry *dentry, -+ struct iattr *ia) - #else - zpl_setattr(struct dentry *dentry, struct iattr *ia) - #endif -@@ -472,8 +491,10 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - - #ifdef HAVE_SETATTR_PREPARE_USERNS - error = zpl_setattr_prepare(user_ns, dentry, ia); -+#elif defined(HAVE_SETATTR_PREPARE_IDMAP) -+ error = zpl_setattr_prepare(user_ns, dentry, ia); - #else -- error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); -+ error = zpl_setattr_prepare(zfs_init_idmap, dentry, ia); - #endif - if (error) - return (error); -@@ -505,10 +526,12 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip); - - cookie = spl_fstrans_mark(); --#ifdef HAVE_SETATTR_PREPARE_USERNS -+#ifdef HAVE_USERNS_IOPS_SETATTR -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); -+#elif defined(HAVE_IDMAP_IOPS_SETATTR) - error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); - #else -- error = -zfs_setattr(ITOZ(ip), vap, 0, cr, kcred->user_ns); -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_idmap); - #endif - if (!error && (ia->ia_valid & ATTR_MODE)) - error = zpl_chmod_acl(ip); -@@ -526,6 +549,10 @@ static int - zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, - struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, - unsigned int flags) -+#elif defined(HAVE_IOPS_RENAME_IDMAP) -+zpl_rename2(struct mnt_idmap *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) -@@ -534,8 +561,8 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - cred_t *cr = CRED(); - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_IOPS_RENAME_USERNS -- zuserns_t *user_ns = kcred->user_ns; -+#if !(defined(HAVE_IOPS_RENAME_USERNS) || defined(HAVE_IOPS_RENAME_IDMAP)) -+ zidmap_t *user_ns = kcred->user_ns; - #endif - - /* We don't have renameat2(2) support */ -@@ -553,7 +580,10 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - return (error); - } - --#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) -+#if !defined(HAVE_IOPS_RENAME_USERNS) && \ -+ !defined(HAVE_RENAME_WANTS_FLAGS) && \ -+ !defined(HAVE_RENAME2) && \ -+ !defined(HAVE_IOPS_RENAME_IDMAP) - static int - zpl_rename(struct inode *sdip, struct dentry *sdentry, - struct inode *tdip, struct dentry *tdentry) -@@ -566,6 +596,9 @@ static int - #ifdef HAVE_IOPS_SYMLINK_USERNS - zpl_symlink(struct user_namespace *user_ns, struct inode *dir, - struct dentry *dentry, const char *name) -+#elif defined(HAVE_IOPS_SYMLINK_IDMAP) -+zpl_symlink(struct mnt_idmap *user_ns, struct inode *dir, -+ struct dentry *dentry, const char *name) - #else - zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) - #endif -@@ -575,8 +608,8 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) - znode_t *zp; - int error; - fstrans_cookie_t cookie; --#ifndef HAVE_IOPS_SYMLINK_USERNS -- zuserns_t *user_ns = kcred->user_ns; -+#if !(defined(HAVE_IOPS_SYMLINK_USERNS) || defined(HAVE_IOPS_SYMLINK_IDMAP)) -+ zidmap_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -@@ -787,6 +820,8 @@ const struct inode_operations zpl_dir_inode_operations = { - .mknod = zpl_mknod, - #if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) - .rename = zpl_rename2, -+#elif defined(HAVE_IOPS_RENAME_IDMAP) -+ .rename = zpl_rename2, - #else - .rename = zpl_rename, - #endif -diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c -index b377651bad4..bffc86b3006 100644 ---- a/module/os/linux/zfs/zpl_xattr.c -+++ b/module/os/linux/zfs/zpl_xattr.c -@@ -496,7 +496,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, - vap->va_gid = crgetgid(cr); - - error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, -- cr, 0, NULL, kcred->user_ns); -+ cr, ATTR_NOACLCHECK, NULL, zfs_init_idmap); - if (error) - goto out; - } -@@ -725,7 +725,7 @@ __zpl_xattr_user_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get); - - static int --__zpl_xattr_user_set(struct user_namespace *user_ns, -+__zpl_xattr_user_set(zidmap_t *user_ns, - struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -@@ -796,7 +796,7 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get); - - static int --__zpl_xattr_trusted_set(struct user_namespace *user_ns, -+__zpl_xattr_trusted_set(zidmap_t *user_ns, - struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -@@ -867,7 +867,7 @@ __zpl_xattr_security_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get); - - static int --__zpl_xattr_security_set(struct user_namespace *user_ns, -+__zpl_xattr_security_set(zidmap_t *user_ns, - struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -@@ -1010,6 +1010,9 @@ int - #ifdef HAVE_SET_ACL_USERNS - zpl_set_acl(struct user_namespace *userns, struct inode *ip, - struct posix_acl *acl, int type) -+#elif defined(HAVE_SET_ACL_IDMAP_DENTRY) -+zpl_set_acl(struct mnt_idmap *userns, struct dentry *dentry, -+ struct posix_acl *acl, int type) - #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2) - zpl_set_acl(struct user_namespace *userns, struct dentry *dentry, - struct posix_acl *acl, int type) -@@ -1019,6 +1022,8 @@ zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type) - { - #ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2 - return (zpl_set_acl_impl(d_inode(dentry), acl, type)); -+#elif defined(HAVE_SET_ACL_IDMAP_DENTRY) -+ return (zpl_set_acl_impl(d_inode(dentry), acl, type)); - #else - return (zpl_set_acl_impl(ip, acl, type)); - #endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */ -@@ -1262,7 +1267,7 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default); - - static int --__zpl_xattr_acl_set_access(struct user_namespace *mnt_ns, -+__zpl_xattr_acl_set_access(zidmap_t *mnt_ns, - struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -@@ -1277,12 +1282,12 @@ __zpl_xattr_acl_set_access(struct user_namespace *mnt_ns, - if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) - return (-EOPNOTSUPP); - --#if defined(HAVE_XATTR_SET_USERNS) -+#if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP) - if (!zpl_inode_owner_or_capable(mnt_ns, ip)) - return (-EPERM); - #else - (void) mnt_ns; -- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) - return (-EPERM); - #endif - -@@ -1308,7 +1313,7 @@ __zpl_xattr_acl_set_access(struct user_namespace *mnt_ns, - ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access); - - static int --__zpl_xattr_acl_set_default(struct user_namespace *mnt_ns, -+__zpl_xattr_acl_set_default(zidmap_t *mnt_ns, - struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -@@ -1323,12 +1328,12 @@ __zpl_xattr_acl_set_default(struct user_namespace *mnt_ns, - if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) - return (-EOPNOTSUPP); - --#if defined(HAVE_XATTR_SET_USERNS) -+#if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP) - if (!zpl_inode_owner_or_capable(mnt_ns, ip)) - return (-EPERM); - #else - (void) mnt_ns; -- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) - return (-EPERM); - #endif - -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index 755bbc6cd98..db5aefbe104 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -386,7 +386,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - - #if defined(__linux__) - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, &vsec, kcred->user_ns); -+ 0, 0, &zp, kcred, vflg, &vsec, zfs_init_idmap); - #else - error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, &vsec, NULL); -@@ -421,7 +421,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - } - #if defined(__linux__) - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, &vsec, kcred->user_ns); -+ &zp, kcred, vflg, &vsec, zfs_init_idmap); - #else - error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, &vsec, NULL); -@@ -536,7 +536,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - - #if defined(__linux__) - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, NULL, kcred->user_ns); -+ 0, 0, &zp, kcred, vflg, NULL, zfs_init_idmap); - #else - error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, NULL, NULL); -@@ -558,7 +558,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - - #if defined(__linux__) - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, NULL, kcred->user_ns); -+ &zp, kcred, vflg, NULL, zfs_init_idmap); - #else - error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, NULL, NULL); -@@ -573,7 +573,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - link = name + strlen(name) + 1; - #if defined(__linux__) - error = zfs_symlink(dzp, name, &xva.xva_vattr, -- link, &zp, kcred, vflg, kcred->user_ns); -+ link, &zp, kcred, vflg, zfs_init_idmap); - #else - error = zfs_symlink(dzp, name, &xva.xva_vattr, - link, &zp, kcred, vflg, NULL); -@@ -691,7 +691,7 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - - #if defined(__linux__) - error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, -- kcred->user_ns); -+ zfs_init_idmap); - #else - error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, - NULL); -@@ -890,7 +890,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - - #if defined(__linux__) -- error = zfs_setattr(zp, vap, 0, kcred, kcred->user_ns); -+ error = zfs_setattr(zp, vap, 0, kcred, zfs_init_idmap); - #else - error = zfs_setattr(zp, vap, 0, kcred, NULL); - #endif -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index 2b6d35282a0..7590a985266 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -167,14 +167,14 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - if (flag & V_ACE_MASK) - #if defined(__linux__) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, -- kcred->user_ns); -+ zfs_init_idmap); - #else - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, - NULL); - #endif - else - #if defined(__linux__) -- error = zfs_zaccess_rwx(zp, mode, flag, cr, kcred->user_ns); -+ error = zfs_zaccess_rwx(zp, mode, flag, cr, zfs_init_idmap); - #else - error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL); - #endif diff --git a/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-writepage_t-typedef-change.patch b/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-writepage_t-typedef-change.patch deleted file mode 100644 index 948dcfdf5a97504727d60267e5a2ac8b988911db..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-6.3-compat-writepage_t-typedef-change.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 87b91626330696dc57d3f1de6d6659b1b71fed1b Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 13:04:16 -0500 -Subject: [PATCH 1/2] Backport "Linux 6.3 compat: writepage_t first arg struct - folio*" - ---- - config/kernel-writepage_t.m4 | 26 ++++++++++++++++++++++++++ - config/kernel.m4 | 2 ++ - module/os/linux/zfs/zpl_file.c | 17 +++++++++++++++++ - 3 files changed, 45 insertions(+) - create mode 100644 config/kernel-writepage_t.m4 - -diff --git a/config/kernel-writepage_t.m4 b/config/kernel-writepage_t.m4 -new file mode 100644 -index 00000000000..3a0cffd9857 ---- /dev/null -+++ b/config/kernel-writepage_t.m4 -@@ -0,0 +1,26 @@ -+AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [ -+ dnl # -+ dnl # 6.3 API change -+ dnl # The writepage_t function type now has its first argument as -+ dnl # struct folio* instead of struct page* -+ dnl # -+ ZFS_LINUX_TEST_SRC([writepage_t_folio], [ -+ #include <linux/writeback.h> -+ int putpage(struct folio *folio, -+ struct writeback_control *wbc, void *data) -+ { return 0; } -+ writepage_t func = putpage; -+ ],[]) -+]) -+ -+AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [ -+ AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*]) -+ ZFS_LINUX_TEST_RESULT([writepage_t_folio], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1, -+ [int (*writepage_t)() takes struct folio*]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) -+]) -+ -diff --git a/config/kernel.m4 b/config/kernel.m4 -index b376a151694..b64cca7a1f9 100644 ---- a/config/kernel.m4 -+++ b/config/kernel.m4 -@@ -148,6 +148,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC - ZFS_AC_KERNEL_SRC_IDMAP_MNT_API - ZFS_AC_KERNEL_SRC_IATTR_VFSID -+ ZFS_AC_KERNEL_SRC_WRITEPAGE_T - - AC_MSG_CHECKING([for available kernel interfaces]) - ZFS_LINUX_TEST_COMPILE_ALL([kabi]) -@@ -269,6 +270,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC - ZFS_AC_KERNEL_IDMAP_MNT_API - ZFS_AC_KERNEL_IATTR_VFSID -+ ZFS_AC_KERNEL_WRITEPAGE_T - ]) - - dnl # -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index f124599393f..2bdb53579ae 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -701,6 +701,15 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data) - return (0); - } - -+#ifdef HAVE_WRITEPAGE_T_FOLIO -+static int -+zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data) -+{ -+ (void) zpl_putpage(&pp->page, wbc, data); -+ return (0); -+} -+#endif -+ - static int - zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - { -@@ -723,7 +732,11 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - * and then we commit it all in one go. - */ - wbc->sync_mode = WB_SYNC_NONE; -+#ifdef HAVE_WRITEPAGE_T_FOLIO -+ result = write_cache_pages(mapping, wbc, zpl_putfolio, mapping); -+#else - result = write_cache_pages(mapping, wbc, zpl_putpage, mapping); -+#endif - if (sync_mode != wbc->sync_mode) { - ZPL_ENTER(zfsvfs); - ZPL_VERIFY_ZP(zp); -@@ -739,7 +752,11 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - * details). That being said, this is a no-op in most cases. - */ - wbc->sync_mode = sync_mode; -+#ifdef HAVE_WRITEPAGE_T_FOLIO -+ result = write_cache_pages(mapping, wbc, zpl_putfolio, mapping); -+#else - result = write_cache_pages(mapping, wbc, zpl_putpage, mapping); -+#endif - } - return (result); - } - -From 04e8c37ff2490d1933fcb7f5c42da3e11b50bf7c Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 13:11:02 -0500 -Subject: [PATCH 2/2] Backport "Add zpl_write_cache_pages()" - ---- - module/os/linux/zfs/zpl_file.c | 26 ++++++++++++++++---------- - 1 file changed, 16 insertions(+), 10 deletions(-) - -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index 2bdb53579ae..30013c38d8e 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -710,6 +710,20 @@ zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data) - } - #endif - -+static inline int -+zpl_write_cache_pages(struct address_space *mapping, -+ struct writeback_control *wbc, void *data) -+{ -+ int result; -+ -+#ifdef HAVE_WRITEPAGE_T_FOLIO -+ result = write_cache_pages(mapping, wbc, zpl_putfolio, data); -+#else -+ result = write_cache_pages(mapping, wbc, zpl_putpage, data); -+#endif -+ return (result); -+} -+ - static int - zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - { -@@ -732,11 +746,7 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - * and then we commit it all in one go. - */ - wbc->sync_mode = WB_SYNC_NONE; --#ifdef HAVE_WRITEPAGE_T_FOLIO -- result = write_cache_pages(mapping, wbc, zpl_putfolio, mapping); --#else -- result = write_cache_pages(mapping, wbc, zpl_putpage, mapping); --#endif -+ result = zpl_write_cache_pages(mapping, wbc, mapping); - if (sync_mode != wbc->sync_mode) { - ZPL_ENTER(zfsvfs); - ZPL_VERIFY_ZP(zp); -@@ -752,11 +762,7 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) - * details). That being said, this is a no-op in most cases. - */ - wbc->sync_mode = sync_mode; --#ifdef HAVE_WRITEPAGE_T_FOLIO -- result = write_cache_pages(mapping, wbc, zpl_putfolio, mapping); --#else -- result = write_cache_pages(mapping, wbc, zpl_putpage, mapping); --#endif -+ result = zpl_write_cache_pages(mapping, wbc, mapping); - } - return (result); - } diff --git a/sys-fs/zfs-kmod/files/2.1.11-expose-additional-attributes.patch b/sys-fs/zfs-kmod/files/2.1.11-expose-additional-attributes.patch deleted file mode 100644 index 79838bcdc1f53013bbc9430cb75df01206190158..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-expose-additional-attributes.patch +++ /dev/null @@ -1,1272 +0,0 @@ -From 2f38cb2c0640a7d53062b57aab3bf8620fc49237 Mon Sep 17 00:00:00 2001 -From: Umer Saleem <usaleem@ixsystems.com> -Date: Fri, 18 Feb 2022 21:21:20 +0500 -Subject: [PATCH] Expose additional file level attributes - -ZFS allows to update and retrieve additional file level attributes for -FreeBSD. This commit allows additional file level attributes to be -updated and retrieved for Linux. These include the flags stored in the -upper half of z_pflags only. - -Two new IOCTLs have been added for this purpose. ZFS_IOC_GETDOSFLAGS -can be used to retieve the attributes, while ZFS_IOC_SETDOSFLAGS can -be used to update the attributes. - -Attributes that are allowed to be updated include ZFS_IMMUTABLE, -ZFS_APPENDONLY, ZFS_NOUNLINK, ZFS_ARCHIVE, ZFS_NODUMP, ZFS_SYSTEM, -ZFS_HIDDEN, ZFS_READONLY, ZFS_REPARSE, ZFS_OFFLINE and ZFS_SPARSE. -Flags can be or'd together while calling ZFS_IOC_SETDOSFLAGS. - -Signed-off-by: Umer Saleem <usaleem@ixsystems.com> ---- - configure.ac | 3 + - include/sys/fs/zfs.h | 35 +++ - include/sys/zfs_znode.h | 2 +- - module/os/linux/zfs/zpl_file.c | 125 +++++++++-- - tests/runfiles/common.run | 2 +- - tests/runfiles/freebsd.run | 4 - - tests/runfiles/linux.run | 4 + - tests/zfs-tests/cmd/Makefile.am | 2 + - .../cmd/read_dos_attributes/.gitignore | 1 + - .../cmd/read_dos_attributes/Makefile.am | 6 + - .../read_dos_attributes/read_dos_attributes.c | 167 +++++++++++++++ - .../cmd/write_dos_attributes/.gitignore | 1 + - .../cmd/write_dos_attributes/Makefile.am | 6 + - .../write_dos_attributes.c | 201 ++++++++++++++++++ - tests/zfs-tests/include/commands.cfg | 2 + - tests/zfs-tests/tests/functional/Makefile.am | 1 + - .../tests/functional/acl/off/Makefile.am | 2 - - .../tests/functional/acl/off/dosmode.ksh | 97 +++++---- - .../acl/off/dosmode_readonly_write.c | 11 + - .../functional/dos_attributes/Makefile.am | 8 + - .../functional/dos_attributes/cleanup.ksh | 34 +++ - .../dos_attributes/read_dos_attrs_001.ksh | 60 ++++++ - .../tests/functional/dos_attributes/setup.ksh | 35 +++ - .../dos_attributes/write_dos_attrs_001.ksh | 61 ++++++ - 24 files changed, 806 insertions(+), 64 deletions(-) - create mode 100644 tests/zfs-tests/cmd/read_dos_attributes/.gitignore - create mode 100644 tests/zfs-tests/cmd/read_dos_attributes/Makefile.am - create mode 100644 tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c - create mode 100644 tests/zfs-tests/cmd/write_dos_attributes/.gitignore - create mode 100644 tests/zfs-tests/cmd/write_dos_attributes/Makefile.am - create mode 100644 tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c - create mode 100644 tests/zfs-tests/tests/functional/dos_attributes/Makefile.am - create mode 100755 tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh - create mode 100755 tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh - create mode 100755 tests/zfs-tests/tests/functional/dos_attributes/setup.ksh - create mode 100755 tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh - -diff --git a/configure.ac b/configure.ac -index 7037c06b225..990958bafa1 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -226,12 +226,14 @@ AC_CONFIG_FILES([ - tests/zfs-tests/cmd/randfree_file/Makefile - tests/zfs-tests/cmd/randwritecomp/Makefile - tests/zfs-tests/cmd/readmmap/Makefile -+ tests/zfs-tests/cmd/read_dos_attributes/Makefile - tests/zfs-tests/cmd/rename_dir/Makefile - tests/zfs-tests/cmd/rm_lnkcnt_zero_file/Makefile - tests/zfs-tests/cmd/send_doall/Makefile - tests/zfs-tests/cmd/stride_dd/Makefile - tests/zfs-tests/cmd/threadsappend/Makefile - tests/zfs-tests/cmd/user_ns_exec/Makefile -+ tests/zfs-tests/cmd/write_dos_attributes/Makefile - tests/zfs-tests/cmd/xattrtest/Makefile - tests/zfs-tests/include/Makefile - tests/zfs-tests/tests/Makefile -@@ -333,6 +335,7 @@ AC_CONFIG_FILES([ - tests/zfs-tests/tests/functional/deadman/Makefile - tests/zfs-tests/tests/functional/delegate/Makefile - tests/zfs-tests/tests/functional/devices/Makefile -+ tests/zfs-tests/tests/functional/dos_attributes/Makefile - tests/zfs-tests/tests/functional/events/Makefile - tests/zfs-tests/tests/functional/exec/Makefile - tests/zfs-tests/tests/functional/fallocate/Makefile -diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h -index 6e85c4b7b39..ab29b4e2ef3 100644 ---- a/include/sys/fs/zfs.h -+++ b/include/sys/fs/zfs.h -@@ -1459,6 +1459,41 @@ typedef enum zfs_ioc { - */ - #define BLKZNAME _IOR(0x12, 125, char[ZFS_MAX_DATASET_NAME_LEN]) - -+#ifdef __linux__ -+ -+/* -+ * IOCTLs to update and retrieve additional file level attributes on -+ * Linux. -+ */ -+#define ZFS_IOC_GETDOSFLAGS _IOR(0x83, 1, uint64_t) -+#define ZFS_IOC_SETDOSFLAGS _IOW(0x83, 2, uint64_t) -+ -+/* -+ * Additional file level attributes, that are stored -+ * in the upper half of z_pflags -+ */ -+#define ZFS_READONLY 0x0000000100000000ull -+#define ZFS_HIDDEN 0x0000000200000000ull -+#define ZFS_SYSTEM 0x0000000400000000ull -+#define ZFS_ARCHIVE 0x0000000800000000ull -+#define ZFS_IMMUTABLE 0x0000001000000000ull -+#define ZFS_NOUNLINK 0x0000002000000000ull -+#define ZFS_APPENDONLY 0x0000004000000000ull -+#define ZFS_NODUMP 0x0000008000000000ull -+#define ZFS_OPAQUE 0x0000010000000000ull -+#define ZFS_AV_QUARANTINED 0x0000020000000000ull -+#define ZFS_AV_MODIFIED 0x0000040000000000ull -+#define ZFS_REPARSE 0x0000080000000000ull -+#define ZFS_OFFLINE 0x0000100000000000ull -+#define ZFS_SPARSE 0x0000200000000000ull -+ -+#define ZFS_DOS_FL_USER_VISIBLE (ZFS_IMMUTABLE | ZFS_APPENDONLY | \ -+ ZFS_NOUNLINK | ZFS_ARCHIVE | ZFS_NODUMP | ZFS_SYSTEM | \ -+ ZFS_HIDDEN | ZFS_READONLY | ZFS_REPARSE | ZFS_OFFLINE | \ -+ ZFS_SPARSE) -+ -+#endif -+ - /* - * ZFS-specific error codes used for returning descriptive errors - * to the userland through zfs ioctls. -diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h -index e20c18cc2b6..127fd8736ff 100644 ---- a/include/sys/zfs_znode.h -+++ b/include/sys/zfs_znode.h -@@ -37,7 +37,7 @@ extern "C" { - - /* - * Additional file level attributes, that are stored -- * in the upper half of zp_flags -+ * in the upper half of z_pflags - */ - #define ZFS_READONLY 0x0000000100000000ull - #define ZFS_HIDDEN 0x0000000200000000ull -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index 982b424197e..f78e50262af 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -905,21 +905,24 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva) - xva_init(xva); - xoap = xva_getxoptattr(xva); - -- XVA_SET_REQ(xva, XAT_IMMUTABLE); -- if (ioctl_flags & FS_IMMUTABLE_FL) -- xoap->xoa_immutable = B_TRUE; -- -- XVA_SET_REQ(xva, XAT_APPENDONLY); -- if (ioctl_flags & FS_APPEND_FL) -- xoap->xoa_appendonly = B_TRUE; -- -- XVA_SET_REQ(xva, XAT_NODUMP); -- if (ioctl_flags & FS_NODUMP_FL) -- xoap->xoa_nodump = B_TRUE; -- -- XVA_SET_REQ(xva, XAT_PROJINHERIT); -- if (ioctl_flags & ZFS_PROJINHERIT_FL) -- xoap->xoa_projinherit = B_TRUE; -+#define FLAG_CHANGE(iflag, zflag, xflag, xfield) do { \ -+ if (((ioctl_flags & (iflag)) && !(zfs_flags & (zflag))) || \ -+ ((zfs_flags & (zflag)) && !(ioctl_flags & (iflag)))) { \ -+ XVA_SET_REQ(xva, (xflag)); \ -+ (xfield) = ((ioctl_flags & (iflag)) != 0); \ -+ } \ -+} while (0) -+ -+ FLAG_CHANGE(FS_IMMUTABLE_FL, ZFS_IMMUTABLE, XAT_IMMUTABLE, -+ xoap->xoa_immutable); -+ FLAG_CHANGE(FS_APPEND_FL, ZFS_APPENDONLY, XAT_APPENDONLY, -+ xoap->xoa_appendonly); -+ FLAG_CHANGE(FS_NODUMP_FL, ZFS_NODUMP, XAT_NODUMP, -+ xoap->xoa_nodump); -+ FLAG_CHANGE(ZFS_PROJINHERIT_FL, ZFS_PROJINHERIT, XAT_PROJINHERIT, -+ xoap->xoa_projinherit); -+ -+#undef FLAG_CHANGE - - return (0); - } -@@ -998,6 +1001,94 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) - return (err); - } - -+/* -+ * Expose Additional File Level Attributes of ZFS. -+ */ -+static int -+zpl_ioctl_getdosflags(struct file *filp, void __user *arg) -+{ -+ struct inode *ip = file_inode(filp); -+ uint64_t dosflags = ITOZ(ip)->z_pflags; -+ dosflags &= ZFS_DOS_FL_USER_VISIBLE; -+ int err = copy_to_user(arg, &dosflags, sizeof (dosflags)); -+ -+ return (err); -+} -+ -+static int -+__zpl_ioctl_setdosflags(struct inode *ip, uint64_t ioctl_flags, xvattr_t *xva) -+{ -+ uint64_t zfs_flags = ITOZ(ip)->z_pflags; -+ xoptattr_t *xoap; -+ -+ if (ioctl_flags & (~ZFS_DOS_FL_USER_VISIBLE)) -+ return (-EOPNOTSUPP); -+ -+ if ((fchange(ioctl_flags, zfs_flags, ZFS_IMMUTABLE, ZFS_IMMUTABLE) || -+ fchange(ioctl_flags, zfs_flags, ZFS_APPENDONLY, ZFS_APPENDONLY)) && -+ !capable(CAP_LINUX_IMMUTABLE)) -+ return (-EPERM); -+ -+ if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) -+ return (-EACCES); -+ -+ xva_init(xva); -+ xoap = xva_getxoptattr(xva); -+ -+#define FLAG_CHANGE(iflag, xflag, xfield) do { \ -+ if (((ioctl_flags & (iflag)) && !(zfs_flags & (iflag))) || \ -+ ((zfs_flags & (iflag)) && !(ioctl_flags & (iflag)))) { \ -+ XVA_SET_REQ(xva, (xflag)); \ -+ (xfield) = ((ioctl_flags & (iflag)) != 0); \ -+ } \ -+} while (0) -+ -+ FLAG_CHANGE(ZFS_IMMUTABLE, XAT_IMMUTABLE, xoap->xoa_immutable); -+ FLAG_CHANGE(ZFS_APPENDONLY, XAT_APPENDONLY, xoap->xoa_appendonly); -+ FLAG_CHANGE(ZFS_NODUMP, XAT_NODUMP, xoap->xoa_nodump); -+ FLAG_CHANGE(ZFS_READONLY, XAT_READONLY, xoap->xoa_readonly); -+ FLAG_CHANGE(ZFS_HIDDEN, XAT_HIDDEN, xoap->xoa_hidden); -+ FLAG_CHANGE(ZFS_SYSTEM, XAT_SYSTEM, xoap->xoa_system); -+ FLAG_CHANGE(ZFS_ARCHIVE, XAT_ARCHIVE, xoap->xoa_archive); -+ FLAG_CHANGE(ZFS_NOUNLINK, XAT_NOUNLINK, xoap->xoa_nounlink); -+ FLAG_CHANGE(ZFS_REPARSE, XAT_REPARSE, xoap->xoa_reparse); -+ FLAG_CHANGE(ZFS_OFFLINE, XAT_OFFLINE, xoap->xoa_offline); -+ FLAG_CHANGE(ZFS_SPARSE, XAT_SPARSE, xoap->xoa_sparse); -+ -+#undef FLAG_CHANGE -+ -+ return (0); -+} -+ -+/* -+ * Set Additional File Level Attributes of ZFS. -+ */ -+static int -+zpl_ioctl_setdosflags(struct file *filp, void __user *arg) -+{ -+ struct inode *ip = file_inode(filp); -+ uint64_t dosflags; -+ cred_t *cr = CRED(); -+ xvattr_t xva; -+ int err; -+ fstrans_cookie_t cookie; -+ -+ if (copy_from_user(&dosflags, arg, sizeof (dosflags))) -+ return (-EFAULT); -+ -+ err = __zpl_ioctl_setdosflags(ip, dosflags, &xva); -+ if (err) -+ return (err); -+ -+ crhold(cr); -+ cookie = spl_fstrans_mark(); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr); -+ spl_fstrans_unmark(cookie); -+ crfree(cr); -+ -+ return (err); -+} -+ - static long - zpl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { -@@ -1012,6 +1103,10 @@ zpl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - return (zpl_ioctl_getxattr(filp, (void *)arg)); - case ZFS_IOC_FSSETXATTR: - return (zpl_ioctl_setxattr(filp, (void *)arg)); -+ case ZFS_IOC_GETDOSFLAGS: -+ return (zpl_ioctl_getdosflags(filp, (void *)arg)); -+ case ZFS_IOC_SETDOSFLAGS: -+ return (zpl_ioctl_setdosflags(filp, (void *)arg)); - default: - return (-ENOTTY); - } -diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run -index 9f11284ad62..eb0d451351f 100644 ---- a/tests/runfiles/common.run -+++ b/tests/runfiles/common.run -@@ -29,7 +29,7 @@ outputdir = /var/tmp/test_results - tags = ['functional'] - - [tests/functional/acl/off] --tests = ['posixmode'] -+tests = ['dosmode', 'posixmode'] - tags = ['functional', 'acl'] - - [tests/functional/alloc_class] -diff --git a/tests/runfiles/freebsd.run b/tests/runfiles/freebsd.run -index 153b204b493..c7ca1d769fc 100644 ---- a/tests/runfiles/freebsd.run -+++ b/tests/runfiles/freebsd.run -@@ -22,10 +22,6 @@ failsafe = callbacks/zfs_failsafe - outputdir = /var/tmp/test_results - tags = ['functional'] - --[tests/functional/acl/off:FreeBSD] --tests = ['dosmode'] --tags = ['functional', 'acl'] -- - [tests/functional/cli_root/zfs_jail:FreeBSD] - tests = ['zfs_jail_001_pos'] - tags = ['functional', 'cli_root', 'zfs_jail'] -diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run -index 7186d5d67ac..8412a7ea5a9 100644 ---- a/tests/runfiles/linux.run -+++ b/tests/runfiles/linux.run -@@ -149,6 +149,10 @@ tests = ['projectid_001_pos', 'projectid_002_pos', 'projectid_003_pos', - 'projecttree_001_pos', 'projecttree_002_pos', 'projecttree_003_neg'] - tags = ['functional', 'projectquota'] - -+[tests/functional/dos_attributes:Linux] -+tests = ['read_dos_attrs_001', 'write_dos_attrs_001'] -+tags = ['functional', 'dos_attributes'] -+ - [tests/functional/rsend:Linux] - tests = ['send_realloc_dnode_size', 'send_encrypted_files'] - tags = ['functional', 'rsend'] -diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am -index 2470397a90a..88d8c8cf08b 100644 ---- a/tests/zfs-tests/cmd/Makefile.am -+++ b/tests/zfs-tests/cmd/Makefile.am -@@ -34,6 +34,8 @@ if BUILD_LINUX - SUBDIRS += \ - getversion \ - randfree_file \ -+ read_dos_attributes \ - user_ns_exec \ -+ write_dos_attributes \ - xattrtest - endif -diff --git a/tests/zfs-tests/cmd/read_dos_attributes/.gitignore b/tests/zfs-tests/cmd/read_dos_attributes/.gitignore -new file mode 100644 -index 00000000000..52584e4a738 ---- /dev/null -+++ b/tests/zfs-tests/cmd/read_dos_attributes/.gitignore -@@ -0,0 +1 @@ -+/read_dos_attributes -diff --git a/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am b/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am -new file mode 100644 -index 00000000000..69412f05f65 ---- /dev/null -+++ b/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am -@@ -0,0 +1,6 @@ -+include $(top_srcdir)/config/Rules.am -+ -+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin -+ -+pkgexec_PROGRAMS = read_dos_attributes -+read_dos_attributes_SOURCES = read_dos_attributes.c -diff --git a/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c b/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c -new file mode 100644 -index 00000000000..ed0906c36a6 ---- /dev/null -+++ b/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c -@@ -0,0 +1,167 @@ -+/* -+ * This file and its contents are supplied under the terms of the -+ * Common Development and Distribution License ("CDDL"), version 1.0. -+ * You may only use this file in accordance with the terms of version -+ * 1.0 of the CDDL. -+ * -+ * A full copy of the text of the CDDL should have accompanied this -+ * source. A copy of the CDDL is also available via the Internet at -+ * http://www.illumos.org/license/CDDL. -+ */ -+ -+/* -+ * Copyright 2022 iXsystems, Inc. -+ */ -+ -+/* -+ * FreeBSD allows to update and retreive additional file level attributes. -+ * For Linux, two IOCTLs have been added to update and retrieve additional -+ * level attributes. -+ * -+ * This application reads additional file level attributes on a given -+ * file and prints FreeBSD keywords that map to respective attributes. -+ * -+ * Usage: 'read_dos_attributes filepath' -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdint.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <sys/ioctl.h> -+#include <err.h> -+#include <sys/fs/zfs.h> -+#include <string.h> -+ -+#define SU_ARCH_SHORT "arch" -+#define SU_ARCH_FULL "archived" -+#define SU_NODUMP "nodump" -+#define SU_APPEND_SHORT "sappnd" -+#define SU_APPEND_FULL "sappend" -+#define SU_IMMUTABLE "schg" -+#define SU_IMMUTABLE_SHORT "schange" -+#define SU_IMMUTABLE_FULL "simmutable" -+#define SU_UNLINK_SHORT "sunlnk" -+#define SU_UNLINK_FULL "sunlink" -+#define U_APPEND_SHORT "uappnd" -+#define U_APPEND_FULL "uappend" -+#define U_ARCH_SHORT "uarch" -+#define U_ARCH_FULL "uarchive" -+#define U_IMMUTABLE "uchg" -+#define U_IMMUTABLE_SHORT "uchange" -+#define U_IMMUTABLE_FULL "uimmutable" -+#define U_HIDDEN_SHORT "hidden" -+#define U_HIDDEN_FULL "uhidden" -+#define U_OFFLINE_SHORT "offline" -+#define U_OFFLINE_FULL "uoffline" -+#define U_RDONLY "rdonly" -+#define U_RDONLY_SHORT "urdonly" -+#define U_RDONLY_FULL "readonly" -+#define U_SPARSE_SHORT "sparse" -+#define U_SPARSE_FULL "usparse" -+#define U_SYSTEM_SHORT "system" -+#define U_SYSTEM_FULL "usystem" -+#define U_REPARSE_SHORT "reparse" -+#define U_REPARSE_FULL "ureparse" -+#define U_UNLINK_SHORT "uunlnk" -+#define U_UNLINK_FULL "uunlink" -+#define UNSET_NODUMP "dump" -+ -+#define NO_ATTRIBUTE "-" -+ -+#define SEPARATOR "," -+ -+#define BUFFER_SIZE 0x200 -+ -+void attribute_to_str(uint64_t attributes, char *buff); -+ -+void -+attribute_to_str(uint64_t attributes, char *buff) -+{ -+ if (attributes & ZFS_ARCHIVE) { -+ strcat(buff, U_ARCH_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_APPENDONLY) { -+ strcat(buff, U_APPEND_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_IMMUTABLE) { -+ strcat(buff, U_IMMUTABLE_FULL); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_NOUNLINK) { -+ strcat(buff, U_UNLINK_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_NODUMP) { -+ strcat(buff, SU_NODUMP); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_HIDDEN) { -+ strcat(buff, U_HIDDEN_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_OFFLINE) { -+ strcat(buff, U_OFFLINE_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_READONLY) { -+ strcat(buff, U_RDONLY); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_SPARSE) { -+ strcat(buff, U_SPARSE_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_SYSTEM) { -+ strcat(buff, U_SYSTEM_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (attributes & ZFS_REPARSE) { -+ strcat(buff, U_REPARSE_SHORT); -+ strcat(buff, SEPARATOR); -+ } -+ -+ if (buff[0] == '\0') -+ strcat(buff, NO_ATTRIBUTE); -+ else -+ buff[strlen(buff) - 1] = '\0'; -+} -+ -+int -+main(int argc, const char * const argv[]) -+{ -+ if (argc != 2) -+ errx(EXIT_FAILURE, "Usage: %s filepath", argv[0]); -+ -+ int fd = open(argv[1], O_RDWR | O_APPEND); -+ if (fd < 0) -+ err(EXIT_FAILURE, "Failed to open %s", argv[1]); -+ -+ uint64_t dosflags = 0; -+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1) -+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed"); -+ -+ (void) close(fd); -+ -+ char buffer[BUFFER_SIZE]; -+ memset(buffer, 0, BUFFER_SIZE); -+ -+ (void) attribute_to_str(dosflags, buffer); -+ -+ (void) printf("%s\n", buffer); -+ -+ return (EXIT_SUCCESS); -+} -diff --git a/tests/zfs-tests/cmd/write_dos_attributes/.gitignore b/tests/zfs-tests/cmd/write_dos_attributes/.gitignore -new file mode 100644 -index 00000000000..f3949ac8282 ---- /dev/null -+++ b/tests/zfs-tests/cmd/write_dos_attributes/.gitignore -@@ -0,0 +1 @@ -+/write_dos_attributes -diff --git a/tests/zfs-tests/cmd/write_dos_attributes/Makefile.am b/tests/zfs-tests/cmd/write_dos_attributes/Makefile.am -new file mode 100644 -index 00000000000..c297fd49e0e ---- /dev/null -+++ b/tests/zfs-tests/cmd/write_dos_attributes/Makefile.am -@@ -0,0 +1,6 @@ -+include $(top_srcdir)/config/Rules.am -+ -+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin -+ -+pkgexec_PROGRAMS = write_dos_attributes -+write_dos_attributes_SOURCES = write_dos_attributes.c -diff --git a/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c b/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c -new file mode 100644 -index 00000000000..c373d3b1531 ---- /dev/null -+++ b/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c -@@ -0,0 +1,201 @@ -+/* -+ * This file and its contents are supplied under the terms of the -+ * Common Development and Distribution License ("CDDL"), version 1.0. -+ * You may only use this file in accordance with the terms of version -+ * 1.0 of the CDDL. -+ * -+ * A full copy of the text of the CDDL should have accompanied this -+ * source. A copy of the CDDL is also available via the Internet at -+ * http://www.illumos.org/license/CDDL. -+ */ -+ -+/* -+ * Copyright 2022 iXsystems, Inc. -+ */ -+ -+/* -+ * FreeBSD allows to update and retreive additional file level attributes. -+ * For Linux, two IOCTLs have been added to update and retrieve additional -+ * level attributes. -+ * -+ * This application updates additional file level attributes on a given -+ * file. FreeBSD keywords can be used to specify the flag. -+ * -+ * Usage: 'write_dos_attributes flag filepath' -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdint.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <sys/ioctl.h> -+#include <err.h> -+#include <sys/fs/zfs.h> -+#include <string.h> -+#include <ctype.h> -+ -+#define SU_ARCH_SHORT "arch" -+#define SU_ARCH_FULL "archived" -+#define SU_NODUMP "nodump" -+#define SU_APPEND_SHORT "sappnd" -+#define SU_APPEND_FULL "sappend" -+#define SU_IMMUTABLE "schg" -+#define SU_IMMUTABLE_SHORT "schange" -+#define SU_IMMUTABLE_FULL "simmutable" -+#define SU_UNLINK_SHORT "sunlnk" -+#define SU_UNLINK_FULL "sunlink" -+#define U_APPEND_SHORT "uappnd" -+#define U_APPEND_FULL "uappend" -+#define U_ARCH_SHORT "uarch" -+#define U_ARCH_FULL "uarchive" -+#define U_IMMUTABLE "uchg" -+#define U_IMMUTABLE_SHORT "uchange" -+#define U_IMMUTABLE_FULL "uimmutable" -+#define U_HIDDEN_SHORT "hidden" -+#define U_HIDDEN_FULL "uhidden" -+#define U_OFFLINE_SHORT "offline" -+#define U_OFFLINE_FULL "uoffline" -+#define U_RDONLY "rdonly" -+#define U_RDONLY_SHORT "urdonly" -+#define U_RDONLY_FULL "readonly" -+#define U_SPARSE_SHORT "sparse" -+#define U_SPARSE_FULL "usparse" -+#define U_SYSTEM_SHORT "system" -+#define U_SYSTEM_FULL "usystem" -+#define U_REPARSE_SHORT "reparse" -+#define U_REPARSE_FULL "ureparse" -+#define U_UNLINK_SHORT "uunlnk" -+#define U_UNLINK_FULL "uunlink" -+#define UNSET_NODUMP "dump" -+ -+#define IS_NO(s) (s[0] == 'n' && s[1] == 'o') -+ -+uint64_t str_to_attribute(char *str); -+ -+uint64_t -+str_to_attribute(char *str) -+{ -+ if ((strcmp(str, SU_ARCH_SHORT) == 0) || -+ (strcmp(str, SU_ARCH_FULL) == 0) || -+ (strcmp(str, U_ARCH_SHORT) == 0) || -+ (strcmp(str, U_ARCH_FULL) == 0)) -+ return (ZFS_ARCHIVE); -+ -+ else if ((strcmp(str, SU_APPEND_SHORT) == 0) || -+ (strcmp(str, SU_APPEND_FULL) == 0) || -+ (strcmp(str, U_APPEND_SHORT) == 0) || -+ (strcmp(str, U_APPEND_FULL) == 0)) -+ return (ZFS_APPENDONLY); -+ -+ else if ((strcmp(str, SU_IMMUTABLE) == 0) || -+ (strcmp(str, SU_IMMUTABLE_SHORT) == 0) || -+ (strcmp(str, SU_IMMUTABLE_FULL) == 0)) -+ return (ZFS_IMMUTABLE); -+ -+ else if ((strcmp(str, SU_UNLINK_SHORT) == 0) || -+ (strcmp(str, SU_UNLINK_FULL) == 0) || -+ (strcmp(str, U_UNLINK_SHORT) == 0) || -+ (strcmp(str, SU_UNLINK_FULL) == 0)) -+ return (ZFS_NOUNLINK); -+ -+ else if ((strcmp(str, U_HIDDEN_SHORT) == 0) || -+ (strcmp(str, U_HIDDEN_FULL) == 0)) -+ return (ZFS_HIDDEN); -+ -+ else if ((strcmp(str, U_OFFLINE_SHORT) == 0) || -+ (strcmp(str, U_OFFLINE_FULL) == 0)) -+ return (ZFS_OFFLINE); -+ -+ else if ((strcmp(str, U_RDONLY) == 0) || -+ (strcmp(str, U_RDONLY_SHORT) == 0) || -+ (strcmp(str, U_RDONLY_FULL) == 0)) -+ return (ZFS_READONLY); -+ -+ else if ((strcmp(str, U_SPARSE_SHORT) == 0) || -+ (strcmp(str, U_SPARSE_FULL) == 0)) -+ return (ZFS_SPARSE); -+ -+ else if ((strcmp(str, U_SYSTEM_SHORT) == 0) || -+ (strcmp(str, U_SYSTEM_FULL) == 0)) -+ return (ZFS_SYSTEM); -+ -+ else if ((strcmp(str, U_REPARSE_SHORT) == 0) || -+ (strcmp(str, U_REPARSE_FULL) == 0)) -+ return (ZFS_REPARSE); -+ -+ return (-1); -+} -+ -+int -+main(int argc, const char * const argv[]) -+{ -+ if (argc != 3) -+ errx(EXIT_FAILURE, "Usage: %s flag filepath", argv[0]); -+ -+ uint8_t unset, unset_all; -+ uint64_t attribute, dosflags; -+ char *flag = strdup(argv[1]); -+ unset = unset_all = 0; -+ attribute = dosflags = 0; -+ -+ // convert the flag to lower case -+ for (int i = 0; i < strlen(argv[1]); ++i) -+ flag[i] = tolower((unsigned char) flag[i]); -+ -+ // check if flag starts with 'no' -+ if (IS_NO(flag)) { -+ if (strcmp(flag, SU_NODUMP) == 0) { -+ attribute = ZFS_NODUMP; -+ } else { -+ attribute = str_to_attribute(flag + 2); -+ unset = 1; -+ } -+ } -+ // check if '0' was passed -+ else if (strcmp(flag, "0") == 0) { -+ unset_all = 1; -+ } -+ // check if the flag is 'dump' -+ else if (strcmp(flag, UNSET_NODUMP) == 0) { -+ attribute = ZFS_NODUMP; -+ unset = 1; -+ } else { -+ attribute = str_to_attribute(flag); -+ } -+ -+ if (attribute == -1) -+ errx(EXIT_FAILURE, "Invalid Flag %s", argv[1]); -+ -+ int fd = open(argv[2], O_RDWR | O_APPEND); -+ if (fd < 0) -+ err(EXIT_FAILURE, "Failed to open %s", argv[2]); -+ -+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1) -+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed"); -+ -+ if (unset == 0 && attribute != 0) -+ attribute |= dosflags; -+ else if (unset == 1 && attribute != 0) -+ attribute = dosflags & (~attribute); -+ else if (unset_all == 1) -+ attribute = 0; -+ -+ // set the attribute/s -+ if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &attribute) == -1) -+ err(EXIT_FAILURE, "ZFS_IOC_SETDOSFLAGS failed"); -+ -+ // get the attributes to confirm -+ dosflags = -1; -+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1) -+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed"); -+ -+ (void) close(fd); -+ -+ if (dosflags != attribute) -+ errx(EXIT_FAILURE, "Could not set %s attribute", argv[1]); -+ -+ (void) printf("New Dos Flags: 0x%llx\n", (u_longlong_t)dosflags); -+ -+ return (EXIT_SUCCESS); -+} -diff --git a/tests/zfs-tests/include/commands.cfg b/tests/zfs-tests/include/commands.cfg -index fa3d12d669f..b247a67ff66 100644 ---- a/tests/zfs-tests/include/commands.cfg -+++ b/tests/zfs-tests/include/commands.cfg -@@ -215,10 +215,12 @@ export ZFSTEST_FILES='badsend - randfree_file - randwritecomp - readmmap -+ read_dos_attributes - rename_dir - rm_lnkcnt_zero_file - send_doall - threadsappend - user_ns_exec -+ write_dos_attributes - xattrtest - stride_dd' -diff --git a/tests/zfs-tests/tests/functional/Makefile.am b/tests/zfs-tests/tests/functional/Makefile.am -index e71172b8e86..9164650e341 100644 ---- a/tests/zfs-tests/tests/functional/Makefile.am -+++ b/tests/zfs-tests/tests/functional/Makefile.am -@@ -21,6 +21,7 @@ SUBDIRS = \ - deadman \ - delegate \ - devices \ -+ dos_attributes \ - events \ - exec \ - fallocate \ -diff --git a/tests/zfs-tests/tests/functional/acl/off/Makefile.am b/tests/zfs-tests/tests/functional/acl/off/Makefile.am -index 36aa13dd03f..ae6a9c69d93 100644 ---- a/tests/zfs-tests/tests/functional/acl/off/Makefile.am -+++ b/tests/zfs-tests/tests/functional/acl/off/Makefile.am -@@ -10,7 +10,5 @@ dist_pkgdata_SCRIPTS = \ - - pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl/off - --if BUILD_FREEBSD - pkgexec_PROGRAMS = dosmode_readonly_write - dosmode_readonly_write_SOURCES = dosmode_readonly_write.c --endif -diff --git a/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh b/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh -index e232dfd525c..585aa025390 100755 ---- a/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh -+++ b/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh -@@ -31,8 +31,6 @@ - # DESCRIPTION: - # Verify that DOS mode flags function correctly. - # --# These flags are not currently exposed on Linux, so the test is --# only useful on FreeBSD. - # - # STRATEGY: - # 1. ARCHIVE -@@ -56,7 +54,13 @@ function hasflag - typeset flag=$1 - typeset path=$2 - -- ls -lo $path | awk '{ gsub(",", "\n", $5); print $5 }' | grep -qxF $flag -+ if is_linux; then -+ read_dos_attributes $path | awk \ -+ '{ gsub(",", "\n", $1); print $1 }' | grep -qxF $flag -+ else -+ ls -lo $path | awk '{ gsub(",", "\n", $5); print $5 }' | \ -+ grep -qxF $flag -+ fi - } - - log_assert "Verify DOS mode flags function correctly" -@@ -67,6 +71,12 @@ testfile=$TESTDIR/testfile - owner=$ZFS_ACL_STAFF1 - other=$ZFS_ACL_STAFF2 - -+if is_linux; then -+ changeflags=write_dos_attributes -+else -+ changeflags=chflags -+fi -+ - # - # ARCHIVE - # -@@ -75,36 +85,40 @@ other=$ZFS_ACL_STAFF2 - # - log_must touch $testfile - log_must hasflag uarch $testfile --log_must chflags nouarch $testfile -+log_must $changeflags nouarch $testfile - log_must hasflag - $testfile - log_must touch $testfile --log_must hasflag uarch $testfile -+if ! is_linux; then -+ log_must hasflag uarch $testfile -+fi - log_must rm $testfile - log_must user_run $owner touch $testfile - log_must hasflag uarch $testfile --log_must user_run $owner chflags nouarch $testfile --log_mustnot user_run $other chflags uarch $testfile -+log_must user_run $owner $changeflags nouarch $testfile -+log_mustnot user_run $other $changeflags uarch $testfile - log_must hasflag - $testfile - log_must user_run $owner touch $testfile --log_mustnot user_run $other chflags nouarch $testfile --log_must hasflag uarch $testfile -+log_mustnot user_run $other $changeflags nouarch $testfile -+if ! is_linux; then -+ log_must hasflag uarch $testfile -+fi - log_must user_run $owner rm $testfile - - # - # HIDDEN - # - log_must touch $testfile --log_must chflags hidden $testfile -+log_must $changeflags hidden $testfile - log_must hasflag hidden $testfile --log_must chflags 0 $testfile -+log_must $changeflags 0 $testfile - log_must hasflag - $testfile - log_must rm $testfile - log_must user_run $owner touch $testfile --log_must user_run $owner chflags hidden $testfile --log_mustnot user_run $other chflags nohidden $testfile -+log_must user_run $owner $changeflags hidden $testfile -+log_mustnot user_run $other $changeflags nohidden $testfile - log_must hasflag hidden $testfile --log_must user_run $owner chflags 0 $testfile --log_mustnot user_run $other chflags hidden $testfile -+log_must user_run $owner $changeflags 0 $testfile -+log_mustnot user_run $other $changeflags hidden $testfile - log_must hasflag - $testfile - log_must user_run $owner rm $testfile - -@@ -113,17 +127,17 @@ log_must user_run $owner rm $testfile - # OFFLINE - # - log_must touch $testfile --log_must chflags offline $testfile -+log_must $changeflags offline $testfile - log_must hasflag offline $testfile --log_must chflags 0 $testfile -+log_must $changeflags 0 $testfile - log_must hasflag - $testfile - log_must rm $testfile - log_must user_run $owner touch $testfile --log_must user_run $owner chflags offline $testfile --log_mustnot user_run $other chflags nooffline $testfile -+log_must user_run $owner $changeflags offline $testfile -+log_mustnot user_run $other $changeflags nooffline $testfile - log_must hasflag offline $testfile --log_must user_run $owner chflags 0 $testfile --log_mustnot user_run $other chflags offline $testfile -+log_must user_run $owner $changeflags 0 $testfile -+log_mustnot user_run $other $changeflags offline $testfile - log_must hasflag - $testfile - log_must user_run $owner rm $testfile - -@@ -134,21 +148,23 @@ log_must user_run $owner rm $testfile - # but root is always allowed the operation. - # - log_must touch $testfile --log_must chflags rdonly $testfile -+log_must $changeflags rdonly $testfile - log_must hasflag rdonly $testfile - log_must eval "echo 'root write allowed' >> $testfile" - log_must cat $testfile --log_must chflags 0 $testfile --log_must hasflag - $tesfile -+log_must $changeflags 0 $testfile -+log_must hasflag - $testfile - log_must rm $testfile - # It is required to still be able to write to an fd that was opened RW before - # READONLY is set. We have a special test program for that. - log_must user_run $owner touch $testfile --log_mustnot user_run $other chflags rdonly $testfile -+log_mustnot user_run $other $changeflags rdonly $testfile - log_must user_run $owner $tests_base/dosmode_readonly_write $testfile --log_mustnot user_run $other chflags nordonly $testfile -+log_mustnot user_run $other $changeflags nordonly $testfile - log_must hasflag rdonly $testfile --log_mustnot user_run $owner "echo 'user write forbidden' >> $testfile" -+if ! is_linux; then -+ log_mustnot user_run $owner "echo 'user write forbidden' >> $testfile" -+fi - log_must eval "echo 'root write allowed' >> $testfile" - # We are still allowed to read and remove the file when READONLY is set. - log_must user_run $owner cat $testfile -@@ -157,24 +173,23 @@ log_must user_run $owner rm $testfile - # - # REPARSE - # --# FIXME: does not work, not sure if broken or testing wrong --# -+# not allowed to be changed - - # - # SPARSE - # - log_must truncate -s 1m $testfile --log_must chflags sparse $testfile -+log_must $changeflags sparse $testfile - log_must hasflag sparse $testfile --log_must chflags 0 $testfile -+log_must $changeflags 0 $testfile - log_must hasflag - $testfile - log_must rm $testfile - log_must user_run $owner truncate -s 1m $testfile --log_must user_run $owner chflags sparse $testfile --log_mustnot user_run $other chflags nosparse $testfile -+log_must user_run $owner $changeflags sparse $testfile -+log_mustnot user_run $other $changeflags nosparse $testfile - log_must hasflag sparse $testfile --log_must user_run $owner chflags 0 $testfile --log_mustnot user_run $other chflags sparse $testfile -+log_must user_run $owner $changeflags 0 $testfile -+log_mustnot user_run $other $changeflags sparse $testfile - log_must hasflag - $testfile - log_must user_run $owner rm $testfile - -@@ -182,17 +197,17 @@ log_must user_run $owner rm $testfile - # SYSTEM - # - log_must touch $testfile --log_must chflags system $testfile -+log_must $changeflags system $testfile - log_must hasflag system $testfile --log_must chflags 0 $testfile -+log_must $changeflags 0 $testfile - log_must hasflag - $testfile - log_must rm $testfile - log_must user_run $owner touch $testfile --log_must user_run $owner chflags system $testfile --log_mustnot user_run $other chflags nosystem $testfile -+log_must user_run $owner $changeflags system $testfile -+log_mustnot user_run $other $changeflags nosystem $testfile - log_must hasflag system $testfile --log_must user_run $owner chflags 0 $testfile --log_mustnot user_run $other chflags system $testfile -+log_must user_run $owner $changeflags 0 $testfile -+log_mustnot user_run $other $changeflags system $testfile - log_must hasflag - $testfile - log_must user_run $owner rm $testfile - -diff --git a/tests/zfs-tests/tests/functional/acl/off/dosmode_readonly_write.c b/tests/zfs-tests/tests/functional/acl/off/dosmode_readonly_write.c -index 372c3f7f64d..0441d1c7b47 100644 ---- a/tests/zfs-tests/tests/functional/acl/off/dosmode_readonly_write.c -+++ b/tests/zfs-tests/tests/functional/acl/off/dosmode_readonly_write.c -@@ -36,6 +36,11 @@ - #include <string.h> - #include <unistd.h> - -+#ifdef __linux__ -+#include <stdint.h> -+#include <sys/fs/zfs.h> -+#endif -+ - int - main(int argc, const char *argv[]) - { -@@ -51,8 +56,14 @@ main(int argc, const char *argv[]) - fd = open(path, O_CREAT|O_RDWR, 0777); - if (fd == -1) - err(EXIT_FAILURE, "%s: open failed", path); -+#ifdef __linux__ -+ uint64_t dosflags = ZFS_READONLY; -+ if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &dosflags) == -1) -+ err(EXIT_FAILURE, "%s: ZFS_IOC_SETDOSFLAGS failed", path); -+#else - if (chflags(path, UF_READONLY) == -1) - err(EXIT_FAILURE, "%s: chflags failed", path); -+#endif - if (write(fd, buf, strlen(buf)) == -1) - err(EXIT_FAILURE, "%s: write failed", path); - if (close(fd) == -1) -diff --git a/tests/zfs-tests/tests/functional/dos_attributes/Makefile.am b/tests/zfs-tests/tests/functional/dos_attributes/Makefile.am -new file mode 100644 -index 00000000000..436bcdb1f31 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/dos_attributes/Makefile.am -@@ -0,0 +1,8 @@ -+include $(top_srcdir)/config/Rules.am -+ -+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/dos_attributes -+dist_pkgdata_SCRIPTS = \ -+ cleanup.ksh \ -+ read_dos_attrs_001.ksh \ -+ write_dos_attrs_001.ksh \ -+ setup.ksh -diff --git a/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh b/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh -new file mode 100755 -index 00000000000..3166bd6ec16 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh -@@ -0,0 +1,34 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or http://www.opensolaris.org/os/licensing. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+# -+# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -+# Use is subject to license terms. -+# -+ -+# -+# Copyright (c) 2013 by Delphix. All rights reserved. -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+default_cleanup -diff --git a/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh b/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh -new file mode 100755 -index 00000000000..c36c0183315 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh -@@ -0,0 +1,60 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or http://www.opensolaris.org/os/licensing. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+# -+# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -+# Use is subject to license terms. -+# -+ -+# -+# Copyright (c) 2013, 2016 by Delphix. All rights reserved. -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+# -+# DESCRIPTION: -+# -+# Read additional file level attributes stored in upper half of z_pflags -+# -+# STARTEGY: -+# 1) Create a file -+# 2) Execute read_dos_attributes on the file we created -+# 3) Verify that read_dos_attributes exited successfully -+# -+ -+verify_runnable "global" -+ -+FILETOTEST="$TESTDIR/test_read_dos_attrs.txt" -+ -+function cleanup -+{ -+ rm -f $FILETOTEST -+} -+ -+log_onexit cleanup -+ -+log_must chmod 777 $TESTDIR -+log_must eval "echo 'This is a test file.' > $FILETOTEST" -+log_must read_dos_attributes $FILETOTEST -+ -+log_pass "reading DOS attributes succeeded." -diff --git a/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh b/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh -new file mode 100755 -index 00000000000..fc5cec3063a ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh -@@ -0,0 +1,35 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or http://www.opensolaris.org/os/licensing. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+# -+# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -+# Use is subject to license terms. -+# -+ -+# -+# Copyright (c) 2013 by Delphix. All rights reserved. -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+DISK=${DISKS%% *} -+default_setup $DISK -diff --git a/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh b/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh -new file mode 100755 -index 00000000000..9d66cd35759 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh -@@ -0,0 +1,61 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or http://www.opensolaris.org/os/licensing. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+# -+# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -+# Use is subject to license terms. -+# -+ -+# -+# Copyright (c) 2013, 2016 by Delphix. All rights reserved. -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+# -+# DESCRIPTION: -+# -+# Write additional file level attributes stored in upper half of z_pflags -+# -+# STARTEGY: -+# 1) Create a file -+# 2) Execute write_dos_attributes on the file we created -+# 3) Verify that write_dos_attributes exited successfully -+# -+ -+verify_runnable "global" -+ -+FILETOTEST="$TESTDIR/test_write_dos_attrs.txt" -+ -+function cleanup -+{ -+ rm -f $FILETOTEST -+} -+ -+log_onexit cleanup -+ -+log_must chmod 777 $TESTDIR -+log_must eval "echo 'This is a test file.' > $FILETOTEST" -+log_must write_dos_attributes offline $FILETOTEST -+log_must write_dos_attributes nooffline $FILETOTEST -+ -+log_pass "writing DOS attributes succeeded." diff --git a/sys-fs/zfs-kmod/files/2.1.11-optimize-access-checks.patch b/sys-fs/zfs-kmod/files/2.1.11-optimize-access-checks.patch deleted file mode 100644 index a59a9866cd93cddebd35b3794dfdcb59cd99878b..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-optimize-access-checks.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 9e7724f9011c0b42b982ed9d67ce3a5d75e33441 Mon Sep 17 00:00:00 2001 -From: Andrew Walker <awalker@ixsystems.com> -Date: Tue, 15 Mar 2022 11:03:29 -0400 -Subject: [PATCH 1/2] Linux optimize access checks when ACL is trivial - -Bypass check of ZFS aces if the ACL is trivial. When an ACL is -trivial its permissions are represented by the mode without any -loss of information. In this case, it is safe to convert the -access request into equivalent mode and then pass desired mask -and inode to generic_permission(). This has the added benefit -of also checking whether entries in a POSIX ACL on the file grant -the desired access. - -This commit also skips the ACL check on looking up the xattr dir -since such restrictions don't exist in Linux kernel and it makes -xattr lookup behavior inconsistent between SA and file-based -xattrs. We also don't want to perform a POSIX ACL check while -looking up the POSIX ACL if for some reason it is located in -the xattr dir rather than an SA. - -Signed-off-by: Andrew Walker <awalker@ixsystems.com> ---- - module/os/linux/zfs/zfs_acl.c | 70 ++++++++++++++++++++++++++++++ - module/os/linux/zfs/zfs_vnops_os.c | 2 +- - 2 files changed, 71 insertions(+), 1 deletion(-) - -diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c -index 351e4dad799..b70691ab31c 100644 ---- a/module/os/linux/zfs/zfs_acl.c -+++ b/module/os/linux/zfs/zfs_acl.c -@@ -863,6 +863,26 @@ zfs_unix_to_v4(uint32_t access_mask) - return (new_mask); - } - -+ -+static int -+zfs_v4_to_unix(uint32_t access_mask, int *unmapped) -+{ -+ int new_mask = 0; -+ -+ *unmapped = access_mask & -+ (ACE_WRITE_OWNER | ACE_WRITE_ACL | ACE_DELETE); -+ -+ if (access_mask & WRITE_MASK) -+ new_mask |= S_IWOTH; -+ if (access_mask & ACE_READ_DATA) -+ new_mask |= S_IROTH; -+ if (access_mask & ACE_EXECUTE) -+ new_mask |= S_IXOTH; -+ -+ return (new_mask); -+} -+ -+ - static void - zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, - uint16_t access_type, uint64_t fuid, uint16_t entry_type) -@@ -2399,6 +2419,53 @@ zfs_has_access(znode_t *zp, cred_t *cr) - return (B_TRUE); - } - -+/* -+ * Simplified access check for case where ACL is known to not contain -+ * information beyond what is defined in the mode. In this case, we -+ * can pass along to the kernel / vfs generic_permission() check, which -+ * evaluates the mode and POSIX ACL. -+ * -+ * NFSv4 ACLs allow granting permissions that are usually relegated only -+ * to the file owner or superuser. Examples are ACE_WRITE_OWNER (chown), -+ * ACE_WRITE_ACL(chmod), and ACE_DELETE. ACE_DELETE requests must fail -+ * because with conventional posix permissions, right to delete file -+ * is determined by write bit on the parent dir. -+ * -+ * If unmappable perms are requested, then we must return EPERM -+ * and include those bits in the working_mode so that the caller of -+ * zfs_zaccess_common() can decide whether to perform additional -+ * policy / capability checks. EACCES is used in zfs_zaccess_aces_check() -+ * to indicate access check failed due to explicit DENY entry, and so -+ * we want to avoid that here. -+ */ -+static int -+zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) -+{ -+ int err, mask; -+ int unmapped = 0; -+ -+ ASSERT(zp->z_pflags & ZFS_ACL_TRIVIAL); -+ -+ mask = zfs_v4_to_unix(*working_mode, &unmapped); -+ if (mask == 0 || unmapped) { -+ *working_mode = unmapped; -+ return (unmapped ? SET_ERROR(EPERM) : 0); -+ } -+ -+#if defined(HAVE_IOPS_PERMISSION_USERNS) -+ err = generic_permission(cr->user_ns, ZTOI(zp), mask); -+#else -+ err = generic_permission(ZTOI(zp), mask); -+#endif -+ if (err != 0) { -+ return (SET_ERROR(EPERM)); -+ } -+ -+ *working_mode = unmapped; -+ -+ return (0); -+} -+ - static int - zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, - boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) -@@ -2450,6 +2517,9 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, - return (SET_ERROR(EPERM)); - } - -+ if (zp->z_pflags & ZFS_ACL_TRIVIAL) -+ return (zfs_zaccess_trivial(zp, working_mode, cr)); -+ - return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); - } - -diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c -index ece7c373e85..b65728f0d4c 100644 ---- a/module/os/linux/zfs/zfs_vnops_os.c -+++ b/module/os/linux/zfs/zfs_vnops_os.c -@@ -474,7 +474,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, -- B_FALSE, cr))) { -+ B_TRUE, cr))) { - zrele(*zpp); - *zpp = NULL; - } - -From 6947cd4d94945b1014f69801efbd92fc526ab373 Mon Sep 17 00:00:00 2001 -From: Ryan Moeller <ryan@iXsystems.com> -Date: Wed, 3 Nov 2021 08:03:08 -0400 -Subject: [PATCH 2/2] Add configure check for "permission" inode operation - -The "permission" inode operation takes a new `struct user_namespace *` -parameter starting in Linux 5.12. - -Add a configure check and adapt accordingly. - -Signed-off-by: Ryan Moeller <ryan@iXsystems.com> ---- - config/kernel-inode-permission.m4 | 29 +++++++++++++++++++++++++++++ - config/kernel.m4 | 2 ++ - 2 files changed, 31 insertions(+) - create mode 100644 config/kernel-inode-permission.m4 - -diff --git a/config/kernel-inode-permission.m4 b/config/kernel-inode-permission.m4 -new file mode 100644 -index 00000000000..ba9ff5d43d4 ---- /dev/null -+++ b/config/kernel-inode-permission.m4 -@@ -0,0 +1,29 @@ -+AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [ -+ 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([permission_userns], [ -+ #include <linux/fs.h> -+ #include <linux/sched.h> -+ -+ int inode_permission(struct user_namespace *userns, -+ struct inode *inode, int mask) { return 0; } -+ -+ static const struct inode_operations -+ iops __attribute__ ((unused)) = { -+ .permission = inode_permission, -+ }; -+ ],[]) -+]) -+ -+AC_DEFUN([ZFS_AC_KERNEL_PERMISSION], [ -+ AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*]) -+ ZFS_LINUX_TEST_RESULT([permission_userns], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1, -+ [iops->permission() takes struct user_namespace*]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) -+]) -diff --git a/config/kernel.m4 b/config/kernel.m4 -index d1d3dede175..639d1837712 100644 ---- a/config/kernel.m4 -+++ b/config/kernel.m4 -@@ -82,6 +82,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC_MKDIR - ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS - ZFS_AC_KERNEL_SRC_CREATE -+ ZFS_AC_KERNEL_SRC_PERMISSION - ZFS_AC_KERNEL_SRC_GET_LINK - ZFS_AC_KERNEL_SRC_PUT_LINK - ZFS_AC_KERNEL_SRC_TMPFILE -@@ -193,6 +194,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL_MKDIR - ZFS_AC_KERNEL_LOOKUP_FLAGS - ZFS_AC_KERNEL_CREATE -+ ZFS_AC_KERNEL_PERMISSION - ZFS_AC_KERNEL_GET_LINK - ZFS_AC_KERNEL_PUT_LINK - ZFS_AC_KERNEL_TMPFILE diff --git a/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount-in-user-ns.patch b/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount-in-user-ns.patch deleted file mode 100644 index de3cede5d6a6e1de9c8d1a4fcc1b81c1cb44ec46..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount-in-user-ns.patch +++ /dev/null @@ -1,2012 +0,0 @@ -From de47f78acbfd3fc19eadc72801cdd963df1eb41d Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:24:30 -0500 -Subject: [PATCH 1/8] Backport "Support idmapped mount in user namespace" - ---- - include/os/linux/kernel/linux/xattr_compat.h | 10 +- - include/os/linux/spl/sys/cred.h | 83 ++++++++--- - include/os/linux/spl/sys/types.h | 1 + - include/os/linux/zfs/sys/policy.h | 5 +- - module/os/linux/spl/spl-cred.c | 8 + - module/os/linux/zfs/policy.c | 17 ++- - module/os/linux/zfs/zfs_acl.c | 24 +-- - module/os/linux/zfs/zfs_dir.c | 5 +- - module/os/linux/zfs/zfs_ioctl_os.c | 7 + - module/os/linux/zfs/zfs_vnops_os.c | 25 ++-- - module/os/linux/zfs/zfs_znode.c | 2 +- - module/os/linux/zfs/zpl_ctldir.c | 2 +- - module/os/linux/zfs/zpl_file.c | 6 +- - module/os/linux/zfs/zpl_inode.c | 22 +-- - module/os/linux/zfs/zpl_xattr.c | 36 ++++- - module/zfs/zfs_replay.c | 14 +- - module/zfs/zfs_vnops.c | 5 +- - tests/runfiles/linux.run | 2 +- - tests/test-runner/bin/zts-report.py.in | 1 + - tests/zfs-tests/cmd/idmap_util/idmap_util.c | 49 +++++-- - .../idmap_mount/idmap_mount_005.ksh | 138 ++++++++++++++++++ - 21 files changed, 361 insertions(+), 101 deletions(-) - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh - -diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h -index 30403fe8739..2c33a58d5c7 100644 ---- a/include/os/linux/kernel/linux/xattr_compat.h -+++ b/include/os/linux/kernel/linux/xattr_compat.h -@@ -146,7 +146,7 @@ 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)); \ -+ return (__ ## fn(user_ns, inode, name, buffer, size, flags)); \ - } - /* - * 4.7 API change, -@@ -160,7 +160,7 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \ - struct inode *inode, const char *name, const void *buffer, \ - size_t size, int flags) \ - { \ -- return (__ ## fn(inode, name, buffer, size, flags)); \ -+ return (__ ## fn(zfs_init_user_ns, inode, name, buffer, size, flags));\ - } - /* - * 4.4 API change, -@@ -174,7 +174,8 @@ static int \ - fn(const struct xattr_handler *handler, struct dentry *dentry, \ - const char *name, const void *buffer, size_t size, int flags) \ - { \ -- return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ -+ return (__ ## fn(zfs_init_user_ns, dentry->d_inode, name, \ -+ buffer, size, flags)); \ - } - /* - * 2.6.33 API change, -@@ -187,7 +188,8 @@ static int \ - fn(struct dentry *dentry, const char *name, const void *buffer, \ - size_t size, int flags, int unused_handler_flags) \ - { \ -- return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ -+ return (__ ## fn(zfs_init_user_ns, dentry->d_inode, name, \ -+ buffer, size, flags)); \ - } - #else - #error "Unsupported kernel" -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index dc3c260dbba..13e420e8de2 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -45,32 +45,82 @@ typedef struct cred cred_t; - #define SGID_TO_KGID(x) (KGIDT_INIT(x)) - #define KGIDP_TO_SGIDP(x) (&(x)->val) - --static inline uid_t zfs_uid_into_mnt(struct user_namespace *mnt_ns, uid_t uid) -+extern struct user_namespace *zfs_get_init_userns(void); -+ -+/* Check if the user ns is the initial one */ -+static inline boolean_t -+zfs_is_init_userns(struct user_namespace *user_ns) - { -- if (mnt_ns) -- return (__kuid_val(make_kuid(mnt_ns, uid))); -- return (uid); -+#if defined(CONFIG_USER_NS) -+ return (user_ns == zfs_init_user_ns); -+#else -+ return (B_FALSE); -+#endif - } - --static inline gid_t zfs_gid_into_mnt(struct user_namespace *mnt_ns, gid_t gid) -+static inline struct user_namespace *zfs_i_user_ns(struct inode *inode) - { -- if (mnt_ns) -- return (__kgid_val(make_kgid(mnt_ns, gid))); -- return (gid); -+#ifdef HAVE_SUPER_USER_NS -+ return (inode->i_sb->s_user_ns); -+#else -+ return (zfs_init_user_ns); -+#endif - } - --static inline uid_t zfs_uid_from_mnt(struct user_namespace *mnt_ns, uid_t uid) -+static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns, -+ struct user_namespace *fs_userns) - { -- if (mnt_ns) -- return (from_kuid(mnt_ns, KUIDT_INIT(uid))); -- return (uid); -+ return (zfs_is_init_userns(mnt_userns) || mnt_userns == fs_userns); - } - --static inline gid_t zfs_gid_from_mnt(struct user_namespace *mnt_ns, gid_t gid) -+static inline uid_t zfs_uid_to_vfsuid(struct user_namespace *mnt_userns, -+ struct user_namespace *fs_userns, uid_t uid) - { -- if (mnt_ns) -- return (from_kgid(mnt_ns, KGIDT_INIT(gid))); -- return (gid); -+ if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ return (uid); -+ if (!zfs_is_init_userns(fs_userns)) -+ uid = from_kuid(fs_userns, KUIDT_INIT(uid)); -+ if (uid == (uid_t)-1) -+ return (uid); -+ return (__kuid_val(make_kuid(mnt_userns, uid))); -+} -+ -+static inline gid_t zfs_gid_to_vfsgid(struct user_namespace *mnt_userns, -+ struct user_namespace *fs_userns, gid_t gid) -+{ -+ if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ return (gid); -+ if (!zfs_is_init_userns(fs_userns)) -+ gid = from_kgid(fs_userns, KGIDT_INIT(gid)); -+ if (gid == (gid_t)-1) -+ return (gid); -+ return (__kgid_val(make_kgid(mnt_userns, gid))); -+} -+ -+static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns, -+ struct user_namespace *fs_userns, uid_t uid) -+{ -+ if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ return (uid); -+ uid = from_kuid(mnt_userns, KUIDT_INIT(uid)); -+ if (uid == (uid_t)-1) -+ return (uid); -+ if (zfs_is_init_userns(fs_userns)) -+ return (uid); -+ return (__kuid_val(make_kuid(fs_userns, uid))); -+} -+ -+static inline gid_t zfs_vfsgid_to_gid(struct user_namespace *mnt_userns, -+ struct user_namespace *fs_userns, gid_t gid) -+{ -+ if (zfs_no_idmapping(mnt_userns, fs_userns)) -+ return (gid); -+ gid = from_kgid(mnt_userns, KGIDT_INIT(gid)); -+ if (gid == (gid_t)-1) -+ return (gid); -+ if (zfs_is_init_userns(fs_userns)) -+ return (gid); -+ return (__kgid_val(make_kgid(fs_userns, gid))); - } - - extern void crhold(cred_t *cr); -@@ -81,5 +131,4 @@ extern gid_t crgetgid(const cred_t *cr); - extern int crgetngroups(const cred_t *cr); - extern gid_t *crgetgroups(const cred_t *cr); - extern int groupmember(gid_t gid, const cred_t *cr); -- - #endif /* _SPL_CRED_H */ -diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h -index cae1bbddf10..e682c0560d5 100644 ---- a/include/os/linux/spl/sys/types.h -+++ b/include/os/linux/spl/sys/types.h -@@ -56,5 +56,6 @@ typedef int minor_t; - - struct user_namespace; - typedef struct user_namespace zuserns_t; -+extern zuserns_t *zfs_init_user_ns; - - #endif /* _SPL_TYPES_H */ -diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h -index 5ec51392f17..7548804b9ee 100644 ---- a/include/os/linux/zfs/sys/policy.h -+++ b/include/os/linux/zfs/sys/policy.h -@@ -47,13 +47,14 @@ int secpolicy_vnode_create_gid(const cred_t *); - int secpolicy_vnode_remove(const cred_t *); - int secpolicy_vnode_setdac(const cred_t *, uid_t); - int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t); --int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *); -+int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *, -+ zuserns_t *); - int secpolicy_zinject(const cred_t *); - int secpolicy_zfs(const cred_t *); - int secpolicy_zfs_proc(const cred_t *, proc_t *); - void secpolicy_setid_clear(vattr_t *, cred_t *); - int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *, -- const vattr_t *, cred_t *, zuserns_t *); -+ const vattr_t *, cred_t *, zuserns_t *, zuserns_t *); - int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t); - int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *, - const struct vattr *, int, int (void *, int, cred_t *), void *); -diff --git a/module/os/linux/spl/spl-cred.c b/module/os/linux/spl/spl-cred.c -index f81b9540a63..1f406ec540b 100644 ---- a/module/os/linux/spl/spl-cred.c -+++ b/module/os/linux/spl/spl-cred.c -@@ -145,6 +145,14 @@ crgetgid(const cred_t *cr) - return (KGID_TO_SGID(cr->fsgid)); - } - -+/* Return the initial user ns */ -+struct user_namespace * -+zfs_get_init_userns(void) -+{ -+ return (&init_user_ns); -+} -+ -+EXPORT_SYMBOL(zfs_get_init_userns); - EXPORT_SYMBOL(crhold); - EXPORT_SYMBOL(crfree); - EXPORT_SYMBOL(crgetuid); -diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c -index d68f3561210..e879ec32c20 100644 ---- a/module/os/linux/zfs/policy.c -+++ b/module/os/linux/zfs/policy.c -@@ -214,9 +214,10 @@ secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr, - * Determine that subject can set the file setgid flag. - */ - int --secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns) -+secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns, -+ zuserns_t *fs_ns) - { -- gid = zfs_gid_into_mnt(mnt_ns, gid); -+ gid = zfs_gid_to_vfsgid(mnt_ns, fs_ns, gid); - #if defined(CONFIG_USER_NS) - if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid))) - return (EPERM); -@@ -285,9 +286,10 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr) - * Determine that subject can set the file setid flags. - */ - static int --secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns) -+secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns, -+ zuserns_t *fs_ns) - { -- owner = zfs_uid_into_mnt(mnt_ns, owner); -+ owner = zfs_uid_to_vfsuid(mnt_ns, fs_ns, owner); - - if (crgetuid(cr) == owner) - return (0); -@@ -313,13 +315,13 @@ secpolicy_vnode_stky_modify(const cred_t *cr) - - int - secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, -- const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns) -+ const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns, zuserns_t *fs_ns) - { - int error; - - if ((vap->va_mode & S_ISUID) != 0 && - (error = secpolicy_vnode_setid_modify(cr, -- ovap->va_uid, mnt_ns)) != 0) { -+ ovap->va_uid, mnt_ns, fs_ns)) != 0) { - return (error); - } - -@@ -337,7 +339,8 @@ secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, - * group-id bit. - */ - if ((vap->va_mode & S_ISGID) != 0 && -- secpolicy_vnode_setids_setgids(cr, ovap->va_gid, mnt_ns) != 0) { -+ secpolicy_vnode_setids_setgids(cr, ovap->va_gid, -+ mnt_ns, fs_ns) != 0) { - vap->va_mode &= ~S_ISGID; - } - -diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c -index fcb767e9e4a..52978c1133e 100644 ---- a/module/os/linux/zfs/zfs_acl.c -+++ b/module/os/linux/zfs/zfs_acl.c -@@ -1888,7 +1888,8 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, - acl_ids->z_mode |= S_ISGID; - } else { - if ((acl_ids->z_mode & S_ISGID) && -- secpolicy_vnode_setids_setgids(cr, gid, mnt_ns) != 0) { -+ secpolicy_vnode_setids_setgids(cr, gid, mnt_ns, -+ zfs_i_user_ns(ZTOI(dzp))) != 0) { - acl_ids->z_mode &= ~S_ISGID; - } - } -@@ -1978,7 +1979,8 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (mask == 0) - return (SET_ERROR(ENOSYS)); - -- if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) -+ if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, -+ zfs_init_user_ns))) - return (error); - - mutex_enter(&zp->z_acl_lock); -@@ -2137,7 +2139,8 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (zp->z_pflags & ZFS_IMMUTABLE) - return (SET_ERROR(EPERM)); - -- if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) -+ if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, -+ zfs_init_user_ns))) - return (error); - - error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, -@@ -2300,9 +2303,9 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, - uid_t fowner; - - if (mnt_ns) { -- fowner = zfs_uid_into_mnt(mnt_ns, -+ fowner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), - KUID_TO_SUID(ZTOI(zp)->i_uid)); -- gowner = zfs_gid_into_mnt(mnt_ns, -+ gowner = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), - KGID_TO_SGID(ZTOI(zp)->i_gid)); - } else - zfs_fuid_map_ids(zp, cr, &fowner, &gowner); -@@ -2416,7 +2419,8 @@ zfs_has_access(znode_t *zp, cred_t *cr) - { - uint32_t have = ACE_ALL_PERMS; - -- if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, NULL) != 0) { -+ if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, -+ zfs_init_user_ns) != 0) { - uid_t owner; - - owner = zfs_fuid_map_id(ZTOZSB(zp), -@@ -2608,7 +2612,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - slow: - DTRACE_PROBE(zfs__fastpath__execute__access__miss); - ZFS_ENTER(ZTOZSB(zdp)); -- error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); -+ error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -+ zfs_init_user_ns); - ZFS_EXIT(ZTOZSB(zdp)); - return (error); - } -@@ -2660,7 +2665,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, - } - } - -- owner = zfs_uid_into_mnt(mnt_ns, KUID_TO_SUID(ZTOI(zp)->i_uid)); -+ owner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), -+ KUID_TO_SUID(ZTOI(zp)->i_uid)); - owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER); - - /* -@@ -2784,7 +2790,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) - { - int v4_mode = zfs_unix_to_v4(mode >> 6); - -- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); -+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_user_ns)); - } - - /* See zfs_zaccess_delete() */ -diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c -index 9bb11d6d4c2..4a04cc37d5c 100644 ---- a/module/os/linux/zfs/zfs_dir.c -+++ b/module/os/linux/zfs/zfs_dir.c -@@ -1067,7 +1067,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr) - *xzpp = NULL; - - if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, -- &acl_ids, NULL)) != 0) -+ &acl_ids, zfs_init_user_ns)) != 0) - return (error); - if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { - zfs_acl_ids_free(&acl_ids); -@@ -1215,7 +1215,8 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) - cr, ZFS_OWNER); - - if ((uid = crgetuid(cr)) == downer || uid == fowner || -- zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0) -+ zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -+ zfs_init_user_ns) == 0) - return (0); - else - return (secpolicy_vnode_remove(cr)); -diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c -index 79b9d777dc8..ad17973e7ad 100644 ---- a/module/os/linux/zfs/zfs_ioctl_os.c -+++ b/module/os/linux/zfs/zfs_ioctl_os.c -@@ -58,6 +58,9 @@ - #include <sys/zvol.h> - #include <sys/fm/util.h> - #include <sys/dsl_crypt.h> -+#include <sys/crypto/icp.h> -+#include <sys/zstd/zstd.h> -+#include <sys/cred.h> - - #include <sys/zfs_ioctl_impl.h> - -@@ -288,6 +291,8 @@ zfsdev_detach(void) - #define ZFS_DEBUG_STR "" - #endif - -+zuserns_t *zfs_init_user_ns; -+ - static int __init - openzfs_init(void) - { -@@ -311,6 +316,8 @@ openzfs_init(void) - printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); - #endif /* CONFIG_FS_POSIX_ACL */ - -+ zfs_init_user_ns = (zuserns_t *)zfs_get_init_userns(); -+ - return (0); - } - -diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c -index b81b4298620..d7abe558cd0 100644 ---- a/module/os/linux/zfs/zfs_vnops_os.c -+++ b/module/os/linux/zfs/zfs_vnops_os.c -@@ -501,7 +501,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, -- B_TRUE, cr, NULL))) { -+ B_TRUE, cr, zfs_init_user_ns))) { - zrele(*zpp); - *zpp = NULL; - } -@@ -519,7 +519,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - * Check accessibility of directory. - */ - -- if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL))) { -+ if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -+ zfs_init_user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -1001,7 +1002,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_user_ns))) { - goto out; - } - -@@ -1417,7 +1418,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_user_ns))) { - goto out; - } - -@@ -2056,10 +2057,10 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) - * Take ownership or chgrp to group we are a member of - */ - -- uid = zfs_uid_into_mnt((struct user_namespace *)mnt_ns, -- vap->va_uid); -- gid = zfs_gid_into_mnt((struct user_namespace *)mnt_ns, -- vap->va_gid); -+ uid = zfs_uid_to_vfsuid((struct user_namespace *)mnt_ns, -+ zfs_i_user_ns(ip), vap->va_uid); -+ gid = zfs_gid_to_vfsgid((struct user_namespace *)mnt_ns, -+ zfs_i_user_ns(ip), vap->va_gid); - take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr)); - take_group = (mask & ATTR_GID) && - zfs_groupmember(zfsvfs, gid, cr); -@@ -2194,7 +2195,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) - if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, - mnt_ns) == 0) { - err = secpolicy_setid_setsticky_clear(ip, vap, -- &oldva, cr, mnt_ns); -+ &oldva, cr, mnt_ns, zfs_i_user_ns(ip)); - if (err) - goto out3; - trim_mask |= ATTR_MODE; -@@ -3371,7 +3372,8 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, - return (SET_ERROR(EPERM)); - } - -- if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { -+ if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, -+ zfs_init_user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3959,7 +3961,8 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, - * On Linux we can get here through truncate_range() which - * operates directly on inodes, so we need to check access rights. - */ -- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { -+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -+ zfs_init_user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c -index 619ef68a947..956346e0afd 100644 ---- a/module/os/linux/zfs/zfs_znode.c -+++ b/module/os/linux/zfs/zfs_znode.c -@@ -1947,7 +1947,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) - } - - VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, -- cr, NULL, &acl_ids, NULL)); -+ cr, NULL, &acl_ids, zfs_init_user_ns)); - zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, rootzp); - error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); -diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c -index 9e7e1806f8c..6cc99d6f37a 100644 ---- a/module/os/linux/zfs/zpl_ctldir.c -+++ b/module/os/linux/zfs/zpl_ctldir.c -@@ -366,7 +366,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) - #ifdef HAVE_IOPS_MKDIR_USERNS - zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); - #else -- zpl_vap_init(vap, dip, mode | S_IFDIR, cr, NULL); -+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_user_ns); - #endif - - error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index 92babf04a92..8d320101ee3 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -971,7 +971,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1019,7 +1019,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1107,7 +1107,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c -index d218045d11c..5eb95676e88 100644 ---- a/module/os/linux/zfs/zpl_inode.c -+++ b/module/os/linux/zfs/zpl_inode.c -@@ -117,16 +117,16 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, - vap->va_mask = ATTR_MODE; - vap->va_mode = mode; - -- vap->va_uid = zfs_uid_from_mnt((struct user_namespace *)mnt_ns, -- crgetuid(cr)); -+ vap->va_uid = zfs_vfsuid_to_uid((struct user_namespace *)mnt_ns, -+ zfs_i_user_ns(dir), crgetuid(cr)); - - if (dir && dir->i_mode & S_ISGID) { - vap->va_gid = KGID_TO_SGID(dir->i_gid); - if (S_ISDIR(mode)) - vap->va_mode |= S_ISGID; - } else { -- vap->va_gid = zfs_gid_from_mnt((struct user_namespace *)mnt_ns, -- crgetgid(cr)); -+ vap->va_gid = zfs_vfsgid_to_gid((struct user_namespace *)mnt_ns, -+ zfs_i_user_ns(dir), crgetgid(cr)); - } - } - -@@ -144,7 +144,7 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_CREATE_USERNS -- zuserns_t *user_ns = NULL; -+ zuserns_t *user_ns = zfs_init_user_ns; - #endif - - crhold(cr); -@@ -191,7 +191,7 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_MKNOD_USERNS -- zuserns_t *user_ns = NULL; -+ zuserns_t *user_ns = zfs_init_user_ns; - #endif - - /* -@@ -251,7 +251,7 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_TMPFILE_USERNS -- zuserns_t *userns = NULL; -+ zuserns_t *userns = zfs_init_user_ns; - #endif - - crhold(cr); -@@ -339,7 +339,7 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_MKDIR_USERNS -- zuserns_t *user_ns = NULL; -+ zuserns_t *user_ns = zfs_init_user_ns; - #endif - - crhold(cr); -@@ -496,7 +496,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - #ifdef HAVE_SETATTR_PREPARE_USERNS - error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); - #else -- error = -zfs_setattr(ITOZ(ip), vap, 0, cr, NULL); -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_user_ns); - #endif - if (!error && (ia->ia_valid & ATTR_MODE)) - error = zpl_chmod_acl(ip); -@@ -523,7 +523,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_RENAME_USERNS -- zuserns_t *user_ns = NULL; -+ zuserns_t *user_ns = zfs_init_user_ns; - #endif - - /* We don't have renameat2(2) support */ -@@ -564,7 +564,7 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_SYMLINK_USERNS -- zuserns_t *user_ns = NULL; -+ zuserns_t *user_ns = zfs_init_user_ns; - #endif - - crhold(cr); -diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c -index 5f0be5f6418..c2be9352ae1 100644 ---- a/module/os/linux/zfs/zpl_xattr.c -+++ b/module/os/linux/zfs/zpl_xattr.c -@@ -496,7 +496,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, - vap->va_gid = crgetgid(cr); - - error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, -- cr, 0, NULL, NULL); -+ cr, 0, NULL, zfs_init_user_ns); - if (error) - goto out; - } -@@ -725,11 +725,13 @@ __zpl_xattr_user_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get); - - static int --__zpl_xattr_user_set(struct inode *ip, const char *name, -+__zpl_xattr_user_set(struct user_namespace *user_ns, -+ struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { - char *xattr_name; -- int error; -+ (void) user_ns; -+ int error = 0; - /* xattr_resolve_name will do this for us if this is defined */ - #ifndef HAVE_XATTR_HANDLER_NAME - if (strcmp(name, "") == 0) -@@ -794,9 +796,11 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get); - - static int --__zpl_xattr_trusted_set(struct inode *ip, const char *name, -+__zpl_xattr_trusted_set(struct user_namespace *user_ns, -+ struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -+ (void) user_ns; - char *xattr_name; - int error; - -@@ -863,9 +867,11 @@ __zpl_xattr_security_get(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get); - - static int --__zpl_xattr_security_set(struct inode *ip, const char *name, -+__zpl_xattr_security_set(struct user_namespace *user_ns, -+ struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { -+ (void) user_ns; - char *xattr_name; - int error; - /* xattr_resolve_name will do this for us if this is defined */ -@@ -889,7 +895,7 @@ zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs, - int error = 0; - - for (xattr = xattrs; xattr->name != NULL; xattr++) { -- error = __zpl_xattr_security_set(ip, -+ error = __zpl_xattr_security_set(NULL, ip, - xattr->name, xattr->value, xattr->value_len, 0); - - if (error < 0) -@@ -1256,7 +1262,8 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name, - ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default); - - static int --__zpl_xattr_acl_set_access(struct inode *ip, const char *name, -+__zpl_xattr_acl_set_access(struct user_namespace *mnt_ns, -+ struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { - struct posix_acl *acl; -@@ -1270,8 +1277,14 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, - if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) - return (-EOPNOTSUPP); - -+#if defined(HAVE_XATTR_SET_USERNS) -+ if (!zpl_inode_owner_or_capable(mnt_ns, ip)) -+ return (-EPERM); -+#else -+ (void) mnt_ns; - if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) - return (-EPERM); -+#endif - - if (value) { - acl = zpl_acl_from_xattr(value, size); -@@ -1295,7 +1308,8 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, - ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access); - - static int --__zpl_xattr_acl_set_default(struct inode *ip, const char *name, -+__zpl_xattr_acl_set_default(struct user_namespace *mnt_ns, -+ struct inode *ip, const char *name, - const void *value, size_t size, int flags) - { - struct posix_acl *acl; -@@ -1309,8 +1323,14 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name, - if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) - return (-EOPNOTSUPP); - -+#if defined(HAVE_XATTR_SET_USERNS) -+ if (!zpl_inode_owner_or_capable(mnt_ns, ip)) -+ return (-EPERM); -+#else -+ (void) mnt_ns; - if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) - return (-EPERM); -+#endif - - if (value) { - acl = zpl_acl_from_xattr(value, size); -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index c7a3486cd36..950339ceade 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -385,7 +385,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - } - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, &vsec, NULL); -+ 0, 0, &zp, kcred, vflg, &vsec, zfs_init_user_ns); - break; - case TX_MKDIR_ACL: - aclstart = (caddr_t)(lracl + 1); -@@ -415,7 +415,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - } - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, &vsec, NULL); -+ &zp, kcred, vflg, &vsec, zfs_init_user_ns); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -525,7 +525,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)start; - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, NULL, NULL); -+ 0, 0, &zp, kcred, vflg, NULL, zfs_init_user_ns); - break; - case TX_MKDIR_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); -@@ -542,7 +542,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, NULL, NULL); -+ &zp, kcred, vflg, NULL, zfs_init_user_ns); - break; - case TX_MKXATTR: - error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); -@@ -551,7 +551,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - link = name + strlen(name) + 1; - error = zfs_symlink(dzp, name, &xva.xva_vattr, -- link, &zp, kcred, vflg, NULL); -+ link, &zp, kcred, vflg, zfs_init_user_ns); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -663,7 +663,7 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - if (lr->lr_common.lrc_txtype & TX_CI) - vflg |= FIGNORECASE; - -- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, NULL); -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, zfs_init_user_ns); - - zrele(tdzp); - zrele(sdzp); -@@ -857,7 +857,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) - zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, - lr->lr_uid, lr->lr_gid); - -- error = zfs_setattr(zp, vap, 0, kcred, NULL); -+ error = zfs_setattr(zp, vap, 0, kcred, zfs_init_user_ns); - - zfs_fuid_info_free(zfsvfs->z_fuid_replay); - zfsvfs->z_fuid_replay = NULL; -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index 6d74ffb633c..7ef1fcf99ed 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -165,9 +165,10 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - ZFS_VERIFY_ZP(zp); - - if (flag & V_ACE_MASK) -- error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, NULL); -+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, -+ zfs_init_user_ns); - else -- error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL); -+ error = zfs_zaccess_rwx(zp, mode, flag, cr, zfs_init_user_ns); - - ZFS_EXIT(zfsvfs); - return (error); -diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run -index 211e6a1dd41..56029b44677 100644 ---- a/tests/runfiles/linux.run -+++ b/tests/runfiles/linux.run -@@ -191,5 +191,5 @@ tags = ['functional', 'userquota'] - - [tests/functional/idmap_mount:Linux] - tests = ['idmap_mount_001', 'idmap_mount_002', 'idmap_mount_003', -- 'idmap_mount_004'] -+ 'idmap_mount_004', 'idmap_mount_005'] - tags = ['functional', 'idmap_mount'] -diff --git a/tests/test-runner/bin/zts-report.py.in b/tests/test-runner/bin/zts-report.py.in -index a98e8175b06..2bbd765dd73 100755 ---- a/tests/test-runner/bin/zts-report.py.in -+++ b/tests/test-runner/bin/zts-report.py.in -@@ -298,6 +298,7 @@ elif sys.platform.startswith('linux'): - 'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason], -+ 'idmap_mount/idmap_mount_005': ['SKIP', idmap_reason], - }) - - -diff --git a/tests/zfs-tests/cmd/idmap_util/idmap_util.c b/tests/zfs-tests/cmd/idmap_util/idmap_util.c -index a9731f00dbc..39a2a147701 100644 ---- a/tests/zfs-tests/cmd/idmap_util/idmap_util.c -+++ b/tests/zfs-tests/cmd/idmap_util/idmap_util.c -@@ -36,6 +36,7 @@ - #include <errno.h> - #include <sched.h> - #include <syscall.h> -+#include <sys/socket.h> - - #include <sys/list.h> - -@@ -460,43 +461,56 @@ userns_fd_from_idmap(list_t *head) - { - pid_t pid; - int ret, fd; -- int pipe_fd[2]; -+ int fds[2]; - char c; - int saved_errno = 0; - -- /* pipe for bidirectional communication */ -- ret = pipe(pipe_fd); -+ /* socketpair for bidirectional communication */ -+ ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); - if (ret) { -- log_errno("pipe"); -+ log_errno("socketpair"); - return (-errno); - } - - pid = fork(); - if (pid < 0) { - log_errno("fork"); -- return (-errno); -+ fd = -errno; -+ goto out; - } - - if (pid == 0) { - /* child process */ -- close(pipe_fd[0]); - ret = unshare(CLONE_NEWUSER); - if (ret == 0) { - /* notify the parent of success */ -- ret = write_buf(pipe_fd[1], "1", 1); -+ ret = write_buf(fds[1], "1", 1); -+ if (ret < 0) -+ saved_errno = errno; -+ else { -+ /* -+ * Until the parent has written to idmap, -+ * we cannot exit, otherwise the defunct -+ * process is owned by the real root, writing -+ * to its idmap ends up with EPERM in the -+ * context of a user ns -+ */ -+ ret = read_buf(fds[1], &c, 1); -+ if (ret < 0) -+ saved_errno = errno; -+ } - } else { - saved_errno = errno; - log_errno("unshare"); -- ret = write_buf(pipe_fd[1], "0", 1); -+ ret = write_buf(fds[1], "0", 1); -+ if (ret < 0) -+ saved_errno = errno; - } -- if (ret < 0) -- saved_errno = errno; -- close(pipe_fd[1]); - exit(saved_errno); - } -+ - /* parent process */ -- close(pipe_fd[1]); -- ret = read_buf(pipe_fd[0], &c, 1); -+ ret = read_buf(fds[0], &c, 1); - if (ret == 1 && c == '1') { - ret = write_pid_idmaps(pid, head); - if (!ret) { -@@ -506,11 +520,15 @@ userns_fd_from_idmap(list_t *head) - } else { - fd = -ret; - } -+ /* Let child know it can exit */ -+ (void) write_buf(fds[0], "1", 1); - } else { - fd = -EBADF; - } -- close(pipe_fd[0]); - (void) wait_for_pid(pid); -+out: -+ close(fds[0]); -+ close(fds[1]); - return (fd); - } - -@@ -534,7 +552,8 @@ is_idmap_supported(char *path) - }; - - /* strtok_r() won't be happy with a const string */ -- char *input = strdup("b:0:1000000:1000000"); -+ /* To check if idmapped mount can be done in a user ns, map 0 to 0 */ -+ char *input = strdup("b:0:0:1"); - - if (!input) { - errno = ENOMEM; -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh -new file mode 100755 -index 00000000000..a4ecea92c12 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh -@@ -0,0 +1,138 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib -+ -+# -+# -+# DESCRIPTION: -+# Test idmapped mount in a user namespace -+# -+# STRATEGY: -+# 1. Create a zoned dataset -+# 2. Create a user namespace and designate the dataset to the zone -+# 3. In the zone, mount the dataset to "idmap_test" -+# 4. In the zone, idmap mount the dataset mountpoint to "idmap_dest" -+# 5. Do some file operations in the idmapped mountpoint "idmap_dest" -+# 6. Check the owner of files/folder in the mount point "idmap_test" -+# 7. unmount the mountpoints in the zone -+# 8. Remount the dataset in global zone to "idmap_test" -+# 9. Check the owenr of filers/folder in the mountpoint "idmap_test" -+# -+ -+verify_runnable "global" -+ -+export WORKDIR=$TESTDIR/idmap_test -+export IDMAPDIR=$TESTDIR/idmap_dest -+ -+function cleanup -+{ -+ if [[ -v unshared_pid ]]; then -+ zfs unzone /proc/$unshared_pid/ns/user "$TESTPOOL/userns" -+ kill -TERM ${unshared_pid} -+ fi -+ if mountpoint $WORKDIR; then -+ log_must umount $WORKDIR -+ fi -+ log_must rm -rf $WORKDIR -+} -+ -+log_onexit cleanup -+ -+if ! idmap_util -c $TESTDIR; then -+ log_unsupported "Idmap mount not supported." -+fi -+ -+unshare -Urm echo test -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+ -+log_must zfs create -o zoned=off -o mountpoint=$WORKDIR "$TESTPOOL/userns" -+ -+# "root" user and group in the user ns -+log_must chown 1000000:1000000 $WORKDIR -+log_must zfs set zoned=on "$TESTPOOL/userns" -+ -+log_must mkdir -p $IDMAPDIR -+ -+unshare -Um /usr/bin/sleep 2h & -+unshared_pid=$! -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+# wait for userns to be ready -+sleep 1 -+echo "0 1000000 1000000" > /proc/$unshared_pid/uid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to uid_map" -+fi -+echo "0 1000000 1000000" > /proc/$unshared_pid/gid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to gid_map" -+fi -+ -+NSENTER="nsenter -t $unshared_pid --all -S 0 -G 0" -+ -+log_must zfs zone /proc/$unshared_pid/ns/user "$TESTPOOL/userns" -+log_must $NSENTER zfs mount "$TESTPOOL/userns" -+log_must $NSENTER chmod 777 $WORKDIR -+ -+$NSENTER idmap_util -c $WORKDIR -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Idmapped mount not supported in a user namespace" -+fi -+ -+log_must $NSENTER idmap_util -m b:0:10000:100000 $WORKDIR $IDMAPDIR -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups touch $IDMAPDIR/file -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups mkdir $IDMAPDIR/folder -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups ln -s file $IDMAPDIR/file-soft -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups ln $IDMAPDIR/file $IDMAPDIR/file-hard -+ -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups cp -p $IDMAPDIR/file $IDMAPDIR/folder/file-p -+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups cp $IDMAPDIR/file $IDMAPDIR/folder/file -+ -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file)" -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder)" -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file-soft)" -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file-hard)" -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder/file-p)" -+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder/file)" -+ -+log_must $NSENTER umount $IDMAPDIR -+log_must $NSENTER umount $WORKDIR -+ -+log_must zfs unzone /proc/$unshared_pid/ns/user "$TESTPOOL/userns" -+log_must kill -TERM $unshared_pid -+unset unshared_pid -+log_must zfs set zoned=off "$TESTPOOL/userns" -+log_must zfs mount "$TESTPOOL/userns" -+ -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file)" -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder)" -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file-soft)" -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file-hard)" -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder/file-p)" -+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder/file)" -+ -+log_pass "Testing idmapped mount in a user ns is successful." -+ - -From bff61819cd1f0cd1e44b06dca4e8fb24506340f0 Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:27:12 -0500 -Subject: [PATCH 2/8] Backport "Use kcred->user_ns to reference &init_user_ns" - ---- - include/os/linux/kernel/linux/xattr_compat.h | 6 +++--- - include/os/linux/spl/sys/cred.h | 6 ++---- - include/os/linux/spl/sys/types.h | 1 - - module/os/linux/spl/spl-cred.c | 8 -------- - module/os/linux/zfs/zfs_acl.c | 10 +++++----- - module/os/linux/zfs/zfs_dir.c | 4 ++-- - module/os/linux/zfs/zfs_ioctl_os.c | 4 ---- - module/os/linux/zfs/zfs_vnops_os.c | 12 ++++++------ - module/os/linux/zfs/zfs_znode.c | 2 +- - module/os/linux/zfs/zpl_ctldir.c | 2 +- - module/os/linux/zfs/zpl_file.c | 6 +++--- - module/os/linux/zfs/zpl_inode.c | 14 +++++++------- - module/os/linux/zfs/zpl_xattr.c | 2 +- - module/zfs/zfs_replay.c | 14 +++++++------- - module/zfs/zfs_vnops.c | 4 ++-- - 15 files changed, 40 insertions(+), 55 deletions(-) - -diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h -index 2c33a58d5c7..83763c64a14 100644 ---- a/include/os/linux/kernel/linux/xattr_compat.h -+++ b/include/os/linux/kernel/linux/xattr_compat.h -@@ -160,7 +160,7 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \ - struct inode *inode, const char *name, const void *buffer, \ - size_t size, int flags) \ - { \ -- return (__ ## fn(zfs_init_user_ns, inode, name, buffer, size, flags));\ -+ return (__ ## fn(kcred->user_ns, inode, name, buffer, size, flags));\ - } - /* - * 4.4 API change, -@@ -174,7 +174,7 @@ static int \ - fn(const struct xattr_handler *handler, struct dentry *dentry, \ - const char *name, const void *buffer, size_t size, int flags) \ - { \ -- return (__ ## fn(zfs_init_user_ns, dentry->d_inode, name, \ -+ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, \ - buffer, size, flags)); \ - } - /* -@@ -188,7 +188,7 @@ static int \ - fn(struct dentry *dentry, const char *name, const void *buffer, \ - size_t size, int flags, int unused_handler_flags) \ - { \ -- return (__ ## fn(zfs_init_user_ns, dentry->d_inode, name, \ -+ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, \ - buffer, size, flags)); \ - } - #else -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index 13e420e8de2..6c891164b08 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -45,14 +45,12 @@ typedef struct cred cred_t; - #define SGID_TO_KGID(x) (KGIDT_INIT(x)) - #define KGIDP_TO_SGIDP(x) (&(x)->val) - --extern struct user_namespace *zfs_get_init_userns(void); -- - /* Check if the user ns is the initial one */ - static inline boolean_t - zfs_is_init_userns(struct user_namespace *user_ns) - { - #if defined(CONFIG_USER_NS) -- return (user_ns == zfs_init_user_ns); -+ return (user_ns == kcred->user_ns); - #else - return (B_FALSE); - #endif -@@ -63,7 +61,7 @@ static inline struct user_namespace *zfs_i_user_ns(struct inode *inode) - #ifdef HAVE_SUPER_USER_NS - return (inode->i_sb->s_user_ns); - #else -- return (zfs_init_user_ns); -+ return (kcred->user_ns); - #endif - } - -diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h -index e682c0560d5..cae1bbddf10 100644 ---- a/include/os/linux/spl/sys/types.h -+++ b/include/os/linux/spl/sys/types.h -@@ -56,6 +56,5 @@ typedef int minor_t; - - struct user_namespace; - typedef struct user_namespace zuserns_t; --extern zuserns_t *zfs_init_user_ns; - - #endif /* _SPL_TYPES_H */ -diff --git a/module/os/linux/spl/spl-cred.c b/module/os/linux/spl/spl-cred.c -index 1f406ec540b..f81b9540a63 100644 ---- a/module/os/linux/spl/spl-cred.c -+++ b/module/os/linux/spl/spl-cred.c -@@ -145,14 +145,6 @@ crgetgid(const cred_t *cr) - return (KGID_TO_SGID(cr->fsgid)); - } - --/* Return the initial user ns */ --struct user_namespace * --zfs_get_init_userns(void) --{ -- return (&init_user_ns); --} -- --EXPORT_SYMBOL(zfs_get_init_userns); - EXPORT_SYMBOL(crhold); - EXPORT_SYMBOL(crfree); - EXPORT_SYMBOL(crgetuid); -diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c -index 52978c1133e..3d31da6e35b 100644 ---- a/module/os/linux/zfs/zfs_acl.c -+++ b/module/os/linux/zfs/zfs_acl.c -@@ -1980,7 +1980,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - return (SET_ERROR(ENOSYS)); - - if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, -- zfs_init_user_ns))) -+ kcred->user_ns))) - return (error); - - mutex_enter(&zp->z_acl_lock); -@@ -2140,7 +2140,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - return (SET_ERROR(EPERM)); - - if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, -- zfs_init_user_ns))) -+ kcred->user_ns))) - return (error); - - error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, -@@ -2420,7 +2420,7 @@ zfs_has_access(znode_t *zp, cred_t *cr) - uint32_t have = ACE_ALL_PERMS; - - if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, -- zfs_init_user_ns) != 0) { -+ kcred->user_ns) != 0) { - uid_t owner; - - owner = zfs_fuid_map_id(ZTOZSB(zp), -@@ -2613,7 +2613,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - DTRACE_PROBE(zfs__fastpath__execute__access__miss); - ZFS_ENTER(ZTOZSB(zdp)); - error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -- zfs_init_user_ns); -+ kcred->user_ns); - ZFS_EXIT(ZTOZSB(zdp)); - return (error); - } -@@ -2790,7 +2790,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) - { - int v4_mode = zfs_unix_to_v4(mode >> 6); - -- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_user_ns)); -+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, kcred->user_ns)); - } - - /* See zfs_zaccess_delete() */ -diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c -index 4a04cc37d5c..8c65c33628d 100644 ---- a/module/os/linux/zfs/zfs_dir.c -+++ b/module/os/linux/zfs/zfs_dir.c -@@ -1067,7 +1067,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr) - *xzpp = NULL; - - if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, -- &acl_ids, zfs_init_user_ns)) != 0) -+ &acl_ids, kcred->user_ns)) != 0) - return (error); - if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { - zfs_acl_ids_free(&acl_ids); -@@ -1216,7 +1216,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) - - if ((uid = crgetuid(cr)) == downer || uid == fowner || - zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -- zfs_init_user_ns) == 0) -+ kcred->user_ns) == 0) - return (0); - else - return (secpolicy_vnode_remove(cr)); -diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c -index ad17973e7ad..29d968d22a4 100644 ---- a/module/os/linux/zfs/zfs_ioctl_os.c -+++ b/module/os/linux/zfs/zfs_ioctl_os.c -@@ -291,8 +291,6 @@ zfsdev_detach(void) - #define ZFS_DEBUG_STR "" - #endif - --zuserns_t *zfs_init_user_ns; -- - static int __init - openzfs_init(void) - { -@@ -316,8 +314,6 @@ openzfs_init(void) - printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); - #endif /* CONFIG_FS_POSIX_ACL */ - -- zfs_init_user_ns = (zuserns_t *)zfs_get_init_userns(); -- - return (0); - } - -diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c -index d7abe558cd0..23f3d140cf5 100644 ---- a/module/os/linux/zfs/zfs_vnops_os.c -+++ b/module/os/linux/zfs/zfs_vnops_os.c -@@ -501,7 +501,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, -- B_TRUE, cr, zfs_init_user_ns))) { -+ B_TRUE, cr, kcred->user_ns))) { - zrele(*zpp); - *zpp = NULL; - } -@@ -520,7 +520,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -- zfs_init_user_ns))) { -+ kcred->user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -1002,7 +1002,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_user_ns))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { - goto out; - } - -@@ -1418,7 +1418,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_user_ns))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { - goto out; - } - -@@ -3373,7 +3373,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, - } - - if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, -- zfs_init_user_ns))) { -+ kcred->user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3962,7 +3962,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, - * operates directly on inodes, so we need to check access rights. - */ - if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, -- zfs_init_user_ns))) { -+ kcred->user_ns))) { - ZFS_EXIT(zfsvfs); - return (error); - } -diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c -index 956346e0afd..5e820587388 100644 ---- a/module/os/linux/zfs/zfs_znode.c -+++ b/module/os/linux/zfs/zfs_znode.c -@@ -1947,7 +1947,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) - } - - VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, -- cr, NULL, &acl_ids, zfs_init_user_ns)); -+ cr, NULL, &acl_ids, kcred->user_ns)); - zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, rootzp); - error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); -diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c -index 6cc99d6f37a..e4f191ba051 100644 ---- a/module/os/linux/zfs/zpl_ctldir.c -+++ b/module/os/linux/zfs/zpl_ctldir.c -@@ -366,7 +366,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) - #ifdef HAVE_IOPS_MKDIR_USERNS - zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); - #else -- zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_user_ns); -+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, kcred->user_ns); - #endif - - error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index 8d320101ee3..4ad30efd3ec 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -971,7 +971,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1019,7 +1019,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1107,7 +1107,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_user_ns); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - -diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c -index 5eb95676e88..62461841248 100644 ---- a/module/os/linux/zfs/zpl_inode.c -+++ b/module/os/linux/zfs/zpl_inode.c -@@ -144,7 +144,7 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_CREATE_USERNS -- zuserns_t *user_ns = zfs_init_user_ns; -+ zuserns_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -@@ -191,7 +191,7 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_MKNOD_USERNS -- zuserns_t *user_ns = zfs_init_user_ns; -+ zuserns_t *user_ns = kcred->user_ns; - #endif - - /* -@@ -251,7 +251,7 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_TMPFILE_USERNS -- zuserns_t *userns = zfs_init_user_ns; -+ zuserns_t *userns = kcred->user_ns; - #endif - - crhold(cr); -@@ -339,7 +339,7 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_MKDIR_USERNS -- zuserns_t *user_ns = zfs_init_user_ns; -+ zuserns_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -@@ -496,7 +496,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - #ifdef HAVE_SETATTR_PREPARE_USERNS - error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); - #else -- error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_user_ns); -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, kcred->user_ns); - #endif - if (!error && (ia->ia_valid & ATTR_MODE)) - error = zpl_chmod_acl(ip); -@@ -523,7 +523,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_RENAME_USERNS -- zuserns_t *user_ns = zfs_init_user_ns; -+ zuserns_t *user_ns = kcred->user_ns; - #endif - - /* We don't have renameat2(2) support */ -@@ -564,7 +564,7 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) - int error; - fstrans_cookie_t cookie; - #ifndef HAVE_IOPS_SYMLINK_USERNS -- zuserns_t *user_ns = zfs_init_user_ns; -+ zuserns_t *user_ns = kcred->user_ns; - #endif - - crhold(cr); -diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c -index c2be9352ae1..b377651bad4 100644 ---- a/module/os/linux/zfs/zpl_xattr.c -+++ b/module/os/linux/zfs/zpl_xattr.c -@@ -496,7 +496,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, - vap->va_gid = crgetgid(cr); - - error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, -- cr, 0, NULL, zfs_init_user_ns); -+ cr, 0, NULL, kcred->user_ns); - if (error) - goto out; - } -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index 950339ceade..c83867fe535 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -385,7 +385,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - } - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, &vsec, zfs_init_user_ns); -+ 0, 0, &zp, kcred, vflg, &vsec, kcred->user_ns); - break; - case TX_MKDIR_ACL: - aclstart = (caddr_t)(lracl + 1); -@@ -415,7 +415,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - } - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, &vsec, zfs_init_user_ns); -+ &zp, kcred, vflg, &vsec, kcred->user_ns); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -525,7 +525,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)start; - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, NULL, zfs_init_user_ns); -+ 0, 0, &zp, kcred, vflg, NULL, kcred->user_ns); - break; - case TX_MKDIR_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); -@@ -542,7 +542,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, NULL, zfs_init_user_ns); -+ &zp, kcred, vflg, NULL, kcred->user_ns); - break; - case TX_MKXATTR: - error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); -@@ -551,7 +551,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - link = name + strlen(name) + 1; - error = zfs_symlink(dzp, name, &xva.xva_vattr, -- link, &zp, kcred, vflg, zfs_init_user_ns); -+ link, &zp, kcred, vflg, kcred->user_ns); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -663,7 +663,7 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - if (lr->lr_common.lrc_txtype & TX_CI) - vflg |= FIGNORECASE; - -- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, zfs_init_user_ns); -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, kcred->user_ns); - - zrele(tdzp); - zrele(sdzp); -@@ -857,7 +857,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) - zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, - lr->lr_uid, lr->lr_gid); - -- error = zfs_setattr(zp, vap, 0, kcred, zfs_init_user_ns); -+ error = zfs_setattr(zp, vap, 0, kcred, kcred->user_ns); - - zfs_fuid_info_free(zfsvfs->z_fuid_replay); - zfsvfs->z_fuid_replay = NULL; -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index 7ef1fcf99ed..f8fa53bd615 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -166,9 +166,9 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - - if (flag & V_ACE_MASK) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, -- zfs_init_user_ns); -+ kcred->user_ns); - else -- error = zfs_zaccess_rwx(zp, mode, flag, cr, zfs_init_user_ns); -+ error = zfs_zaccess_rwx(zp, mode, flag, cr, kcred->user_ns); - - ZFS_EXIT(zfsvfs); - return (error); - -From 1ba71ae1eccf1057d89253f94ac638d493c5486f Mon Sep 17 00:00:00 2001 -From: Youzhong Yang <yyang@mathworks.com> -Date: Tue, 1 Nov 2022 19:18:59 -0400 -Subject: [PATCH 3/8] No need to include sys/cred.h - -Signed-off-by: Youzhong Yang <yyang@mathworks.com> ---- - module/os/linux/zfs/zfs_ioctl_os.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c -index 29d968d22a4..d70b31f9f10 100644 ---- a/module/os/linux/zfs/zfs_ioctl_os.c -+++ b/module/os/linux/zfs/zfs_ioctl_os.c -@@ -60,7 +60,6 @@ - #include <sys/dsl_crypt.h> - #include <sys/crypto/icp.h> - #include <sys/zstd/zstd.h> --#include <sys/cred.h> - - #include <sys/zfs_ioctl_impl.h> - - -From 132f2bfb9ed8f7544415d0ef5e921a556b8ed613 Mon Sep 17 00:00:00 2001 -From: Youzhong Yang <yyang@mathworks.com> -Date: Thu, 3 Nov 2022 13:49:46 +0000 -Subject: [PATCH 4/8] Declare init_task in cred.h, fix build error on 18.04 - -Signed-off-by: Youzhong Yang <yyang@mathworks.com> ---- - include/os/linux/spl/sys/cred.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index 6c891164b08..3bed5fa013e 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -31,6 +31,8 @@ - - typedef struct cred cred_t; - -+extern struct task_struct init_task; -+ - #define kcred ((cred_t *)(init_task.cred)) - #define CRED() ((cred_t *)current_cred()) - - -From 61d77dcd1a284c64c533c34c11c688f5003b5ca8 Mon Sep 17 00:00:00 2001 -From: Youzhong Yang <yyang@mathworks.com> -Date: Thu, 3 Nov 2022 10:35:25 -0400 -Subject: [PATCH 5/8] Include sched.h for task_struct - -Signed-off-by: Youzhong Yang <yyang@mathworks.com> ---- - include/os/linux/spl/sys/cred.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index 3bed5fa013e..75ad400d312 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -26,6 +26,7 @@ - - #include <linux/module.h> - #include <linux/cred.h> -+#include <linux/sched.h> - #include <sys/types.h> - #include <sys/vfs.h> - - -From 9919d64fe026ab3361bdea443957d95fcc928c49 Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:27:44 -0500 -Subject: [PATCH 6/8] Backport "Fix FreeBSD build errors" - ---- - module/zfs/zfs_replay.c | 32 +++++++++++++++++++++++++++++++- - module/zfs/zfs_vnops.c | 8 ++++++++ - 2 files changed, 39 insertions(+), 1 deletion(-) - -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index c83867fe535..491314716fa 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -385,7 +385,11 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - } - - error = zfs_create(dzp, name, &xva.xva_vattr, -+#if defined(__linux__) - 0, 0, &zp, kcred, vflg, &vsec, kcred->user_ns); -+#else -+ 0, 0, &zp, kcred, vflg, &vsec, NULL); -+#endif - break; - case TX_MKDIR_ACL: - aclstart = (caddr_t)(lracl + 1); -@@ -415,7 +419,11 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - } - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -+#if defined(__linux__) - &zp, kcred, vflg, &vsec, kcred->user_ns); -+#else -+ &zp, kcred, vflg, &vsec, NULL); -+#endif - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -525,7 +533,11 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)start; - - error = zfs_create(dzp, name, &xva.xva_vattr, -+#if defined(__linux__) - 0, 0, &zp, kcred, vflg, NULL, kcred->user_ns); -+#else -+ 0, 0, &zp, kcred, vflg, NULL, NULL); -+#endif - break; - case TX_MKDIR_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); -@@ -542,7 +554,12 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -+#if defined(__linux__) - &zp, kcred, vflg, NULL, kcred->user_ns); -+#else -+ &zp, kcred, vflg, NULL, NULL); -+#endif -+ - break; - case TX_MKXATTR: - error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); -@@ -551,7 +568,11 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - link = name + strlen(name) + 1; - error = zfs_symlink(dzp, name, &xva.xva_vattr, -+#if defined(__linux__) - link, &zp, kcred, vflg, kcred->user_ns); -+#else -+ link, &zp, kcred, vflg, NULL); -+#endif - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -663,7 +684,12 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - if (lr->lr_common.lrc_txtype & TX_CI) - vflg |= FIGNORECASE; - -- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, kcred->user_ns); -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, -+#if defined(__linux__) -+ kcred->user_ns); -+#else -+ NULL); -+#endif - - zrele(tdzp); - zrele(sdzp); -@@ -857,7 +883,11 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) - zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, - lr->lr_uid, lr->lr_gid); - -+#if defined(__linux__) - error = zfs_setattr(zp, vap, 0, kcred, kcred->user_ns); -+#else -+ error = zfs_setattr(zp, vap, 0, kcred, NULL); -+#endif - - zfs_fuid_info_free(zfsvfs->z_fuid_replay); - zfsvfs->z_fuid_replay = NULL; -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index f8fa53bd615..3a46e1d0686 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -166,9 +166,17 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - - if (flag & V_ACE_MASK) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, -+#if defined(__linux__) - kcred->user_ns); -+#else -+ NULL); -+#endif - else -+#if defined(__linux__) - error = zfs_zaccess_rwx(zp, mode, flag, cr, kcred->user_ns); -+#else -+ error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL); -+#endif - - ZFS_EXIT(zfsvfs); - return (error); - -From 0eac99fb03f77c4dc19a11850f62993ae6340c59 Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:28:39 -0500 -Subject: [PATCH 7/8] Backport "Fix style errors" - ---- - module/zfs/zfs_replay.c | 18 ++++++++++++------ - module/zfs/zfs_vnops.c | 3 ++- - 2 files changed, 14 insertions(+), 7 deletions(-) - -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index 491314716fa..755bbc6cd98 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -384,10 +384,11 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - } - -- error = zfs_create(dzp, name, &xva.xva_vattr, - #if defined(__linux__) -+ error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, &vsec, kcred->user_ns); - #else -+ error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, &vsec, NULL); - #endif - break; -@@ -418,10 +419,11 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, - lr->lr_uid, lr->lr_gid); - } -- error = zfs_mkdir(dzp, name, &xva.xva_vattr, - #if defined(__linux__) -+ error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, &vsec, kcred->user_ns); - #else -+ error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, &vsec, NULL); - #endif - break; -@@ -532,10 +534,11 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - if (name == NULL) - name = (char *)start; - -- error = zfs_create(dzp, name, &xva.xva_vattr, - #if defined(__linux__) -+ error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, NULL, kcred->user_ns); - #else -+ error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, NULL, NULL); - #endif - break; -@@ -553,10 +556,11 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - if (name == NULL) - name = (char *)(lr + 1); - -- error = zfs_mkdir(dzp, name, &xva.xva_vattr, - #if defined(__linux__) -+ error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, NULL, kcred->user_ns); - #else -+ error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, NULL, NULL); - #endif - -@@ -567,10 +571,11 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - case TX_SYMLINK: - name = (char *)(lr + 1); - link = name + strlen(name) + 1; -- error = zfs_symlink(dzp, name, &xva.xva_vattr, - #if defined(__linux__) -+ error = zfs_symlink(dzp, name, &xva.xva_vattr, - link, &zp, kcred, vflg, kcred->user_ns); - #else -+ error = zfs_symlink(dzp, name, &xva.xva_vattr, - link, &zp, kcred, vflg, NULL); - #endif - break; -@@ -684,10 +689,11 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - if (lr->lr_common.lrc_txtype & TX_CI) - vflg |= FIGNORECASE; - -- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, - #if defined(__linux__) -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, - kcred->user_ns); - #else -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, - NULL); - #endif - -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index 3a46e1d0686..2b6d35282a0 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -165,10 +165,11 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - ZFS_VERIFY_ZP(zp); - - if (flag & V_ACE_MASK) -- error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, - #if defined(__linux__) -+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, - kcred->user_ns); - #else -+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, - NULL); - #endif - else - -From d628d7ff4325a034afbf23460f667ece64781bbf Mon Sep 17 00:00:00 2001 -From: Youzhong Yang <yyang@mathworks.com> -Date: Sat, 5 Nov 2022 00:56:25 +0000 -Subject: [PATCH 8/8] zpl_setattr() needs a fix to work on kernel 6 - -Signed-off-by: Youzhong Yang <yyang@mathworks.com> ---- - config/kernel-iattr-vfsid.m4 | 24 ++++++++++++++++++++++++ - config/kernel.m4 | 2 ++ - module/os/linux/zfs/zpl_inode.c | 16 ++++++++++++++-- - 3 files changed, 40 insertions(+), 2 deletions(-) - create mode 100644 config/kernel-iattr-vfsid.m4 - -diff --git a/config/kernel-iattr-vfsid.m4 b/config/kernel-iattr-vfsid.m4 -new file mode 100644 -index 00000000000..75bc4613b83 ---- /dev/null -+++ b/config/kernel-iattr-vfsid.m4 -@@ -0,0 +1,24 @@ -+dnl # -+dnl # 6.0 API change -+dnl # struct iattr has two unions for the uid and gid -+dnl # -+AC_DEFUN([ZFS_AC_KERNEL_SRC_IATTR_VFSID], [ -+ ZFS_LINUX_TEST_SRC([iattr_vfsid], [ -+ #include <linux/fs.h> -+ ], [ -+ struct iattr ia; -+ ia.ia_vfsuid = (vfsuid_t){0}; -+ ia.ia_vfsgid = (vfsgid_t){0}; -+ ]) -+]) -+ -+AC_DEFUN([ZFS_AC_KERNEL_IATTR_VFSID], [ -+ AC_MSG_CHECKING([whether iattr->ia_vfsuid and iattr->ia_vfsgid exist]) -+ ZFS_LINUX_TEST_RESULT([iattr_vfsid], [ -+ AC_MSG_RESULT(yes) -+ AC_DEFINE(HAVE_IATTR_VFSID, 1, -+ [iattr->ia_vfsuid and iattr->ia_vfsgid exist]) -+ ],[ -+ AC_MSG_RESULT(no) -+ ]) -+]) -diff --git a/config/kernel.m4 b/config/kernel.m4 -index 44f4d072501..1998b831e96 100644 ---- a/config/kernel.m4 -+++ b/config/kernel.m4 -@@ -146,6 +146,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC_ZERO_PAGE - ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC - ZFS_AC_KERNEL_SRC_IDMAP_MNT_API -+ ZFS_AC_KERNEL_SRC_IATTR_VFSID - - AC_MSG_CHECKING([for available kernel interfaces]) - ZFS_LINUX_TEST_COMPILE_ALL([kabi]) -@@ -265,6 +266,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL_ZERO_PAGE - ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC - ZFS_AC_KERNEL_IDMAP_MNT_API -+ ZFS_AC_KERNEL_IATTR_VFSID - ]) - - dnl # -diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c -index 62461841248..ea659d9618a 100644 ---- a/module/os/linux/zfs/zpl_inode.c -+++ b/module/os/linux/zfs/zpl_inode.c -@@ -482,8 +482,20 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK; - vap->va_mode = ia->ia_mode; -- vap->va_uid = KUID_TO_SUID(ia->ia_uid); -- vap->va_gid = KGID_TO_SGID(ia->ia_gid); -+ if (ia->ia_valid & ATTR_UID) -+#ifdef HAVE_IATTR_VFSID -+ vap->va_uid = zfs_vfsuid_to_uid(user_ns, zfs_i_user_ns(ip), -+ __vfsuid_val(ia->ia_vfsuid)); -+#else -+ vap->va_uid = KUID_TO_SUID(ia->ia_uid); -+#endif -+ if (ia->ia_valid & ATTR_GID) -+#ifdef HAVE_IATTR_VFSID -+ vap->va_gid = zfs_vfsgid_to_gid(user_ns, zfs_i_user_ns(ip), -+ __vfsgid_val(ia->ia_vfsgid)); -+#else -+ vap->va_gid = KGID_TO_SGID(ia->ia_gid); -+#endif - vap->va_size = ia->ia_size; - vap->va_atime = ia->ia_atime; - vap->va_mtime = ia->ia_mtime; diff --git a/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount.patch b/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount.patch deleted file mode 100644 index ae05264c10a7dac154cd50c987ac9844aef45bee..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/files/2.1.11-support-idmapped-mount.patch +++ /dev/null @@ -1,3203 +0,0 @@ -From 259662bc5e8b234dd8f253acc8cff9083927f560 Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:04:02 -0500 -Subject: [PATCH 1/3] Backport "Support idmapped mount" - ---- - config/kernel-idmap_mnt_api.m4 | 25 ++++++++ - config/kernel.m4 | 2 + - include/os/freebsd/spl/sys/types.h | 2 + - include/os/freebsd/zfs/sys/zfs_vnops_os.h | 12 ++-- - include/os/linux/spl/sys/cred.h | 28 +++++++++ - include/os/linux/spl/sys/types.h | 3 + - include/os/linux/zfs/sys/policy.h | 4 +- - include/os/linux/zfs/sys/zfs_vnops_os.h | 15 +++-- - include/os/linux/zfs/sys/zpl.h | 2 +- - include/sys/zfs_acl.h | 11 ++-- - module/os/freebsd/zfs/zfs_acl.c | 30 +++++---- - module/os/freebsd/zfs/zfs_dir.c | 4 +- - module/os/freebsd/zfs/zfs_vnops_os.c | 60 ++++++++++-------- - module/os/freebsd/zfs/zfs_znode.c | 4 +- - module/os/linux/zfs/policy.c | 13 ++-- - module/os/linux/zfs/zfs_acl.c | 76 +++++++++++++--------- - module/os/linux/zfs/zfs_dir.c | 4 +- - module/os/linux/zfs/zfs_vnops_os.c | 77 ++++++++++++++--------- - module/os/linux/zfs/zfs_znode.c | 2 +- - module/os/linux/zfs/zpl_ctldir.c | 6 +- - module/os/linux/zfs/zpl_file.c | 6 +- - module/os/linux/zfs/zpl_inode.c | 62 +++++++++++++----- - module/os/linux/zfs/zpl_super.c | 5 ++ - module/os/linux/zfs/zpl_xattr.c | 2 +- - module/zfs/zfs_replay.c | 14 ++--- - module/zfs/zfs_vnops.c | 4 +- - 26 files changed, 312 insertions(+), 161 deletions(-) - create mode 100644 config/kernel-idmap_mnt_api.m4 - -diff --git a/config/kernel-idmap_mnt_api.m4 b/config/kernel-idmap_mnt_api.m4 -new file mode 100644 -index 00000000000..47ddc5702fb ---- /dev/null -+++ b/config/kernel-idmap_mnt_api.m4 -@@ -0,0 +1,25 @@ -+dnl # -+dnl # 5.12 API -+dnl # -+dnl # Check if APIs for idmapped mount are available -+dnl # -+AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_MNT_API], [ -+ ZFS_LINUX_TEST_SRC([idmap_mnt_api], [ -+ #include <linux/fs.h> -+ ],[ -+ int fs_flags = 0; -+ fs_flags |= FS_ALLOW_IDMAP; -+ ]) -+]) -+ -+AC_DEFUN([ZFS_AC_KERNEL_IDMAP_MNT_API], [ -+ AC_MSG_CHECKING([whether APIs for idmapped mount are present]) -+ ZFS_LINUX_TEST_RESULT([idmap_mnt_api], [ -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE(HAVE_IDMAP_MNT_API, 1, -+ [APIs for idmapped mount are present]) -+ ],[ -+ AC_MSG_RESULT([no]) -+ ]) -+]) -+ -diff --git a/config/kernel.m4 b/config/kernel.m4 -index 7b0c59d26d4..44f4d072501 100644 ---- a/config/kernel.m4 -+++ b/config/kernel.m4 -@@ -145,6 +145,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ - ZFS_AC_KERNEL_SRC_KTHREAD - ZFS_AC_KERNEL_SRC_ZERO_PAGE - ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC -+ ZFS_AC_KERNEL_SRC_IDMAP_MNT_API - - AC_MSG_CHECKING([for available kernel interfaces]) - ZFS_LINUX_TEST_COMPILE_ALL([kabi]) -@@ -263,6 +264,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ - ZFS_AC_KERNEL_KTHREAD - ZFS_AC_KERNEL_ZERO_PAGE - ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC -+ ZFS_AC_KERNEL_IDMAP_MNT_API - ]) - - dnl # -diff --git a/include/os/freebsd/spl/sys/types.h b/include/os/freebsd/spl/sys/types.h -index ecb91fd1bb8..6557c840feb 100644 ---- a/include/os/freebsd/spl/sys/types.h -+++ b/include/os/freebsd/spl/sys/types.h -@@ -104,5 +104,7 @@ typedef u_longlong_t len_t; - - typedef longlong_t diskaddr_t; - -+typedef void zuserns_t; -+ - #include <sys/debug.h> - #endif /* !_OPENSOLARIS_SYS_TYPES_H_ */ -diff --git a/include/os/freebsd/zfs/sys/zfs_vnops_os.h b/include/os/freebsd/zfs/sys/zfs_vnops_os.h -index bf5e03b24c0..460aecd2e70 100644 ---- a/include/os/freebsd/zfs/sys/zfs_vnops_os.h -+++ b/include/os/freebsd/zfs/sys/zfs_vnops_os.h -@@ -35,20 +35,22 @@ int dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count, - int *rbehind, int *rahead, int last_size); - extern int zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags); - extern int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, -- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp); -+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); - extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd, - cred_t *cr, int flags); --extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); -+extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, -+ zuserns_t *mnt_ns); - extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp, -- const char *tnm, cred_t *cr, int flags); -+ const char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); - extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, -- const char *link, znode_t **zpp, cred_t *cr, int flags); -+ const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); - extern int zfs_link(znode_t *tdzp, znode_t *sp, - const char *name, cred_t *cr, int flags); - extern int zfs_space(znode_t *zp, int cmd, struct flock *bfp, int flag, - offset_t offset, cred_t *cr); - extern int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, -- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp); -+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -+ zuserns_t *mnt_ns); - extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, - cred_t *cr); - extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, -diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h -index b7d3f38d70b..dc3c260dbba 100644 ---- a/include/os/linux/spl/sys/cred.h -+++ b/include/os/linux/spl/sys/cred.h -@@ -45,6 +45,34 @@ typedef struct cred cred_t; - #define SGID_TO_KGID(x) (KGIDT_INIT(x)) - #define KGIDP_TO_SGIDP(x) (&(x)->val) - -+static inline uid_t zfs_uid_into_mnt(struct user_namespace *mnt_ns, uid_t uid) -+{ -+ if (mnt_ns) -+ return (__kuid_val(make_kuid(mnt_ns, uid))); -+ return (uid); -+} -+ -+static inline gid_t zfs_gid_into_mnt(struct user_namespace *mnt_ns, gid_t gid) -+{ -+ if (mnt_ns) -+ return (__kgid_val(make_kgid(mnt_ns, gid))); -+ return (gid); -+} -+ -+static inline uid_t zfs_uid_from_mnt(struct user_namespace *mnt_ns, uid_t uid) -+{ -+ if (mnt_ns) -+ return (from_kuid(mnt_ns, KUIDT_INIT(uid))); -+ return (uid); -+} -+ -+static inline gid_t zfs_gid_from_mnt(struct user_namespace *mnt_ns, gid_t gid) -+{ -+ if (mnt_ns) -+ return (from_kgid(mnt_ns, KGIDT_INIT(gid))); -+ return (gid); -+} -+ - extern void crhold(cred_t *cr); - extern void crfree(cred_t *cr); - extern uid_t crgetuid(const cred_t *cr); -diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h -index b44c9451875..cae1bbddf10 100644 ---- a/include/os/linux/spl/sys/types.h -+++ b/include/os/linux/spl/sys/types.h -@@ -54,4 +54,7 @@ typedef ulong_t pgcnt_t; - typedef int major_t; - typedef int minor_t; - -+struct user_namespace; -+typedef struct user_namespace zuserns_t; -+ - #endif /* _SPL_TYPES_H */ -diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h -index 61afc376550..5ec51392f17 100644 ---- a/include/os/linux/zfs/sys/policy.h -+++ b/include/os/linux/zfs/sys/policy.h -@@ -47,13 +47,13 @@ int secpolicy_vnode_create_gid(const cred_t *); - int secpolicy_vnode_remove(const cred_t *); - int secpolicy_vnode_setdac(const cred_t *, uid_t); - int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t); --int secpolicy_vnode_setids_setgids(const cred_t *, gid_t); -+int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *); - int secpolicy_zinject(const cred_t *); - int secpolicy_zfs(const cred_t *); - int secpolicy_zfs_proc(const cred_t *, proc_t *); - void secpolicy_setid_clear(vattr_t *, cred_t *); - int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *, -- const vattr_t *, cred_t *); -+ const vattr_t *, cred_t *, zuserns_t *); - int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t); - int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *, - const struct vattr *, int, int (void *, int, cred_t *), void *); -diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h -index 47f91e4a6cf..fcb32308562 100644 ---- a/include/os/linux/zfs/sys/zfs_vnops_os.h -+++ b/include/os/linux/zfs/sys/zfs_vnops_os.h -@@ -45,22 +45,25 @@ extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, - extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags, - cred_t *cr, int *direntflags, pathname_t *realpnp); - extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, -- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp); -+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -+ zuserns_t *mnt_ns); - extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl, -- int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp); -+ int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, -+ zuserns_t *mnt_ns); - extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags); - extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, -- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp); -+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); - 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 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_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, -+ zuserns_t *mnt_ns); - extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, -- char *tnm, cred_t *cr, int flags); -+ char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); - extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, -- char *link, znode_t **zpp, cred_t *cr, int flags); -+ char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); - extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr); - extern int zfs_link(znode_t *tdzp, znode_t *szp, - char *name, cred_t *cr, int flags); -diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h -index ac9815d4ee0..703e335c28a 100644 ---- a/include/os/linux/zfs/sys/zpl.h -+++ b/include/os/linux/zfs/sys/zpl.h -@@ -39,7 +39,7 @@ - - /* zpl_inode.c */ - extern void zpl_vap_init(vattr_t *vap, struct inode *dir, -- umode_t mode, cred_t *cr); -+ umode_t mode, cred_t *cr, zuserns_t *mnt_ns); - - extern const struct inode_operations zpl_inode_operations; - extern const struct inode_operations zpl_dir_inode_operations; -diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h -index 010686a9121..93a1f7f6172 100644 ---- a/include/sys/zfs_acl.h -+++ b/include/sys/zfs_acl.h -@@ -206,7 +206,7 @@ struct zfsvfs; - - #ifdef _KERNEL - int zfs_acl_ids_create(struct znode *, int, vattr_t *, -- cred_t *, vsecattr_t *, zfs_acl_ids_t *); -+ cred_t *, vsecattr_t *, zfs_acl_ids_t *, zuserns_t *); - void zfs_acl_ids_free(zfs_acl_ids_t *); - boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t); - int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *); -@@ -215,15 +215,16 @@ void zfs_acl_rele(void *); - void zfs_oldace_byteswap(ace_t *, int); - void zfs_ace_byteswap(void *, size_t, boolean_t); - extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr); --extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *); -+extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *, -+ zuserns_t *); - int zfs_fastaccesschk_execute(struct znode *, cred_t *); --extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *); -+extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zuserns_t *); - extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *); - extern int zfs_acl_access(struct znode *, int, cred_t *); - int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t); --int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *); -+int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zuserns_t *); - int zfs_zaccess_rename(struct znode *, struct znode *, -- struct znode *, struct znode *, cred_t *cr); -+ struct znode *, struct znode *, cred_t *cr, zuserns_t *mnt_ns); - void zfs_acl_free(zfs_acl_t *); - int zfs_vsec_2_aclp(struct zfsvfs *, umode_t, vsecattr_t *, cred_t *, - struct zfs_fuid_info **, zfs_acl_t **); -diff --git a/module/os/freebsd/zfs/zfs_acl.c b/module/os/freebsd/zfs/zfs_acl.c -index fe0f6913232..ca50f442a07 100644 ---- a/module/os/freebsd/zfs/zfs_acl.c -+++ b/module/os/freebsd/zfs/zfs_acl.c -@@ -1618,7 +1618,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, - */ - int - zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, -- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) -+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) - { - int error; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -1788,7 +1788,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (mask == 0) - return (SET_ERROR(ENOSYS)); - -- if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr))) -+ if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) - return (error); - - mutex_enter(&zp->z_acl_lock); -@@ -1951,7 +1951,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (zp->z_pflags & ZFS_IMMUTABLE) - return (SET_ERROR(EPERM)); - -- if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr))) -+ if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) - return (error); - - error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, -@@ -2340,7 +2340,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - * can define any form of access. - */ - int --zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) -+zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, -+ zuserns_t *mnt_ns) - { - uint32_t working_mode; - int error; -@@ -2470,9 +2471,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) - * NFSv4-style ZFS ACL format and call zfs_zaccess() - */ - int --zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) -+zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, -+ zuserns_t *mnt_ns) - { -- return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); -+ return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, -+ mnt_ns)); - } - - /* -@@ -2483,7 +2486,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) - { - int v4_mode = zfs_unix_to_v4(mode >> 6); - -- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr)); -+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); - } - - static int -@@ -2539,7 +2542,7 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp, - * - */ - int --zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) -+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) - { - uint32_t dzp_working_mode = 0; - uint32_t zp_working_mode = 0; -@@ -2626,7 +2629,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) - - int - zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, -- znode_t *tzp, cred_t *cr) -+ znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) - { - int add_perm; - int error; -@@ -2646,7 +2649,8 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, - * to another. - */ - if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) { -- if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr))) -+ if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr, -+ mnt_ns))) - return (error); - } - -@@ -2656,19 +2660,19 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, - * If that succeeds then check for add_file/add_subdir permissions - */ - -- if ((error = zfs_zaccess_delete(sdzp, szp, cr))) -+ if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) - return (error); - - /* - * If we have a tzp, see if we can delete it? - */ -- if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr))) -+ if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) - return (error); - - /* - * Now check for add permissions - */ -- error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); -+ error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); - - return (error); - } -diff --git a/module/os/freebsd/zfs/zfs_dir.c b/module/os/freebsd/zfs/zfs_dir.c -index 7fff329a939..eebe34228e7 100644 ---- a/module/os/freebsd/zfs/zfs_dir.c -+++ b/module/os/freebsd/zfs/zfs_dir.c -@@ -810,7 +810,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xvpp, cred_t *cr) - *xvpp = NULL; - - if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, -- &acl_ids)) != 0) -+ &acl_ids, NULL)) != 0) - return (error); - if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, 0)) { - zfs_acl_ids_free(&acl_ids); -@@ -956,7 +956,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) - - if ((uid = crgetuid(cr)) == downer || uid == fowner || - (ZTOV(zp)->v_type == VREG && -- zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0)) -+ zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0)) - return (0); - else - return (secpolicy_vnode_remove(ZTOV(zp), cr)); -diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c -index ea6388dd515..0b7bbbdc52b 100644 ---- a/module/os/freebsd/zfs/zfs_vnops_os.c -+++ b/module/os/freebsd/zfs/zfs_vnops_os.c -@@ -852,7 +852,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, - /* - * Do we have permission to get into attribute directory? - */ -- error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr); -+ error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); - if (error) { - vrele(ZTOV(zp)); - } -@@ -871,7 +871,8 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, - cnp->cn_flags &= ~NOEXECCHECK; - } else - #endif -- if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, -+ NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -1047,6 +1048,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, - * flag - large file flag [UNUSED]. - * ct - caller context - * vsecp - ACL to be set -+ * mnt_ns - Unused on FreeBSD - * - * OUT: vpp - vnode of created or trunc'd entry. - * -@@ -1060,7 +1062,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, - /* ARGSUSED */ - int - zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, -- znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp) -+ znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, zuserns_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -1122,7 +1124,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, - * Create a new file object and update the directory - * to reference it. - */ -- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { - goto out; - } - -@@ -1138,7 +1140,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, - } - - if ((error = zfs_acl_ids_create(dzp, 0, vap, -- cr, vsecp, &acl_ids)) != 0) -+ cr, vsecp, &acl_ids, NULL)) != 0) - goto out; - - if (S_ISREG(vap->va_mode) || S_ISDIR(vap->va_mode)) -@@ -1242,7 +1244,7 @@ zfs_remove_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr) - xattr_obj = 0; - xzp = NULL; - -- if ((error = zfs_zaccess_delete(dzp, zp, cr))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { - goto out; - } - -@@ -1398,6 +1400,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags) - * ct - caller context - * flags - case flags - * vsecp - ACL to be set -+ * mnt_ns - Unused on FreeBSD - * - * OUT: vpp - vnode of created directory. - * -@@ -1410,7 +1413,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags) - /*ARGSUSED*/ - int - zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, -- cred_t *cr, int flags, vsecattr_t *vsecp) -+ cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = dzp->z_zfsvfs; -@@ -1458,7 +1461,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, - } - - if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, -- NULL, &acl_ids)) != 0) { -+ NULL, &acl_ids, NULL)) != 0) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -1479,7 +1482,8 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, - } - ASSERT3P(zp, ==, NULL); - -- if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr, -+ mnt_ns))) { - zfs_acl_ids_free(&acl_ids); - ZFS_EXIT(zfsvfs); - return (error); -@@ -1594,7 +1598,7 @@ zfs_rmdir_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr) - zilog = zfsvfs->z_log; - - -- if ((error = zfs_zaccess_delete(dzp, zp, cr))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { - goto out; - } - -@@ -2045,7 +2049,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) - if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) && - (vap->va_uid != crgetuid(cr))) { - if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0, -- skipaclchk, cr))) { -+ skipaclchk, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -2211,7 +2215,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) - * flags - ATTR_UTIME set if non-default time values provided. - * - ATTR_NOACLCHECK (CIFS context only). - * cr - credentials of caller. -- * ct - caller context -+ * mnt_ns - Unused on FreeBSD - * - * RETURN: 0 on success, error code on failure. - * -@@ -2220,7 +2224,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) - */ - /* ARGSUSED */ - int --zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) -+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) - { - vnode_t *vp = ZTOV(zp); - zfsvfs_t *zfsvfs = zp->z_zfsvfs; -@@ -2392,7 +2396,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - XVA_ISSET_REQ(xvap, XAT_CREATETIME) || - XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { - need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, -- skipaclchk, cr); -+ skipaclchk, cr, mnt_ns); - } - - if (mask & (AT_UID|AT_GID)) { -@@ -2429,7 +2433,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - ((idmask == AT_UID) && take_owner) || - ((idmask == AT_GID) && take_group)) { - if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, -- skipaclchk, cr) == 0) { -+ skipaclchk, cr, mnt_ns) == 0) { - /* - * Remove setuid/setgid for non-privileged users - */ -@@ -2538,7 +2542,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - } - - if (mask & AT_MODE) { -- if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { -+ if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, -+ mnt_ns) == 0) { - err = secpolicy_setid_setsticky_clear(vp, vap, - &oldva, cr); - if (err) { -@@ -3322,7 +3327,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, - * Note that if target and source are the same, this can be - * done in a single check. - */ -- if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))) -+ if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, NULL))) - goto out; - - if ((*svpp)->v_type == VDIR) { -@@ -3473,7 +3478,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, - - int - zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, -- cred_t *cr, int flags) -+ cred_t *cr, int flags, zuserns_t *mnt_ns) - { - struct componentname scn, tcn; - vnode_t *sdvp, *tdvp; -@@ -3518,6 +3523,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, - * cr - credentials of caller. - * ct - caller context - * flags - case flags -+ * mnt_ns - Unused on FreeBSD - * - * RETURN: 0 on success, error code on failure. - * -@@ -3527,7 +3533,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, - /*ARGSUSED*/ - int - zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, -- const char *link, znode_t **zpp, cred_t *cr, int flags) -+ const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) - { - znode_t *zp; - dmu_tx_t *tx; -@@ -3572,7 +3578,7 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, - return (error); - } - -- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { - zfs_acl_ids_free(&acl_ids); - ZFS_EXIT(zfsvfs); - return (error); -@@ -3785,7 +3791,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr, - return (SET_ERROR(EPERM)); - } - -- if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3886,7 +3892,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, - * On Linux we can get here through truncate_range() which - * operates directly on inodes, so we need to check access rights. - */ -- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -4658,8 +4664,8 @@ zfs_freebsd_create(struct vop_create_args *ap) - zfsvfs = ap->a_dvp->v_mount->mnt_data; - *ap->a_vpp = NULL; - -- rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, !EXCL, mode, -- &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */); -+ rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode, -+ &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL); - if (rc == 0) - *ap->a_vpp = ZTOV(zp); - if (zfsvfs->z_use_namecache && -@@ -4713,7 +4719,7 @@ zfs_freebsd_mkdir(struct vop_mkdir_args *ap) - *ap->a_vpp = NULL; - - rc = zfs_mkdir(VTOZ(ap->a_dvp), ap->a_cnp->cn_nameptr, vap, &zp, -- ap->a_cnp->cn_cred, 0, NULL); -+ ap->a_cnp->cn_cred, 0, NULL, NULL); - - if (rc == 0) - *ap->a_vpp = ZTOV(zp); -@@ -4966,7 +4972,7 @@ zfs_freebsd_setattr(struct vop_setattr_args *ap) - xvap.xva_vattr.va_mask |= AT_XVATTR; - XVA_SET_REQ(&xvap, XAT_CREATETIME); - } -- return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred)); -+ return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred, NULL)); - } - - #ifndef _SYS_SYSPROTO_H_ -@@ -5037,7 +5043,7 @@ zfs_freebsd_symlink(struct vop_symlink_args *ap) - *ap->a_vpp = NULL; - - rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, -- ap->a_target, &zp, cnp->cn_cred, 0 /* flags */); -+ ap->a_target, &zp, cnp->cn_cred, 0 /* flags */, NULL); - if (rc == 0) { - *ap->a_vpp = ZTOV(zp); - ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); -diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c -index 1debc3ec3df..76c040d3797 100644 ---- a/module/os/freebsd/zfs/zfs_znode.c -+++ b/module/os/freebsd/zfs/zfs_znode.c -@@ -296,7 +296,7 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) - sharezp->z_is_sa = zfsvfs->z_use_sa; - - VERIFY0(zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, -- kcred, NULL, &acl_ids)); -+ kcred, NULL, &acl_ids, NULL)); - zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, sharezp); - POINTER_INVALIDATE(&sharezp->z_zfsvfs); -@@ -1772,7 +1772,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) - - rootzp->z_zfsvfs = zfsvfs; - VERIFY0(zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, -- cr, NULL, &acl_ids)); -+ cr, NULL, &acl_ids, NULL)); - zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, rootzp); - error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); -diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c -index 5a52092bb90..d68f3561210 100644 ---- a/module/os/linux/zfs/policy.c -+++ b/module/os/linux/zfs/policy.c -@@ -214,8 +214,9 @@ secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr, - * Determine that subject can set the file setgid flag. - */ - int --secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid) -+secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns) - { -+ gid = zfs_gid_into_mnt(mnt_ns, gid); - #if defined(CONFIG_USER_NS) - if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid))) - return (EPERM); -@@ -284,8 +285,10 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr) - * Determine that subject can set the file setid flags. - */ - static int --secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner) -+secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns) - { -+ owner = zfs_uid_into_mnt(mnt_ns, owner); -+ - if (crgetuid(cr) == owner) - return (0); - -@@ -310,13 +313,13 @@ secpolicy_vnode_stky_modify(const cred_t *cr) - - int - secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, -- const vattr_t *ovap, cred_t *cr) -+ const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns) - { - int error; - - if ((vap->va_mode & S_ISUID) != 0 && - (error = secpolicy_vnode_setid_modify(cr, -- ovap->va_uid)) != 0) { -+ ovap->va_uid, mnt_ns)) != 0) { - return (error); - } - -@@ -334,7 +337,7 @@ secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, - * group-id bit. - */ - if ((vap->va_mode & S_ISGID) != 0 && -- secpolicy_vnode_setids_setgids(cr, ovap->va_gid) != 0) { -+ secpolicy_vnode_setids_setgids(cr, ovap->va_gid, mnt_ns) != 0) { - vap->va_mode &= ~S_ISGID; - } - -diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c -index 8e96cc8e35a..fcb767e9e4a 100644 ---- a/module/os/linux/zfs/zfs_acl.c -+++ b/module/os/linux/zfs/zfs_acl.c -@@ -1801,7 +1801,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp, - */ - int - zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, -- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) -+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) - { - int error; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -1888,8 +1888,9 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, - acl_ids->z_mode |= S_ISGID; - } else { - if ((acl_ids->z_mode & S_ISGID) && -- secpolicy_vnode_setids_setgids(cr, gid) != 0) -+ secpolicy_vnode_setids_setgids(cr, gid, mnt_ns) != 0) { - acl_ids->z_mode &= ~S_ISGID; -+ } - } - - if (acl_ids->z_aclp == NULL) { -@@ -1977,7 +1978,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (mask == 0) - return (SET_ERROR(ENOSYS)); - -- if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr))) -+ if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) - return (error); - - mutex_enter(&zp->z_acl_lock); -@@ -2136,7 +2137,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) - if (zp->z_pflags & ZFS_IMMUTABLE) - return (SET_ERROR(EPERM)); - -- if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr))) -+ if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) - return (error); - - error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, -@@ -2282,7 +2283,7 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) - */ - static int - zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, -- boolean_t anyaccess, cred_t *cr) -+ boolean_t anyaccess, cred_t *cr, zuserns_t *mnt_ns) - { - zfsvfs_t *zfsvfs = ZTOZSB(zp); - zfs_acl_t *aclp; -@@ -2298,7 +2299,13 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, - uid_t gowner; - uid_t fowner; - -- zfs_fuid_map_ids(zp, cr, &fowner, &gowner); -+ if (mnt_ns) { -+ fowner = zfs_uid_into_mnt(mnt_ns, -+ KUID_TO_SUID(ZTOI(zp)->i_uid)); -+ gowner = zfs_gid_into_mnt(mnt_ns, -+ KGID_TO_SGID(ZTOI(zp)->i_gid)); -+ } else -+ zfs_fuid_map_ids(zp, cr, &fowner, &gowner); - - mutex_enter(&zp->z_acl_lock); - -@@ -2409,7 +2416,7 @@ zfs_has_access(znode_t *zp, cred_t *cr) - { - uint32_t have = ACE_ALL_PERMS; - -- if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) { -+ if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, NULL) != 0) { - uid_t owner; - - owner = zfs_fuid_map_id(ZTOZSB(zp), -@@ -2439,7 +2446,8 @@ zfs_has_access(znode_t *zp, cred_t *cr) - * we want to avoid that here. - */ - static int --zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) -+zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, -+ zuserns_t *mnt_ns) - { - int err, mask; - int unmapped = 0; -@@ -2453,7 +2461,10 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) - } - - #if defined(HAVE_IOPS_PERMISSION_USERNS) -- err = generic_permission(cr->user_ns, ZTOI(zp), mask); -+ if (mnt_ns) -+ err = generic_permission(mnt_ns, ZTOI(zp), mask); -+ else -+ err = generic_permission(cr->user_ns, ZTOI(zp), mask); - #else - err = generic_permission(ZTOI(zp), mask); - #endif -@@ -2468,7 +2479,7 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) - - static int - zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, -- boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) -+ boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zuserns_t *mnt_ns) - { - zfsvfs_t *zfsvfs = ZTOZSB(zp); - int err; -@@ -2518,20 +2529,20 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, - } - - if (zp->z_pflags & ZFS_ACL_TRIVIAL) -- return (zfs_zaccess_trivial(zp, working_mode, cr)); -+ return (zfs_zaccess_trivial(zp, working_mode, cr, mnt_ns)); - -- return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); -+ return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr, mnt_ns)); - } - - static int - zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, -- cred_t *cr) -+ cred_t *cr, zuserns_t *mnt_ns) - { - if (*working_mode != ACE_WRITE_DATA) - return (SET_ERROR(EACCES)); - - return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, -- check_privs, B_FALSE, cr)); -+ check_privs, B_FALSE, cr, mnt_ns)); - } - - int -@@ -2597,7 +2608,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - slow: - DTRACE_PROBE(zfs__fastpath__execute__access__miss); - ZFS_ENTER(ZTOZSB(zdp)); -- error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr); -+ error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); - ZFS_EXIT(ZTOZSB(zdp)); - return (error); - } -@@ -2609,7 +2620,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) - * can define any form of access. - */ - int --zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) -+zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, -+ zuserns_t *mnt_ns) - { - uint32_t working_mode; - int error; -@@ -2648,8 +2660,9 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) - } - } - -- owner = zfs_fuid_map_id(ZTOZSB(zp), KUID_TO_SUID(ZTOI(zp)->i_uid), -- cr, ZFS_OWNER); -+ owner = zfs_uid_into_mnt(mnt_ns, KUID_TO_SUID(ZTOI(zp)->i_uid)); -+ owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER); -+ - /* - * Map the bits required to the standard inode flags - * S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits. Map the bits -@@ -2674,7 +2687,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) - needed_bits |= S_IXUSR; - - if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, -- &check_privs, skipaclchk, cr)) == 0) { -+ &check_privs, skipaclchk, cr, mnt_ns)) == 0) { - if (is_attr) - zrele(xzp); - return (secpolicy_vnode_access2(cr, ZTOI(zp), owner, -@@ -2688,7 +2701,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) - } - - if (error && (flags & V_APPEND)) { -- error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); -+ error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr, -+ mnt_ns); - } - - if (error && check_privs) { -@@ -2755,9 +2769,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) - * NFSv4-style ZFS ACL format and call zfs_zaccess() - */ - int --zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) -+zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, -+ zuserns_t *mnt_ns) - { -- return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); -+ return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, -+ mnt_ns)); - } - - /* -@@ -2768,7 +2784,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) - { - int v4_mode = zfs_unix_to_v4(mode >> 6); - -- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr)); -+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); - } - - /* See zfs_zaccess_delete() */ -@@ -2845,7 +2861,7 @@ int zfs_write_implies_delete_child = 1; - * zfs_write_implies_delete_child - */ - int --zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) -+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) - { - uint32_t wanted_dirperms; - uint32_t dzp_working_mode = 0; -@@ -2872,7 +2888,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) - * (This is part of why we're checking the target first.) - */ - zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, -- &zpcheck_privs, B_FALSE, cr); -+ &zpcheck_privs, B_FALSE, cr, mnt_ns); - if (zp_error == EACCES) { - /* We hit a DENY ACE. */ - if (!zpcheck_privs) -@@ -2894,7 +2910,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) - if (zfs_write_implies_delete_child) - wanted_dirperms |= ACE_WRITE_DATA; - dzp_error = zfs_zaccess_common(dzp, wanted_dirperms, -- &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr); -+ &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr, mnt_ns); - if (dzp_error == EACCES) { - /* We hit a DENY ACE. */ - if (!dzpcheck_privs) -@@ -2976,7 +2992,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) - - int - zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, -- znode_t *tzp, cred_t *cr) -+ znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) - { - int add_perm; - int error; -@@ -2998,21 +3014,21 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, - * If that succeeds then check for add_file/add_subdir permissions - */ - -- if ((error = zfs_zaccess_delete(sdzp, szp, cr))) -+ if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) - return (error); - - /* - * If we have a tzp, see if we can delete it? - */ - if (tzp) { -- if ((error = zfs_zaccess_delete(tdzp, tzp, cr))) -+ if ((error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) - return (error); - } - - /* - * Now check for add permissions - */ -- error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); -+ error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); - - return (error); - } -diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c -index 8ad5454b5a7..9bb11d6d4c2 100644 ---- a/module/os/linux/zfs/zfs_dir.c -+++ b/module/os/linux/zfs/zfs_dir.c -@@ -1067,7 +1067,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr) - *xzpp = NULL; - - if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, -- &acl_ids)) != 0) -+ &acl_ids, NULL)) != 0) - return (error); - if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { - zfs_acl_ids_free(&acl_ids); -@@ -1215,7 +1215,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) - cr, ZFS_OWNER); - - if ((uid = crgetuid(cr)) == downer || uid == fowner || -- zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0) -+ zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0) - return (0); - else - return (secpolicy_vnode_remove(cr)); -diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c -index 025768fb4e7..b81b4298620 100644 ---- a/module/os/linux/zfs/zfs_vnops_os.c -+++ b/module/os/linux/zfs/zfs_vnops_os.c -@@ -501,7 +501,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - */ - - if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, -- B_TRUE, cr))) { -+ B_TRUE, cr, NULL))) { - zrele(*zpp); - *zpp = NULL; - } -@@ -519,7 +519,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - * Check accessibility of directory. - */ - -- if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -551,6 +551,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - * cr - credentials of caller. - * flag - file flag. - * vsecp - ACL to be set -+ * mnt_ns - user namespace of the mount - * - * OUT: zpp - znode of created or trunc'd entry. - * -@@ -564,7 +565,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, - /* ARGSUSED */ - int - zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, -- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp) -+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, -+ zuserns_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -652,7 +654,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - * Create a new file object and update the directory - * to reference it. - */ -- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, skip_acl, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, -+ mnt_ns))) { - if (have_acl) - zfs_acl_ids_free(&acl_ids); - goto out; -@@ -671,7 +674,7 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - } - - if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap, -- cr, vsecp, &acl_ids)) != 0) -+ cr, vsecp, &acl_ids, mnt_ns)) != 0) - goto out; - have_acl = B_TRUE; - -@@ -766,7 +769,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - /* - * Verify requested access to file. - */ -- if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr))) { -+ if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr, -+ mnt_ns))) { - goto out; - } - -@@ -811,7 +815,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - /* ARGSUSED */ - int - zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl, -- int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp) -+ int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, -+ zuserns_t *mnt_ns) - { - znode_t *zp = NULL, *dzp = ITOZ(dip); - zfsvfs_t *zfsvfs = ITOZSB(dip); -@@ -857,14 +862,14 @@ zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl, - * Create a new file object and update the directory - * to reference it. - */ -- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { - if (have_acl) - zfs_acl_ids_free(&acl_ids); - goto out; - } - - if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap, -- cr, vsecp, &acl_ids)) != 0) -+ cr, vsecp, &acl_ids, mnt_ns)) != 0) - goto out; - have_acl = B_TRUE; - -@@ -996,7 +1001,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { - goto out; - } - -@@ -1176,6 +1181,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - * cr - credentials of caller. - * flags - case flags. - * vsecp - ACL to be set -+ * mnt_ns - user namespace of the mount - * - * OUT: zpp - znode of created directory. - * -@@ -1189,7 +1195,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) - /*ARGSUSED*/ - int - zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, -- cred_t *cr, int flags, vsecattr_t *vsecp) -+ cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) - { - znode_t *zp; - zfsvfs_t *zfsvfs = ZTOZSB(dzp); -@@ -1246,7 +1252,7 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, - } - - if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, -- vsecp, &acl_ids)) != 0) { -+ vsecp, &acl_ids, mnt_ns)) != 0) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -1267,7 +1273,8 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, - return (error); - } - -- if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr, -+ mnt_ns))) { - zfs_acl_ids_free(&acl_ids); - zfs_dirent_unlock(dl); - ZFS_EXIT(zfsvfs); -@@ -1410,7 +1417,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, - return (error); - } - -- if ((error = zfs_zaccess_delete(dzp, zp, cr))) { -+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { - goto out; - } - -@@ -1842,6 +1849,7 @@ zfs_setattr_dir(znode_t *dzp) - * flags - ATTR_UTIME set if non-default time values provided. - * - ATTR_NOACLCHECK (CIFS context only). - * cr - credentials of caller. -+ * mnt_ns - user namespace of the mount - * - * RETURN: 0 if success - * error code if failure -@@ -1851,7 +1859,7 @@ zfs_setattr_dir(znode_t *dzp) - */ - /* ARGSUSED */ - int --zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) -+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) - { - struct inode *ip; - zfsvfs_t *zfsvfs = ZTOZSB(zp); -@@ -2000,7 +2008,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - */ - - if (mask & ATTR_SIZE) { -- err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr); -+ err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr, -+ mnt_ns); - if (err) - goto out3; - -@@ -2025,13 +2034,15 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - XVA_ISSET_REQ(xvap, XAT_CREATETIME) || - XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { - need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, -- skipaclchk, cr); -+ skipaclchk, cr, mnt_ns); - } - - if (mask & (ATTR_UID|ATTR_GID)) { - int idmask = (mask & (ATTR_UID|ATTR_GID)); - int take_owner; - int take_group; -+ uid_t uid; -+ gid_t gid; - - /* - * NOTE: even if a new mode is being set, -@@ -2045,9 +2056,13 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - * Take ownership or chgrp to group we are a member of - */ - -- take_owner = (mask & ATTR_UID) && (vap->va_uid == crgetuid(cr)); -+ uid = zfs_uid_into_mnt((struct user_namespace *)mnt_ns, -+ vap->va_uid); -+ gid = zfs_gid_into_mnt((struct user_namespace *)mnt_ns, -+ vap->va_gid); -+ take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr)); - take_group = (mask & ATTR_GID) && -- zfs_groupmember(zfsvfs, vap->va_gid, cr); -+ zfs_groupmember(zfsvfs, gid, cr); - - /* - * If both ATTR_UID and ATTR_GID are set then take_owner and -@@ -2063,7 +2078,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - ((idmask == ATTR_UID) && take_owner) || - ((idmask == ATTR_GID) && take_group)) { - if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, -- skipaclchk, cr) == 0) { -+ skipaclchk, cr, mnt_ns) == 0) { - /* - * Remove setuid/setgid for non-privileged users - */ -@@ -2176,12 +2191,12 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) - mutex_exit(&zp->z_lock); - - if (mask & ATTR_MODE) { -- if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { -+ if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, -+ mnt_ns) == 0) { - err = secpolicy_setid_setsticky_clear(ip, vap, -- &oldva, cr); -+ &oldva, cr, mnt_ns); - if (err) - goto out3; -- - trim_mask |= ATTR_MODE; - } else { - need_policy = TRUE; -@@ -2672,6 +2687,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) - * tnm - New entry name. - * cr - credentials of caller. - * flags - case flags -+ * mnt_ns - user namespace of the mount - * - * RETURN: 0 on success, error code on failure. - * -@@ -2681,7 +2697,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) - /*ARGSUSED*/ - int - zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, -- cred_t *cr, int flags) -+ cred_t *cr, int flags, zuserns_t *mnt_ns) - { - znode_t *szp, *tzp; - zfsvfs_t *zfsvfs = ZTOZSB(sdzp); -@@ -2871,7 +2887,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, - * done in a single check. - */ - -- if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))) -+ if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, mnt_ns))) - goto out; - - if (S_ISDIR(ZTOI(szp)->i_mode)) { -@@ -3038,6 +3054,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, - * link - Name for new symlink entry. - * cr - credentials of caller. - * flags - case flags -+ * mnt_ns - user namespace of the mount - * - * OUT: zpp - Znode for new symbolic link. - * -@@ -3049,7 +3066,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, - /*ARGSUSED*/ - int - zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, -- znode_t **zpp, cred_t *cr, int flags) -+ znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) - { - znode_t *zp; - zfs_dirlock_t *dl; -@@ -3087,7 +3104,7 @@ zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, - } - - if ((error = zfs_acl_ids_create(dzp, 0, -- vap, cr, NULL, &acl_ids)) != 0) { -+ vap, cr, NULL, &acl_ids, mnt_ns)) != 0) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3104,7 +3121,7 @@ zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, - return (error); - } - -- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { - zfs_acl_ids_free(&acl_ids); - zfs_dirent_unlock(dl); - ZFS_EXIT(zfsvfs); -@@ -3354,7 +3371,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, - return (SET_ERROR(EPERM)); - } - -- if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -@@ -3942,7 +3959,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, - * On Linux we can get here through truncate_range() which - * operates directly on inodes, so we need to check access rights. - */ -- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) { -+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { - ZFS_EXIT(zfsvfs); - return (error); - } -diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c -index f3475b4d979..619ef68a947 100644 ---- a/module/os/linux/zfs/zfs_znode.c -+++ b/module/os/linux/zfs/zfs_znode.c -@@ -1947,7 +1947,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) - } - - VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, -- cr, NULL, &acl_ids)); -+ cr, NULL, &acl_ids, NULL)); - zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); - ASSERT3P(zp, ==, rootzp); - error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); -diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c -index 9b526afd000..9e7e1806f8c 100644 ---- a/module/os/linux/zfs/zpl_ctldir.c -+++ b/module/os/linux/zfs/zpl_ctldir.c -@@ -363,7 +363,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -- zpl_vap_init(vap, dip, mode | S_IFDIR, cr); -+#ifdef HAVE_IOPS_MKDIR_USERNS -+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); -+#else -+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, NULL); -+#endif - - error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); - if (error == 0) { -diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c -index b045786f203..92babf04a92 100644 ---- a/module/os/linux/zfs/zpl_file.c -+++ b/module/os/linux/zfs/zpl_file.c -@@ -971,7 +971,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1019,7 +1019,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); - spl_fstrans_unmark(cookie); - crfree(cr); - -@@ -1107,7 +1107,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg) - - crhold(cr); - cookie = spl_fstrans_mark(); -- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr); -+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); - spl_fstrans_unmark(cookie); - crfree(cr); - -diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c -index dd634f70eb7..d218045d11c 100644 ---- a/module/os/linux/zfs/zpl_inode.c -+++ b/module/os/linux/zfs/zpl_inode.c -@@ -33,7 +33,6 @@ - #include <sys/zpl.h> - #include <sys/file.h> - -- - static struct dentry * - zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) - { -@@ -112,18 +111,22 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) - } - - void --zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr) -+zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, -+ zuserns_t *mnt_ns) - { - vap->va_mask = ATTR_MODE; - vap->va_mode = mode; -- vap->va_uid = crgetuid(cr); -+ -+ vap->va_uid = zfs_uid_from_mnt((struct user_namespace *)mnt_ns, -+ crgetuid(cr)); - - if (dir && dir->i_mode & S_ISGID) { - vap->va_gid = KGID_TO_SGID(dir->i_gid); - if (S_ISDIR(mode)) - vap->va_mode |= S_ISGID; - } else { -- vap->va_gid = crgetgid(cr); -+ vap->va_gid = zfs_gid_from_mnt((struct user_namespace *)mnt_ns, -+ crgetgid(cr)); - } - } - -@@ -140,14 +143,17 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) - vattr_t *vap; - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_IOPS_CREATE_USERNS -+ zuserns_t *user_ns = NULL; -+#endif - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -- zpl_vap_init(vap, dir, mode, cr); -+ zpl_vap_init(vap, dir, mode, cr, user_ns); - - cookie = spl_fstrans_mark(); - error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, -- mode, &zp, cr, 0, NULL); -+ mode, &zp, cr, 0, NULL, user_ns); - if (error == 0) { - error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); - if (error == 0) -@@ -184,6 +190,9 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - vattr_t *vap; - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_IOPS_MKNOD_USERNS -+ zuserns_t *user_ns = NULL; -+#endif - - /* - * We currently expect Linux to supply rdev=0 for all sockets -@@ -194,12 +203,12 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -- zpl_vap_init(vap, dir, mode, cr); -+ zpl_vap_init(vap, dir, mode, cr, user_ns); - vap->va_rdev = rdev; - - cookie = spl_fstrans_mark(); - error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, -- mode, &zp, cr, 0, NULL); -+ mode, &zp, cr, 0, NULL, user_ns); - if (error == 0) { - error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); - if (error == 0) -@@ -241,6 +250,9 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) - vattr_t *vap; - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_TMPFILE_USERNS -+ zuserns_t *userns = NULL; -+#endif - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -@@ -250,10 +262,10 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) - */ - if (!IS_POSIXACL(dir)) - mode &= ~current_umask(); -- zpl_vap_init(vap, dir, mode, cr); -+ zpl_vap_init(vap, dir, mode, cr, userns); - - cookie = spl_fstrans_mark(); -- error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL); -+ error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns); - if (error == 0) { - /* d_tmpfile will do drop_nlink, so we should set it first */ - set_nlink(ip, 1); -@@ -326,13 +338,17 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - znode_t *zp; - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_IOPS_MKDIR_USERNS -+ zuserns_t *user_ns = NULL; -+#endif - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -- zpl_vap_init(vap, dir, mode | S_IFDIR, cr); -+ zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns); - - cookie = spl_fstrans_mark(); -- error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL); -+ error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL, -+ user_ns); - if (error == 0) { - error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); - if (error == 0) -@@ -454,7 +470,11 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - int error; - fstrans_cookie_t cookie; - -+#ifdef HAVE_SETATTR_PREPARE_USERNS -+ error = zpl_setattr_prepare(user_ns, dentry, ia); -+#else - error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); -+#endif - if (error) - return (error); - -@@ -473,7 +493,11 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) - ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip); - - cookie = spl_fstrans_mark(); -- error = -zfs_setattr(ITOZ(ip), vap, 0, cr); -+#ifdef HAVE_SETATTR_PREPARE_USERNS -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); -+#else -+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, NULL); -+#endif - if (!error && (ia->ia_valid & ATTR_MODE)) - error = zpl_chmod_acl(ip); - -@@ -498,6 +522,9 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - cred_t *cr = CRED(); - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_IOPS_RENAME_USERNS -+ zuserns_t *user_ns = NULL; -+#endif - - /* We don't have renameat2(2) support */ - if (flags) -@@ -506,7 +533,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, - crhold(cr); - cookie = spl_fstrans_mark(); - error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip), -- dname(tdentry), cr, 0); -+ dname(tdentry), cr, 0, user_ns); - spl_fstrans_unmark(cookie); - crfree(cr); - ASSERT3S(error, <=, 0); -@@ -536,14 +563,17 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) - znode_t *zp; - int error; - fstrans_cookie_t cookie; -+#ifndef HAVE_IOPS_SYMLINK_USERNS -+ zuserns_t *user_ns = NULL; -+#endif - - crhold(cr); - vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); -- zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr); -+ zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns); - - cookie = spl_fstrans_mark(); - error = -zfs_symlink(ITOZ(dir), dname(dentry), vap, -- (char *)name, &zp, cr, 0); -+ (char *)name, &zp, cr, 0, user_ns); - if (error == 0) { - error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); - if (error) { -diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c -index c2fd3fee140..21db088942b 100644 ---- a/module/os/linux/zfs/zpl_super.c -+++ b/module/os/linux/zfs/zpl_super.c -@@ -360,6 +360,11 @@ const struct super_operations zpl_super_operations = { - struct file_system_type zpl_fs_type = { - .owner = THIS_MODULE, - .name = ZFS_DRIVER, -+#if defined(HAVE_IDMAP_MNT_API) -+ .fs_flags = FS_USERNS_MOUNT | FS_ALLOW_IDMAP, -+#else -+ .fs_flags = FS_USERNS_MOUNT, -+#endif - .mount = zpl_mount, - .kill_sb = zpl_kill_sb, - }; -diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c -index 364cd34c163..5f0be5f6418 100644 ---- a/module/os/linux/zfs/zpl_xattr.c -+++ b/module/os/linux/zfs/zpl_xattr.c -@@ -496,7 +496,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, - vap->va_gid = crgetgid(cr); - - error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, -- cr, ATTR_NOACLCHECK, NULL); -+ cr, 0, NULL, NULL); - if (error) - goto out; - } -diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c -index f3d209f1fbd..c7a3486cd36 100644 ---- a/module/zfs/zfs_replay.c -+++ b/module/zfs/zfs_replay.c -@@ -385,7 +385,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - } - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, &vsec); -+ 0, 0, &zp, kcred, vflg, &vsec, NULL); - break; - case TX_MKDIR_ACL: - aclstart = (caddr_t)(lracl + 1); -@@ -415,7 +415,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) - lr->lr_uid, lr->lr_gid); - } - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, &vsec); -+ &zp, kcred, vflg, &vsec, NULL); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -525,7 +525,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)start; - - error = zfs_create(dzp, name, &xva.xva_vattr, -- 0, 0, &zp, kcred, vflg, NULL); -+ 0, 0, &zp, kcred, vflg, NULL, NULL); - break; - case TX_MKDIR_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); -@@ -542,7 +542,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - - error = zfs_mkdir(dzp, name, &xva.xva_vattr, -- &zp, kcred, vflg, NULL); -+ &zp, kcred, vflg, NULL, NULL); - break; - case TX_MKXATTR: - error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); -@@ -551,7 +551,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) - name = (char *)(lr + 1); - link = name + strlen(name) + 1; - error = zfs_symlink(dzp, name, &xva.xva_vattr, -- link, &zp, kcred, vflg); -+ link, &zp, kcred, vflg, NULL); - break; - default: - error = SET_ERROR(ENOTSUP); -@@ -663,7 +663,7 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) - if (lr->lr_common.lrc_txtype & TX_CI) - vflg |= FIGNORECASE; - -- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg); -+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, NULL); - - zrele(tdzp); - zrele(sdzp); -@@ -857,7 +857,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) - zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, - lr->lr_uid, lr->lr_gid); - -- error = zfs_setattr(zp, vap, 0, kcred); -+ error = zfs_setattr(zp, vap, 0, kcred, NULL); - - zfs_fuid_info_free(zfsvfs->z_fuid_replay); - zfsvfs->z_fuid_replay = NULL; -diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c -index b9498d17ee2..6d74ffb633c 100644 ---- a/module/zfs/zfs_vnops.c -+++ b/module/zfs/zfs_vnops.c -@@ -165,9 +165,9 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) - ZFS_VERIFY_ZP(zp); - - if (flag & V_ACE_MASK) -- error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); -+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, NULL); - else -- error = zfs_zaccess_rwx(zp, mode, flag, cr); -+ error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL); - - ZFS_EXIT(zfsvfs); - return (error); - -From 99435ad33fdffdcf710255c7ed25eea3a3e21a4b Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:11:02 -0500 -Subject: [PATCH 2/3] Backport "Add tests for idmapped mount functionality" - ---- - tests/runfiles/linux.run | 5 + - tests/zfs-tests/cmd/Makefile.am | 1 + - tests/zfs-tests/cmd/idmap_util/.gitignore | 1 + - tests/zfs-tests/cmd/idmap_util/Makefile.am | 9 + - tests/zfs-tests/cmd/idmap_util/idmap_util.c | 791 ++++++++++++++++++ - tests/zfs-tests/include/commands.cfg | 2 +- - .../tests/functional/idmap_mount/cleanup.ksh | 25 + - .../functional/idmap_mount/idmap_mount.cfg | 25 + - .../idmap_mount/idmap_mount_001.ksh | 76 ++ - .../idmap_mount/idmap_mount_002.ksh | 97 +++ - .../idmap_mount/idmap_mount_003.ksh | 121 +++ - .../idmap_mount/idmap_mount_004.ksh | 106 +++ - .../idmap_mount/idmap_mount_common.kshlib | 23 + - .../tests/functional/idmap_mount/setup.ksh | 30 + - 14 files changed, 1311 insertions(+), 1 deletion(-) - create mode 100644 tests/zfs-tests/cmd/idmap_util/.gitignore - create mode 100644 tests/zfs-tests/cmd/idmap_util/Makefile.am - create mode 100644 tests/zfs-tests/cmd/idmap_util/idmap_util.c - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh - create mode 100644 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh - create mode 100644 tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib - create mode 100755 tests/zfs-tests/tests/functional/idmap_mount/setup.ksh - -diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run -index a94472d1261..211e6a1dd41 100644 ---- a/tests/runfiles/linux.run -+++ b/tests/runfiles/linux.run -@@ -188,3 +188,8 @@ tags = ['functional', 'user_namespace'] - tests = ['groupspace_001_pos', 'groupspace_002_pos', 'groupspace_003_pos', - 'userquota_013_pos', 'userspace_003_pos'] - tags = ['functional', 'userquota'] -+ -+[tests/functional/idmap_mount:Linux] -+tests = ['idmap_mount_001', 'idmap_mount_002', 'idmap_mount_003', -+ 'idmap_mount_004'] -+tags = ['functional', 'idmap_mount'] -diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am -index 7202e00711d..4bd6747a81d 100644 ---- a/tests/zfs-tests/cmd/Makefile.am -+++ b/tests/zfs-tests/cmd/Makefile.am -@@ -32,6 +32,7 @@ SUBDIRS = \ - - if BUILD_LINUX - SUBDIRS += \ -+ idmap_util \ - randfree_file \ - read_dos_attributes \ - user_ns_exec \ -diff --git a/tests/zfs-tests/cmd/idmap_util/.gitignore b/tests/zfs-tests/cmd/idmap_util/.gitignore -new file mode 100644 -index 00000000000..37982f07a5e ---- /dev/null -+++ b/tests/zfs-tests/cmd/idmap_util/.gitignore -@@ -0,0 +1 @@ -+/idmap_util -diff --git a/tests/zfs-tests/cmd/idmap_util/Makefile.am b/tests/zfs-tests/cmd/idmap_util/Makefile.am -new file mode 100644 -index 00000000000..38b62eb0272 ---- /dev/null -+++ b/tests/zfs-tests/cmd/idmap_util/Makefile.am -@@ -0,0 +1,9 @@ -+include $(top_srcdir)/config/Rules.am -+ -+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin -+ -+pkgexec_PROGRAMS = idmap_util -+ -+idmap_util_SOURCES = idmap_util.c -+idmap_util_LDADD = \ -+ $(abs_top_builddir)/lib/libspl/libspl.la -diff --git a/tests/zfs-tests/cmd/idmap_util/idmap_util.c b/tests/zfs-tests/cmd/idmap_util/idmap_util.c -new file mode 100644 -index 00000000000..a9731f00dbc ---- /dev/null -+++ b/tests/zfs-tests/cmd/idmap_util/idmap_util.c -@@ -0,0 +1,791 @@ -+/* -+ * CDDL HEADER START -+ * -+ * The contents of this file are subject to the terms of the -+ * Common Development and Distribution License (the "License"). -+ * You may not use this file except in compliance with the License. -+ * -+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+ * or https://opensource.org/licenses/CDDL-1.0. -+ * See the License for the specific language governing permissions -+ * and limitations under the License. -+ * -+ * When distributing Covered Code, include this CDDL HEADER in each -+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+ * If applicable, add the following below this CDDL HEADER, with the -+ * fields enclosed by brackets "[]" replaced with your own identifying -+ * information: Portions Copyright [yyyy] [name of copyright owner] -+ * -+ * CDDL HEADER END -+ */ -+ -+#ifndef _GNU_SOURCE -+#define _GNU_SOURCE -+#endif -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdbool.h> -+#include <stddef.h> -+#include <string.h> -+#include <linux/types.h> -+#include <sys/wait.h> -+#include <sys/stat.h> -+#include <sys/mount.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <sched.h> -+#include <syscall.h> -+ -+#include <sys/list.h> -+ -+#ifndef UINT_MAX -+#define UINT_MAX 4294967295U -+#endif -+ -+#ifndef __NR_Linux -+#if defined __alpha__ -+#define __NR_Linux 110 -+#elif defined _MIPS_SIM -+#if _MIPS_SIM == _MIPS_SIM_ABI32 -+#define __NR_Linux 4000 -+#endif -+#if _MIPS_SIM == _MIPS_SIM_NABI32 -+#define __NR_Linux 6000 -+#endif -+#if _MIPS_SIM == _MIPS_SIM_ABI64 -+#define __NR_Linux 5000 -+#endif -+#elif defined __ia64__ -+#define __NR_Linux 1024 -+#else -+#define __NR_Linux 0 -+#endif -+#endif -+ -+#ifndef __NR_mount_setattr -+#define __NR_mount_setattr (442 + __NR_Linux) -+#endif -+ -+#ifndef __NR_open_tree -+#define __NR_open_tree (428 + __NR_Linux) -+#endif -+ -+#ifndef __NR_move_mount -+#define __NR_move_mount (429 + __NR_Linux) -+#endif -+ -+#ifndef MNT_DETACH -+#define MNT_DETACH 2 -+#endif -+ -+#ifndef MOVE_MOUNT_F_EMPTY_PATH -+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 -+#endif -+ -+#ifndef MOUNT_ATTR_IDMAP -+#define MOUNT_ATTR_IDMAP 0x00100000 -+#endif -+ -+#ifndef OPEN_TREE_CLONE -+#define OPEN_TREE_CLONE 1 -+#endif -+ -+#ifndef OPEN_TREE_CLOEXEC -+#define OPEN_TREE_CLOEXEC O_CLOEXEC -+#endif -+ -+#ifndef AT_RECURSIVE -+#define AT_RECURSIVE 0x8000 -+#endif -+ -+#ifndef mount_attr -+struct mount_attr { -+ __u64 attr_set; -+ __u64 attr_clr; -+ __u64 propagation; -+ __u64 userns_fd; -+}; -+#endif -+ -+static inline int -+sys_mount_setattr(int dfd, const char *path, unsigned int flags, -+ struct mount_attr *attr, size_t size) -+{ -+ return (syscall(__NR_mount_setattr, dfd, path, flags, attr, size)); -+} -+ -+static inline int -+sys_open_tree(int dfd, const char *filename, unsigned int flags) -+{ -+ return (syscall(__NR_open_tree, dfd, filename, flags)); -+} -+ -+static inline int sys_move_mount(int from_dfd, const char *from_pathname, -+ int to_dfd, const char *to_pathname, unsigned int flags) -+{ -+ return (syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, -+ to_pathname, flags)); -+} -+ -+typedef enum idmap_type_t { -+ TYPE_UID, -+ TYPE_GID, -+ TYPE_BOTH -+} idmap_type_t; -+ -+struct idmap_entry { -+ __u32 first; -+ __u32 lower_first; -+ __u32 count; -+ idmap_type_t type; -+ list_node_t node; -+}; -+ -+static void -+log_msg(const char *msg, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, msg); -+ vfprintf(stderr, msg, ap); -+ fputc('\n', stderr); -+ va_end(ap); -+} -+ -+#define log_errno(msg, args...) \ -+ do { \ -+ log_msg("%s:%d:%s: [%m] " msg, __FILE__, __LINE__,\ -+ __FUNCTION__, ##args); \ -+ } while (0) -+ -+/* -+ * Parse the idmapping in the following format -+ * and add to the list: -+ * -+ * u:nsid_first:hostid_first:count -+ * g:nsid_first:hostid_first:count -+ * b:nsid_first:hostid_first:count -+ * -+ * The delimiter can be : or space character. -+ * -+ * Return: -+ * 0 if success -+ * ENOMEM if out of memory -+ * EINVAL if wrong arg or input -+ */ -+static int -+parse_idmap_entry(list_t *head, char *input) -+{ -+ char *token, *savedptr = NULL; -+ struct idmap_entry *entry; -+ unsigned long ul; -+ char *delimiter = (char *)": "; -+ char c; -+ -+ if (!input || !head) -+ return (EINVAL); -+ entry = malloc(sizeof (*entry)); -+ if (!entry) -+ return (ENOMEM); -+ -+ token = strtok_r(input, delimiter, &savedptr); -+ if (token) -+ c = token[0]; -+ if (!token || (c != 'b' && c != 'u' && c != 'g')) -+ goto errout; -+ entry->type = (c == 'b') ? TYPE_BOTH : -+ ((c == 'u') ? TYPE_UID : TYPE_GID); -+ -+ token = strtok_r(NULL, delimiter, &savedptr); -+ if (!token) -+ goto errout; -+ ul = strtoul(token, NULL, 10); -+ if (ul > UINT_MAX || errno != 0) -+ goto errout; -+ entry->first = (__u32)ul; -+ -+ token = strtok_r(NULL, delimiter, &savedptr); -+ if (!token) -+ goto errout; -+ ul = strtoul(token, NULL, 10); -+ if (ul > UINT_MAX || errno != 0) -+ goto errout; -+ entry->lower_first = (__u32)ul; -+ -+ token = strtok_r(NULL, delimiter, &savedptr); -+ if (!token) -+ goto errout; -+ ul = strtoul(token, NULL, 10); -+ if (ul > UINT_MAX || errno != 0) -+ goto errout; -+ entry->count = (__u32)ul; -+ -+ list_insert_tail(head, entry); -+ -+ return (0); -+ -+errout: -+ free(entry); -+ return (EINVAL); -+} -+ -+/* -+ * Release all the entries in the list -+ */ -+static void -+free_idmap(list_t *head) -+{ -+ struct idmap_entry *entry; -+ -+ while ((entry = list_remove_head(head)) != NULL) -+ free(entry); -+ /* list_destroy() to be done by the caller */ -+} -+ -+/* -+ * Write all bytes in the buffer to fd -+ */ -+static ssize_t -+write_buf(int fd, const char *buf, size_t buf_size) -+{ -+ ssize_t written, total_written = 0; -+ size_t remaining = buf_size; -+ char *position = (char *)buf; -+ -+ for (;;) { -+ written = write(fd, position, remaining); -+ if (written < 0 && errno == EINTR) -+ continue; -+ if (written < 0) { -+ log_errno("write"); -+ return (written); -+ } -+ total_written += written; -+ if (total_written == buf_size) -+ break; -+ remaining -= written; -+ position += written; -+ } -+ -+ return (total_written); -+} -+ -+/* -+ * Read data from file into buffer -+ */ -+static ssize_t -+read_buf(int fd, char *buf, size_t buf_size) -+{ -+ int ret; -+ for (;;) { -+ ret = read(fd, buf, buf_size); -+ if (ret < 0 && errno == EINTR) -+ continue; -+ break; -+ } -+ if (ret < 0) -+ log_errno("read"); -+ return (ret); -+} -+ -+/* -+ * Write idmap of the given type in the buffer to the -+ * process' uid_map or gid_map proc file. -+ * -+ * Return: -+ * 0 if success -+ * errno if there's any error -+ */ -+static int -+write_idmap(pid_t pid, char *buf, size_t buf_size, idmap_type_t type) -+{ -+ char path[PATH_MAX]; -+ int fd = -EBADF; -+ int ret; -+ -+ (void) snprintf(path, sizeof (path), "/proc/%d/%cid_map", -+ pid, type == TYPE_UID ? 'u' : 'g'); -+ fd = open(path, O_WRONLY | O_CLOEXEC); -+ if (fd < 0) { -+ ret = errno; -+ log_errno("open(%s)", path); -+ goto out; -+ } -+ ret = write_buf(fd, buf, buf_size); -+ if (ret < 0) -+ ret = errno; -+ else -+ ret = 0; -+out: -+ if (fd > 0) -+ close(fd); -+ return (ret); -+} -+ -+/* -+ * Write idmap info in the list to the process -+ * user namespace, i.e. its /proc/<pid>/uid_map -+ * and /proc/<pid>/gid_map file. -+ * -+ * Return: -+ * 0 if success -+ * errno if it fails -+ */ -+static int -+write_pid_idmaps(pid_t pid, list_t *head) -+{ -+ char *buf_uids, *buf_gids; -+ char *curr_bufu, *curr_bufg; -+ /* max 4k to be allowed for each map */ -+ int size_buf_uids = 4096, size_buf_gids = 4096; -+ struct idmap_entry *entry; -+ int uid_filled, gid_filled; -+ int ret; -+ int has_uids = 0, has_gids = 0; -+ size_t buf_size; -+ -+ buf_uids = malloc(size_buf_uids); -+ if (!buf_uids) -+ return (ENOMEM); -+ buf_gids = malloc(size_buf_gids); -+ if (!buf_gids) { -+ free(buf_uids); -+ return (ENOMEM); -+ } -+ curr_bufu = buf_uids; -+ curr_bufg = buf_gids; -+ -+ for (entry = list_head(head); entry; entry = list_next(head, entry)) { -+ if (entry->type == TYPE_UID || entry->type == TYPE_BOTH) { -+ uid_filled = snprintf(curr_bufu, size_buf_uids, -+ "%u %u %u\n", entry->first, entry->lower_first, -+ entry->count); -+ if (uid_filled <= 0 || uid_filled >= size_buf_uids) { -+ ret = E2BIG; -+ goto out; -+ } -+ curr_bufu += uid_filled; -+ size_buf_uids -= uid_filled; -+ has_uids = 1; -+ } -+ if (entry->type == TYPE_GID || entry->type == TYPE_BOTH) { -+ gid_filled = snprintf(curr_bufg, size_buf_gids, -+ "%u %u %u\n", entry->first, entry->lower_first, -+ entry->count); -+ if (gid_filled <= 0 || gid_filled >= size_buf_gids) { -+ ret = E2BIG; -+ goto out; -+ } -+ curr_bufg += gid_filled; -+ size_buf_gids -= gid_filled; -+ has_gids = 1; -+ } -+ } -+ if (has_uids) { -+ buf_size = curr_bufu - buf_uids; -+ ret = write_idmap(pid, buf_uids, buf_size, TYPE_UID); -+ if (ret) -+ goto out; -+ } -+ if (has_gids) { -+ buf_size = curr_bufg - buf_gids; -+ ret = write_idmap(pid, buf_gids, buf_size, TYPE_GID); -+ } -+ -+out: -+ free(buf_uids); -+ free(buf_gids); -+ return (ret); -+} -+ -+/* -+ * Wait for the child process to exit -+ * and reap it. -+ * -+ * Return: -+ * process exit code if available -+ */ -+static int -+wait_for_pid(pid_t pid) -+{ -+ int status; -+ int ret; -+ -+ for (;;) { -+ ret = waitpid(pid, &status, 0); -+ if (ret < 0) { -+ if (errno == EINTR) -+ continue; -+ return (EXIT_FAILURE); -+ } -+ break; -+ } -+ if (!WIFEXITED(status)) -+ return (EXIT_FAILURE); -+ return (WEXITSTATUS(status)); -+} -+ -+/* -+ * Get the file descriptor of the process user namespace -+ * given its pid. -+ * -+ * Return: -+ * fd if success -+ * -1 if it fails -+ */ -+static int -+userns_fd_from_pid(pid_t pid) -+{ -+ int fd; -+ char path[PATH_MAX]; -+ -+ (void) snprintf(path, sizeof (path), "/proc/%d/ns/user", pid); -+ fd = open(path, O_RDONLY | O_CLOEXEC); -+ if (fd < 0) -+ log_errno("open(%s)", path); -+ return (fd); -+} -+ -+/* -+ * Get the user namespace file descriptor given a list -+ * of idmap info. -+ * -+ * Return: -+ * fd if success -+ * -errno if it fails -+ */ -+static int -+userns_fd_from_idmap(list_t *head) -+{ -+ pid_t pid; -+ int ret, fd; -+ int pipe_fd[2]; -+ char c; -+ int saved_errno = 0; -+ -+ /* pipe for bidirectional communication */ -+ ret = pipe(pipe_fd); -+ if (ret) { -+ log_errno("pipe"); -+ return (-errno); -+ } -+ -+ pid = fork(); -+ if (pid < 0) { -+ log_errno("fork"); -+ return (-errno); -+ } -+ -+ if (pid == 0) { -+ /* child process */ -+ close(pipe_fd[0]); -+ ret = unshare(CLONE_NEWUSER); -+ if (ret == 0) { -+ /* notify the parent of success */ -+ ret = write_buf(pipe_fd[1], "1", 1); -+ } else { -+ saved_errno = errno; -+ log_errno("unshare"); -+ ret = write_buf(pipe_fd[1], "0", 1); -+ } -+ if (ret < 0) -+ saved_errno = errno; -+ close(pipe_fd[1]); -+ exit(saved_errno); -+ } -+ /* parent process */ -+ close(pipe_fd[1]); -+ ret = read_buf(pipe_fd[0], &c, 1); -+ if (ret == 1 && c == '1') { -+ ret = write_pid_idmaps(pid, head); -+ if (!ret) { -+ fd = userns_fd_from_pid(pid); -+ if (fd < 0) -+ fd = -errno; -+ } else { -+ fd = -ret; -+ } -+ } else { -+ fd = -EBADF; -+ } -+ close(pipe_fd[0]); -+ (void) wait_for_pid(pid); -+ return (fd); -+} -+ -+/* -+ * Check if the operating system supports idmapped mount on the -+ * given path or not. -+ * -+ * Return: -+ * true if supported -+ * false if not supported -+ */ -+static bool -+is_idmap_supported(char *path) -+{ -+ list_t head; -+ int ret; -+ int tree_fd = -EBADF, path_fd = -EBADF; -+ struct mount_attr attr = { -+ .attr_set = MOUNT_ATTR_IDMAP, -+ .userns_fd = -EBADF, -+ }; -+ -+ /* strtok_r() won't be happy with a const string */ -+ char *input = strdup("b:0:1000000:1000000"); -+ -+ if (!input) { -+ errno = ENOMEM; -+ log_errno("strdup"); -+ return (false); -+ } -+ -+ list_create(&head, sizeof (struct idmap_entry), -+ offsetof(struct idmap_entry, node)); -+ ret = parse_idmap_entry(&head, input); -+ if (ret) { -+ errno = ret; -+ log_errno("parse_idmap_entry(%s)", input); -+ goto out; -+ } -+ ret = userns_fd_from_idmap(&head); -+ if (ret < 0) -+ goto out; -+ attr.userns_fd = ret; -+ ret = openat(-EBADF, path, O_DIRECTORY | O_CLOEXEC); -+ if (ret < 0) { -+ log_errno("openat(%s)", path); -+ goto out; -+ } -+ path_fd = ret; -+ ret = sys_open_tree(path_fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT | -+ AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); -+ if (ret < 0) { -+ log_errno("sys_open_tree"); -+ goto out; -+ } -+ tree_fd = ret; -+ ret = sys_mount_setattr(tree_fd, "", AT_EMPTY_PATH, &attr, -+ sizeof (attr)); -+ if (ret < 0) { -+ log_errno("sys_mount_setattr"); -+ } -+out: -+ free_idmap(&head); -+ list_destroy(&head); -+ if (tree_fd > 0) -+ close(tree_fd); -+ if (path_fd > 0) -+ close(path_fd); -+ if (attr.userns_fd > 0) -+ close(attr.userns_fd); -+ free(input); -+ return (ret == 0); -+} -+ -+/* -+ * Check if the given path is a mount point or not. -+ * -+ * Return: -+ * true if it is -+ * false otherwise -+ */ -+static bool -+is_mountpoint(char *path) -+{ -+ char *parent; -+ struct stat st_me, st_parent; -+ bool ret; -+ -+ parent = malloc(strlen(path)+4); -+ if (!parent) { -+ errno = ENOMEM; -+ log_errno("malloc"); -+ return (false); -+ } -+ strcat(strcpy(parent, path), "/.."); -+ if (lstat(path, &st_me) != 0 || -+ lstat(parent, &st_parent) != 0) -+ ret = false; -+ else -+ if (st_me.st_dev != st_parent.st_dev || -+ st_me.st_ino == st_parent.st_ino) -+ ret = true; -+ else -+ ret = false; -+ free(parent); -+ return (ret); -+} -+ -+/* -+ * Remount the source on the new target folder with the given -+ * list of idmap info. If target is NULL, the source will be -+ * unmounted and then remounted if it is a mountpoint, otherwise -+ * no unmount is done, the source is simply idmap remounted. -+ * -+ * Return: -+ * 0 if success -+ * -errno otherwise -+ */ -+static int -+do_idmap_mount(list_t *idmap, char *source, char *target, int flags) -+{ -+ int ret; -+ int tree_fd = -EBADF, source_fd = -EBADF; -+ struct mount_attr attr = { -+ .attr_set = MOUNT_ATTR_IDMAP, -+ .userns_fd = -EBADF, -+ }; -+ -+ ret = userns_fd_from_idmap(idmap); -+ if (ret < 0) -+ goto out; -+ attr.userns_fd = ret; -+ ret = openat(-EBADF, source, O_DIRECTORY | O_CLOEXEC); -+ if (ret < 0) { -+ ret = -errno; -+ log_errno("openat(%s)", source); -+ goto out; -+ } -+ source_fd = ret; -+ ret = sys_open_tree(source_fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT | -+ AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE | flags); -+ if (ret < 0) { -+ ret = -errno; -+ log_errno("sys_open_tree"); -+ goto out; -+ } -+ tree_fd = ret; -+ ret = sys_mount_setattr(tree_fd, "", AT_EMPTY_PATH | flags, &attr, -+ sizeof (attr)); -+ if (ret < 0) { -+ ret = -errno; -+ log_errno("sys_mount_setattr"); -+ goto out; -+ } -+ if (source != NULL && target == NULL && is_mountpoint(source)) { -+ ret = umount2(source, MNT_DETACH); -+ if (ret < 0) { -+ ret = -errno; -+ log_errno("umount2(%s)", source); -+ goto out; -+ } -+ } -+ ret = sys_move_mount(tree_fd, "", -EBADF, target == NULL ? -+ source : target, MOVE_MOUNT_F_EMPTY_PATH); -+ if (ret < 0) { -+ ret = -errno; -+ log_errno("sys_move_mount(%s)", target == NULL ? -+ source : target); -+ } -+out: -+ if (tree_fd > 0) -+ close(tree_fd); -+ if (source_fd > 0) -+ close(source_fd); -+ if (attr.userns_fd > 0) -+ close(attr.userns_fd); -+ return (ret); -+} -+ -+static void -+print_usage(char *argv[]) -+{ -+ fprintf(stderr, "Usage: %s [-r] [-c] [-m <idmap1>] [-m <idmap2>]" \ -+ " ... [<source>] [<target>]\n", argv[0]); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " -r Recursively do idmapped mount.\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " -c Checks if idmapped mount is supported " \ -+ "on the <source> by the operating system or not.\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " -m <idmap> to specify the idmap info, " \ -+ "in the following format:\n"); -+ fprintf(stderr, " <id_type>:<nsid_first>:<hostid_first>:<count>\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " <id_type> can be either of 'b', 'u', and 'g'.\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "The <source> folder will be mounted at <target> " \ -+ "with the provided idmap information.\nIf no <target> is " \ -+ "specified, and <source> is a mount point, " \ -+ "then <source> will be unmounted and then remounted.\n"); -+} -+ -+int -+main(int argc, char *argv[]) -+{ -+ int opt; -+ list_t idmap_head; -+ int check_supported = 0; -+ int ret = EXIT_SUCCESS; -+ char *source = NULL, *target = NULL; -+ int flags = 0; -+ -+ list_create(&idmap_head, sizeof (struct idmap_entry), -+ offsetof(struct idmap_entry, node)); -+ -+ while ((opt = getopt(argc, argv, "rcm:")) != -1) { -+ switch (opt) { -+ case 'r': -+ flags |= AT_RECURSIVE; -+ break; -+ case 'c': -+ check_supported = 1; -+ break; -+ case 'm': -+ ret = parse_idmap_entry(&idmap_head, optarg); -+ if (ret) { -+ errno = ret; -+ log_errno("parse_idmap_entry(%s)", optarg); -+ ret = EXIT_FAILURE; -+ goto out; -+ } -+ break; -+ default: -+ print_usage(argv); -+ exit(EXIT_FAILURE); -+ } -+ } -+ -+ if (check_supported == 0 && list_is_empty(&idmap_head)) { -+ print_usage(argv); -+ ret = EXIT_FAILURE; -+ goto out; -+ } -+ -+ if (optind >= argc) { -+ fprintf(stderr, "Expected to have <source>, <target>.\n"); -+ print_usage(argv); -+ ret = EXIT_FAILURE; -+ goto out; -+ } -+ -+ source = argv[optind]; -+ if (optind < (argc - 1)) { -+ target = argv[optind + 1]; -+ } -+ -+ if (check_supported) { -+ free_idmap(&idmap_head); -+ list_destroy(&idmap_head); -+ if (is_idmap_supported(source)) { -+ printf("idmapped mount is supported on [%s].\n", -+ source); -+ return (EXIT_SUCCESS); -+ } else { -+ printf("idmapped mount is NOT supported.\n"); -+ return (EXIT_FAILURE); -+ } -+ } -+ -+ ret = do_idmap_mount(&idmap_head, source, target, flags); -+ if (ret) -+ ret = EXIT_FAILURE; -+out: -+ free_idmap(&idmap_head); -+ list_destroy(&idmap_head); -+ -+ exit(ret); -+} -diff --git a/tests/zfs-tests/include/commands.cfg b/tests/zfs-tests/include/commands.cfg -index 9953c94952e..db6ee24417c 100644 ---- a/tests/zfs-tests/include/commands.cfg -+++ b/tests/zfs-tests/include/commands.cfg -@@ -220,4 +220,4 @@ export ZFSTEST_FILES='badsend - user_ns_exec - write_dos_attributes - xattrtest -- stride_dd' -+ idmap_util' -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh b/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh -new file mode 100755 -index 00000000000..4895aa23ee4 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh -@@ -0,0 +1,25 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+default_cleanup -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg -new file mode 100644 -index 00000000000..51998945d0d ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg -@@ -0,0 +1,25 @@ -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+export UID1=1000000 -+export GID1=1000000 -+export UID2=2000000 -+export GID2=2000000 -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh -new file mode 100755 -index 00000000000..e7187935e53 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh -@@ -0,0 +1,76 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib -+ -+# -+# -+# DESCRIPTION: -+# Test uid and gid of files in idmapped folder are mapped correctly -+# -+# -+# STRATEGY: -+# 1. Create files/folder owned by $UID1 and $GID1 under "idmap_test" -+# 2. Idmap the folder to "idmap_dest" -+# 3. Verify the owner of files/folder under "idmap_dest" -+# -+ -+verify_runnable "global" -+ -+export WORKDIR=$TESTDIR/idmap_test -+export IDMAPDIR=$TESTDIR/idmap_dest -+ -+function cleanup -+{ -+ log_must rm -rf $WORKDIR -+ if mountpoint $IDMAPDIR; then -+ log_must umount $IDMAPDIR -+ fi -+ log_must rm -rf $IDMAPDIR -+} -+ -+log_onexit cleanup -+ -+if ! idmap_util -c $TESTDIR; then -+ log_unsupported "Idmap mount not supported." -+fi -+ -+log_must mkdir -p $WORKDIR -+log_must mkdir -p $IDMAPDIR -+log_must touch $WORKDIR/file1 -+log_must mkdir $WORKDIR/subdir -+log_must ln -s $WORKDIR/file1 $WORKDIR/file1_sym -+log_must ln $WORKDIR/file1 $WORKDIR/subdir/file1_hard -+log_must touch $WORKDIR/subdir/file2 -+log_must chown -R $UID1:$GID1 $WORKDIR -+log_must chown $UID2:$GID2 $WORKDIR/subdir/file2 -+ -+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR -+ -+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/file1)" -+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/file1_sym)" -+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir)" -+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir/file1_hard)" -+log_mustnot test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir/file2)" -+ -+log_pass "Owner verification of entries under idmapped folder is successful." -+ -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh -new file mode 100755 -index 00000000000..8cba90ea58b ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh -@@ -0,0 +1,97 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib -+ -+# -+# -+# DESCRIPTION: -+# Perform file operations in idmapped folder, check owner in its base. -+# -+# -+# STRATEGY: -+# 1. Create folder "idmap_test" -+# 2. Idmap the folder to "idmap_dest" -+# 3. Do basic file operations in "idmap_dest" folder, verify the owner in -+# the base folder "idmap_test" -+# -+ -+verify_runnable "global" -+ -+export WORKDIR=$TESTDIR/idmap_test -+export IDMAPDIR=$TESTDIR/idmap_dest -+ -+function cleanup -+{ -+ log_must rm -rf $IDMAPDIR/* -+ if mountpoint $IDMAPDIR; then -+ log_must umount $IDMAPDIR -+ fi -+ log_must rm -rf $IDMAPDIR $WORKDIR -+} -+ -+log_onexit cleanup -+ -+if ! idmap_util -c $TESTDIR; then -+ log_unsupported "Idmap mount not supported." -+fi -+ -+log_must mkdir -p $WORKDIR -+log_must mkdir -p $IDMAPDIR -+ -+log_must chown $UID1:$GID1 $WORKDIR -+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR -+ -+SETPRIV="setpriv --reuid $UID2 --regid $GID2 --clear-groups" -+ -+log_must $SETPRIV touch $IDMAPDIR/file1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)" -+ -+log_must $SETPRIV mv $IDMAPDIR/file1 $IDMAPDIR/file1_renamed -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_renamed)" -+ -+log_must $SETPRIV mv $IDMAPDIR/file1_renamed $IDMAPDIR/file1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)" -+ -+log_must $SETPRIV mkdir $IDMAPDIR/subdir -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir)" -+ -+log_must $SETPRIV ln -s $IDMAPDIR/file1 $IDMAPDIR/file1_sym -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_sym)" -+ -+log_must $SETPRIV ln $IDMAPDIR/file1 $IDMAPDIR/subdir/file1_hard -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir/file1_hard)" -+ -+log_must $SETPRIV touch $IDMAPDIR/subdir/file2 -+log_must $SETPRIV chown $UID2:$GID2 $IDMAPDIR/subdir/file2 -+log_mustnot $SETPRIV chown $UID1 $IDMAPDIR/subdir/file2 -+ -+log_must $SETPRIV cp -r $IDMAPDIR/subdir $IDMAPDIR/subdir1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file2)" -+log_must $SETPRIV rm -rf $IDMAPDIR/subdir1 -+ -+log_must $SETPRIV cp -rp $IDMAPDIR/subdir $IDMAPDIR/subdir1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file1_hard)" -+log_must $SETPRIV rm -rf $IDMAPDIR/subdir1 -+ -+log_pass "Owner verification of entries under base folder is successful." -+ -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh -new file mode 100755 -index 00000000000..1f1a2aec655 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh -@@ -0,0 +1,121 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib -+ -+# -+# -+# DESCRIPTION: -+# Perform file operations in idmapped folder in user namespace, -+# then check the owner in its base. -+# -+# -+# STRATEGY: -+# 1. Create folder "idmap_test" -+# 2. Idmap the folder to "idmap_dest" -+# 3. Perform file operations in the idmapped folder in the user -+# namespace having the same idmap info as the idmapped mount -+# 4. Verify the owner of entries under the base folder "idmap_test" -+# -+ -+verify_runnable "global" -+ -+export WORKDIR=$TESTDIR/idmap_test -+export IDMAPDIR=$TESTDIR/idmap_dest -+ -+function cleanup -+{ -+ kill -TERM ${unshared_pid} -+ log_must rm -rf $IDMAPDIR/* -+ if mountpoint $IDMAPDIR; then -+ log_must umount $IDMAPDIR -+ fi -+ log_must rm -rf $IDMAPDIR $WORKDIR -+} -+ -+log_onexit cleanup -+ -+if ! idmap_util -c $TESTDIR; then -+ log_unsupported "Idmap mount not supported." -+fi -+ -+log_must mkdir -p $WORKDIR -+log_must mkdir -p $IDMAPDIR -+ -+log_must chown $UID1:$GID1 $WORKDIR -+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR -+ -+# Create a user namespace with the same idmapping -+unshare -Urm echo test -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+unshare -Um /usr/bin/sleep 2h & -+unshared_pid=$! -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+# wait for userns to be ready -+sleep 1 -+echo "${UID1} ${UID2} 1" > /proc/$unshared_pid/uid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to uid_map" -+fi -+echo "${GID1} ${GID2} 1" > /proc/$unshared_pid/gid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to gid_map" -+fi -+ -+NSENTER="nsenter -t $unshared_pid --all -S ${UID1} -G ${GID1}" -+ -+log_must $NSENTER touch $IDMAPDIR/file1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)" -+ -+log_must $NSENTER mv $IDMAPDIR/file1 $IDMAPDIR/file1_renamed -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_renamed)" -+ -+log_must $NSENTER mv $IDMAPDIR/file1_renamed $IDMAPDIR/file1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)" -+ -+log_must $NSENTER mkdir $IDMAPDIR/subdir -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir)" -+ -+log_must $NSENTER ln -s $IDMAPDIR/file1 $IDMAPDIR/file1_sym -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_sym)" -+ -+log_must $NSENTER ln $IDMAPDIR/file1 $IDMAPDIR/subdir/file1_hard -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir/file1_hard)" -+ -+log_must $NSENTER touch $IDMAPDIR/subdir/file2 -+log_must $NSENTER chown $UID1:$GID1 $IDMAPDIR/subdir/file2 -+log_mustnot $NSENTER chown $UID2 $IDMAPDIR/subdir/file2 -+ -+log_must $NSENTER cp -r $IDMAPDIR/subdir $IDMAPDIR/subdir1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file2)" -+log_must $NSENTER rm -rf $IDMAPDIR/subdir1 -+ -+log_must $NSENTER cp -rp $IDMAPDIR/subdir $IDMAPDIR/subdir1 -+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file1_hard)" -+log_must $NSENTER rm -rf $IDMAPDIR/subdir1 -+ -+log_pass "Owner verification of entries under the base folder is successful." -+ -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh -new file mode 100755 -index 00000000000..89f2f750d23 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh -@@ -0,0 +1,106 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib -+ -+# -+# -+# DESCRIPTION: -+# Test setgid bit is set properly on the idmapped mount -+# in a user namespace. -+# -+# STRATEGY: -+# 1. Create folder "idmap_test", set gid bit on it -+# 2. Idmap the folder to "idmap_dest" -+# 3. Create file and folder in the idmapped folder in the user -+# namespace having the same idmap info -+# 4. Verify the gid bit of the file and folder is set -+# -+ -+verify_runnable "global" -+ -+export WORKDIR=$TESTDIR/idmap_test -+export IDMAPDIR=$TESTDIR/idmap_dest -+ -+function cleanup -+{ -+ kill -TERM ${unshared_pid} -+ log_must rm -rf $IDMAPDIR/* -+ if mountpoint $IDMAPDIR; then -+ log_must umount $IDMAPDIR -+ fi -+ log_must rm -rf $IDMAPDIR $WORKDIR -+} -+ -+log_onexit cleanup -+ -+if ! idmap_util -c $TESTDIR; then -+ log_unsupported "Idmap mount not supported." -+fi -+ -+log_must mkdir -p $WORKDIR -+log_must mkdir -p $IDMAPDIR -+ -+log_must chown $UID1:$GID1 $WORKDIR -+# set gid bit -+log_must chmod 2755 $WORKDIR -+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR -+log_must test -g $IDMAPDIR -+ -+# Create a user namespace with the same idmapping -+unshare -Urm echo test -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+unshare -Um /usr/bin/sleep 2h & -+unshared_pid=$! -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to create user namespace" -+fi -+# wait for userns to be ready -+sleep 1 -+echo "${UID1} ${UID2} 1" > /proc/$unshared_pid/uid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to uid_map" -+fi -+echo "${GID1} ${GID2} 1" > /proc/$unshared_pid/gid_map -+if [ "$?" -ne "0" ]; then -+ log_unsupported "Failed to write to gid_map" -+fi -+ -+NSENTER="nsenter -t $unshared_pid --all -S ${UID1} -G ${GID1}" -+ -+# gid bit can be set on the file -+log_must $NSENTER touch $IDMAPDIR/file1 -+log_must $NSENTER chmod 2654 $IDMAPDIR/file1 -+log_must test -g $WORKDIR/file1 -+log_must test -g $IDMAPDIR/file1 -+log_must test "$UID1 $GID1" = "$($NSENTER stat -c '%u %g' $IDMAPDIR/file1)" -+ -+# gid bit is carried over to new folder -+log_must $NSENTER mkdir $IDMAPDIR/subdir -+log_must test -g $WORKDIR/subdir -+log_must test -g $IDMAPDIR/subdir -+log_must test "$UID1 $GID1" = "$($NSENTER stat -c '%u %g' $IDMAPDIR/subdir)" -+ -+log_pass "Verification of setting gid bit in userns is successful." -+ -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib -new file mode 100644 -index 00000000000..980845ca209 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib -@@ -0,0 +1,23 @@ -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/include/libtest.shlib -+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount.cfg -diff --git a/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh b/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh -new file mode 100755 -index 00000000000..90a14f12058 ---- /dev/null -+++ b/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh -@@ -0,0 +1,30 @@ -+#!/bin/ksh -p -+# -+# CDDL HEADER START -+# -+# The contents of this file are subject to the terms of the -+# Common Development and Distribution License (the "License"). -+# You may not use this file except in compliance with the License. -+# -+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -+# or https://opensource.org/licenses/CDDL-1.0. -+# See the License for the specific language governing permissions -+# and limitations under the License. -+# -+# When distributing Covered Code, include this CDDL HEADER in each -+# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -+# If applicable, add the following below this CDDL HEADER, with the -+# fields enclosed by brackets "[]" replaced with your own identifying -+# information: Portions Copyright [yyyy] [name of copyright owner] -+# -+# CDDL HEADER END -+# -+ -+. $STF_SUITE/include/libtest.shlib -+ -+# unable to do idmapped mount in a local zone -+verify_runnable "global" -+ -+DISK=${DISKS%% *} -+default_setup $DISK -+ - -From d6b868c52df987a992908763b253172112f895ec Mon Sep 17 00:00:00 2001 -From: Spotlight <spotlight@joscomputing.space> -Date: Wed, 26 Apr 2023 12:13:04 -0500 -Subject: [PATCH 3/3] Backport "idmap_mount tests can be skipped on older - kernel" - ---- - tests/test-runner/bin/zts-report.py.in | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/tests/test-runner/bin/zts-report.py.in b/tests/test-runner/bin/zts-report.py.in -index 432899c21f4..a98e8175b06 100755 ---- a/tests/test-runner/bin/zts-report.py.in -+++ b/tests/test-runner/bin/zts-report.py.in -@@ -146,6 +146,11 @@ na_reason = "Not applicable" - # - ci_reason = 'CI runner doesn\'t have all requirements' - -+# -+# Idmapped mount is only supported in kernel version >= 5.12 -+# -+idmap_reason = 'Idmapped mount needs kernel 5.12+' -+ - summary = { - 'total': float(0), - 'passed': float(0), -@@ -289,6 +294,10 @@ elif sys.platform.startswith('linux'): - 'mmp/mmp_inactive_import': ['FAIL', known_reason], - 'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', '12621'], - 'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason], -+ 'idmap_mount/idmap_mount_001': ['SKIP', idmap_reason], -+ 'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason], -+ 'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason], -+ 'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason], - }) - - diff --git a/sys-fs/zfs-kmod/files/zfs-kmod-2.1.11-gentoo.patch b/sys-fs/zfs-kmod/files/zfs-kmod-2.1.11-gentoo.patch new file mode 100644 index 0000000000000000000000000000000000000000..53c5f27b3beda3eda96d9d0c281fb8a4105c9383 --- /dev/null +++ b/sys-fs/zfs-kmod/files/zfs-kmod-2.1.11-gentoo.patch @@ -0,0 +1,24 @@ +Hack to pass the full linux-mod-r1 toolchain to make during ./configure. +Not needed at build time given can pass it normally then. + +Eclass has workarounds, compiler/version matching, and its own set of +user variables which creates disparity between ebuilds if not used. + +For the (normal) alternative: KERNEL_{CC,LD} alone is insufficient, +but combining with KERNEL_LLVM=1 when CC_IS_CLANG will allow it +to work for *most* people (will likely still need KERNEL_LD from +linux-mod-r1, or ThinLTO kernels may fail with sandbox violations). + +Note KERNEL_* also cause failure if they contain spaces. + +https://bugs.gentoo.org/865157 +--- a/config/kernel.m4 ++++ b/config/kernel.m4 +@@ -646,6 +646,5 @@ + AC_TRY_COMMAND([ + KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6" +- make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC} +- ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM} ++ make modules -k -j$TEST_JOBS '${GENTOO_MAKEARGS_EVAL}' + CONFIG_MODULES=y CFLAGS_MODULE=-DCONFIG_MODULES + -C $LINUX_OBJ $ARCH_UM M=$PWD/$1 >$1/build.log 2>&1]) diff --git a/sys-fs/zfs-kmod/metadata.xml b/sys-fs/zfs-kmod/metadata.xml index 936f4ff82c8eca95dfec689ae3c5feb641992a7d..7e27782c6aeb55d33e3cbf3326a6b19491e67335 100644 --- a/sys-fs/zfs-kmod/metadata.xml +++ b/sys-fs/zfs-kmod/metadata.xml @@ -10,6 +10,7 @@ <name>Sam James</name> </maintainer> <use> + <flag name="dist-kernel-cap">Prevents upgrading to an unsupported kernel version when combined with USE=dist-kernel</flag> <flag name="rootfs">Pull dependencies and check kernel options required for root-on-zfs</flag> </use> <upstream> diff --git a/sys-fs/zfs-kmod/zfs-kmod-2.1.11.ebuild b/sys-fs/zfs-kmod/zfs-kmod-2.1.11.ebuild deleted file mode 100644 index 2ea9af3d86769e72d2964b41782d09cf8bb7235b..0000000000000000000000000000000000000000 --- a/sys-fs/zfs-kmod/zfs-kmod-2.1.11.ebuild +++ /dev/null @@ -1,233 +0,0 @@ -# Copyright 1999-2023 Gentoo Authors -# Distributed under the terms of the GNU General Public License v2 - -EAPI=8 - -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 - VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/openzfs.asc - inherit verify-sig - - MY_PV="${PV/_rc/-rc}" - SRC_URI="https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz" - SRC_URI+=" verify-sig? ( https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz.asc )" - S="${WORKDIR}/zfs-${PV%_rc?}" - ZFS_KERNEL_COMPAT="6.3" - - # increments minor eg 5.14 -> 5.15, and still supports override. - ZFS_KERNEL_DEP="${ZFS_KERNEL_COMPAT_OVERRIDE:-${ZFS_KERNEL_COMPAT}}" - ZFS_KERNEL_DEP="${ZFS_KERNEL_DEP%%.*}.$(( ${ZFS_KERNEL_DEP##*.} + 1))" - - if [[ ${PV} != *_rc* ]]; then - KEYWORDS="~amd64 ~arm64 ~ppc64 ~riscv ~sparc" - fi -fi - -LICENSE="CDDL MIT debug? ( GPL-2+ )" -SLOT="0/${PVR}" -IUSE="custom-cflags debug +rootfs" - -RDEPEND="${DEPEND}" - -BDEPEND=" - dev-lang/perl - app-alternatives/awk -" - -# we want dist-kernel block in BDEPEND because of portage resolver. -# since linux-mod.eclass already sets version-unbounded dep, portage -# will pull new versions. So we set it in BDEPEND which takes priority. -# and we don't need in in git ebuild. -if [[ ${PV} != "9999" ]] ; then - BDEPEND+=" - verify-sig? ( sec-keys/openpgp-keys-openzfs ) - dist-kernel? ( <virtual/dist-kernel-${ZFS_KERNEL_DEP}:= ) - " -fi - -# PDEPEND in this form is needed to trick portage suggest -# enabling dist-kernel if only 1 package have it set -PDEPEND="dist-kernel? ( ~sys-fs/zfs-${PV}[dist-kernel] )" - -RESTRICT="debug? ( strip ) test" - -DOCS=( AUTHORS COPYRIGHT META README.md ) - -PATCHES=( - # Prerequisite to idmap patch: "Use generic_permission() on Linux if ACL is trivial" - # https://github.com/openzfs/zfs/pull/13237 - "${FILESDIR}"/2.1.11-optimize-access-checks.patch - # Prerequesite to idmap patch: "Expose additional file level attributes" - # https://github.com/openzfs/zfs/pull/13118 - "${FILESDIR}"/2.1.11-expose-additional-attributes.patch - # Backported version of "Support idmapped mount" - # https://github.com/openzfs/zfs/pull/13671 - "${FILESDIR}"/2.1.11-support-idmapped-mount.patch - # Backported version of "Support idmapped mount in user namespace" - # https://github.com/openzfs/zfs/pull/14097 - "${FILESDIR}"/2.1.11-support-idmapped-mount-in-user-ns.patch - # Backported version of "Linux 6.3 compat: idmapped mount API changes" - # https://github.com/openzfs/zfs/pull/14682 - "${FILESDIR}"/2.1.11-6.3-compat-idmapped-mount-api-changes.patch - # "Linux 6.3 compat: writepage_t first arg struct folio*" - # https://github.com/openzfs/zfs/pull/14699 - "${FILESDIR}"/2.1.11-6.3-compat-writepage_t-typedef-change.patch -) - -pkg_pretend() { - use rootfs || return 0 - - if has_version virtual/dist-kernel && ! use dist-kernel; then - ewarn "You have virtual/dist-kernel installed, but" - ewarn "USE=\"dist-kernel\" is not enabled for ${CATEGORY}/${PN}" - ewarn "It's recommended to globally enable dist-kernel USE flag" - ewarn "to auto-trigger initrd rebuilds with kernel updates" - fi -} - -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_unpack() { - if use verify-sig ; then - # Needed for downloaded patch (which is unsigned, which is fine) - verify-sig_verify_detached "${DISTDIR}"/zfs-${MY_PV}.tar.gz{,.asc} - fi - - default -} - -src_prepare() { - default - - # Run unconditionally (bug #792627) - eautoreconf - - if [[ ${PV} != "9999" ]]; then - # Set module revision number - sed -i "s/\(Release:\)\(.*\)1/\1\2${PR}-gentoo/" META || die "Could not set Gentoo release" - fi -} - -src_configure() { - set_arch_to_kernel - - use custom-cflags || strip-flags - - filter-ldflags -Wl,* - - # Set CROSS_COMPILE in the environment. - # This allows the user to override it via make.conf or via a local Makefile. - # https://bugs.gentoo.org/811600 - export CROSS_COMPILE=${CROSS_COMPILE-${CHOST}-} - - local myconf=( - 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=( - HOSTCC="$(tc-getBUILD_CC)" - V=1 - ) - - emake "${myemakeargs[@]}" -} - -src_install() { - set_arch_to_kernel - - myemakeargs+=( - DEPMOD=: - # INSTALL_MOD_PATH ?= $(DESTDIR) in module/Makefile - DESTDIR="${D}" - ) - - emake "${myemakeargs[@]}" install - - einstalldocs -} - -pkg_postinst() { - linux-mod_pkg_postinst - - if [[ -z ${ROOT} ]] && use dist-kernel; then - set_arch_to_pkgmgr - 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 - - if has_version sys-boot/grub; then - 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 OpenZFS. To" - ewarn "create a new pool that is backward compatible wih GRUB2, use " - ewarn - ewarn "zpool create -o compatibility=grub2 ..." - ewarn - ewarn "Refer to /usr/share/zfs/compatibility.d/grub2 for list of features." - fi -} diff --git a/sys-fs/zfs-kmod/zfs-kmod-2.1.12.ebuild b/sys-fs/zfs-kmod/zfs-kmod-2.1.12.ebuild new file mode 100644 index 0000000000000000000000000000000000000000..3ecceb388ea8d506d923e7ea238e4d5372afee34 --- /dev/null +++ b/sys-fs/zfs-kmod/zfs-kmod-2.1.12.ebuild @@ -0,0 +1,177 @@ +# Copyright 1999-2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit autotools dist-kernel-utils flag-o-matic linux-mod-r1 multiprocessing + +DESCRIPTION="Linux ZFS kernel module for sys-fs/zfs" +HOMEPAGE="https://github.com/openzfs/zfs" + +MODULES_KERNEL_MAX=6.4 +MODULES_KERNEL_MIN=3.10 + +if [[ ${PV} == 9999 ]] ; then + EGIT_REPO_URI="https://github.com/openzfs/zfs.git" + inherit git-r3 + unset MODULES_KERNEL_MAX +else + VERIFY_SIG_OPENPGP_KEY_PATH="${BROOT}"/usr/share/openpgp-keys/openzfs.asc + inherit verify-sig + + MY_PV=${PV/_rc/-rc} + SRC_URI="https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz" + SRC_URI+=" verify-sig? ( https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz.asc )" + S="${WORKDIR}/zfs-${PV%_rc?}" + + ZFS_KERNEL_COMPAT="${MODULES_KERNEL_MAX}" + # Increments minor eg 5.14 -> 5.15, and still supports override. + ZFS_KERNEL_DEP="${ZFS_KERNEL_COMPAT_OVERRIDE:-${ZFS_KERNEL_COMPAT}}" + ZFS_KERNEL_DEP="${ZFS_KERNEL_DEP%%.*}.$(( ${ZFS_KERNEL_DEP##*.} + 1))" + + if [[ ${PV} != *_rc* ]] ; then + KEYWORDS="~amd64 ~arm64 ~ppc64 ~riscv ~sparc" + fi +fi + +LICENSE="CDDL MIT debug? ( GPL-2+ )" +SLOT="0/${PVR}" +IUSE="custom-cflags debug +rootfs" +RESTRICT="test" + +BDEPEND=" + dev-lang/perl + app-alternatives/awk +" + +if [[ ${PV} != 9999 ]] ; then + BDEPEND+=" verify-sig? ( sec-keys/openpgp-keys-openzfs )" + + IUSE+=" +dist-kernel-cap" + RDEPEND=" + dist-kernel-cap? ( dist-kernel? ( + <virtual/dist-kernel-${ZFS_KERNEL_DEP} + ) ) + " +fi + +# Used to suggest matching USE, but without suggesting to disable +PDEPEND="dist-kernel? ( ~sys-fs/zfs-${PV}[dist-kernel] )" + +PATCHES=( + "${FILESDIR}"/${PN}-2.1.11-gentoo.patch +) + +pkg_pretend() { + use rootfs || return 0 + + if has_version virtual/dist-kernel && ! use dist-kernel; then + ewarn "You have virtual/dist-kernel installed, but" + ewarn "USE=\"dist-kernel\" is not enabled for ${CATEGORY}/${PN}" + ewarn "It's recommended to globally enable dist-kernel USE flag" + ewarn "to auto-trigger initrd rebuilds with kernel updates" + fi +} + +pkg_setup() { + local CONFIG_CHECK=" + EFI_PARTITION + ZLIB_DEFLATE + ZLIB_INFLATE + !DEBUG_LOCK_ALLOC + !PAX_KERNEXEC_PLUGIN_METHOD_OR + " + use debug && CONFIG_CHECK+=" + DEBUG_INFO + FRAME_POINTER + !DEBUG_INFO_REDUCED + " + use rootfs && CONFIG_CHECK+=" + BLK_DEV_INITRD + DEVTMPFS + " + + kernel_is -lt 5 && 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 + + linux-mod-r1_pkg_setup +} + +src_prepare() { + default + + # Run unconditionally (bug #792627) + eautoreconf + + if [[ ${PV} != 9999 ]] ; then + # Set module revision number + sed -Ei "s/(Release:.*)1/\1${PR}-gentoo/" META || die + fi +} + +src_configure() { + use custom-cflags || strip-flags + filter-ldflags -Wl,* + + local myconf=( + --bindir="${EPREFIX}"/bin + --sbindir="${EPREFIX}"/sbin + --with-config=kernel + --with-linux="${KV_DIR}" + --with-linux-obj="${KV_OUT_DIR}" + $(use_enable debug) + + # See gentoo.patch + GENTOO_MAKEARGS_EVAL="${MODULES_MAKEARGS[*]@Q}" + TEST_JOBS="$(makeopts_jobs)" + ) + + econf "${myconf[@]}" +} + +src_compile() { + emake "${MODULES_MAKEARGS[@]}" +} + +src_install() { + emake "${MODULES_MAKEARGS[@]}" DESTDIR="${ED}" install + modules_post_process + + dodoc AUTHORS COPYRIGHT META README.md +} + +pkg_postinst() { + linux-mod-r1_pkg_postinst + + if [[ -z ${ROOT} ]] && use dist-kernel ; then + 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 + + if has_version sys-boot/grub ; then + 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 OpenZFS. To" + ewarn "create a new pool that is backward compatible wih GRUB2, use " + ewarn + ewarn "zpool create -o compatibility=grub2 ..." + ewarn + ewarn "Refer to /usr/share/zfs/compatibility.d/grub2 for list of features." + fi +} diff --git a/sys-fs/zfs-kmod/zfs-kmod-9999.ebuild b/sys-fs/zfs-kmod/zfs-kmod-9999.ebuild index 1df8508ad03df05d390ecbb1acb1d9fb3044d9e9..0c5bfab161cc9df16f46d069f76c7234d038035b 100644 --- a/sys-fs/zfs-kmod/zfs-kmod-9999.ebuild +++ b/sys-fs/zfs-kmod/zfs-kmod-9999.ebuild @@ -3,29 +3,33 @@ EAPI=8 -inherit autotools dist-kernel-utils flag-o-matic linux-mod toolchain-funcs +inherit autotools dist-kernel-utils flag-o-matic linux-mod-r1 multiprocessing DESCRIPTION="Linux ZFS kernel module for sys-fs/zfs" HOMEPAGE="https://github.com/openzfs/zfs" -if [[ ${PV} == "9999" ]]; then - inherit git-r3 +MODULES_KERNEL_MAX=6.3 +MODULES_KERNEL_MIN=3.10 + +if [[ ${PV} == 9999 ]] ; then EGIT_REPO_URI="https://github.com/openzfs/zfs.git" + inherit git-r3 + unset MODULES_KERNEL_MAX else - VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/openzfs.asc + VERIFY_SIG_OPENPGP_KEY_PATH="${BROOT}"/usr/share/openpgp-keys/openzfs.asc inherit verify-sig - MY_PV="${PV/_rc/-rc}" + MY_PV=${PV/_rc/-rc} SRC_URI="https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz" SRC_URI+=" verify-sig? ( https://github.com/openzfs/zfs/releases/download/zfs-${MY_PV}/zfs-${MY_PV}.tar.gz.asc )" S="${WORKDIR}/zfs-${PV%_rc?}" - ZFS_KERNEL_COMPAT="6.2" - # increments minor eg 5.14 -> 5.15, and still supports override. + ZFS_KERNEL_COMPAT="${MODULES_KERNEL_MAX}" + # Increments minor eg 5.14 -> 5.15, and still supports override. ZFS_KERNEL_DEP="${ZFS_KERNEL_COMPAT_OVERRIDE:-${ZFS_KERNEL_COMPAT}}" ZFS_KERNEL_DEP="${ZFS_KERNEL_DEP%%.*}.$(( ${ZFS_KERNEL_DEP##*.} + 1))" - if [[ ${PV} != *_rc* ]]; then + if [[ ${PV} != *_rc* ]] ; then KEYWORDS="~amd64 ~arm64 ~ppc64 ~riscv ~sparc" fi fi @@ -33,32 +37,30 @@ fi LICENSE="CDDL MIT debug? ( GPL-2+ )" SLOT="0/${PVR}" IUSE="custom-cflags debug +rootfs" - -RDEPEND="${DEPEND}" +RESTRICT="test" BDEPEND=" dev-lang/perl app-alternatives/awk " -# we want dist-kernel block in BDEPEND because of portage resolver. -# since linux-mod.eclass already sets version-unbounded dep, portage -# will pull new versions. So we set it in BDEPEND which takes priority. -# and we don't need in in git ebuild. -if [[ ${PV} != "9999" ]] ; then - BDEPEND+=" - verify-sig? ( sec-keys/openpgp-keys-openzfs ) - dist-kernel? ( <virtual/dist-kernel-${ZFS_KERNEL_DEP}:= ) +if [[ ${PV} != 9999 ]] ; then + BDEPEND+=" verify-sig? ( sec-keys/openpgp-keys-openzfs )" + + IUSE+=" +dist-kernel-cap" + RDEPEND=" + dist-kernel-cap? ( dist-kernel? ( + <virtual/dist-kernel-${ZFS_KERNEL_DEP} + ) ) " fi -# PDEPEND in this form is needed to trick portage suggest -# enabling dist-kernel if only 1 package have it set +# Used to suggest matching USE, but without suggesting to disable PDEPEND="dist-kernel? ( ~sys-fs/zfs-${PV}[dist-kernel] )" -RESTRICT="debug? ( strip ) test" - -DOCS=( AUTHORS COPYRIGHT META README.md ) +PATCHES=( + "${FILESDIR}"/${PN}-2.1.11-gentoo.patch +) pkg_pretend() { use rootfs || return 0 @@ -72,31 +74,26 @@ pkg_pretend() { } pkg_setup() { - CONFIG_CHECK=" - !DEBUG_LOCK_ALLOC + local CONFIG_CHECK=" EFI_PARTITION - MODULES - !PAX_KERNEXEC_PLUGIN_METHOD_OR - !TRIM_UNUSED_KSYMS ZLIB_DEFLATE ZLIB_INFLATE + !DEBUG_LOCK_ALLOC + !PAX_KERNEXEC_PLUGIN_METHOD_OR " - - use debug && CONFIG_CHECK="${CONFIG_CHECK} - FRAME_POINTER + use debug && CONFIG_CHECK+=" DEBUG_INFO + FRAME_POINTER !DEBUG_INFO_REDUCED " - - use rootfs && \ - CONFIG_CHECK="${CONFIG_CHECK} - BLK_DEV_INITRD - DEVTMPFS + use rootfs && CONFIG_CHECK+=" + BLK_DEV_INITRD + DEVTMPFS " - kernel_is -lt 5 && CONFIG_CHECK="${CONFIG_CHECK} IOSCHED_NOOP" + kernel_is -lt 5 && CONFIG_CHECK+=" IOSCHED_NOOP" - if [[ ${PV} != "9999" ]]; then + if [[ ${PV} != 9999 ]] ; then local kv_major_max kv_minor_max zcompat zcompat="${ZFS_KERNEL_COMPAT_OVERRIDE:-${ZFS_KERNEL_COMPAT}}" kv_major_max="${zcompat%%.*}" @@ -104,12 +101,9 @@ pkg_setup() { 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 + linux-mod-r1_pkg_setup } src_prepare() { @@ -118,60 +112,41 @@ src_prepare() { # Run unconditionally (bug #792627) eautoreconf - if [[ ${PV} != "9999" ]]; then + if [[ ${PV} != 9999 ]] ; then # Set module revision number - sed -i "s/\(Release:\)\(.*\)1/\1\2${PR}-gentoo/" META || die "Could not set Gentoo release" + sed -Ei "s/(Release:.*)1/\1${PR}-gentoo/" META || die fi } src_configure() { - set_arch_to_kernel - use custom-cflags || strip-flags - filter-ldflags -Wl,* - # Set CROSS_COMPILE in the environment. - # This allows the user to override it via make.conf or via a local Makefile. - # https://bugs.gentoo.org/811600 - export CROSS_COMPILE=${CROSS_COMPILE-${CHOST}-} - local myconf=( - HOSTCC="$(tc-getBUILD_CC)" - --bindir="${EPREFIX}/bin" - --sbindir="${EPREFIX}/sbin" + --bindir="${EPREFIX}"/bin + --sbindir="${EPREFIX}"/sbin --with-config=kernel --with-linux="${KV_DIR}" --with-linux-obj="${KV_OUT_DIR}" $(use_enable debug) + + # See gentoo.patch + GENTOO_MAKEARGS_EVAL="${MODULES_MAKEARGS[*]@Q}" + TEST_JOBS="$(makeopts_jobs)" ) econf "${myconf[@]}" } src_compile() { - set_arch_to_kernel - - myemakeargs=( - HOSTCC="$(tc-getBUILD_CC)" - V=1 - ) - - emake "${myemakeargs[@]}" + emake "${MODULES_MAKEARGS[@]}" } src_install() { - set_arch_to_kernel - - myemakeargs+=( - DEPMOD=: - # INSTALL_MOD_PATH ?= $(DESTDIR) in module/Makefile - DESTDIR="${D}" - ) - - emake "${myemakeargs[@]}" install + emake "${MODULES_MAKEARGS[@]}" DESTDIR="${ED}" install + modules_post_process - einstalldocs + dodoc AUTHORS COPYRIGHT META README.md } _old_layout_cleanup() { @@ -190,7 +165,7 @@ _old_layout_cleanup() { # kernel/module/Kconfig contains possible compressed extentions. local kext kextfiles - for kext in .ko{,.{gz,xz,zst}}; do + for kext in .ko{,.{gz,xz,zst}}; do kextfiles+=( "${olddir[@]/%/${kext}}" ) done @@ -214,19 +189,19 @@ pkg_postinst() { # we check first array member, if glob above did not exand, it will be "zfs.ko*" and -f will return false. # if glob expanded -f will do correct file precense check. [[ -f ${newko[0]} ]] && _old_layout_cleanup - linux-mod_pkg_postinst - if [[ -z ${ROOT} ]] && use dist-kernel; then - set_arch_to_pkgmgr + linux-mod-r1_pkg_postinst + + if [[ -z ${ROOT} ]] && use dist-kernel ; then dist-kernel_reinstall_initramfs "${KV_DIR}" "${KV_FULL}" fi - if use x86 || use arm; then + 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 - if has_version sys-boot/grub; then + if has_version sys-boot/grub ; then 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."