#endif /* HAVE_FMODE_T */
/*
- * 2.6.36 API change,
+ * 4.7 - 4.x API,
+ * The blk_queue_write_cache() interface has replaced blk_queue_flush()
+ * interface. However, the new interface is GPL-only thus we implement
+ * our own trivial wrapper when the GPL-only version is detected.
+ *
+ * 2.6.36 - 4.6 API,
* The blk_queue_flush() interface has replaced blk_queue_ordered()
* interface. However, while the old interface was available to all the
* new one is GPL-only. Thus if the GPL-only version is detected we
- * implement our own trivial helper compatibility funcion. The hope is
- * that long term this function will be opened up.
+ * implement our own trivial helper.
+ *
+ * 2.6.x - 2.6.35
+ * Legacy blk_queue_ordered() interface.
*/
-#if defined(HAVE_BLK_QUEUE_FLUSH) && defined(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY)
-#define blk_queue_flush __blk_queue_flush
static inline void
-__blk_queue_flush(struct request_queue *q, unsigned int flags)
+blk_queue_set_write_cache(struct request_queue *q, bool wc, bool fua)
{
- q->flush_flags = flags & (REQ_FLUSH | REQ_FUA);
+#if defined(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY)
+ 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);
+#elif defined(HAVE_BLK_QUEUE_WRITE_CACHE)
+ blk_queue_write_cache(q, wc, fua);
+#elif defined(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY)
+ if (wc)
+ q->flush_flags |= REQ_FLUSH;
+ if (fua)
+ q->flush_flags |= REQ_FUA;
+#elif defined(HAVE_BLK_QUEUE_FLUSH)
+ blk_queue_flush(q, (wc ? REQ_FLUSH : 0) | (fua ? REQ_FUA : 0));
+#else
+ blk_queue_ordered(q, QUEUE_ORDERED_DRAIN, NULL);
+#endif
}
-#endif /* HAVE_BLK_QUEUE_FLUSH && HAVE_BLK_QUEUE_FLUSH_GPL_ONLY */
+
/*
* Most of the blk_* macros were removed in 2.6.36. Ostensibly this was
* done to improve readability and allow easier grepping. However, from
#define BIO_BI_SECTOR(bio) (bio)->bi_iter.bi_sector
#define BIO_BI_SIZE(bio) (bio)->bi_iter.bi_size
#define BIO_BI_IDX(bio) (bio)->bi_iter.bi_idx
+#define BIO_BI_SKIP(bio) (bio)->bi_iter.bi_bvec_done
#define bio_for_each_segment4(bv, bvp, b, i) \
bio_for_each_segment((bv), (b), (i))
typedef struct bvec_iter bvec_iterator_t;
#define BIO_BI_SECTOR(bio) (bio)->bi_sector
#define BIO_BI_SIZE(bio) (bio)->bi_size
#define BIO_BI_IDX(bio) (bio)->bi_idx
+#define BIO_BI_SKIP(bio) (0)
#define bio_for_each_segment4(bv, bvp, b, i) \
bio_for_each_segment((bvp), (b), (i))
typedef int bvec_iterator_t;
/*
* 2.6.27 API change
- * The function was exported for use, prior to this it existed by the
+ * The function was exported for use, prior to this it existed but the
* symbol was not exported.
+ *
+ * 4.4.0-6.21 API change for Ubuntu
+ * lookup_bdev() gained a second argument, FMODE_*, to check inode permissions.
*/
-#ifndef HAVE_LOOKUP_BDEV
-#define lookup_bdev(path) ERR_PTR(-ENOTSUP)
-#endif
+#ifdef HAVE_1ARG_LOOKUP_BDEV
+#define vdev_lookup_bdev(path) lookup_bdev(path)
+#else
+#ifdef HAVE_2ARGS_LOOKUP_BDEV
+#define vdev_lookup_bdev(path) lookup_bdev(path, 0)
+#else
+#define vdev_lookup_bdev(path) ERR_PTR(-ENOTSUP)
+#endif /* HAVE_2ARGS_LOOKUP_BDEV */
+#endif /* HAVE_1ARG_LOOKUP_BDEV */
/*
* 2.6.30 API change
#endif /* HAVE_BDEV_LOGICAL_BLOCK_SIZE */
#endif /* HAVE_BDEV_PHYSICAL_BLOCK_SIZE */
+#ifndef HAVE_BIO_SET_OP_ATTRS
/*
- * 2.6.37 API change
- * The WRITE_FLUSH, WRITE_FUA, and WRITE_FLUSH_FUA flags have been
- * introduced as a replacement for WRITE_BARRIER. This was done to
- * allow richer semantics to be expressed to the block layer. It is
- * the block layers responsibility to choose the correct way to
- * implement these semantics.
+ * Kernels without bio_set_op_attrs use bi_rw for the bio flags.
+ */
+static inline void
+bio_set_op_attrs(struct bio *bio, unsigned rw, unsigned flags)
+{
+ bio->bi_rw |= rw | flags;
+}
+#endif
+
+/*
+ * bio_set_flush - Set the appropriate flags in a bio to guarantee
+ * data are on non-volatile media on completion.
+ *
+ * 2.6.X - 2.6.36 API,
+ * WRITE_BARRIER - Tells the block layer to commit all previously submitted
+ * writes to stable storage before this one is started and that the current
+ * write is on stable storage upon completion. Also prevents reordering
+ * on both sides of the current operation.
+ *
+ * 2.6.37 - 4.8 API,
+ * Introduce WRITE_FLUSH, WRITE_FUA, and WRITE_FLUSH_FUA flags as a
+ * replacement for WRITE_BARRIER to allow expressing richer semantics
+ * to the block layer. It's up to the block layer to implement the
+ * semantics correctly. Use the WRITE_FLUSH_FUA flag combination.
*
- * The existence of these flags implies that REQ_FLUSH an REQ_FUA are
- * defined. Thus we can safely define VDEV_REQ_FLUSH and VDEV_REQ_FUA
- * compatibility macros.
+ * 4.8 - 4.9 API,
+ * REQ_FLUSH was renamed to REQ_PREFLUSH. For consistency with previous
+ * ZoL releases, prefer the WRITE_FLUSH_FUA flag set if it's available.
+ *
+ * 4.10 API,
+ * The read/write flags and their modifiers, including WRITE_FLUSH,
+ * WRITE_FUA and WRITE_FLUSH_FUA were removed from fs.h in
+ * torvalds/linux@70fd7614 and replaced by direct flag modification
+ * of the REQ_ flags in bio->bi_opf. Use REQ_PREFLUSH.
*/
-#ifdef WRITE_FLUSH_FUA
-#define VDEV_WRITE_FLUSH_FUA WRITE_FLUSH_FUA
-#define VDEV_REQ_FLUSH REQ_FLUSH
-#define VDEV_REQ_FUA REQ_FUA
+static inline void
+bio_set_flush(struct bio *bio)
+{
+#if defined(WRITE_BARRIER) /* < 2.6.37 */
+ bio_set_op_attrs(bio, 0, WRITE_BARRIER);
+#elif defined(WRITE_FLUSH_FUA) /* >= 2.6.37 and <= 4.9 */
+ bio_set_op_attrs(bio, 0, WRITE_FLUSH_FUA);
+#elif defined(REQ_PREFLUSH) /* >= 4.10 */
+ bio_set_op_attrs(bio, 0, REQ_PREFLUSH);
#else
-#define VDEV_WRITE_FLUSH_FUA WRITE_BARRIER
-#ifdef HAVE_BIO_RW_BARRIER
-#define VDEV_REQ_FLUSH (1 << BIO_RW_BARRIER)
-#define VDEV_REQ_FUA (1 << BIO_RW_BARRIER)
+#error "Allowing the build will cause bio_set_flush requests to be ignored."
+#endif
+}
+
+/*
+ * 4.8 - 4.x API,
+ * REQ_OP_FLUSH
+ *
+ * 4.8-rc0 - 4.8-rc1,
+ * REQ_PREFLUSH
+ *
+ * 2.6.36 - 4.7 API,
+ * REQ_FLUSH
+ *
+ * 2.6.x - 2.6.35 API,
+ * HAVE_BIO_RW_BARRIER
+ *
+ * Used to determine if a cache flush has been requested. This check has
+ * been left intentionally broad in order to cover both a legacy flush
+ * and the new preflush behavior introduced in Linux 4.8. This is correct
+ * in all cases but may have a performance impact for some kernels. It
+ * has the advantage of minimizing kernel specific changes in the zvol code.
+ *
+ * Note that 2.6.32 era kernels provide both BIO_RW_BARRIER and REQ_FLUSH,
+ * where BIO_RW_BARRIER is the correct interface. Therefore, it is important
+ * that the HAVE_BIO_RW_BARRIER check occur before the REQ_FLUSH check.
+ */
+static inline boolean_t
+bio_is_flush(struct bio *bio)
+{
+#if defined(HAVE_REQ_OP_FLUSH) && defined(HAVE_BIO_BI_OPF)
+ return ((bio_op(bio) == REQ_OP_FLUSH) || (bio->bi_opf & REQ_PREFLUSH));
+#elif defined(REQ_PREFLUSH) && defined(HAVE_BIO_BI_OPF)
+ return (bio->bi_opf & REQ_PREFLUSH);
+#elif defined(REQ_PREFLUSH) && !defined(HAVE_BIO_BI_OPF)
+ return (bio->bi_rw & REQ_PREFLUSH);
+#elif defined(HAVE_BIO_RW_BARRIER)
+ return (bio->bi_rw & (1 << BIO_RW_BARRIER));
+#elif defined(REQ_FLUSH)
+ return (bio->bi_rw & REQ_FLUSH);
#else
-#define VDEV_REQ_FLUSH REQ_HARDBARRIER
-#define VDEV_REQ_FUA REQ_FUA
+#error "Allowing the build will cause flush requests to be ignored."
#endif
+}
+
+/*
+ * 4.8 - 4.x API,
+ * REQ_FUA flag moved to bio->bi_opf
+ *
+ * 2.6.x - 4.7 API,
+ * REQ_FUA
+ */
+static inline boolean_t
+bio_is_fua(struct bio *bio)
+{
+#if defined(HAVE_BIO_BI_OPF)
+ return (bio->bi_opf & REQ_FUA);
+#elif defined(REQ_FUA)
+ return (bio->bi_rw & REQ_FUA);
+#else
+#error "Allowing the build will cause fua requests to be ignored."
#endif
+}
/*
- * 2.6.32 API change
- * Use the normal I/O patch for discards.
+ * 4.8 - 4.x API,
+ * REQ_OP_DISCARD
+ *
+ * 2.6.36 - 4.7 API,
+ * REQ_DISCARD
+ *
+ * 2.6.28 - 2.6.35 API,
+ * BIO_RW_DISCARD
+ *
+ * In all cases the normal I/O path is used for discards. The only
+ * difference is how the kernel tags individual I/Os as discards.
+ *
+ * Note that 2.6.32 era kernels provide both BIO_RW_DISCARD and REQ_DISCARD,
+ * where BIO_RW_DISCARD is the correct interface. Therefore, it is important
+ * that the HAVE_BIO_RW_DISCARD check occur before the REQ_DISCARD check.
*/
-#ifdef QUEUE_FLAG_DISCARD
-#ifdef HAVE_BIO_RW_DISCARD
-#define VDEV_REQ_DISCARD (1 << BIO_RW_DISCARD)
+static inline boolean_t
+bio_is_discard(struct bio *bio)
+{
+#if defined(HAVE_REQ_OP_DISCARD)
+ return (bio_op(bio) == REQ_OP_DISCARD);
+#elif defined(HAVE_BIO_RW_DISCARD)
+ return (bio->bi_rw & (1 << BIO_RW_DISCARD));
+#elif defined(REQ_DISCARD)
+ return (bio->bi_rw & REQ_DISCARD);
#else
-#define VDEV_REQ_DISCARD REQ_DISCARD
+/* potentially triggering the DMU_MAX_ACCESS assertion. */
+#error "Allowing the build will cause discard requests to become writes."
#endif
+}
+
+/*
+ * 4.8 - 4.x API,
+ * REQ_OP_SECURE_ERASE
+ *
+ * 2.6.36 - 4.7 API,
+ * REQ_SECURE
+ *
+ * 2.6.x - 2.6.35 API,
+ * Unsupported by kernel
+ */
+static inline boolean_t
+bio_is_secure_erase(struct bio *bio)
+{
+#if defined(HAVE_REQ_OP_SECURE_ERASE)
+ return (bio_op(bio) == REQ_OP_SECURE_ERASE);
+#elif defined(REQ_SECURE)
+ return (bio->bi_rw & REQ_SECURE);
#else
-#error "Allowing the build will cause discard requests to become writes "
- "potentially triggering the DMU_MAX_ACCESS assertion. Please file a "
- "an issue report at: https://github.com/zfsonlinux/zfs/issues/new"
+ return (0);
#endif
+}
/*
* 2.6.33 API change