1 From: Hannes Reinecke <hare@suse.de>
2 Subject: Kernel oops in free_bio_clone()
7 static int setup_clone(struct request *clone, struct request *rq,
8 struct dm_rq_target_io *tio)
12 blk_rq_init(NULL, clone);
14 r = clone_request_bios(clone, rq, tio->md);
18 copy_request_info(clone, rq);
19 clone->start_time = jiffies;
20 clone->end_io = end_clone_request;
21 clone->end_io_data = tio;
26 clone_request_bios() might end up calling free_bio_clone(), which references:
28 static void free_bio_clone(struct request *clone)
30 struct dm_rq_target_io *tio = clone->end_io_data;
31 struct mapped_device *md = tio->md;
34 but end_io_data will be set only _after_ the call to clone_request_bios().
35 So we should be passing the 'md' argument directly here to avoid this
36 bug and several pointless derefencings.
38 Signed-off-by: Hannes Reinecke <hare@suse.de>
40 --- linux-2.6.27-SLE11_BRANCH/drivers/md/dm.c.orig 2009-02-04 10:33:22.656627650 +0100
41 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/dm.c 2009-02-05 11:03:35.843251773 +0100
42 @@ -709,10 +709,8 @@ static void end_clone_bio(struct bio *cl
43 blk_update_request(tio->orig, 0, nr_bytes);
46 -static void free_bio_clone(struct request *clone)
47 +static void free_bio_clone(struct request *clone, struct mapped_device *md)
49 - struct dm_rq_target_io *tio = clone->end_io_data;
50 - struct mapped_device *md = tio->md;
53 while ((bio = clone->bio) != NULL) {
54 @@ -743,7 +741,7 @@ static void dm_unprep_request(struct req
56 rq->cmd_flags &= ~REQ_DONTPREP;
58 - free_bio_clone(clone);
59 + free_bio_clone(clone, tio->md);
61 free_rq_tio(tio->md, tio);
63 @@ -820,7 +818,7 @@ static void dm_end_request(struct reques
64 rq->sense_len = clone->sense_len;
67 - free_bio_clone(clone);
68 + free_bio_clone(clone, tio->md);
70 free_rq_tio(tio->md, tio);
72 @@ -1406,7 +1404,7 @@ static int clone_request_bios(struct req
76 - free_bio_clone(clone);
77 + free_bio_clone(clone, md);