]> granicus.if.org Git - zfs/commitdiff
Linux 3.14 compat: rq_for_each_segment in dmu_req_copy
authorChunwei Chen <tuxoko@gmail.com>
Sat, 29 Mar 2014 12:26:17 +0000 (20:26 +0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Apr 2014 21:28:51 +0000 (14:28 -0700)
rq_for_each_segment changed from taking bio_vec * to taking bio_vec.
We provide rq_for_each_segment4 which takes both.

Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #2124

config/kernel-rq-for-each_segment.m4
include/linux/blkdev_compat.h
module/zfs/dmu.c

index 449168d088eb803e8bf47551b9ee85273cd8ae4f..84ce7d1ec00d2cb4253067ab15c5fe6369999dbd 100644 (file)
@@ -1,10 +1,13 @@
 dnl #
 dnl # 2.6.x API change
 dnl #
+dnl # 3.14 API change
+dnl #
 AC_DEFUN([ZFS_AC_KERNEL_RQ_FOR_EACH_SEGMENT], [
-       AC_MSG_CHECKING([whether rq_for_each_segment() is available])
        tmp_flags="$EXTRA_KCFLAGS"
        EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+
+       AC_MSG_CHECKING([whether rq_for_each_segment() wants bio_vec *])
        ZFS_LINUX_TRY_COMPILE([
                #include <linux/blkdev.h>
        ],[
@@ -16,8 +19,29 @@ AC_DEFUN([ZFS_AC_KERNEL_RQ_FOR_EACH_SEGMENT], [
                AC_MSG_RESULT(yes)
                AC_DEFINE(HAVE_RQ_FOR_EACH_SEGMENT, 1,
                          [rq_for_each_segment() is available])
+               AC_DEFINE(HAVE_RQ_FOR_EACH_SEGMENT_BVP, 1,
+                         [rq_for_each_segment() wants bio_vec *])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([whether rq_for_each_segment() wants bio_vec])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/blkdev.h>
+       ],[
+               struct bio_vec bv;
+               struct req_iterator iter;
+               struct request *req = NULL;
+               rq_for_each_segment(bv, req, iter) { }
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_RQ_FOR_EACH_SEGMENT, 1,
+                         [rq_for_each_segment() is available])
+               AC_DEFINE(HAVE_RQ_FOR_EACH_SEGMENT_BV, 1,
+                         [rq_for_each_segment() wants bio_vec])
        ],[
                AC_MSG_RESULT(no)
        ])
+
        EXTRA_KCFLAGS="$tmp_flags"
 ])
index be22ae700f0ce19ba0ee256423700c32fe6e53b8..8566033fcfd22525254e0fd96ca864397df5a906 100644 (file)
@@ -284,8 +284,32 @@ struct req_iterator {
 #define        rq_for_each_segment(bvl, _rq, _iter)                    \
        __rq_for_each_bio(_iter.bio, _rq)                       \
                bio_for_each_segment(bvl, _iter.bio, _iter.i)
+
+#define        HAVE_RQ_FOR_EACH_SEGMENT_BVP 1
 #endif /* HAVE_RQ_FOR_EACH_SEGMENT */
 
+/*
+ * 3.14 API change
+ * rq_for_each_segment changed from taking bio_vec * to taking bio_vec.
+ * We provide rq_for_each_segment4 which takes both.
+ * You should not modify the fields in @bv and @bvp.
+ *
+ * Note: the if-else is just to inject the assignment before the loop body.
+ */
+#ifdef HAVE_RQ_FOR_EACH_SEGMENT_BVP
+#define        rq_for_each_segment4(bv, bvp, rq, iter) \
+       rq_for_each_segment(bvp, rq, iter)      \
+               if ((bv = *bvp), 0)             \
+                       ;                       \
+               else
+#else
+#define        rq_for_each_segment4(bv, bvp, rq, iter) \
+       rq_for_each_segment(bv, rq, iter)       \
+               if ((bvp = &bv), 0)             \
+                       ;                       \
+               else
+#endif
+
 #ifdef HAVE_BIO_BVEC_ITER
 #define        BIO_BI_SECTOR(bio)      (bio)->bi_iter.bi_sector
 #define        BIO_BI_SIZE(bio)        (bio)->bi_iter.bi_size
index 5d9337f65b8390587b90d5be0153a75bfdca6237..edad9b4969a5a3b382be8d397c4acf3396223c3b 100644 (file)
@@ -1011,13 +1011,13 @@ xuio_stat_wbuf_nocopy()
 static int
 dmu_req_copy(void *arg_buf, int size, struct request *req, size_t req_offset)
 {
-       struct bio_vec *bv;
+       struct bio_vec bv, *bvp;
        struct req_iterator iter;
        char *bv_buf;
        int tocpy, bv_len, bv_offset;
        int offset = 0;
 
-       rq_for_each_segment(bv, req, iter) {
+       rq_for_each_segment4(bv, bvp, req, iter) {
                /*
                 * Fully consumed the passed arg_buf. We use goto here because
                 * rq_for_each_segment is a double loop
@@ -1027,19 +1027,19 @@ dmu_req_copy(void *arg_buf, int size, struct request *req, size_t req_offset)
                        goto out;
 
                /* Skip already copied bv */
-               if (req_offset >=  bv->bv_len) {
-                       req_offset -= bv->bv_len;
+               if (req_offset >=  bv.bv_len) {
+                       req_offset -= bv.bv_len;
                        continue;
                }
 
-               bv_len = bv->bv_len - req_offset;
-               bv_offset = bv->bv_offset + req_offset;
+               bv_len = bv.bv_len - req_offset;
+               bv_offset = bv.bv_offset + req_offset;
                req_offset = 0;
 
                tocpy = MIN(bv_len, size - offset);
                ASSERT3S(tocpy, >=, 0);
 
-               bv_buf = page_address(bv->bv_page) + bv_offset;
+               bv_buf = page_address(bv.bv_page) + bv_offset;
                ASSERT3P(bv_buf, !=, NULL);
 
                if (rq_data_dir(req) == WRITE)