Skip to content

Commit

Permalink
Linux 4.7 compat: fix zpl_get_acl returns invalid acl pointer
Browse files Browse the repository at this point in the history
Starting from Linux 4.7, get_acl will set acl cache pointer to temporary
sentinel value before calling i_op->get_acl. Therefore we can't compare
against ACL_NOT_CACHED and return.

Since from Linux 3.14, get_acl already check the cache for us, so we
disable this in zpl_get_acl.

Linux 4.7 also does set_cached_acl for us so we disable it in zpl_get_acl.

Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Nikolay Borisov <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#4944
Closes openzfs#4946
  • Loading branch information
Chunwei Chen committed Sep 7, 2016
1 parent 1a8a108 commit c24dd95
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
20 changes: 20 additions & 0 deletions config/kernel-acl.m4
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,23 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.7 API change,
dnl # The kernel get_acl will now check cache before calling i_op->get_acl and
dnl # do set_cached_acl after that, so i_op->get_acl don't need to do that
dnl # anymore.
dnl #
AC_DEFUN([ZFS_AC_KERNE_GET_ACL_HANDLE_CACHE], [
AC_MSG_CHECKING([whether uncached_acl_sentinel() exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/fs.h>
],[
void *sentinel __attribute__ ((unused)) = uncached_acl_sentinel(NULL);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1, [uncached_acl_sentinel() exists])
],[
AC_MSG_RESULT(no)
])
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
ZFS_AC_KERNE_GET_ACL_HANDLE_CACHE
ZFS_AC_KERNEL_SHOW_OPTIONS
ZFS_AC_KERNEL_FILE_INODE
ZFS_AC_KERNEL_FSYNC
Expand Down
10 changes: 10 additions & 0 deletions module/zfs/zpl_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,16 @@ zpl_get_acl(struct inode *ip, int type)
char *name;
int size;

/*
* As of Linux 3.14, the kernel get_acl will check this for us.
* Also as of Linux 4.7, comparing against ACL_NOT_CACHED is wrong
* as the kernel get_acl will set it to temporary sentinel value.
*/
#ifndef HAVE_KERNEL_GET_ACL_HANDLE_CACHE
acl = get_cached_acl(ip, type);
if (acl != ACL_NOT_CACHED)
return (acl);
#endif

switch (type) {
case ACL_TYPE_ACCESS:
Expand Down Expand Up @@ -1049,8 +1056,11 @@ zpl_get_acl(struct inode *ip, int type)
if (size > 0)
kmem_free(value, size);

/* As of Linux 4.7, the kernel get_acl will set this for us */
#ifndef HAVE_KERNEL_GET_ACL_HANDLE_CACHE
if (!IS_ERR(acl))
zpl_set_cached_acl(ip, type, acl);
#endif

return (acl);
}
Expand Down

0 comments on commit c24dd95

Please sign in to comment.