[dm-devel] [PATCH 07/10] fix blk_rq_map_user_iov bounce code

michaelc at cs.wisc.edu michaelc at cs.wisc.edu
Sat Oct 20 05:44:41 UTC 2007


From: Mike Christie <michaelc at cs.wisc.edu>

bio_map_user_iov grabs a extra reference to the bio incase
a function that does not exist (bio_map_user_iov comments
reference __bio_map_user) bounced the bio.

This patch has blk_rq_map_user_iov grab a extra reference instead
of the bio function (blk_rq_map_user_iov was actually already
grabbing an extra reference), and it adds a blk_queue_bounce to bounce
the bio.

It also removes the bio_endio call in the failure path. This should
be needed because the bio layer did not bounce the bio.

There was also an extra bio_put in bio_unmap_user to handle the
extra get in bio_map_user_iov. This patch also removes that since
it is not needed.

Signed-off-by: Mike Christie <michaelc at cs.wisc.edu>
---
 block/ll_rw_blk.c |    9 +++++++--
 fs/bio.c          |   43 +++++++++++--------------------------------
 2 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index fad17de..2e00bd2 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -2692,13 +2692,18 @@ int blk_rq_map_user_iov(struct bio_set *bs, struct request *rq,
 		return PTR_ERR(bio);
 
 	if (bio->bi_size != len) {
-		bio_endio(bio, 0);
 		bio_unmap_user(bio);
 		return -EINVAL;
 	}
 
-	bio_get(bio);
 	blk_rq_bio_prep(rq->q, rq, bio);
+	blk_queue_bounce(rq->q, &rq->bio);
+	/*
+	 * If the bio was bounced then the bounced bio would be freed
+	 * when its endio is called, so we must grab an extra reference
+	 * for the unamp code.
+	 */
+	bio_get(rq->bio);
 	rq->buffer = rq->data = NULL;
 	return 0;
 }
diff --git a/fs/bio.c b/fs/bio.c
index df90896..05ffe68 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -727,25 +727,19 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct bio_set *bs,
 			     struct sg_iovec *iov, int iov_count,
 			     int write_to_vm, gfp_t gfp_mask)
 {
-	struct bio *bio;
-
-	bio = __bio_map_user_iov(q, bs, iov, iov_count, write_to_vm, gfp_mask);
-
-	if (IS_ERR(bio))
-		return bio;
-
-	/*
-	 * subtle -- if __bio_map_user() ended up bouncing a bio,
-	 * it would normally disappear when its bi_end_io is run.
-	 * however, we need it for the unmap, so grab an extra
-	 * reference to it
-	 */
-	bio_get(bio);
-
-	return bio;
+	return __bio_map_user_iov(q, bs, iov, iov_count, write_to_vm, gfp_mask);
 }
 
-static void __bio_unmap_user(struct bio *bio)
+/**
+ *	bio_unmap_user	-	unmap a bio
+ *	@bio:		the bio being unmapped
+ *
+ *	Unmap a bio previously mapped by bio_map_user(). Must be called with
+ *	a process context.
+ *
+ *	bio_unmap_user() may sleep.
+ */
+void bio_unmap_user(struct bio *bio)
 {
 	struct bio_vec *bvec;
 	int i;
@@ -763,21 +757,6 @@ static void __bio_unmap_user(struct bio *bio)
 	bio_put(bio);
 }
 
-/**
- *	bio_unmap_user	-	unmap a bio
- *	@bio:		the bio being unmapped
- *
- *	Unmap a bio previously mapped by bio_map_user(). Must be called with
- *	a process context.
- *
- *	bio_unmap_user() may sleep.
- */
-void bio_unmap_user(struct bio *bio)
-{
-	__bio_unmap_user(bio);
-	bio_put(bio);
-}
-
 static void bio_map_kern_endio(struct bio *bio, int err)
 {
 	bio_put(bio);
-- 
1.5.1.2




More information about the dm-devel mailing list