OSDN Git Service

powerpc/pseries: Allow not having ibm, hypertas-functions::hcall-multi-tce for DDW
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / block / blk-merge.c
index b966db8..b8f1eae 100644 (file)
@@ -92,9 +92,31 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
        bool do_split = true;
        struct bio *new = NULL;
        const unsigned max_sectors = get_max_io_size(q, bio);
+       unsigned bvecs = 0;
 
        bio_for_each_segment(bv, bio, iter) {
                /*
+                * With arbitrary bio size, the incoming bio may be very
+                * big. We have to split the bio into small bios so that
+                * each holds at most BIO_MAX_PAGES bvecs because
+                * bio_clone() can fail to allocate big bvecs.
+                *
+                * It should have been better to apply the limit per
+                * request queue in which bio_clone() is involved,
+                * instead of globally. The biggest blocker is the
+                * bio_clone() in bio bounce.
+                *
+                * If bio is splitted by this reason, we should have
+                * allowed to continue bios merging, but don't do
+                * that now for making the change simple.
+                *
+                * TODO: deal with bio bounce's bio_clone() gracefully
+                * and convert the global limit into per-queue limit.
+                */
+               if (bvecs++ >= BIO_MAX_PAGES)
+                       goto split;
+
+               /*
                 * If the queue doesn't support SG gaps and adding this
                 * offset would create a gap, disallow it.
                 */
@@ -274,13 +296,7 @@ void blk_recalc_rq_segments(struct request *rq)
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-       unsigned short seg_cnt;
-
-       /* estimate segment number by bi_vcnt for non-cloned bio */
-       if (bio_flagged(bio, BIO_CLONED))
-               seg_cnt = bio_segments(bio);
-       else
-               seg_cnt = bio->bi_vcnt;
+       unsigned short seg_cnt = bio_segments(bio);
 
        if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) &&
                        (seg_cnt < queue_max_segments(q)))