diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4 index d2a1821c5..50b502c31 100644 --- a/config/kernel-acl.m4 +++ b/config/kernel-acl.m4 @@ -249,3 +249,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 + ],[ + 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) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 507e81010..7a207f642 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -49,6 +49,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 diff --git a/module/zfs/zpl_xattr.c b/module/zfs/zpl_xattr.c index ab81dd2d0..471cb16c6 100644 --- a/module/zfs/zpl_xattr.c +++ b/module/zfs/zpl_xattr.c @@ -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: @@ -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); }