Linux 5.15 compat: get_acl()

Kernel commits

332f606b32b6 ovl: enable RCU'd ->get_acl()
0cad6246621b vfs: add rcu argument to ->get_acl() callback

Added compatibility code to detect the new ->get_acl() interface
and correctly handle the case where the new rcu argument is set.

Reviewed-by: Coleman Kane <ckane@colemankane.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #12548
This commit is contained in:
Brian Behlendorf 2021-09-09 09:38:35 -07:00 committed by GitHub
parent a68e4b5919
commit 2079111f42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 9 deletions

View File

@ -162,6 +162,9 @@ dnl #
dnl # 3.1 API change, dnl # 3.1 API change,
dnl # Check if inode_operations contains the function get_acl dnl # Check if inode_operations contains the function get_acl
dnl # dnl #
dnl # 5.15 API change,
dnl # Added the bool rcu argument to get_acl for rcu path walk.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [ ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
#include <linux/fs.h> #include <linux/fs.h>
@ -174,16 +177,34 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
.get_acl = get_acl_fn, .get_acl = get_acl_fn,
}; };
],[]) ],[])
ZFS_LINUX_TEST_SRC([inode_operations_get_acl_rcu], [
#include <linux/fs.h>
struct posix_acl *get_acl_fn(struct inode *inode, int type,
bool rcu) { return NULL; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.get_acl = get_acl_fn,
};
],[])
]) ])
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
AC_MSG_CHECKING([whether iops->get_acl() exists]) AC_MSG_CHECKING([whether iops->get_acl() exists])
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [ ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
],[
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl_rcu], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_ACL_RCU, 1, [iops->get_acl() takes rcu])
],[ ],[
ZFS_LINUX_TEST_ERROR([iops->get_acl()]) ZFS_LINUX_TEST_ERROR([iops->get_acl()])
]) ])
]) ])
])
dnl # dnl #
dnl # 3.14 API change, dnl # 3.14 API change,

View File

@ -70,7 +70,11 @@ extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip,
extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type); extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type);
#endif /* HAVE_SET_ACL_USERNS */ #endif /* HAVE_SET_ACL_USERNS */
#endif /* HAVE_SET_ACL */ #endif /* HAVE_SET_ACL */
#if defined(HAVE_GET_ACL_RCU)
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type, bool rcu);
#elif defined(HAVE_GET_ACL)
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type); extern struct posix_acl *zpl_get_acl(struct inode *ip, int type);
#endif
extern int zpl_init_acl(struct inode *ip, struct inode *dir); extern int zpl_init_acl(struct inode *ip, struct inode *dir);
extern int zpl_chmod_acl(struct inode *ip); extern int zpl_chmod_acl(struct inode *ip);
#else #else

View File

@ -1012,13 +1012,12 @@ zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
} }
#endif /* HAVE_SET_ACL */ #endif /* HAVE_SET_ACL */
struct posix_acl * static struct posix_acl *
zpl_get_acl(struct inode *ip, int type) zpl_get_acl_impl(struct inode *ip, int type)
{ {
struct posix_acl *acl; struct posix_acl *acl;
void *value = NULL; void *value = NULL;
char *name; char *name;
int size;
/* /*
* As of Linux 3.14, the kernel get_acl will check this for us. * As of Linux 3.14, the kernel get_acl will check this for us.
@ -1042,7 +1041,7 @@ zpl_get_acl(struct inode *ip, int type)
return (ERR_PTR(-EINVAL)); return (ERR_PTR(-EINVAL));
} }
size = zpl_xattr_get(ip, name, NULL, 0); int size = zpl_xattr_get(ip, name, NULL, 0);
if (size > 0) { if (size > 0) {
value = kmem_alloc(size, KM_SLEEP); value = kmem_alloc(size, KM_SLEEP);
size = zpl_xattr_get(ip, name, value, size); size = zpl_xattr_get(ip, name, value, size);
@ -1068,6 +1067,25 @@ zpl_get_acl(struct inode *ip, int type)
return (acl); return (acl);
} }
#if defined(HAVE_GET_ACL_RCU)
struct posix_acl *
zpl_get_acl(struct inode *ip, int type, bool rcu)
{
if (rcu)
return (ERR_PTR(-ECHILD));
return (zpl_get_acl_impl(ip, type));
}
#elif defined(HAVE_GET_ACL)
struct posix_acl *
zpl_get_acl(struct inode *ip, int type)
{
return (zpl_get_acl_impl(ip, type));
}
#else
#error "Unsupported iops->get_acl() implementation"
#endif /* HAVE_GET_ACL_RCU */
int int
zpl_init_acl(struct inode *ip, struct inode *dir) zpl_init_acl(struct inode *ip, struct inode *dir)
{ {
@ -1078,7 +1096,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir)
return (0); return (0);
if (!S_ISLNK(ip->i_mode)) { if (!S_ISLNK(ip->i_mode)) {
acl = zpl_get_acl(dir, ACL_TYPE_DEFAULT); acl = zpl_get_acl_impl(dir, ACL_TYPE_DEFAULT);
if (IS_ERR(acl)) if (IS_ERR(acl))
return (PTR_ERR(acl)); return (PTR_ERR(acl));
if (!acl) { if (!acl) {
@ -1127,7 +1145,7 @@ zpl_chmod_acl(struct inode *ip)
if (S_ISLNK(ip->i_mode)) if (S_ISLNK(ip->i_mode))
return (-EOPNOTSUPP); return (-EOPNOTSUPP);
acl = zpl_get_acl(ip, ACL_TYPE_ACCESS); acl = zpl_get_acl_impl(ip, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl) if (IS_ERR(acl) || !acl)
return (PTR_ERR(acl)); return (PTR_ERR(acl));
@ -1189,7 +1207,7 @@ __zpl_xattr_acl_get_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);
acl = zpl_get_acl(ip, type); acl = zpl_get_acl_impl(ip, type);
if (IS_ERR(acl)) if (IS_ERR(acl))
return (PTR_ERR(acl)); return (PTR_ERR(acl));
if (acl == NULL) if (acl == NULL)
@ -1217,7 +1235,7 @@ __zpl_xattr_acl_get_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);
acl = zpl_get_acl(ip, type); acl = zpl_get_acl_impl(ip, type);
if (IS_ERR(acl)) if (IS_ERR(acl))
return (PTR_ERR(acl)); return (PTR_ERR(acl));
if (acl == NULL) if (acl == NULL)