aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/kernel-blk-queue-flush.m455
-rw-r--r--include/linux/blkdev_compat.h27
-rw-r--r--module/zfs/zvol.c4
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);