]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - block/blk-merge.c
block: split bios to max possible length
[karo-tx-linux.git] / block / blk-merge.c
index e01405a3e8b3f51ce0424a844fadb3304bda5e44..6b982cacaea85abc3bebd7ea9631154d5c7e7f10 100644 (file)
@@ -81,9 +81,6 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
        struct bio *new = NULL;
 
        bio_for_each_segment(bv, bio, iter) {
-               if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
-                       goto split;
-
                /*
                 * If the queue doesn't support SG gaps and adding this
                 * offset would create a gap, disallow it.
@@ -91,6 +88,22 @@ 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) >
+                               blk_max_size_offset(q, bio->bi_iter.bi_sector)) {
+                       /*
+                        * Consider this a new segment if we're splitting in
+                        * the middle of this vector.
+                        */
+                       if (nsegs < queue_max_segments(q) &&
+                           sectors < blk_max_size_offset(q,
+                                               bio->bi_iter.bi_sector)) {
+                               nsegs++;
+                               sectors = blk_max_size_offset(q,
+                                               bio->bi_iter.bi_sector);
+                       }
+                       goto split;
+               }
+
                if (bvprvp && blk_queue_cluster(q)) {
                        if (seg_size + bv.bv_len > queue_max_segment_size(q))
                                goto new_segment;