Merge tag 'for-5.20/block-2022-07-29' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / block / bio.c
index 51c99f2..6f9f883 100644 (file)
@@ -239,7 +239,7 @@ static void bio_free(struct bio *bio)
  * when IO has completed, or when the bio is released.
  */
 void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
-             unsigned short max_vecs, unsigned int opf)
+             unsigned short max_vecs, blk_opf_t opf)
 {
        bio->bi_next = NULL;
        bio->bi_bdev = bdev;
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(bio_init);
  *   preserved are the ones that are initialized by bio_alloc_bioset(). See
  *   comment in struct bio.
  */
-void bio_reset(struct bio *bio, struct block_device *bdev, unsigned int opf)
+void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf)
 {
        bio_uninit(bio);
        memset(bio, 0, BIO_RESET_BYTES);
@@ -341,7 +341,7 @@ void bio_chain(struct bio *bio, struct bio *parent)
 EXPORT_SYMBOL(bio_chain);
 
 struct bio *blk_next_bio(struct bio *bio, struct block_device *bdev,
-               unsigned int nr_pages, unsigned int opf, gfp_t gfp)
+               unsigned int nr_pages, blk_opf_t opf, gfp_t gfp)
 {
        struct bio *new = bio_alloc(bdev, nr_pages, opf, gfp);
 
@@ -409,7 +409,7 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
 }
 
 static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
-               unsigned short nr_vecs, unsigned int opf, gfp_t gfp,
+               unsigned short nr_vecs, blk_opf_t opf, gfp_t gfp,
                struct bio_set *bs)
 {
        struct bio_alloc_cache *cache;
@@ -468,7 +468,7 @@ static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
  * Returns: Pointer to new bio on success, NULL on failure.
  */
 struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
-                            unsigned int opf, gfp_t gfp_mask,
+                            blk_opf_t opf, gfp_t gfp_mask,
                             struct bio_set *bs)
 {
        gfp_t saved_gfp = gfp_mask;
@@ -1033,7 +1033,7 @@ int bio_add_zone_append_page(struct bio *bio, struct page *page,
        if (WARN_ON_ONCE(bio_op(bio) != REQ_OP_ZONE_APPEND))
                return 0;
 
-       if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
+       if (WARN_ON_ONCE(!bdev_is_zoned(bio->bi_bdev)))
                return 0;
 
        return bio_add_hw_page(q, bio, page, len, offset,
@@ -1159,6 +1159,37 @@ static void bio_put_pages(struct page **pages, size_t size, size_t off)
                put_page(pages[i]);
 }
 
+static int bio_iov_add_page(struct bio *bio, struct page *page,
+               unsigned int len, unsigned int offset)
+{
+       bool same_page = false;
+
+       if (!__bio_try_merge_page(bio, page, len, offset, &same_page)) {
+               if (WARN_ON_ONCE(bio_full(bio, len)))
+                       return -EINVAL;
+               __bio_add_page(bio, page, len, offset);
+               return 0;
+       }
+
+       if (same_page)
+               put_page(page);
+       return 0;
+}
+
+static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page,
+               unsigned int len, unsigned int offset)
+{
+       struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+       bool same_page = false;
+
+       if (bio_add_hw_page(q, bio, page, len, offset,
+                       queue_max_zone_append_sectors(q), &same_page) != len)
+               return -EINVAL;
+       if (same_page)
+               put_page(page);
+       return 0;
+}
+
 #define PAGE_PTRS_PER_BVEC     (sizeof(struct bio_vec) / sizeof(struct page *))
 
 /**
@@ -1177,7 +1208,6 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
        unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt;
        struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;
        struct page **pages = (struct page **)bv;
-       bool same_page = false;
        ssize_t size, left;
        unsigned len, i;
        size_t offset;
@@ -1186,82 +1216,43 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
         * Move page array up in the allocated memory for the bio vecs as far as
         * possible so that we can start filling biovecs from the beginning
         * without overwriting the temporary page array.
-       */
+        */
        BUILD_BUG_ON(PAGE_PTRS_PER_BVEC < 2);
        pages += entries_left * (PAGE_PTRS_PER_BVEC - 1);
 
-       size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset);
-       if (unlikely(size <= 0))
-               return size ? size : -EFAULT;
-
-       for (left = size, i = 0; left > 0; left -= len, i++) {
-               struct page *page = pages[i];
-
-               len = min_t(size_t, PAGE_SIZE - offset, left);
-
-               if (__bio_try_merge_page(bio, page, len, offset, &same_page)) {
-                       if (same_page)
-                               put_page(page);
-               } else {
-                       if (WARN_ON_ONCE(bio_full(bio, len))) {
-                               bio_put_pages(pages + i, left, offset);
-                               return -EINVAL;
-                       }
-                       __bio_add_page(bio, page, len, offset);
-               }
-               offset = 0;
-       }
-
-       iov_iter_advance(iter, size);
-       return 0;
-}
-
-static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter)
-{
-       unsigned short nr_pages = bio->bi_max_vecs - bio->bi_vcnt;
-       unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt;
-       struct request_queue *q = bdev_get_queue(bio->bi_bdev);
-       unsigned int max_append_sectors = queue_max_zone_append_sectors(q);
-       struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;
-       struct page **pages = (struct page **)bv;
-       ssize_t size, left;
-       unsigned len, i;
-       size_t offset;
-       int ret = 0;
-
-       if (WARN_ON_ONCE(!max_append_sectors))
-               return 0;
-
        /*
-        * Move page array up in the allocated memory for the bio vecs as far as
-        * possible so that we can start filling biovecs from the beginning
-        * without overwriting the temporary page array.
+        * Each segment in the iov is required to be a block size multiple.
+        * However, we may not be able to get the entire segment if it spans
+        * more pages than bi_max_vecs allows, so we have to ALIGN_DOWN the
+        * result to ensure the bio's total size is correct. The remainder of
+        * the iov data will be picked up in the next bio iteration.
         */
-       BUILD_BUG_ON(PAGE_PTRS_PER_BVEC < 2);
-       pages += entries_left * (PAGE_PTRS_PER_BVEC - 1);
-
        size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset);
+       if (size > 0)
+               size = ALIGN_DOWN(size, bdev_logical_block_size(bio->bi_bdev));
        if (unlikely(size <= 0))
                return size ? size : -EFAULT;
 
        for (left = size, i = 0; left > 0; left -= len, i++) {
                struct page *page = pages[i];
-               bool same_page = false;
+               int ret;
 
                len = min_t(size_t, PAGE_SIZE - offset, left);
-               if (bio_add_hw_page(q, bio, page, len, offset,
-                               max_append_sectors, &same_page) != len) {
+               if (bio_op(bio) == REQ_OP_ZONE_APPEND)
+                       ret = bio_iov_add_zone_append_page(bio, page, len,
+                                       offset);
+               else
+                       ret = bio_iov_add_page(bio, page, len, offset);
+
+               if (ret) {
                        bio_put_pages(pages + i, left, offset);
-                       ret = -EINVAL;
-                       break;
+                       return ret;
                }
-               if (same_page)
-                       put_page(page);
                offset = 0;
        }
 
-       iov_iter_advance(iter, size - left);
-       return ret;
+       iov_iter_advance(iter, size);
+       return 0;
 }
 
 /**
@@ -1298,10 +1289,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
        }
 
        do {
-               if (bio_op(bio) == REQ_OP_ZONE_APPEND)
-                       ret = __bio_iov_append_get_pages(bio, iter);
-               else
-                       ret = __bio_iov_iter_get_pages(bio, iter);
+               ret = __bio_iov_iter_get_pages(bio, iter);
        } while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
 
        /* don't account direct I/O as memory stall */