From 55b8857346b921dae82231612b253029a1944609 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Wed, 18 May 2016 13:44:13 -0700 Subject: [PATCH] Linux 4.7 compat: handler->get() takes both dentry and inode Signed-off-by: Chunwei Chen Signed-off-by: Brian Behlendorf Issue #4665 --- config/kernel-xattr-handler.m4 | 77 ++++++++++++++++++++++------------ include/linux/xattr_compat.h | 15 ++++++- 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4 index f6142871d1..638557e32e 100644 --- a/config/kernel-xattr-handler.m4 +++ b/config/kernel-xattr-handler.m4 @@ -62,18 +62,17 @@ dnl # Supported xattr handler get() interfaces checked newest to oldest. dnl # AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [ dnl # - dnl # 4.4 API change, - dnl # The xattr_handler->get() callback was changed to take a - dnl # attr_handler, and handler_flags argument was removed and - dnl # should be accessed by handler->flags. + dnl # 4.7 API change, + dnl # The xattr_handler->get() callback was changed to take both + dnl # dentry and inode. dnl # - AC_MSG_CHECKING([whether xattr_handler->get() wants xattr_handler]) + AC_MSG_CHECKING([whether xattr_handler->get() wants both dentry and inode]) ZFS_LINUX_TRY_COMPILE([ #include int get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) { return 0; } + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { return 0; } static const struct xattr_handler xops __attribute__ ((unused)) = { .get = get, @@ -81,23 +80,22 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [ ],[ ],[ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_XATTR_GET_HANDLER, 1, + AC_DEFINE(HAVE_XATTR_GET_DENTRY_INODE, 1, [xattr_handler->get() wants xattr_handler]) ],[ dnl # - dnl # 2.6.33 API change, - dnl # The xattr_handler->get() callback was changed to take - dnl # a dentry instead of an inode, and a handler_flags - dnl # argument was added. + dnl # 4.4 API change, + dnl # The xattr_handler->get() callback was changed to take a + dnl # attr_handler, and handler_flags argument was removed and + dnl # should be accessed by handler->flags. dnl # - AC_MSG_RESULT(no) - AC_MSG_CHECKING([whether xattr_handler->get() wants dentry]) + AC_MSG_CHECKING([whether xattr_handler->get() wants xattr_handler]) ZFS_LINUX_TRY_COMPILE([ #include - int get(struct dentry *dentry, const char *name, - void *buffer, size_t size, int handler_flags) - { return 0; } + int get(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, + void *buffer, size_t size) { return 0; } static const struct xattr_handler xops __attribute__ ((unused)) = { .get = get, @@ -105,20 +103,23 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [ ],[ ],[ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_XATTR_GET_DENTRY, 1, - [xattr_handler->get() wants dentry]) + AC_DEFINE(HAVE_XATTR_GET_HANDLER, 1, + [xattr_handler->get() wants xattr_handler]) ],[ dnl # - dnl # 2.6.32 API + dnl # 2.6.33 API change, + dnl # The xattr_handler->get() callback was changed to take + dnl # a dentry instead of an inode, and a handler_flags + dnl # argument was added. dnl # AC_MSG_RESULT(no) - AC_MSG_CHECKING( - [whether xattr_handler->get() wants inode]) + AC_MSG_CHECKING([whether xattr_handler->get() wants dentry]) ZFS_LINUX_TRY_COMPILE([ #include - int get(struct inode *ip, const char *name, - void *buffer, size_t size) { return 0; } + int get(struct dentry *dentry, const char *name, + void *buffer, size_t size, int handler_flags) + { return 0; } static const struct xattr_handler xops __attribute__ ((unused)) = { .get = get, @@ -126,10 +127,32 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [ ],[ ],[ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_XATTR_GET_INODE, 1, - [xattr_handler->get() wants inode]) + AC_DEFINE(HAVE_XATTR_GET_DENTRY, 1, + [xattr_handler->get() wants dentry]) ],[ - AC_MSG_ERROR([no; please file a bug report]) + dnl # + dnl # 2.6.32 API + dnl # + AC_MSG_RESULT(no) + AC_MSG_CHECKING( + [whether xattr_handler->get() wants inode]) + ZFS_LINUX_TRY_COMPILE([ + #include + + int get(struct inode *ip, const char *name, + void *buffer, size_t size) { return 0; } + static const struct xattr_handler + xops __attribute__ ((unused)) = { + .get = get, + }; + ],[ + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_XATTR_GET_INODE, 1, + [xattr_handler->get() wants inode]) + ],[ + AC_MSG_ERROR([no; please file a bug report]) + ]) ]) ]) ]) diff --git a/include/linux/xattr_compat.h b/include/linux/xattr_compat.h index 5e19ea1e5c..451b6545eb 100644 --- a/include/linux/xattr_compat.h +++ b/include/linux/xattr_compat.h @@ -101,13 +101,26 @@ fn(struct inode *ip, char *list, size_t list_size, \ } #endif +/* + * 4.7 API change, + * The xattr_handler->get() callback was changed to take a both dentry and + * inode, because the dentry might not be attached to an inode yet. + */ +#if defined(HAVE_XATTR_GET_DENTRY_INODE) +#define ZPL_XATTR_GET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + struct inode *inode, const char *name, void *buffer, size_t size) \ +{ \ + return (__ ## fn(inode, name, buffer, size)); \ +} /* * 4.4 API change, * The xattr_handler->get() callback was changed to take a xattr_handler, * and handler_flags argument was removed and should be accessed by * handler->flags. */ -#if defined(HAVE_XATTR_GET_HANDLER) +#elif defined(HAVE_XATTR_GET_HANDLER) #define ZPL_XATTR_GET_WRAPPER(fn) \ static int \ fn(const struct xattr_handler *handler, struct dentry *dentry, \