]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: block: hold extra reference to bio in blk_rq_map_user_iov() |
2 | From: Jens Axboe <jens.axboe@oracle.com> | |
3 | Date: Tue Nov 18 15:08:56 2008 +0100: | |
4 | Git: c26156b2534c75bb3cdedf76f6ad1340971cf5bd | |
5 | ||
6 | If the size passed in is OK but we end up mapping too many segments, | |
7 | we call the unmap path directly like from IO completion. But from IO | |
8 | completion we have an extra reference to the bio, so this error case | |
9 | goes OOPS when it attempts to free and already free bio. | |
10 | ||
11 | Fix it by getting an extra reference to the bio before calling the | |
12 | unmap failure case. | |
13 | ||
14 | Reported-by: Petr Vandrovec <vandrove@vc.cvut.cz> | |
15 | ||
16 | Signed-off-by: Jens Axboe <jens.axboe@oracle.com> | |
17 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
18 | ||
19 | --- | |
20 | block/blk-map.c | 6 ++++++ | |
21 | 1 file changed, 6 insertions(+) | |
22 | ||
23 | --- a/block/blk-map.c | |
24 | +++ b/block/blk-map.c | |
25 | @@ -202,6 +202,12 @@ int blk_rq_map_user_iov(struct request_q | |
26 | return PTR_ERR(bio); | |
27 | ||
28 | if (bio->bi_size != len) { | |
29 | + /* | |
30 | + * Grab an extra reference to this bio, as bio_unmap_user() | |
31 | + * expects to be able to drop it twice as it happens on the | |
32 | + * normal IO completion path | |
33 | + */ | |
34 | + bio_get(bio); | |
35 | bio_endio(bio, 0); | |
36 | bio_unmap_user(bio); | |
37 | return -EINVAL; |