diff options
author | Neil Brown <neilb@suse.de> | 2006-06-26 03:27:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:35 -0400 |
commit | e4c8b3ba34cc1aeab451c7a5cc843c5fd62cbe3d (patch) | |
tree | 2b211393b1ffacd05a7fbae994012b7000e2c233 /drivers/md/dm-raid1.c | |
parent | f0b04115368ff383654a3bd26baf8f4be5e81132 (diff) |
[PATCH] dm: mirror sector offset fix
The device-mapper core does not perform any remapping of bios before passing
them to the targets. If a particular mapping begins part-way into a device,
targets obtain the sector relative to the start of the mapping by subtracting
ti->begin.
The dm-raid1 target didn't do this everywhere: this patch fixes it, taking
care to subtract ti->begin exactly once for each bio.
[akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled]
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 4ad269e66525..346f3a59e776 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -106,12 +106,42 @@ struct region { | |||
106 | struct bio_list delayed_bios; | 106 | struct bio_list delayed_bios; |
107 | }; | 107 | }; |
108 | 108 | ||
109 | |||
110 | /*----------------------------------------------------------------- | ||
111 | * Mirror set structures. | ||
112 | *---------------------------------------------------------------*/ | ||
113 | struct mirror { | ||
114 | atomic_t error_count; | ||
115 | struct dm_dev *dev; | ||
116 | sector_t offset; | ||
117 | }; | ||
118 | |||
119 | struct mirror_set { | ||
120 | struct dm_target *ti; | ||
121 | struct list_head list; | ||
122 | struct region_hash rh; | ||
123 | struct kcopyd_client *kcopyd_client; | ||
124 | |||
125 | spinlock_t lock; /* protects the next two lists */ | ||
126 | struct bio_list reads; | ||
127 | struct bio_list writes; | ||
128 | |||
129 | /* recovery */ | ||
130 | region_t nr_regions; | ||
131 | int in_sync; | ||
132 | |||
133 | struct mirror *default_mirror; /* Default mirror */ | ||
134 | |||
135 | unsigned int nr_mirrors; | ||
136 | struct mirror mirror[0]; | ||
137 | }; | ||
138 | |||
109 | /* | 139 | /* |
110 | * Conversion fns | 140 | * Conversion fns |
111 | */ | 141 | */ |
112 | static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) | 142 | static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) |
113 | { | 143 | { |
114 | return bio->bi_sector >> rh->region_shift; | 144 | return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift; |
115 | } | 145 | } |
116 | 146 | ||
117 | static inline sector_t region_to_sector(struct region_hash *rh, region_t region) | 147 | static inline sector_t region_to_sector(struct region_hash *rh, region_t region) |
@@ -539,35 +569,6 @@ static void rh_start_recovery(struct region_hash *rh) | |||
539 | wake(); | 569 | wake(); |
540 | } | 570 | } |
541 | 571 | ||
542 | /*----------------------------------------------------------------- | ||
543 | * Mirror set structures. | ||
544 | *---------------------------------------------------------------*/ | ||
545 | struct mirror { | ||
546 | atomic_t error_count; | ||
547 | struct dm_dev *dev; | ||
548 | sector_t offset; | ||
549 | }; | ||
550 | |||
551 | struct mirror_set { | ||
552 | struct dm_target *ti; | ||
553 | struct list_head list; | ||
554 | struct region_hash rh; | ||
555 | struct kcopyd_client *kcopyd_client; | ||
556 | |||
557 | spinlock_t lock; /* protects the next two lists */ | ||
558 | struct bio_list reads; | ||
559 | struct bio_list writes; | ||
560 | |||
561 | /* recovery */ | ||
562 | region_t nr_regions; | ||
563 | int in_sync; | ||
564 | |||
565 | struct mirror *default_mirror; /* Default mirror */ | ||
566 | |||
567 | unsigned int nr_mirrors; | ||
568 | struct mirror mirror[0]; | ||
569 | }; | ||
570 | |||
571 | /* | 572 | /* |
572 | * Every mirror should look like this one. | 573 | * Every mirror should look like this one. |
573 | */ | 574 | */ |
@@ -1113,7 +1114,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, | |||
1113 | struct mirror *m; | 1114 | struct mirror *m; |
1114 | struct mirror_set *ms = ti->private; | 1115 | struct mirror_set *ms = ti->private; |
1115 | 1116 | ||
1116 | map_context->ll = bio->bi_sector >> ms->rh.region_shift; | 1117 | map_context->ll = bio_to_region(&ms->rh, bio); |
1117 | 1118 | ||
1118 | if (rw == WRITE) { | 1119 | if (rw == WRITE) { |
1119 | queue_bio(ms, bio, rw); | 1120 | queue_bio(ms, bio, rw); |