]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - block/bio.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / block / bio.c
index 1ba33657160f8f18b020066ecf328c04b51a3f52..0443694ccbb46b77349b9c1469a3b297905bc1cb 100644 (file)
@@ -752,28 +752,30 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                return 0;
 
        /*
-        * we might lose a segment or two here, but rather that than
-        * make this too complex.
+        * setup the new entry, we might clear it again later if we
+        * cannot add the page
+        */
+       bvec = &bio->bi_io_vec[bio->bi_vcnt];
+       bvec->bv_page = page;
+       bvec->bv_len = len;
+       bvec->bv_offset = offset;
+       bio->bi_vcnt++;
+       bio->bi_phys_segments++;
+
+       /*
+        * Perform a recount if the number of segments is greater
+        * than queue_max_segments(q).
         */
 
-       while (bio->bi_phys_segments >= queue_max_segments(q)) {
+       while (bio->bi_phys_segments > queue_max_segments(q)) {
 
                if (retried_segments)
-                       return 0;
+                       goto failed;
 
                retried_segments = 1;
                blk_recount_segments(q, bio);
        }
 
-       /*
-        * setup the new entry, we might clear it again later if we
-        * cannot add the page
-        */
-       bvec = &bio->bi_io_vec[bio->bi_vcnt];
-       bvec->bv_page = page;
-       bvec->bv_len = len;
-       bvec->bv_offset = offset;
-
        /*
         * if queue has other restrictions (eg varying max sector size
         * depending on offset), it can specify a merge_bvec_fn in the
@@ -791,23 +793,25 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                 * merge_bvec_fn() returns number of bytes it can accept
                 * at this offset
                 */
-               if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) {
-                       bvec->bv_page = NULL;
-                       bvec->bv_len = 0;
-                       bvec->bv_offset = 0;
-                       return 0;
-               }
+               if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len)
+                       goto failed;
        }
 
        /* If we may be able to merge these biovecs, force a recount */
-       if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
+       if (bio->bi_vcnt > 1 && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec)))
                bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 
-       bio->bi_vcnt++;
-       bio->bi_phys_segments++;
  done:
        bio->bi_iter.bi_size += len;
        return len;
+
+ failed:
+       bvec->bv_page = NULL;
+       bvec->bv_len = 0;
+       bvec->bv_offset = 0;
+       bio->bi_vcnt--;
+       blk_recount_segments(q, bio);
+       return 0;
 }
 
 /**