Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[linux-2.6-block.git] / fs / iomap.c
index 897c60215dd1b2906913227158d4ae9d77029a79..97cb9d486a7da38527aa8bc7349692fedcce9e70 100644 (file)
@@ -274,8 +274,9 @@ iomap_read_end_io(struct bio *bio)
        int error = blk_status_to_errno(bio->bi_status);
        struct bio_vec *bvec;
        int i;
+       struct bvec_iter_all iter_all;
 
-       bio_for_each_segment_all(bvec, bio, i)
+       bio_for_each_segment_all(bvec, bio, i, iter_all)
                iomap_read_page_end_io(bvec, error);
        bio_put(bio);
 }
@@ -324,7 +325,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
         */
        sector = iomap_sector(iomap, pos);
        if (ctx->bio && bio_end_sector(ctx->bio) == sector) {
-               if (__bio_try_merge_page(ctx->bio, page, plen, poff))
+               if (__bio_try_merge_page(ctx->bio, page, plen, poff, true))
                        goto done;
                is_contig = true;
        }
@@ -355,7 +356,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                ctx->bio->bi_end_io = iomap_read_end_io;
        }
 
-       __bio_add_page(ctx->bio, page, plen, poff);
+       bio_add_page(ctx->bio, page, plen, poff);
 done:
        /*
         * Move the caller beyond our range so that it keeps making progress.
@@ -1463,6 +1464,28 @@ struct iomap_dio {
        };
 };
 
+int iomap_dio_iopoll(struct kiocb *kiocb, bool spin)
+{
+       struct request_queue *q = READ_ONCE(kiocb->private);
+
+       if (!q)
+               return 0;
+       return blk_poll(q, READ_ONCE(kiocb->ki_cookie), spin);
+}
+EXPORT_SYMBOL_GPL(iomap_dio_iopoll);
+
+static void iomap_dio_submit_bio(struct iomap_dio *dio, struct iomap *iomap,
+               struct bio *bio)
+{
+       atomic_inc(&dio->ref);
+
+       if (dio->iocb->ki_flags & IOCB_HIPRI)
+               bio_set_polled(bio, dio->iocb);
+
+       dio->submit.last_queue = bdev_get_queue(iomap->bdev);
+       dio->submit.cookie = submit_bio(bio);
+}
+
 static ssize_t iomap_dio_complete(struct iomap_dio *dio)
 {
        struct kiocb *iocb = dio->iocb;
@@ -1568,14 +1591,15 @@ static void iomap_dio_bio_end_io(struct bio *bio)
        } else {
                struct bio_vec *bvec;
                int i;
+               struct bvec_iter_all iter_all;
 
-               bio_for_each_segment_all(bvec, bio, i)
+               bio_for_each_segment_all(bvec, bio, i, iter_all)
                        put_page(bvec->bv_page);
                bio_put(bio);
        }
 }
 
-static blk_qc_t
+static void
 iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
                unsigned len)
 {
@@ -1589,15 +1613,10 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
        bio->bi_private = dio;
        bio->bi_end_io = iomap_dio_bio_end_io;
 
-       if (dio->iocb->ki_flags & IOCB_HIPRI)
-               flags |= REQ_HIPRI;
-
        get_page(page);
        __bio_add_page(bio, page, len, 0);
        bio_set_op_attrs(bio, REQ_OP_WRITE, flags);
-
-       atomic_inc(&dio->ref);
-       return submit_bio(bio);
+       iomap_dio_submit_bio(dio, iomap, bio);
 }
 
 static loff_t
@@ -1700,9 +1719,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
                                bio_set_pages_dirty(bio);
                }
 
-               if (dio->iocb->ki_flags & IOCB_HIPRI)
-                       bio->bi_opf |= REQ_HIPRI;
-
                iov_iter_advance(dio->submit.iter, n);
 
                dio->size += n;
@@ -1710,11 +1726,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
                copied += n;
 
                nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
-
-               atomic_inc(&dio->ref);
-
-               dio->submit.last_queue = bdev_get_queue(iomap->bdev);
-               dio->submit.cookie = submit_bio(bio);
+               iomap_dio_submit_bio(dio, iomap, bio);
        } while (nr_pages);
 
        /*
@@ -1925,6 +1937,9 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        if (dio->flags & IOMAP_DIO_WRITE_FUA)
                dio->flags &= ~IOMAP_DIO_NEED_SYNC;
 
+       WRITE_ONCE(iocb->ki_cookie, dio->submit.cookie);
+       WRITE_ONCE(iocb->private, dio->submit.last_queue);
+
        /*
         * We are about to drop our additional submission reference, which
         * might be the last reference to the dio.  There are three three