From fd4c7b7a73fda391f94f58530c86ffa5b2ef8e6f 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 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 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 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 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 Signed-off-by: Brian Behlendorf 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 + #include + + 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 + #include #include - 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 + #include + #include + + 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 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 Signed-off-by: Brian Behlendorf 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 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 - 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 + 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 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 Signed-off-by: Chunwei Chen 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 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 - 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 - 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 + + 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, \