diff options
-rw-r--r-- | config/kernel-blk-queue-flush.m4 | 55 | ||||
-rw-r--r-- | include/linux/blkdev_compat.h | 27 | ||||
-rw-r--r-- | 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 bb74ea1c5..1baab83a4 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 0cb07207e..42b474b15 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 be6aea879..9c89493ed 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); |