+++ /dev/null
-From fd4c7b7a73fda391f94f58530c86ffa5b2ef8e6f Mon Sep 17 00:00:00 2001
-From: Chunwei Chen <david.chen@osnexus.com>
-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 <david.chen@osnexus.com>
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-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 f614287..638557e 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 <linux/xattr.h>
-
- 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 <linux/xattr.h>
-
-- 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 <linux/xattr.h>
-
-- 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 <linux/xattr.h>
-+
-+ 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 5e19ea1..451b654 100644
---- a/include/linux/xattr_compat.h
-+++ b/include/linux/xattr_compat.h
-@@ -102,12 +102,25 @@ 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, \
-From 68e8f59afb0fa1b388c7dbb8720ac6756d390146 Mon Sep 17 00:00:00 2001
-From: Chunwei Chen <david.chen@osnexus.com>
-Date: Wed, 18 May 2016 13:45:39 -0700
-Subject: [PATCH] Linux 4.7 compat: replace blk_queue_flush with
- blk_queue_write_cache
-
-Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-Issue #4665
----
- config/kernel-blk-queue-flush.m4 | 55 ++++++++++++++++++++++++++++++++++------
- include/linux/blkdev_compat.h | 27 ++++++++++++++++++++
- module/zfs/zvol.c | 4 ++-
- 3 files changed, 77 insertions(+), 9 deletions(-)
-
-diff --git a/config/kernel-blk-queue-flush.m4 b/config/kernel-blk-queue-flush.m4
-index bb74ea1..1baab83 100644
---- a/config/kernel-blk-queue-flush.m4
-+++ b/config/kernel-blk-queue-flush.m4
-@@ -22,25 +22,64 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_BLK_QUEUE_FLUSH, 1,
- [blk_queue_flush() is available])
-+
-+ AC_MSG_CHECKING([whether blk_queue_flush() is GPL-only])
-+ ZFS_LINUX_TRY_COMPILE([
-+ #include <linux/module.h>
-+ #include <linux/blkdev.h>
-+
-+ MODULE_LICENSE("$ZFS_META_LICENSE");
-+ ],[
-+ struct request_queue *q = NULL;
-+ (void) blk_queue_flush(q, REQ_FLUSH);
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ],[
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY, 1,
-+ [blk_queue_flush() is GPL-only])
-+ ])
- ],[
- AC_MSG_RESULT(no)
- ])
-
-- AC_MSG_CHECKING([whether blk_queue_flush() is GPL-only])
-+ dnl #
-+ dnl # 4.7 API change
-+ dnl # Replace blk_queue_flush with blk_queue_write_cache
-+ dnl #
-+ AC_MSG_CHECKING([whether blk_queue_write_cache() exists])
- ZFS_LINUX_TRY_COMPILE([
-- #include <linux/module.h>
-+ #include <linux/kernel.h>
- #include <linux/blkdev.h>
-
-- MODULE_LICENSE("$ZFS_META_LICENSE");
- ],[
- struct request_queue *q = NULL;
-- (void) blk_queue_flush(q, REQ_FLUSH);
-- ],[
-- AC_MSG_RESULT(no)
-+ blk_queue_write_cache(q, true, true);
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY, 1,
-- [blk_queue_flush() is GPL-only])
-+ AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE, 1,
-+ [blk_queue_write_cache() exists])
-+
-+ AC_MSG_CHECKING([whether blk_queue_write_cache() is GPL-only])
-+ ZFS_LINUX_TRY_COMPILE([
-+ #include <linux/kernel.h>
-+ #include <linux/module.h>
-+ #include <linux/blkdev.h>
-+
-+ MODULE_LICENSE("$ZFS_META_LICENSE");
-+ ],[
-+ struct request_queue *q = NULL;
-+ blk_queue_write_cache(q, true, true);
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ],[
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY, 1,
-+ [blk_queue_write_cache() is GPL-only])
-+ ])
-+ ],[
-+ AC_MSG_RESULT(no)
- ])
-+
- EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/include/linux/blkdev_compat.h b/include/linux/blkdev_compat.h
-index 0cb0720..42b474b 100644
---- a/include/linux/blkdev_compat.h
-+++ b/include/linux/blkdev_compat.h
-@@ -52,6 +52,33 @@ __blk_queue_flush(struct request_queue *q, unsigned int flags)
- q->flush_flags = flags & (REQ_FLUSH | REQ_FUA);
- }
- #endif /* HAVE_BLK_QUEUE_FLUSH && HAVE_BLK_QUEUE_FLUSH_GPL_ONLY */
-+
-+/*
-+ * 4.7 API change,
-+ * The blk_queue_write_cache() interface has replaced blk_queue_flush()
-+ * interface. However, while the new interface is GPL-only. Thus if the
-+ * GPL-only version is detected we implement our own trivial helper
-+ * compatibility funcion.
-+ */
-+#if defined(HAVE_BLK_QUEUE_WRITE_CACHE) && \
-+ defined(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY)
-+#define blk_queue_write_cache __blk_queue_write_cache
-+static inline void
-+__blk_queue_write_cache(struct request_queue *q, bool wc, bool fua)
-+{
-+ spin_lock_irq(q->queue_lock);
-+ if (wc)
-+ queue_flag_set(QUEUE_FLAG_WC, q);
-+ else
-+ queue_flag_clear(QUEUE_FLAG_WC, q);
-+ if (fua)
-+ queue_flag_set(QUEUE_FLAG_FUA, q);
-+ else
-+ queue_flag_clear(QUEUE_FLAG_FUA, q);
-+ spin_unlock_irq(q->queue_lock);
-+}
-+#endif
-+
- /*
- * Most of the blk_* macros were removed in 2.6.36. Ostensibly this was
- * done to improve readability and allow easier grepping. However, from
-diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
-index be6aea8..9c89493 100644
---- a/module/zfs/zvol.c
-+++ b/module/zfs/zvol.c
-@@ -1291,7 +1291,9 @@ zvol_alloc(dev_t dev, const char *name)
-
- blk_queue_make_request(zv->zv_queue, zvol_request);
-
--#ifdef HAVE_BLK_QUEUE_FLUSH
-+#ifdef HAVE_BLK_QUEUE_WRITE_CACHE
-+ blk_queue_write_cache(zv->zv_queue, B_TRUE, B_TRUE);
-+#elif defined(HAVE_BLK_QUEUE_FLUSH)
- blk_queue_flush(zv->zv_queue, VDEV_REQ_FLUSH | VDEV_REQ_FUA);
- #else
- blk_queue_ordered(zv->zv_queue, QUEUE_ORDERED_DRAIN, NULL);
-From 9baaa7deae45c8556dfd79b2011234da5cb37b3a Mon Sep 17 00:00:00 2001
-From: Chunwei Chen <david.chen@osnexus.com>
-Date: Wed, 18 May 2016 14:30:20 -0700
-Subject: [PATCH] Linux 4.7 compat: use iterate_shared for concurrent readdir
-
-Register iterate_shared if it exists so the kernel will used shared
-lock and allowing concurrent readdir.
-
-Also, use shared lock when doing llseek with SEEK_DATA or SEEK_HOLE
-to allow concurrent seeking.
-
-Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-Closes #4664
-Closes #4665
----
- config/kernel-vfs-iterate.m4 | 49 +++++++++++++++++++++++++++++++-------------
- include/sys/zpl.h | 2 +-
- module/zfs/zpl_ctldir.c | 18 ++++++++++------
- module/zfs/zpl_file.c | 10 +++++----
- 4 files changed, 54 insertions(+), 25 deletions(-)
-
-diff --git a/config/kernel-vfs-iterate.m4 b/config/kernel-vfs-iterate.m4
-index c2c6562..7b1599e 100644
---- a/config/kernel-vfs-iterate.m4
-+++ b/config/kernel-vfs-iterate.m4
-@@ -1,8 +1,8 @@
--dnl #
--dnl # 3.11 API change
--dnl #
- AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
-- AC_MSG_CHECKING([whether fops->iterate() is available])
-+ dnl #
-+ dnl # 4.7 API change
-+ dnl #
-+ AC_MSG_CHECKING([whether fops->iterate_shared() is available])
- ZFS_LINUX_TRY_COMPILE([
- #include <linux/fs.h>
- int iterate(struct file *filp, struct dir_context * context)
-@@ -10,34 +10,55 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
-
- static const struct file_operations fops
- __attribute__ ((unused)) = {
-- .iterate = iterate,
-+ .iterate_shared = iterate,
- };
- ],[
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_VFS_ITERATE, 1,
-- [fops->iterate() is available])
-+ AC_DEFINE(HAVE_VFS_ITERATE_SHARED, 1,
-+ [fops->iterate_shared() is available])
- ],[
- AC_MSG_RESULT(no)
-
-- AC_MSG_CHECKING([whether fops->readdir() is available])
-+ dnl #
-+ dnl # 3.11 API change
-+ dnl #
-+ AC_MSG_CHECKING([whether fops->iterate() is available])
- ZFS_LINUX_TRY_COMPILE([
- #include <linux/fs.h>
-- int readdir(struct file *filp, void *entry, filldir_t func)
-+ int iterate(struct file *filp, struct dir_context * context)
- { return 0; }
-
- static const struct file_operations fops
- __attribute__ ((unused)) = {
-- .readdir = readdir,
-+ .iterate = iterate,
- };
- ],[
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_VFS_READDIR, 1,
-- [fops->readdir() is available])
-+ AC_DEFINE(HAVE_VFS_ITERATE, 1,
-+ [fops->iterate() is available])
- ],[
-- AC_MSG_ERROR(no; file a bug report with ZFSOnLinux)
-- ])
-+ AC_MSG_RESULT(no)
-+
-+ AC_MSG_CHECKING([whether fops->readdir() is available])
-+ ZFS_LINUX_TRY_COMPILE([
-+ #include <linux/fs.h>
-+ int readdir(struct file *filp, void *entry, filldir_t func)
-+ { return 0; }
-
-+ static const struct file_operations fops
-+ __attribute__ ((unused)) = {
-+ .readdir = readdir,
-+ };
-+ ],[
-+ ],[
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_VFS_READDIR, 1,
-+ [fops->readdir() is available])
-+ ],[
-+ AC_MSG_ERROR(no; file a bug report with ZFSOnLinux)
-+ ])
-+ ])
- ])
- ])
-diff --git a/include/sys/zpl.h b/include/sys/zpl.h
-index 54b35e0..c608548 100644
---- a/include/sys/zpl.h
-+++ b/include/sys/zpl.h
-@@ -123,7 +123,7 @@ extern const struct inode_operations zpl_ops_snapdirs;
- extern const struct file_operations zpl_fops_shares;
- extern const struct inode_operations zpl_ops_shares;
-
--#ifdef HAVE_VFS_ITERATE
-+#if defined(HAVE_VFS_ITERATE) || defined(HAVE_VFS_ITERATE_SHARED)
-
- #define DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \
- .actor = _actor, \
-diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c
-index dd02e9e..069834e 100644
---- a/module/zfs/zpl_ctldir.c
-+++ b/module/zfs/zpl_ctldir.c
-@@ -81,7 +81,7 @@ zpl_root_iterate(struct file *filp, struct dir_context *ctx)
- return (error);
- }
-
--#if !defined(HAVE_VFS_ITERATE)
-+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
- static int
- zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
-@@ -144,7 +144,9 @@ const struct file_operations zpl_fops_root = {
- .open = zpl_common_open,
- .llseek = generic_file_llseek,
- .read = generic_read_dir,
--#ifdef HAVE_VFS_ITERATE
-+#ifdef HAVE_VFS_ITERATE_SHARED
-+ .iterate_shared = zpl_root_iterate,
-+#elif defined(HAVE_VFS_ITERATE)
- .iterate = zpl_root_iterate,
- #else
- .readdir = zpl_root_readdir,
-@@ -285,7 +287,7 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
- return (error);
- }
-
--#if !defined(HAVE_VFS_ITERATE)
-+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
- static int
- zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
-@@ -385,7 +387,9 @@ const struct file_operations zpl_fops_snapdir = {
- .open = zpl_common_open,
- .llseek = generic_file_llseek,
- .read = generic_read_dir,
--#ifdef HAVE_VFS_ITERATE
-+#ifdef HAVE_VFS_ITERATE_SHARED
-+ .iterate_shared = zpl_snapdir_iterate,
-+#elif defined(HAVE_VFS_ITERATE)
- .iterate = zpl_snapdir_iterate,
- #else
- .readdir = zpl_snapdir_readdir,
-@@ -472,7 +476,7 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
- return (error);
- }
-
--#if !defined(HAVE_VFS_ITERATE)
-+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
- static int
- zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
-@@ -525,7 +529,9 @@ const struct file_operations zpl_fops_shares = {
- .open = zpl_common_open,
- .llseek = generic_file_llseek,
- .read = generic_read_dir,
--#ifdef HAVE_VFS_ITERATE
-+#ifdef HAVE_VFS_ITERATE_SHARED
-+ .iterate_shared = zpl_shares_iterate,
-+#elif defined(HAVE_VFS_ITERATE)
- .iterate = zpl_shares_iterate,
- #else
- .readdir = zpl_shares_readdir,
-diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
-index 36153cb..4481237 100644
---- a/module/zfs/zpl_file.c
-+++ b/module/zfs/zpl_file.c
-@@ -93,7 +93,7 @@ zpl_iterate(struct file *filp, struct dir_context *ctx)
- return (error);
- }
-
--#if !defined(HAVE_VFS_ITERATE)
-+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
- static int
- zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
-@@ -421,13 +421,13 @@ zpl_llseek(struct file *filp, loff_t offset, int whence)
- loff_t maxbytes = ip->i_sb->s_maxbytes;
- loff_t error;
-
-- spl_inode_lock(ip);
-+ spl_inode_lock_shared(ip);
- cookie = spl_fstrans_mark();
- error = -zfs_holey(ip, whence, &offset);
- spl_fstrans_unmark(cookie);
- if (error == 0)
- error = lseek_execute(filp, ip, offset, maxbytes);
-- spl_inode_unlock(ip);
-+ spl_inode_unlock_shared(ip);
-
- return (error);
- }
-@@ -853,7 +853,9 @@ const struct file_operations zpl_file_operations = {
- const struct file_operations zpl_dir_file_operations = {
- .llseek = generic_file_llseek,
- .read = generic_read_dir,
--#ifdef HAVE_VFS_ITERATE
-+#ifdef HAVE_VFS_ITERATE_SHARED
-+ .iterate_shared = zpl_iterate,
-+#elif defined(HAVE_VFS_ITERATE)
- .iterate = zpl_iterate,
- #else
- .readdir = zpl_readdir,
-From 8fbbc6b4cf13f73d517ec4e826a7069a958fa5ba Mon Sep 17 00:00:00 2001
-From: Brian Behlendorf <behlendorf1@llnl.gov>
-Date: Wed, 1 Jun 2016 18:10:06 -0700
-Subject: [PATCH] Linux 4.7 compat: handler->set() takes both dentry and inode
-
-Counterpart to fd4c7b7, the same approach was taken to resolve
-the compatibility issue.
-
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
-Closes #4717
-Issue #4665
----
- config/kernel-xattr-handler.m4 | 83 +++++++++++++++++++++++++++---------------
- include/linux/xattr_compat.h | 16 +++++++-
- 2 files changed, 69 insertions(+), 30 deletions(-)
-
-diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
-index 638557e..dcffd44 100644
---- a/config/kernel-xattr-handler.m4
-+++ b/config/kernel-xattr-handler.m4
-@@ -81,7 +81,7 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
- ],[
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_XATTR_GET_DENTRY_INODE, 1,
-- [xattr_handler->get() wants xattr_handler])
-+ [xattr_handler->get() wants both dentry and inode])
- ],[
- dnl #
- dnl # 4.4 API change,
-@@ -163,18 +163,18 @@ dnl # Supported xattr handler set() interfaces checked newest to oldest.
- dnl #
- AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
- dnl #
-- dnl # 4.4 API change,
-- dnl # The xattr_handler->set() callback was changed to take a
-- dnl # xattr_handler, and handler_flags argument was removed and
-- dnl # should be accessed by handler->flags.
-+ dnl # 4.7 API change,
-+ dnl # The xattr_handler->set() callback was changed to take both
-+ dnl # dentry and inode.
- dnl #
-- AC_MSG_CHECKING([whether xattr_handler->set() wants xattr_handler])
-+ AC_MSG_CHECKING([whether xattr_handler->set() wants both dentry and inode])
- ZFS_LINUX_TRY_COMPILE([
- #include <linux/xattr.h>
-
- int set(const struct xattr_handler *handler,
-- struct dentry *dentry, const char *name,
-- const void *buffer, size_t size, int flags)
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *buffer,
-+ size_t size, int flags)
- { return 0; }
- static const struct xattr_handler
- xops __attribute__ ((unused)) = {
-@@ -183,23 +183,23 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
- ],[
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
-- [xattr_handler->set() wants xattr_handler])
-+ AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
-+ [xattr_handler->set() wants both dentry and inode])
- ],[
- dnl #
-- dnl # 2.6.33 API change,
-+ dnl # 4.4 API change,
- dnl # The xattr_handler->set() callback was changed to take a
-- dnl # dentry instead of an inode, and a handler_flags
-- dnl # argument was added.
-+ dnl # xattr_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->set() wants dentry])
-+ AC_MSG_CHECKING([whether xattr_handler->set() wants xattr_handler])
- ZFS_LINUX_TRY_COMPILE([
- #include <linux/xattr.h>
-
-- int set(struct dentry *dentry, const char *name,
-- const void *buffer, size_t size, int flags,
-- int handler_flags) { return 0; }
-+ int set(const struct xattr_handler *handler,
-+ struct dentry *dentry, const char *name,
-+ const void *buffer, size_t size, int flags)
-+ { return 0; }
- static const struct xattr_handler
- xops __attribute__ ((unused)) = {
- .set = set,
-@@ -207,21 +207,23 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
- ],[
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
-- [xattr_handler->set() wants dentry])
-+ AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
-+ [xattr_handler->set() wants xattr_handler])
- ],[
- dnl #
-- dnl # 2.6.32 API
-+ dnl # 2.6.33 API change,
-+ dnl # The xattr_handler->set() callback was changed to take a
-+ dnl # dentry instead of an inode, and a handler_flags
-+ dnl # argument was added.
- dnl #
- AC_MSG_RESULT(no)
-- AC_MSG_CHECKING(
-- [whether xattr_handler->set() wants inode])
-+ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry])
- ZFS_LINUX_TRY_COMPILE([
- #include <linux/xattr.h>
-
-- int set(struct inode *ip, const char *name,
-- const void *buffer, size_t size, int flags)
-- { return 0; }
-+ int set(struct dentry *dentry, const char *name,
-+ const void *buffer, size_t size, int flags,
-+ int handler_flags) { return 0; }
- static const struct xattr_handler
- xops __attribute__ ((unused)) = {
- .set = set,
-@@ -229,10 +231,33 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
- ],[
- ],[
- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_XATTR_SET_INODE, 1,
-- [xattr_handler->set() wants inode])
-+ AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
-+ [xattr_handler->set() 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->set() wants inode])
-+ ZFS_LINUX_TRY_COMPILE([
-+ #include <linux/xattr.h>
-+
-+ int set(struct inode *ip, const char *name,
-+ const void *buffer, size_t size, int flags)
-+ { return 0; }
-+ static const struct xattr_handler
-+ xops __attribute__ ((unused)) = {
-+ .set = set,
-+ };
-+ ],[
-+ ],[
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_XATTR_SET_INODE, 1,
-+ [xattr_handler->set() 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 451b654..b1c4293 100644
---- a/include/linux/xattr_compat.h
-+++ b/include/linux/xattr_compat.h
-@@ -154,12 +154,26 @@ fn(struct inode *ip, const char *name, void *buffer, size_t size) \
- #endif
-
- /*
-+ * 4.7 API change,
-+ * The xattr_handler->set() 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_SET_DENTRY_INODE)
-+#define ZPL_XATTR_SET_WRAPPER(fn) \
-+static int \
-+fn(const struct xattr_handler *handler, struct dentry *dentry, \
-+ struct inode *inode, const char *name, const void *buffer, \
-+ size_t size, int flags) \
-+{ \
-+ return (__ ## fn(inode, name, buffer, size, flags)); \
-+}
-+/*
- * 4.4 API change,
- * The xattr_handler->set() 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_SET_HANDLER)
-+#elif defined(HAVE_XATTR_SET_HANDLER)
- #define ZPL_XATTR_SET_WRAPPER(fn) \
- static int \
- fn(const struct xattr_handler *handler, struct dentry *dentry, \