]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/dm-use-md-for-free_bio_clone
Move xen patchset to new version's subdir.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / dm-use-md-for-free_bio_clone
CommitLineData
00e5a55c
BS
1From: Hannes Reinecke <hare@suse.de>
2Subject: Kernel oops in free_bio_clone()
3References: bnc#472360
4
5Bug is here:
6
7static int setup_clone(struct request *clone, struct request *rq,
8 struct dm_rq_target_io *tio)
9{
10 int r;
11
12 blk_rq_init(NULL, clone);
13
14 r = clone_request_bios(clone, rq, tio->md);
15 if (r)
16 return r;
17
18 copy_request_info(clone, rq);
19 clone->start_time = jiffies;
20 clone->end_io = end_clone_request;
21 clone->end_io_data = tio;
22
23 return 0;
24}
25
26clone_request_bios() might end up calling free_bio_clone(), which references:
27
28static void free_bio_clone(struct request *clone)
29{
30 struct dm_rq_target_io *tio = clone->end_io_data;
31 struct mapped_device *md = tio->md;
32...
33
34but end_io_data will be set only _after_ the call to clone_request_bios().
35So we should be passing the 'md' argument directly here to avoid this
36bug and several pointless derefencings.
37
38Signed-off-by: Hannes Reinecke <hare@suse.de>
39
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);
44 }
45
46-static void free_bio_clone(struct request *clone)
47+static void free_bio_clone(struct request *clone, struct mapped_device *md)
48 {
49- struct dm_rq_target_io *tio = clone->end_io_data;
50- struct mapped_device *md = tio->md;
51 struct bio *bio;
52
53 while ((bio = clone->bio) != NULL) {
54@@ -743,7 +741,7 @@ static void dm_unprep_request(struct req
55 rq->special = NULL;
56 rq->cmd_flags &= ~REQ_DONTPREP;
57
58- free_bio_clone(clone);
59+ free_bio_clone(clone, tio->md);
60 dec_rq_pending(tio);
61 free_rq_tio(tio->md, tio);
62 }
63@@ -820,7 +818,7 @@ static void dm_end_request(struct reques
64 rq->sense_len = clone->sense_len;
65 }
66
67- free_bio_clone(clone);
68+ free_bio_clone(clone, tio->md);
69 dec_rq_pending(tio);
70 free_rq_tio(tio->md, tio);
71
72@@ -1406,7 +1404,7 @@ static int clone_request_bios(struct req
73 return 0;
74
75 free_and_out:
76- free_bio_clone(clone);
77+ free_bio_clone(clone, md);
78
79 return -ENOMEM;
80 }