From: Mike Christie <michaelc@xxxxxxxxxxx> 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@xxxxxxxxxxx> --- 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 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel