CHROMIUM: md: dm-bootcache: reinitialize bio structure

The bootcache code does multiple large reads and was reusing the bio structure.
Some device drivers appear to leave some clutter in the bio structure.
Between large reads, the bootcache now frees and reallocates the bio structure.

BUG=chrome-os-partner:18830
TEST=POWER-ESC-F3 with USB stick, several times.
Signed-off-by: Paul Taysom <taysom@chromium.org>

Change-Id: I5b835b5f0606f6eb4116fc9719d96a48d0155f57
Reviewed-on: https://gerrit.chromium.org/gerrit/49121
Reviewed-by: Olof Johansson <olofj@chromium.org>
Tested-by: Paul Taysom <taysom@chromium.org>
Commit-Queue: Paul Taysom <taysom@chromium.org>
diff --git a/drivers/md/dm-bootcache.c b/drivers/md/dm-bootcache.c
index d83337d4..c6c0269 100644
--- a/drivers/md/dm-bootcache.c
+++ b/drivers/md/dm-bootcache.c
@@ -577,15 +577,15 @@
 	int j;
 	int rc = 0;
 
-	bio = bio_alloc_bioset(GFP_KERNEL, max_io, cache->bio_set);
-	if (unlikely(!bio)) {
-		DMERR("Out of memory bio_alloc_bioset");
-		return -ENOMEM;
-	}
-	bio->bi_private = &waiter;
-	bio->bi_destructor = bootcache_bio_destructor;
 	p = cache->sectors.pages;
 	for (i = 0; i < chunks_to_read; i++) {
+		bio = bio_alloc_bioset(GFP_KERNEL, max_io, cache->bio_set);
+		if (unlikely(!bio)) {
+			DMERR("Out of memory bio_alloc_bioset");
+			return -ENOMEM;
+		}
+		bio->bi_private = &waiter;
+		bio->bi_destructor = bootcache_bio_destructor;
 		bio->bi_idx = 0;
 		bio->bi_bdev = cache->dev->bdev;
 		bio->bi_end_io = bootcache_read_sectors_end;
@@ -609,6 +609,8 @@
 		wait_for_completion(&waiter.completion);
 		if (waiter.error) {
 			rc = waiter.error;
+			bio->bi_private = cache;
+			bio_put(bio);
 			break;
 		}
 		p = start_page;
@@ -618,9 +620,9 @@
 			p->is_filled = 1;
 		}
 		sector += pages_to_sectors(j);
+		bio->bi_private = cache;
+		bio_put(bio);
 	}
-	bio->bi_private = cache;
-	bio_put(bio);
 	atomic_set(&cache->state, BC_FILLED);
 	return rc;
 }
@@ -645,7 +647,6 @@
 	struct bio_vec *bvec;
 	int pages_to_read = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	int max_io = cache->max_io;
-	int num_pages;
 	int bytes_to_copy;
 	int i;
 	int rc = 0;
@@ -653,24 +654,20 @@
 	u8 *dst = data;
 	u8 *src;
 
-	if (pages_to_read < max_io)
-		num_pages = pages_to_read;
-	else
-		num_pages = max_io;
-	bio = bio_alloc_bioset(GFP_KERNEL, num_pages, cache->bio_set);
-	if (unlikely(!bio)) {
-		DMERR("Out of memory bio_alloc_bioset");
-		return -ENOMEM;
-	}
-	bvec = bio->bi_io_vec;
-	for (i = 0; i < num_pages; i++, bvec++)
-		bvec->bv_page = alloc_page(GFP_KERNEL);
-	bio->bi_private = &waiter;
-	bio->bi_destructor = bootcache_bio_destructor;
 	pages_read = 0;
 	while (len) {
 		if (pages_to_read < max_io)
 			max_io = pages_to_read;
+		bio = bio_alloc_bioset(GFP_KERNEL, max_io, cache->bio_set);
+		if (unlikely(!bio)) {
+			DMERR("Out of memory bio_alloc_bioset");
+			return -ENOMEM;
+		}
+		bvec = bio->bi_io_vec;
+		for (i = 0; i < max_io; i++, bvec++)
+			bvec->bv_page = alloc_page(GFP_KERNEL);
+		bio->bi_private = &waiter;
+		bio->bi_destructor = bootcache_bio_destructor;
 		bio->bi_idx = 0;
 		bio->bi_bdev = cache->dev->bdev;
 		bio->bi_end_io = bootcache_dev_read_end;
@@ -691,10 +688,10 @@
 		wait_for_completion(&waiter.completion);
 		if (waiter.error) {
 			rc = waiter.error;
-			goto exit;
+			goto error;
 		}
 		for (i = 0; i < max_io; i++) {
-			bytes_to_copy = (len < PAGE_SIZE) ? len : PAGE_SIZE;
+			bytes_to_copy = min(len, (int)PAGE_SIZE);
 			src = kmap_atomic(bio_iovec_idx(bio, i)->bv_page);
 			memcpy(dst, src, bytes_to_copy);
 			kunmap_atomic(src);
@@ -704,10 +701,16 @@
 			dst += bytes_to_copy;
 		}
 		sector += pages_to_sectors(max_io);
+		bvec = bio->bi_io_vec;
+		for (i = 0; i < max_io; i++, bvec++)
+			__free_pages(bvec->bv_page, 0);
+		bio->bi_private = cache;
+		bio_put(bio);
 	}
-exit:
+	return rc;
+error:
 	bvec = bio->bi_io_vec;
-	for (i = 0; i < num_pages; i++, bvec++)
+	for (i = 0; i < max_io; i++, bvec++)
 		__free_pages(bvec->bv_page, 0);
 	bio->bi_private = cache;
 	bio_put(bio);