diff options
Diffstat (limited to 'block/ll_rw_blk.c')
-rw-r--r-- | block/ll_rw_blk.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index a66ec30855d8..e07c079e07e6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
@@ -2405,6 +2405,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, | |||
2405 | unsigned long len) | 2405 | unsigned long len) |
2406 | { | 2406 | { |
2407 | unsigned long bytes_read = 0; | 2407 | unsigned long bytes_read = 0; |
2408 | struct bio *bio = NULL; | ||
2408 | int ret; | 2409 | int ret; |
2409 | 2410 | ||
2410 | if (len > (q->max_hw_sectors << 9)) | 2411 | if (len > (q->max_hw_sectors << 9)) |
@@ -2431,6 +2432,8 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, | |||
2431 | ret = __blk_rq_map_user(q, rq, ubuf, map_len); | 2432 | ret = __blk_rq_map_user(q, rq, ubuf, map_len); |
2432 | if (ret < 0) | 2433 | if (ret < 0) |
2433 | goto unmap_rq; | 2434 | goto unmap_rq; |
2435 | if (!bio) | ||
2436 | bio = rq->bio; | ||
2434 | bytes_read += ret; | 2437 | bytes_read += ret; |
2435 | ubuf += ret; | 2438 | ubuf += ret; |
2436 | } | 2439 | } |
@@ -2438,7 +2441,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, | |||
2438 | rq->buffer = rq->data = NULL; | 2441 | rq->buffer = rq->data = NULL; |
2439 | return 0; | 2442 | return 0; |
2440 | unmap_rq: | 2443 | unmap_rq: |
2441 | blk_rq_unmap_user(rq); | 2444 | blk_rq_unmap_user(bio); |
2442 | return ret; | 2445 | return ret; |
2443 | } | 2446 | } |
2444 | 2447 | ||
@@ -2495,29 +2498,30 @@ EXPORT_SYMBOL(blk_rq_map_user_iov); | |||
2495 | 2498 | ||
2496 | /** | 2499 | /** |
2497 | * blk_rq_unmap_user - unmap a request with user data | 2500 | * blk_rq_unmap_user - unmap a request with user data |
2498 | * @rq: rq to be unmapped | 2501 | * @bio: start of bio list |
2499 | * | 2502 | * |
2500 | * Description: | 2503 | * Description: |
2501 | * Unmap a rq previously mapped by blk_rq_map_user(). | 2504 | * Unmap a rq previously mapped by blk_rq_map_user(). The caller must |
2502 | * rq->bio must be set to the original head of the request. | 2505 | * supply the original rq->bio from the blk_rq_map_user() return, since |
2506 | * the io completion may have changed rq->bio. | ||
2503 | */ | 2507 | */ |
2504 | int blk_rq_unmap_user(struct request *rq) | 2508 | int blk_rq_unmap_user(struct bio *bio) |
2505 | { | 2509 | { |
2506 | struct bio *bio, *mapped_bio; | 2510 | struct bio *mapped_bio; |
2507 | int ret = 0, ret2; | 2511 | int ret = 0, ret2; |
2508 | 2512 | ||
2509 | while ((bio = rq->bio)) { | 2513 | while (bio) { |
2510 | if (bio_flagged(bio, BIO_BOUNCED)) | 2514 | mapped_bio = bio; |
2515 | if (unlikely(bio_flagged(bio, BIO_BOUNCED))) | ||
2511 | mapped_bio = bio->bi_private; | 2516 | mapped_bio = bio->bi_private; |
2512 | else | ||
2513 | mapped_bio = bio; | ||
2514 | 2517 | ||
2515 | ret2 = __blk_rq_unmap_user(mapped_bio); | 2518 | ret2 = __blk_rq_unmap_user(mapped_bio); |
2516 | if (ret2 && !ret) | 2519 | if (ret2 && !ret) |
2517 | ret = ret2; | 2520 | ret = ret2; |
2518 | 2521 | ||
2519 | rq->bio = bio->bi_next; | 2522 | mapped_bio = bio; |
2520 | bio_put(bio); | 2523 | bio = bio->bi_next; |
2524 | bio_put(mapped_bio); | ||
2521 | } | 2525 | } |
2522 | 2526 | ||
2523 | return ret; | 2527 | return ret; |