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."