Linux 6.3 compat: idmapped mount API changes

Linux kernel 6.3 changed a bunch of APIs to use the dedicated idmap
type for mounts (struct mnt_idmap), we need to detect these changes
and make zfs work with the new APIs.

NOTE: This backport only includes the configure checks to detect
the 6.3 idmap API changes.  It does not include support for idmap.
When provided the idmap variable is ignored in most case in the
same way the user_ns argument was ignored.  This change is solely
to provide compatibility with the new interfaces.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Youzhong Yang <yyang@mathworks.com>
Closes #14682
This commit is contained in:
youzhongyang 2023-04-10 17:15:36 -04:00 committed by Tony Hutter
parent 04305bbd18
commit f0aca5f7bb
28 changed files with 708 additions and 166 deletions

View File

@ -236,7 +236,22 @@ dnl #
dnl # 6.2 API change, dnl # 6.2 API change,
dnl # set_acl() second paramter changed to a struct dentry * dnl # set_acl() second paramter changed to a struct dentry *
dnl # 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], [ 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], [ ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns_dentry], [
#include <linux/fs.h> #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, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args]) 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_MSG_RESULT(yes)
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1, AC_DEFINE(HAVE_SET_ACL_IDMAP_DENTRY, 1,
[iops->set_acl() takes 4 args, arg2 is struct dentry *]) [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_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])
])
]) ])
]) ])
]) ])

View File

@ -4,7 +4,10 @@ dnl #
dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace* dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace*
dnl # as the first arg, to support idmapped mounts. dnl # as the first arg, to support idmapped mounts.
dnl # 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], [ ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [
#include <linux/fs.h> #include <linux/fs.h>
],[ ],[
@ -13,16 +16,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [
struct kstat *k = NULL; struct kstat *k = NULL;
generic_fillattr(userns, in, k); generic_fillattr(userns, in, k);
]) ])
])
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [ ZFS_LINUX_TEST_SRC([generic_fillattr_mnt_idmap], [
AC_MSG_CHECKING([whether generic_fillattr requires struct user_namespace*]) #include <linux/fs.h>
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]) 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], [
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_IDMAP, 1,
[generic_fillattr requires struct mnt_idmap*])
],[
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])
])
]) ])
]) ])

View File

@ -1,4 +1,22 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [ 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 #
dnl # 5.12 API change that added the struct user_namespace* arg dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list. 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_DEFUN([ZFS_AC_KERNEL_CREATE], [
AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*]) AC_MSG_CHECKING([whether iops->create() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([create_userns], [ ZFS_LINUX_TEST_RESULT([create_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1, AC_DEFINE(HAVE_IOPS_CREATE_IDMAP, 1,
[iops->create() takes struct user_namespace*]) [iops->create() takes struct mnt_idmap*])
],[ ],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether iops->create() passes flags]) AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*])
ZFS_LINUX_TEST_RESULT([create_flags], [ ZFS_LINUX_TEST_RESULT([create_userns], [
AC_MSG_RESULT(yes) 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()])
])
]) ])
]) ])
]) ])

View File

@ -1,4 +1,24 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ 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 #
dnl # Linux 5.12 API dnl # Linux 5.12 API
dnl # The getattr I/O operations handler type was extended to require 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], [ AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [
dnl # dnl #
dnl # Kernel 5.12 test dnl # Kernel 6.3 test
dnl # dnl #
AC_MSG_CHECKING([whether iops->getattr() takes user_namespace]) AC_MSG_CHECKING([whether iops->getattr() takes mnt_idmap])
ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1, AC_DEFINE(HAVE_IDMAP_IOPS_GETATTR, 1,
[iops->getattr() takes struct user_namespace*]) [iops->getattr() takes struct mnt_idmap*])
],[ ],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
dnl # dnl #
dnl # Kernel 4.11 test dnl # Kernel 5.12 test
dnl # dnl #
AC_MSG_CHECKING([whether iops->getattr() takes a path]) AC_MSG_CHECKING([whether iops->getattr() takes user_namespace])
ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1,
[iops->getattr() takes a path]) [iops->getattr() takes struct user_namespace*])
],[ ],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
dnl # dnl #
dnl # Kernel < 4.11 test dnl # Kernel 4.11 test
dnl # dnl #
AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) AC_MSG_CHECKING([whether iops->getattr() takes a path])
ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
[iops->getattr() takes a vfsmount]) [iops->getattr() takes a path])
],[ ],[
AC_MSG_RESULT(no) 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)
])
]) ])
]) ])
]) ])

View File

@ -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)
])
])
])
])

View File

@ -16,12 +16,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [
(void) inode_owner_or_capable(ip); (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> #include <linux/fs.h>
],[ ],[
struct inode *ip = NULL; struct inode *ip = NULL;
(void) inode_owner_or_capable(&init_user_ns, ip); (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], [ 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( AC_MSG_CHECKING(
[whether inode_owner_or_capable() takes user_ns]) [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_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]) [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])
])
]) ])
]) ])
]) ])

View File

@ -2,6 +2,22 @@ dnl #
dnl # Supported mkdir() interfaces checked newest to oldest. dnl # Supported mkdir() interfaces checked newest to oldest.
dnl # dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [ 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 #
dnl # 5.12 API change dnl # 5.12 API change
dnl # The struct user_namespace arg was added as the first argument to 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], [ AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [
dnl # dnl #
dnl # 5.12 API change dnl # 6.3 API change
dnl # The struct user_namespace arg was added as the first argument to dnl # mkdir() takes struct mnt_idmap * as the first arg
dnl # mkdir() of the iops structure.
dnl # dnl #
AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*]) AC_MSG_CHECKING([whether iops->mkdir() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [ ZFS_LINUX_TEST_RESULT([mkdir_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1, AC_DEFINE(HAVE_IOPS_MKDIR_IDMAP, 1,
[iops->mkdir() takes struct user_namespace*]) [iops->mkdir() takes struct mnt_idmap*])
],[ ],[
AC_MSG_RESULT(no) dnl #
dnl # 5.12 API change
AC_MSG_CHECKING([whether iops->mkdir() takes umode_t]) dnl # The struct user_namespace arg was added as the first argument to
ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [ 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_MSG_RESULT(yes)
AC_DEFINE(HAVE_MKDIR_UMODE_T, 1, AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
[iops->mkdir() takes umode_t]) [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()])
])
]) ])
]) ])
]) ])

View File

@ -1,4 +1,22 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [ 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 #
dnl # 5.12 API change that added the struct user_namespace* arg dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list. 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_DEFUN([ZFS_AC_KERNEL_MKNOD], [
AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*]) AC_MSG_CHECKING([whether iops->mknod() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([mknod_userns], [ ZFS_LINUX_TEST_RESULT([mknod_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1, AC_DEFINE(HAVE_IOPS_MKNOD_IDMAP, 1,
[iops->mknod() takes struct user_namespace*]) [iops->mknod() takes struct mnt_idmap*])
],[ ],[
AC_MSG_RESULT(no) 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)
])
]) ])
]) ])

View File

@ -33,24 +33,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
.rename = rename_fn, .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_DEFUN([ZFS_AC_KERNEL_RENAME], [
AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*]) AC_MSG_CHECKING([whether iops->rename() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [ ZFS_LINUX_TEST_RESULT([inode_operations_rename_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1, AC_DEFINE(HAVE_IOPS_RENAME_IDMAP, 1,
[iops->rename() takes struct user_namespace*]) [iops->rename() takes struct mnt_idmap*])
],[ ],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether iop->rename() wants flags]) AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*])
ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [ ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1,
[iops->rename() wants flags]) [iops->rename() takes struct user_namespace*])
],[ ],[
AC_MSG_RESULT(no) 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)
])
]) ])
]) ])
]) ])

View File

@ -27,26 +27,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
int error __attribute__ ((unused)) = int error __attribute__ ((unused)) =
setattr_prepare(userns, dentry, attr); 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_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [
AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*]) AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns], ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_mnt_idmap],
[setattr_prepare], [fs/attr.c], [ [setattr_prepare], [fs/attr.c], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1, AC_DEFINE(HAVE_SETATTR_PREPARE_IDMAP, 1,
[setattr_prepare() accepts user_namespace]) [setattr_prepare() accepts mnt_idmap])
], [ ], [
AC_MSG_RESULT(no) 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, doesn't accept user_namespace]) [setattr_prepare], [fs/attr.c], [
ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
[setattr_prepare], [fs/attr.c], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1, AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1,
[setattr_prepare() is available, doesn't accept user_namespace]) [setattr_prepare() accepts user_namespace])
], [ ], [
AC_MSG_RESULT(no) 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)
])
]) ])
]) ])
]) ])

View File

@ -1,4 +1,20 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [ 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 #
dnl # 5.12 API change that added the struct user_namespace* arg dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list. 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_DEFUN([ZFS_AC_KERNEL_SYMLINK], [
AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*]) AC_MSG_CHECKING([whether iops->symlink() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([symlink_userns], [ ZFS_LINUX_TEST_RESULT([symlink_mnt_idmap], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1, AC_DEFINE(HAVE_IOPS_SYMLINK_IDMAP, 1,
[iops->symlink() takes struct user_namespace*]) [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)
])
]) ])
]) ])

View File

@ -4,6 +4,19 @@ dnl # Add support for i_op->tmpfile
dnl # dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
dnl # 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 # 6.1 API change
dnl # use struct file instead of struct dentry dnl # use struct file instead of struct dentry
dnl # dnl #
@ -44,23 +57,29 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [ AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
AC_MSG_CHECKING([whether i_op->tmpfile() exists]) 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_MSG_RESULT(yes)
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns]) AC_DEFINE(HAVE_TMPFILE_IDMAP, 1, [i_op->tmpfile() has mnt_idmap])
],[ ], [
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry_userns], [ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns]) 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_MSG_RESULT(yes)
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists]) 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]) 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])
])
]) ])
]) ])
]) ])

View File

@ -179,6 +179,21 @@ dnl #
dnl # Supported xattr handler set() interfaces checked newest to oldest. dnl # Supported xattr handler set() interfaces checked newest to oldest.
dnl # dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [ 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], [ ZFS_LINUX_TEST_SRC([xattr_handler_set_userns], [
#include <linux/xattr.h> #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 # The xattr_handler->set() callback was changed to 8 arguments, and
dnl # struct user_namespace* was inserted as arg #2 dnl # struct user_namespace* was inserted as arg #2
dnl # dnl #
AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace]) dnl # 6.3 API change,
ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [ 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_MSG_RESULT(yes)
AC_DEFINE(HAVE_XATTR_SET_USERNS, 1, AC_DEFINE(HAVE_XATTR_SET_IDMAP, 1,
[xattr_handler->set() takes user_namespace]) [xattr_handler->set() takes mnt_idmap])
],[ ], [
dnl # AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace])
dnl # 4.7 API change, ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [
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_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1, AC_DEFINE(HAVE_XATTR_SET_USERNS, 1,
[xattr_handler->set() wants both dentry and inode]) [xattr_handler->set() takes user_namespace])
],[ ],[
dnl # dnl #
dnl # 4.4 API change, dnl # 4.7 API change,
dnl # The xattr_handler->set() callback was changed to take a dnl # The xattr_handler->set() callback was changed to take both
dnl # xattr_handler, and handler_flags argument was removed and dnl # dentry and inode.
dnl # should be accessed by handler->flags.
dnl # dnl #
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING( AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
[whether xattr_handler->set() wants xattr_handler]) ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1, AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
[xattr_handler->set() wants xattr_handler]) [xattr_handler->set() wants both dentry and inode])
],[ ],[
dnl # dnl #
dnl # 2.6.33 API change, dnl # 4.4 API change,
dnl # The xattr_handler->set() callback was changed dnl # The xattr_handler->set() callback was changed to take a
dnl # to take a dentry instead of an inode, and a dnl # xattr_handler, and handler_flags argument was removed and
dnl # handler_flags argument was added. dnl # should be accessed by handler->flags.
dnl # dnl #
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING( AC_MSG_CHECKING(
[whether xattr_handler->set() wants dentry]) [whether xattr_handler->set() wants xattr_handler])
ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [ ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1, AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
[xattr_handler->set() wants dentry]) [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()])
])
]) ])
]) ])
]) ])

View File

@ -69,6 +69,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE
ZFS_AC_KERNEL_SRC_XATTR ZFS_AC_KERNEL_SRC_XATTR
ZFS_AC_KERNEL_SRC_ACL ZFS_AC_KERNEL_SRC_ACL
ZFS_AC_KERNEL_SRC_INODE_SETATTR
ZFS_AC_KERNEL_SRC_INODE_GETATTR ZFS_AC_KERNEL_SRC_INODE_GETATTR
ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS
ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION
@ -130,7 +131,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_KSTRTOUL ZFS_AC_KERNEL_SRC_KSTRTOUL
ZFS_AC_KERNEL_SRC_PERCPU ZFS_AC_KERNEL_SRC_PERCPU
ZFS_AC_KERNEL_SRC_CPU_HOTPLUG 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_MKNOD
ZFS_AC_KERNEL_SRC_SYMLINK ZFS_AC_KERNEL_SRC_SYMLINK
ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
@ -194,6 +195,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE
ZFS_AC_KERNEL_XATTR ZFS_AC_KERNEL_XATTR
ZFS_AC_KERNEL_ACL ZFS_AC_KERNEL_ACL
ZFS_AC_KERNEL_INODE_SETATTR
ZFS_AC_KERNEL_INODE_GETATTR ZFS_AC_KERNEL_INODE_GETATTR
ZFS_AC_KERNEL_INODE_SET_FLAGS ZFS_AC_KERNEL_INODE_SET_FLAGS
ZFS_AC_KERNEL_INODE_SET_IVERSION ZFS_AC_KERNEL_INODE_SET_IVERSION
@ -255,7 +257,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_KSTRTOUL ZFS_AC_KERNEL_KSTRTOUL
ZFS_AC_KERNEL_PERCPU ZFS_AC_KERNEL_PERCPU
ZFS_AC_KERNEL_CPU_HOTPLUG ZFS_AC_KERNEL_CPU_HOTPLUG
ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS ZFS_AC_KERNEL_GENERIC_FILLATTR
ZFS_AC_KERNEL_MKNOD ZFS_AC_KERNEL_MKNOD
ZFS_AC_KERNEL_SYMLINK ZFS_AC_KERNEL_SYMLINK
ZFS_AC_KERNEL_BIO_MAX_SEGS ZFS_AC_KERNEL_BIO_MAX_SEGS

View File

@ -344,7 +344,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid)
* 4.9 API change * 4.9 API change
*/ */
#if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \ #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 static inline int
setattr_prepare(struct dentry *dentry, struct iattr *ia) 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, \ return (func##_impl(user_ns, path, stat, request_mask, \
query_flags)); \ 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 #else
#error #error
#endif #endif
@ -450,8 +460,15 @@ zpl_is_32bit_api(void)
* 5.12 API change * 5.12 API change
* To support id-mapped mounts, generic_fillattr() was modified to * To support id-mapped mounts, generic_fillattr() was modified to
* accept a new struct user_namespace* as its first arg. * 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) \ #define zpl_generic_fillattr(user_ns, ip, sp) \
generic_fillattr(user_ns, ip, sp) generic_fillattr(user_ns, ip, sp)
#else #else

View File

@ -133,20 +133,35 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \
#error "Unsupported kernel" #error "Unsupported kernel"
#endif #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, * 5.12 API change,
* The xattr_handler->set() callback was changed to take the * The xattr_handler->set() callback was changed to take the
* struct user_namespace* as the first arg, to support idmapped * struct user_namespace* as the first arg, to support idmapped
* mounts. * mounts.
*/ */
#if defined(HAVE_XATTR_SET_USERNS) #elif defined(HAVE_XATTR_SET_USERNS)
#define ZPL_XATTR_SET_WRAPPER(fn) \ #define ZPL_XATTR_SET_WRAPPER(fn) \
static int \ static int \
fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \ fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \
struct dentry *dentry, struct inode *inode, const char *name, \ struct dentry *dentry, struct inode *inode, const char *name, \
const void *buffer, size_t size, int flags) \ 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, * 4.7 API change,
@ -160,7 +175,7 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \
struct inode *inode, const char *name, const void *buffer, \ struct inode *inode, const char *name, const void *buffer, \
size_t size, int flags) \ size_t size, int flags) \
{ \ { \
return (__ ## fn(inode, name, buffer, size, flags)); \ return (__ ## fn(kcred->user_ns, inode, name, buffer, size, flags));\
} }
/* /*
* 4.4 API change, * 4.4 API change,
@ -174,7 +189,8 @@ static int \
fn(const struct xattr_handler *handler, struct dentry *dentry, \ fn(const struct xattr_handler *handler, struct dentry *dentry, \
const char *name, const void *buffer, size_t size, int flags) \ const char *name, const void *buffer, size_t size, int flags) \
{ \ { \
return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, \
buffer, size, flags)); \
} }
/* /*
* 2.6.33 API change, * 2.6.33 API change,
@ -187,7 +203,8 @@ static int \
fn(struct dentry *dentry, const char *name, const void *buffer, \ fn(struct dentry *dentry, const char *name, const void *buffer, \
size_t size, int flags, int unused_handler_flags) \ size_t size, int flags, int unused_handler_flags) \
{ \ { \
return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, buffer, \
size, flags)); \
} }
#else #else
#error "Unsupported kernel" #error "Unsupported kernel"

View File

@ -45,6 +45,8 @@ typedef struct cred cred_t;
#define SGID_TO_KGID(x) (KGIDT_INIT(x)) #define SGID_TO_KGID(x) (KGIDT_INIT(x))
#define KGIDP_TO_SGIDP(x) (&(x)->val) #define KGIDP_TO_SGIDP(x) (&(x)->val)
extern zidmap_t *zfs_get_init_idmap(void);
extern void crhold(cred_t *cr); extern void crhold(cred_t *cr);
extern void crfree(cred_t *cr); extern void crfree(cred_t *cr);
extern uid_t crgetuid(const cred_t *cr); extern uid_t crgetuid(const cred_t *cr);

View File

@ -54,4 +54,18 @@ typedef ulong_t pgcnt_t;
typedef int major_t; typedef int major_t;
typedef int minor_t; typedef int minor_t;
struct user_namespace;
#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;
#else
typedef struct user_namespace zidmap_t;
#endif
extern zidmap_t *zfs_init_idmap;
#endif /* _SPL_TYPES_H */ #endif /* _SPL_TYPES_H */

View File

@ -54,8 +54,7 @@ extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap,
extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd,
cred_t *cr, int flags); cred_t *cr, int flags);
extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr); 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, extern int zfs_getattr_fast(zidmap_t *, struct inode *ip, struct kstat *sp);
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);
extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, 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);

View File

@ -64,7 +64,10 @@ extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip,
const struct qstr *qstr); const struct qstr *qstr);
#if defined(CONFIG_FS_POSIX_ACL) #if defined(CONFIG_FS_POSIX_ACL)
#if defined(HAVE_SET_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, extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip,
struct posix_acl *acl, int type); struct posix_acl *acl, int type);
#elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2) #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) #if defined(HAVE_INODE_OWNER_OR_CAPABLE)
#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ip) #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) #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 #else
#error "Unsupported kernel" #error "Unsupported kernel"
#endif #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) #define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia)
#else #else
/* /*

View File

@ -145,6 +145,18 @@ crgetgid(const cred_t *cr)
return (KGID_TO_SGID(cr->fsgid)); 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(crhold);
EXPORT_SYMBOL(crfree); EXPORT_SYMBOL(crfree);
EXPORT_SYMBOL(crgetuid); EXPORT_SYMBOL(crgetuid);

View File

@ -124,7 +124,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
if (crgetuid(cr) == owner) if (crgetuid(cr) == owner)
return (0); return (0);
if (zpl_inode_owner_or_capable(kcred->user_ns, ip)) if (zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (0); return (0);
#if defined(CONFIG_USER_NS) #if defined(CONFIG_USER_NS)

View File

@ -288,6 +288,8 @@ zfsdev_detach(void)
#define ZFS_DEBUG_STR "" #define ZFS_DEBUG_STR ""
#endif #endif
zidmap_t *zfs_init_idmap;
static int __init static int __init
openzfs_init(void) openzfs_init(void)
{ {
@ -311,6 +313,8 @@ openzfs_init(void)
printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n"); printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n");
#endif /* CONFIG_FS_POSIX_ACL */ #endif /* CONFIG_FS_POSIX_ACL */
zfs_init_idmap = (zidmap_t *)zfs_get_init_idmap();
return (0); return (0);
} }

View File

@ -1675,8 +1675,7 @@ out:
*/ */
/* ARGSUSED */ /* ARGSUSED */
int int
zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip, zfs_getattr_fast(zidmap_t *user_ns, struct inode *ip, struct kstat *sp)
struct kstat *sp)
{ {
znode_t *zp = ITOZ(ip); znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip); zfsvfs_t *zfsvfs = ITOZSB(ip);

View File

@ -101,7 +101,11 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/ */
/* ARGSUSED */ /* ARGSUSED */
static int 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, zpl_root_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask, const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags) 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; 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); generic_fillattr(user_ns, ip, stat);
#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
generic_fillattr(user_ns, ip, stat);
#else
(void) user_ns;
#endif
#else #else
generic_fillattr(ip, stat); generic_fillattr(ip, stat);
#endif #endif
@ -304,6 +314,10 @@ static int
zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip, zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip,
struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
unsigned int flags) 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 #else
zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry, unsigned int flags) struct inode *tdip, struct dentry *tdentry, unsigned int flags)
@ -325,7 +339,9 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
return (error); 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 static int
zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry) struct inode *tdip, struct dentry *tdentry)
@ -352,6 +368,9 @@ static int
#ifdef HAVE_IOPS_MKDIR_USERNS #ifdef HAVE_IOPS_MKDIR_USERNS
zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip, zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip,
struct dentry *dentry, umode_t mode) 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 #else
zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
#endif #endif
@ -384,7 +403,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
*/ */
/* ARGSUSED */ /* ARGSUSED */
static int 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, zpl_snapdir_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask, const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags) unsigned int query_flags)
@ -397,8 +420,14 @@ zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
zfsvfs_t *zfsvfs = ITOZSB(ip); zfsvfs_t *zfsvfs = ITOZSB(ip);
ZPL_ENTER(zfsvfs); 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); generic_fillattr(user_ns, ip, stat);
#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
generic_fillattr(user_ns, ip, stat);
#else
(void) user_ns;
#endif
#else #else
generic_fillattr(ip, stat); generic_fillattr(ip, stat);
#endif #endif
@ -439,7 +468,9 @@ const struct file_operations zpl_fops_snapdir = {
const struct inode_operations zpl_ops_snapdir = { const struct inode_operations zpl_ops_snapdir = {
.lookup = zpl_snapdir_lookup, .lookup = zpl_snapdir_lookup,
.getattr = zpl_snapdir_getattr, .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, .rename = zpl_snapdir_rename2,
#else #else
.rename = zpl_snapdir_rename, .rename = zpl_snapdir_rename,
@ -530,6 +561,10 @@ static int
zpl_shares_getattr_impl(struct user_namespace *user_ns, zpl_shares_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask, const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags) 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 #else
zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int query_flags) u32 request_mask, unsigned int query_flags)
@ -543,8 +578,14 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
ZPL_ENTER(zfsvfs); ZPL_ENTER(zfsvfs);
if (zfsvfs->z_shares_dir == 0) { 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); 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 #else
generic_fillattr(path->dentry->d_inode, stat); generic_fillattr(path->dentry->d_inode, stat);
#endif #endif
@ -556,7 +597,7 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
if (error == 0) { 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); error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat);
#else #else
error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat); error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat);

View File

@ -978,7 +978,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
!capable(CAP_LINUX_IMMUTABLE)) !capable(CAP_LINUX_IMMUTABLE))
return (-EPERM); return (-EPERM);
if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EACCES); return (-EACCES);
xva_init(xva); xva_init(xva);

View File

@ -131,6 +131,9 @@ static int
#ifdef HAVE_IOPS_CREATE_USERNS #ifdef HAVE_IOPS_CREATE_USERNS
zpl_create(struct user_namespace *user_ns, struct inode *dir, zpl_create(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool flag) 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 #else
zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)
#endif #endif
@ -174,6 +177,9 @@ static int
#ifdef HAVE_IOPS_MKNOD_USERNS #ifdef HAVE_IOPS_MKNOD_USERNS
zpl_mknod(struct user_namespace *user_ns, struct inode *dir, zpl_mknod(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode, 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 #else
zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
#endif #endif
@ -224,7 +230,10 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
#ifdef HAVE_TMPFILE #ifdef HAVE_TMPFILE
static int 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, zpl_tmpfile(struct user_namespace *userns, struct inode *dir,
struct file *file, umode_t mode) struct file *file, umode_t mode)
#else #else
@ -317,6 +326,9 @@ static int
#ifdef HAVE_IOPS_MKDIR_USERNS #ifdef HAVE_IOPS_MKDIR_USERNS
zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, zpl_mkdir(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode) 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 #else
zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
#endif #endif
@ -386,6 +398,10 @@ static int
zpl_getattr_impl(struct user_namespace *user_ns, zpl_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask, const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags) 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 #else
zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags) unsigned int query_flags)
@ -402,7 +418,7 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
* XXX query_flags currently ignored. * 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); error = -zfs_getattr_fast(user_ns, ip, stat);
#else #else
error = -zfs_getattr_fast(kcred->user_ns, ip, stat); error = -zfs_getattr_fast(kcred->user_ns, ip, stat);
@ -441,9 +457,12 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
ZPL_GETATTR_WRAPPER(zpl_getattr); ZPL_GETATTR_WRAPPER(zpl_getattr);
static int static int
#ifdef HAVE_SETATTR_PREPARE_USERNS #ifdef HAVE_USERNS_IOPS_SETATTR
zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry,
struct iattr *ia) struct iattr *ia)
#elif defined(HAVE_IDMAP_IOPS_SETATTR)
zpl_setattr(struct mnt_idmap *user_ns, struct dentry *dentry,
struct iattr *ia)
#else #else
zpl_setattr(struct dentry *dentry, struct iattr *ia) zpl_setattr(struct dentry *dentry, struct iattr *ia)
#endif #endif
@ -454,7 +473,13 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
int error; int error;
fstrans_cookie_t cookie; fstrans_cookie_t cookie;
error = zpl_setattr_prepare(kcred->user_ns, dentry, 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(zfs_init_idmap, dentry, ia);
#endif
if (error) if (error)
return (error); return (error);
@ -489,10 +514,14 @@ static int
#ifdef HAVE_IOPS_RENAME_USERNS #ifdef HAVE_IOPS_RENAME_USERNS
zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, zpl_rename2(struct user_namespace *user_ns, struct inode *sdip,
struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
unsigned int flags) unsigned int rflags)
#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 rflags)
#else #else
zpl_rename2(struct inode *sdip, struct dentry *sdentry, zpl_rename2(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry, unsigned int flags) struct inode *tdip, struct dentry *tdentry, unsigned int rflags)
#endif #endif
{ {
cred_t *cr = CRED(); cred_t *cr = CRED();
@ -500,7 +529,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry,
fstrans_cookie_t cookie; fstrans_cookie_t cookie;
/* We don't have renameat2(2) support */ /* We don't have renameat2(2) support */
if (flags) if (rflags)
return (-EINVAL); return (-EINVAL);
crhold(cr); crhold(cr);
@ -514,7 +543,9 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry,
return (error); 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_IOPS_RENAME_IDMAP)
static int static int
zpl_rename(struct inode *sdip, struct dentry *sdentry, zpl_rename(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry) struct inode *tdip, struct dentry *tdentry)
@ -527,6 +558,9 @@ static int
#ifdef HAVE_IOPS_SYMLINK_USERNS #ifdef HAVE_IOPS_SYMLINK_USERNS
zpl_symlink(struct user_namespace *user_ns, struct inode *dir, zpl_symlink(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, const char *name) 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 #else
zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
#endif #endif
@ -745,6 +779,8 @@ const struct inode_operations zpl_dir_inode_operations = {
.mknod = zpl_mknod, .mknod = zpl_mknod,
#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) #if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
.rename = zpl_rename2, .rename = zpl_rename2,
#elif defined(HAVE_IOPS_RENAME_IDMAP)
.rename = zpl_rename2,
#else #else
.rename = zpl_rename, .rename = zpl_rename,
#endif #endif

View File

@ -725,9 +725,11 @@ __zpl_xattr_user_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get); ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
static int static int
__zpl_xattr_user_set(struct inode *ip, const char *name, __zpl_xattr_user_set(zidmap_t *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
(void) user_ns;
char *xattr_name; char *xattr_name;
int error; int error;
/* xattr_resolve_name will do this for us if this is defined */ /* xattr_resolve_name will do this for us if this is defined */
@ -794,9 +796,11 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get); ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
static int static int
__zpl_xattr_trusted_set(struct inode *ip, const char *name, __zpl_xattr_trusted_set(zidmap_t *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
(void) user_ns;
char *xattr_name; char *xattr_name;
int error; int error;
@ -863,9 +867,11 @@ __zpl_xattr_security_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get); ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
static int static int
__zpl_xattr_security_set(struct inode *ip, const char *name, __zpl_xattr_security_set(zidmap_t *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
(void) user_ns;
char *xattr_name; char *xattr_name;
int error; int error;
/* xattr_resolve_name will do this for us if this is defined */ /* 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; int error = 0;
for (xattr = xattrs; xattr->name != NULL; xattr++) { 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); xattr->name, xattr->value, xattr->value_len, 0);
if (error < 0) if (error < 0)
@ -1004,6 +1010,9 @@ int
#ifdef HAVE_SET_ACL_USERNS #ifdef HAVE_SET_ACL_USERNS
zpl_set_acl(struct user_namespace *userns, struct inode *ip, zpl_set_acl(struct user_namespace *userns, struct inode *ip,
struct posix_acl *acl, int type) 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) #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
zpl_set_acl(struct user_namespace *userns, struct dentry *dentry, zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
struct posix_acl *acl, int type) struct posix_acl *acl, int type)
@ -1013,6 +1022,8 @@ zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
{ {
#ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2 #ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2
return (zpl_set_acl_impl(d_inode(dentry), acl, type)); 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 #else
return (zpl_set_acl_impl(ip, acl, type)); return (zpl_set_acl_impl(ip, acl, type));
#endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */ #endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */
@ -1256,7 +1267,8 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default); ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default);
static int static int
__zpl_xattr_acl_set_access(struct inode *ip, const char *name, __zpl_xattr_acl_set_access(zidmap_t *mnt_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
struct posix_acl *acl; struct posix_acl *acl;
@ -1270,8 +1282,14 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP); return (-EOPNOTSUPP);
if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM); return (-EPERM);
#else
(void) mnt_ns;
if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EPERM);
#endif
if (value) { if (value) {
acl = zpl_acl_from_xattr(value, size); acl = zpl_acl_from_xattr(value, size);
@ -1295,7 +1313,8 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access); ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access);
static int static int
__zpl_xattr_acl_set_default(struct inode *ip, const char *name, __zpl_xattr_acl_set_default(zidmap_t *mnt_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
struct posix_acl *acl; struct posix_acl *acl;
@ -1309,8 +1328,14 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP); return (-EOPNOTSUPP);
if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM); return (-EPERM);
#else
(void) mnt_ns;
if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EPERM);
#endif
if (value) { if (value) {
acl = zpl_acl_from_xattr(value, size); acl = zpl_acl_from_xattr(value, size);