Merge tag 'platform-drivers-x86-v5.4-2' of git://git.infradead.org/linux-platform...
[linux-2.6-block.git] / block / blk-merge.c
index 57f7990b342dd1957077ae48baf71283663c0e73..48e6725b32eeacc749664d19fe151df6e2b7818c 100644 (file)
@@ -132,19 +132,32 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
        return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
 }
 
+/*
+ * Return the maximum number of sectors from the start of a bio that may be
+ * submitted as a single request to a block device. If enough sectors remain,
+ * align the end to the physical block size. Otherwise align the end to the
+ * logical block size. This approach minimizes the number of non-aligned
+ * requests that are submitted to a block device if the start of a bio is not
+ * aligned to a physical block boundary.
+ */
 static inline unsigned get_max_io_size(struct request_queue *q,
                                       struct bio *bio)
 {
        unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
-       unsigned mask = queue_logical_block_size(q) - 1;
+       unsigned max_sectors = sectors;
+       unsigned pbs = queue_physical_block_size(q) >> SECTOR_SHIFT;
+       unsigned lbs = queue_logical_block_size(q) >> SECTOR_SHIFT;
+       unsigned start_offset = bio->bi_iter.bi_sector & (pbs - 1);
 
-       /* aligned to logical block size */
-       sectors &= ~(mask >> 9);
+       max_sectors += start_offset;
+       max_sectors &= ~(pbs - 1);
+       if (max_sectors > start_offset)
+               return max_sectors - start_offset;
 
-       return sectors;
+       return sectors & (lbs - 1);
 }
 
-static unsigned get_max_segment_size(struct request_queue *q,
+static unsigned get_max_segment_size(const struct request_queue *q,
                                     unsigned offset)
 {
        unsigned long mask = queue_segment_boundary(q);
@@ -157,26 +170,41 @@ static unsigned get_max_segment_size(struct request_queue *q,
                     queue_max_segment_size(q));
 }
 
-/*
- * Split the bvec @bv into segments, and update all kinds of
- * variables.
+/**
+ * bvec_split_segs - verify whether or not a bvec should be split in the middle
+ * @q:        [in] request queue associated with the bio associated with @bv
+ * @bv:       [in] bvec to examine
+ * @nsegs:    [in,out] Number of segments in the bio being built. Incremented
+ *            by the number of segments from @bv that may be appended to that
+ *            bio without exceeding @max_segs
+ * @sectors:  [in,out] Number of sectors in the bio being built. Incremented
+ *            by the number of sectors from @bv that may be appended to that
+ *            bio without exceeding @max_sectors
+ * @max_segs: [in] upper bound for *@nsegs
+ * @max_sectors: [in] upper bound for *@sectors
+ *
+ * When splitting a bio, it can happen that a bvec is encountered that is too
+ * big to fit in a single segment and hence that it has to be split in the
+ * middle. This function verifies whether or not that should happen. The value
+ * %true is returned if and only if appending the entire @bv to a bio with
+ * *@nsegs segments and *@sectors sectors would make that bio unacceptable for
+ * the block driver.
  */
-static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv,
-               unsigned *nsegs, unsigned *sectors, unsigned max_segs)
+static bool bvec_split_segs(const struct request_queue *q,
+                           const struct bio_vec *bv, unsigned *nsegs,
+                           unsigned *sectors, unsigned max_segs,
+                           unsigned max_sectors)
 {
-       unsigned len = bv->bv_len;
+       unsigned max_len = (min(max_sectors, UINT_MAX >> 9) - *sectors) << 9;
+       unsigned len = min(bv->bv_len, max_len);
        unsigned total_len = 0;
-       unsigned new_nsegs = 0, seg_size = 0;
+       unsigned seg_size = 0;
 
-       /*
-        * Multi-page bvec may be too big to hold in one segment, so the
-        * current bvec has to be splitted as multiple segments.
-        */
-       while (len && new_nsegs + *nsegs < max_segs) {
+       while (len && *nsegs < max_segs) {
                seg_size = get_max_segment_size(q, bv->bv_offset + total_len);
                seg_size = min(seg_size, len);
 
-               new_nsegs++;
+               (*nsegs)++;
                total_len += seg_size;
                len -= seg_size;
 
@@ -184,16 +212,31 @@ static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv,
                        break;
        }
 
-       if (new_nsegs) {
-               *nsegs += new_nsegs;
-               if (sectors)
-                       *sectors += total_len >> 9;
-       }
+       *sectors += total_len >> 9;
 
-       /* split in the middle of the bvec if len != 0 */
-       return !!len;
+       /* tell the caller to split the bvec if it is too big to fit */
+       return len > 0 || bv->bv_len > max_len;
 }
 
+/**
+ * blk_bio_segment_split - split a bio in two bios
+ * @q:    [in] request queue pointer
+ * @bio:  [in] bio to be split
+ * @bs:          [in] bio set to allocate the clone from
+ * @segs: [out] number of segments in the bio with the first half of the sectors
+ *
+ * Clone @bio, update the bi_iter of the clone to represent the first sectors
+ * of @bio and update @bio->bi_iter to represent the remaining sectors. The
+ * following is guaranteed for the cloned bio:
+ * - That it has at most get_max_io_size(@q, @bio) sectors.
+ * - That it has at most queue_max_segments(@q) segments.
+ *
+ * Except for discard requests the cloned bio will point at the bi_io_vec of
+ * the original bio. It is the responsibility of the caller to ensure that the
+ * original bio is not freed before the cloned bio. The caller is also
+ * responsible for ensuring that @bs is only destroyed after processing of the
+ * split bio has finished.
+ */
 static struct bio *blk_bio_segment_split(struct request_queue *q,
                                         struct bio *bio,
                                         struct bio_set *bs,
@@ -213,34 +256,18 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
                if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
                        goto split;
 
-               if (sectors + (bv.bv_len >> 9) > max_sectors) {
-                       /*
-                        * Consider this a new segment if we're splitting in
-                        * the middle of this vector.
-                        */
-                       if (nsegs < max_segs &&
-                           sectors < max_sectors) {
-                               /* split in the middle of bvec */
-                               bv.bv_len = (max_sectors - sectors) << 9;
-                               bvec_split_segs(q, &bv, &nsegs,
-                                               &sectors, max_segs);
-                       }
+               if (nsegs < max_segs &&
+                   sectors + (bv.bv_len >> 9) <= max_sectors &&
+                   bv.bv_offset + bv.bv_len <= PAGE_SIZE) {
+                       nsegs++;
+                       sectors += bv.bv_len >> 9;
+               } else if (bvec_split_segs(q, &bv, &nsegs, &sectors, max_segs,
+                                        max_sectors)) {
                        goto split;
                }
 
-               if (nsegs == max_segs)
-                       goto split;
-
                bvprv = bv;
                bvprvp = &bvprv;
-
-               if (bv.bv_offset + bv.bv_len <= PAGE_SIZE) {
-                       nsegs++;
-                       sectors += bv.bv_len >> 9;
-               } else if (bvec_split_segs(q, &bv, &nsegs, &sectors,
-                               max_segs)) {
-                       goto split;
-               }
        }
 
        *segs = nsegs;
@@ -250,6 +277,19 @@ split:
        return bio_split(bio, sectors, GFP_NOIO, bs);
 }
 
+/**
+ * __blk_queue_split - split a bio and submit the second half
+ * @q:       [in] request queue pointer
+ * @bio:     [in, out] bio to be split
+ * @nr_segs: [out] number of segments in the first bio
+ *
+ * Split a bio into two bios, chain the two bios, submit the second half and
+ * store a pointer to the first half in *@bio. If the second bio is still too
+ * big it will be split by a recursive call to this function. Since this
+ * function may allocate a new bio from @q->bio_split, it is the responsibility
+ * of the caller to ensure that @q is only released after processing of the
+ * split bio has finished.
+ */
 void __blk_queue_split(struct request_queue *q, struct bio **bio,
                unsigned int *nr_segs)
 {
@@ -294,6 +334,17 @@ void __blk_queue_split(struct request_queue *q, struct bio **bio,
        }
 }
 
+/**
+ * blk_queue_split - split a bio and submit the second half
+ * @q:   [in] request queue pointer
+ * @bio: [in, out] bio to be split
+ *
+ * Split a bio into two bios, chains the two bios, submit the second half and
+ * store a pointer to the first half in *@bio. Since this function may allocate
+ * a new bio from @q->bio_split, it is the responsibility of the caller to
+ * ensure that @q is only released after processing of the split bio has
+ * finished.
+ */
 void blk_queue_split(struct request_queue *q, struct bio **bio)
 {
        unsigned int nr_segs;
@@ -305,6 +356,7 @@ EXPORT_SYMBOL(blk_queue_split);
 unsigned int blk_recalc_rq_segments(struct request *rq)
 {
        unsigned int nr_phys_segs = 0;
+       unsigned int nr_sectors = 0;
        struct req_iterator iter;
        struct bio_vec bv;
 
@@ -321,7 +373,8 @@ unsigned int blk_recalc_rq_segments(struct request *rq)
        }
 
        rq_for_each_bvec(bv, rq, iter)
-               bvec_split_segs(rq->q, &bv, &nr_phys_segs, NULL, UINT_MAX);
+               bvec_split_segs(rq->q, &bv, &nr_phys_segs, &nr_sectors,
+                               UINT_MAX, UINT_MAX);
        return nr_phys_segs;
 }