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 <david.chen@osnexus.com>
Signed-off-by: Nikolay Borisov <n.borisov.lkml@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4944
Closes #4946
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)
+ ])
+])
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
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:
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);
}