Linux 4.7 compat: fix zpl_get_acl returns invalid acl pointer
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
This commit is contained in:
parent
97a1bbd4ea
commit
26e2bfa770
|
@ -224,3 +224,23 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
|
||||||
AC_MSG_RESULT(no)
|
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)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
|
@ -46,6 +46,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
|
||||||
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
|
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
|
||||||
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
|
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
|
||||||
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
|
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
|
||||||
|
ZFS_AC_KERNE_GET_ACL_HANDLE_CACHE
|
||||||
ZFS_AC_KERNEL_SHOW_OPTIONS
|
ZFS_AC_KERNEL_SHOW_OPTIONS
|
||||||
ZFS_AC_KERNEL_FILE_INODE
|
ZFS_AC_KERNEL_FILE_INODE
|
||||||
ZFS_AC_KERNEL_FSYNC
|
ZFS_AC_KERNEL_FSYNC
|
||||||
|
|
|
@ -1017,9 +1017,16 @@ zpl_get_acl(struct inode *ip, int type)
|
||||||
char *name;
|
char *name;
|
||||||
int size;
|
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);
|
acl = get_cached_acl(ip, type);
|
||||||
if (acl != ACL_NOT_CACHED)
|
if (acl != ACL_NOT_CACHED)
|
||||||
return (acl);
|
return (acl);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACL_TYPE_ACCESS:
|
case ACL_TYPE_ACCESS:
|
||||||
|
@ -1049,8 +1056,11 @@ zpl_get_acl(struct inode *ip, int type)
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
kmem_free(value, size);
|
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))
|
if (!IS_ERR(acl))
|
||||||
zpl_set_cached_acl(ip, type, acl);
|
zpl_set_cached_acl(ip, type, acl);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (acl);
|
return (acl);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue