summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <behlendorf1@llnl.gov>2021-09-09 09:38:35 -0700
committerTony Hutter <hutter2@llnl.gov>2021-09-14 15:42:59 -0700
commit32512acbc07bd4038be68387da90d7cb5bd2daae (patch)
tree19cba7207a48db8ea9547380b19d12c9eb48d345
parentcea0752f8d14792b8a8d4484649c8a7022678b66 (diff)
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
-rw-r--r--config/kernel-acl.m423
-rw-r--r--include/os/linux/zfs/sys/zpl.h4
-rw-r--r--module/os/linux/zfs/zpl_xattr.c34
3 files changed, 52 insertions, 9 deletions
diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4
index c6da4df24..a155b59d0 100644
--- a/config/kernel-acl.m4
+++ b/config/kernel-acl.m4
@@ -162,6 +162,9 @@ dnl #
dnl # 3.1 API change,
dnl # Check if inode_operations contains the function get_acl
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], [
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
#include <linux/fs.h>
@@ -174,14 +177,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
.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_MSG_CHECKING([whether iops->get_acl() exists])
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
],[
- ZFS_LINUX_TEST_ERROR([iops->get_acl()])
+ 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()])
+ ])
])
])
diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
index 54f3fa0fd..ff86e027b 100644
--- a/include/os/linux/zfs/sys/zpl.h
+++ b/include/os/linux/zfs/sys/zpl.h
@@ -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);
#endif /* HAVE_SET_ACL_USERNS */
#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);
+#endif
extern int zpl_init_acl(struct inode *ip, struct inode *dir);
extern int zpl_chmod_acl(struct inode *ip);
#else
diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c
index c6d4da582..928058ef6 100644
--- a/module/os/linux/zfs/zpl_xattr.c
+++ b/module/os/linux/zfs/zpl_xattr.c
@@ -1012,13 +1012,12 @@ zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
}
#endif /* HAVE_SET_ACL */
-struct posix_acl *
-zpl_get_acl(struct inode *ip, int type)
+static struct posix_acl *
+zpl_get_acl_impl(struct inode *ip, int type)
{
struct posix_acl *acl;
void *value = NULL;
char *name;
- int size;
/*
* 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));
}
- size = zpl_xattr_get(ip, name, NULL, 0);
+ int size = zpl_xattr_get(ip, name, NULL, 0);
if (size > 0) {
value = kmem_alloc(size, KM_SLEEP);
size = zpl_xattr_get(ip, name, value, size);
@@ -1068,6 +1067,25 @@ zpl_get_acl(struct inode *ip, int type)
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
zpl_init_acl(struct inode *ip, struct inode *dir)
{
@@ -1078,7 +1096,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir)
return (0);
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))
return (PTR_ERR(acl));
if (!acl) {
@@ -1127,7 +1145,7 @@ zpl_chmod_acl(struct inode *ip)
if (S_ISLNK(ip->i_mode))
return (-EOPNOTSUPP);
- acl = zpl_get_acl(ip, ACL_TYPE_ACCESS);
+ acl = zpl_get_acl_impl(ip, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !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)
return (-EOPNOTSUPP);
- acl = zpl_get_acl(ip, type);
+ acl = zpl_get_acl_impl(ip, type);
if (IS_ERR(acl))
return (PTR_ERR(acl));
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)
return (-EOPNOTSUPP);
- acl = zpl_get_acl(ip, type);
+ acl = zpl_get_acl_impl(ip, type);
if (IS_ERR(acl))
return (PTR_ERR(acl));
if (acl == NULL)