Prep work for multipage bvecs: various code will still need to iterate
over individual pages, so we add primitives to do so

Signed-off-by: Kent Overstreet <k...@daterainc.com>
---
 drivers/scsi/sd_dif.c |  4 +--
 fs/bio.c              | 20 +++++++-----
 fs/mpage.c            |  8 ++---
 include/linux/bio.h   | 85 ++++++++++++++++++++++++++++++++++-----------------
 4 files changed, 76 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index a7a691d..ea92592 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -385,7 +385,7 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
 
                virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff;
 
-               bip_for_each_vec(iv, bio->bi_integrity, iter) {
+               bip_for_each_page(iv, bio->bi_integrity, iter) {
                        sdt = kmap_atomic(iv.bv_page)
                                + iv.bv_offset;
 
@@ -436,7 +436,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int 
good_bytes)
 
                virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff;
 
-               bip_for_each_vec(iv, bio->bi_integrity, iter) {
+               bip_for_each_page(iv, bio->bi_integrity, iter) {
                        sdt = kmap_atomic(iv.bv_page)
                                + iv.bv_offset;
 
diff --git a/fs/bio.c b/fs/bio.c
index e9d1c05..da8aa81 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -496,16 +496,22 @@ EXPORT_SYMBOL(bio_alloc_bioset);
 
 void zero_fill_bio(struct bio *bio)
 {
-       unsigned long flags;
        struct bio_vec bv;
        struct bvec_iter iter;
 
-       bio_for_each_segment(bv, bio, iter) {
+#if defined(CONFIG_HIGHMEM) || defined(ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE)
+       bio_for_each_page(bv, bio, iter) {
+               unsigned long flags;
                char *data = bvec_kmap_irq(&bv, &flags);
                memset(data, 0, bv.bv_len);
                flush_dcache_page(bv.bv_page);
                bvec_kunmap_irq(data, &flags);
        }
+#else
+       bio_for_each_segment(bv, bio, iter)
+               memset(page_address(bv.bv_page) + bv.bv_offset,
+                      0, bv.bv_len);
+#endif
 }
 EXPORT_SYMBOL(zero_fill_bio);
 
@@ -1474,11 +1480,11 @@ EXPORT_SYMBOL(bio_copy_kern);
  */
 void bio_set_pages_dirty(struct bio *bio)
 {
-       struct bio_vec *bvec;
-       int i;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
-       bio_for_each_segment_all(bvec, bio, i) {
-               struct page *page = bvec->bv_page;
+       bio_for_each_page_all(bvec, bio, iter) {
+               struct page *page = bvec.bv_page;
 
                if (page && !PageCompound(page))
                        set_page_dirty_lock(page);
@@ -1574,7 +1580,7 @@ void bio_flush_dcache_pages(struct bio *bi)
        struct bio_vec *bvec;
        struct bvec_iter iter;
 
-       bio_for_each_segment(bvec, bi, iter)
+       bio_for_each_page(bvec, bi, iter)
                flush_dcache_page(bvec->bv_page);
 }
 EXPORT_SYMBOL(bio_flush_dcache_pages);
diff --git a/fs/mpage.c b/fs/mpage.c
index 8e0a471..7507811 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -43,11 +43,11 @@
  */
 static void mpage_end_io(struct bio *bio, int err)
 {
-       struct bio_vec *bv;
-       int i;
+       struct bio_vec bv;
+       struct bvec_iter iter;
 
-       bio_for_each_segment_all(bv, bio, i) {
-               struct page *page = bv->bv_page;
+       bio_for_each_page_all(bv, bio, iter) {
+               struct page *page = bv.bv_page;
 
                if (bio_data_dir(bio) == READ) {
                        if (!err) {
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 231ae67..f6f0e99 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -63,16 +63,24 @@
  */
 #define __bvec_iter_bvec(bvec, iter)   (&(bvec)[(iter).bi_idx])
 
-#define bvec_iter_page(bvec, iter)                             \
-       (__bvec_iter_bvec((bvec), (iter))->bv_page)
+#define bvec_iter_page(bvec, iter)                                     \
+       nth_page(__bvec_iter_bvec((bvec), (iter))->bv_page,             \
+                __bvec_iter_offset((bvec), (iter)) >> PAGE_SHIFT)
 
-#define bvec_iter_len(bvec, iter)                              \
-       min((iter).bi_size,                                     \
+#define bvec_iter_page_bytes(bvec, iter)                               \
+       min_t(unsigned, bvec_iter_len((bvec), (iter)),                  \
+             PAGE_SIZE - bvec_iter_offset((bvec), (iter)))
+
+#define bvec_iter_len(bvec, iter)                                      \
+       min((iter).bi_size,                                             \
            __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
 
-#define bvec_iter_offset(bvec, iter)                           \
+#define __bvec_iter_offset(bvec, iter)                                 \
        (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
 
+#define bvec_iter_offset(bvec, iter)                                   \
+       (__bvec_iter_offset((bvec), (iter)) & (PAGE_SIZE - 1))
+
 #define bvec_iter_bvec(bvec, iter)                             \
 ((struct bio_vec) {                                            \
        .bv_page        = bvec_iter_page((bvec), (iter)),       \
@@ -85,6 +93,8 @@
 
 #define bio_iter_page(bio, iter)                               \
        bvec_iter_page((bio)->bi_io_vec, (iter))
+#define bio_iter_page_bytes(bio, iter)                         \
+       bvec_iter_page_bytes((bio)->bi_io_vec, (iter))
 #define bio_iter_len(bio, iter)                                        \
        bvec_iter_len((bio)->bi_io_vec, (iter))
 #define bio_iter_offset(bio, iter)                             \
@@ -188,13 +198,6 @@ static inline void *bio_data(struct bio *bio)
 
 #define bio_io_error(bio) bio_endio((bio), -EIO)
 
-/*
- * drivers should _never_ use the all version - the bio may have been split
- * before it got to the driver and the driver won't own all of it
- */
-#define bio_for_each_segment_all(bvl, bio, i)                          \
-       for (i = 0, bvl = (bio)->bi_io_vec; i < (bio)->bi_vcnt; i++, bvl++)
-
 static inline void bvec_iter_advance(struct bio_vec *bv, struct bvec_iter 
*iter,
                                     unsigned bytes)
 {
@@ -215,13 +218,6 @@ static inline void bvec_iter_advance(struct bio_vec *bv, 
struct bvec_iter *iter,
        }
 }
 
-#define for_each_bvec(bvl, bio_vec, iter, start)                       \
-       for ((iter) = start;                                            \
-            (bvl) = bvec_iter_bvec((bio_vec), (iter)),                 \
-               (iter).bi_size;                                         \
-            bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
-
-
 static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
                                    unsigned bytes)
 {
@@ -233,15 +229,42 @@ static inline void bio_advance_iter(struct bio *bio, 
struct bvec_iter *iter,
                bvec_iter_advance(bio->bi_io_vec, iter, bytes);
 }
 
-#define __bio_for_each_segment(bvl, bio, iter, start)                  \
+#define BVEC_ITER_ALL_INITIALIZER (struct bvec_iter)                   \
+{                                                                      \
+       .bi_sector      = 0,                                            \
+       .bi_size        = UINT_MAX,                                     \
+       .bi_idx         = 0,                                            \
+       .bi_bvec_done   = 0,                                            \
+}
+
+#define __bio_for_each(bvl, bio, iter, start, condition, advance)      \
        for (iter = (start);                                            \
-            (iter).bi_size &&                                          \
-               ((bvl = bio_iter_iovec((bio), (iter))), 1);             \
-            bio_advance_iter((bio), &(iter), (bvl).bv_len))
+            (condition) &&                                             \
+               ((bvl) = bio_iter_iovec((bio), (iter)), 1);             \
+            bio_advance_iter((bio), &(iter), advance((bio), (iter))))
+
+#define __bio_for_each_segment(bvl, bio, iter, start)                  \
+       __bio_for_each((bvl), (bio), (iter), (start),                   \
+                      (iter).bi_size, bio_iter_len)
 
 #define bio_for_each_segment(bvl, bio, iter)                           \
        __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter)
 
+#define bio_for_each_page(bvl, bio, iter)                              \
+       __bio_for_each((bvl), (bio), (iter), (bio)->bi_iter,            \
+                      (iter).bi_size, bio_iter_page_bytes)
+
+/*
+ * drivers should _never_ use the all version - the bio may have been split
+ * before it got to the driver and the driver won't own all of it
+ */
+#define bio_for_each_segment_all(bvl, bio, i)                          \
+       for (i = 0, bvl = (bio)->bi_io_vec; i < (bio)->bi_vcnt; i++, bvl++)
+
+#define bio_for_each_page_all(bvl, bio, iter)                          \
+       __bio_for_each((bvl), (bio), (iter), BVEC_ITER_ALL_INITIALIZER, \
+                      (iter).bi_idx < (bio)->bi_vcnt, bio_iter_page_bytes)
+
 #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
 
 /*
@@ -616,16 +639,22 @@ struct biovec_slab {
 
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
 
+#define __bip_for_each(bvl, bip, iter, advance)                                
\
+       for ((iter) = (bip)->bip_iter;                                  \
+            (iter).bi_size &&                                          \
+               ((bvl) = bvec_iter_bvec((bip)->bip_vec, (iter)), 1);    \
+            bvec_iter_advance((bip)->bip_vec, &(iter),                 \
+                              advance((bip)->bip_vec, (iter))))
 
+#define bip_for_each_segment(bvl, bip, iter)                           \
+       __bip_for_each(bvl, bip, iter, bvec_iter_len)
 
-#define bip_vec_idx(bip, idx)  (&(bip->bip_vec[(idx)]))
-
-#define bip_for_each_vec(bvl, bip, iter)                               \
-       for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter)
+#define bip_for_each_page(bvl, bip, iter)                              \
+       __bip_for_each(bvl, bip, iter, bvec_iter_page_bytes)
 
 #define bio_for_each_integrity_vec(_bvl, _bio, _iter)                  \
        for_each_bio(_bio)                                              \
-               bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
+               bip_for_each_segment(_bvl, _bio->bi_integrity, _iter)
 
 #define bio_integrity(bio) (bio->bi_integrity != NULL)
 
-- 
1.8.4.rc3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to