aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-06-26 03:27:26 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:35 -0400
commite4c8b3ba34cc1aeab451c7a5cc843c5fd62cbe3d (patch)
tree2b211393b1ffacd05a7fbae994012b7000e2c233
parentf0b04115368ff383654a3bd26baf8f4be5e81132 (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>
-rw-r--r--drivers/md/dm-raid1.c63
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 *---------------------------------------------------------------*/
113struct mirror {
114 atomic_t error_count;
115 struct dm_dev *dev;
116 sector_t offset;
117};
118
119struct 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 */
112static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) 142static 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
117static inline sector_t region_to_sector(struct region_hash *rh, region_t region) 147static 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 *---------------------------------------------------------------*/
545struct mirror {
546 atomic_t error_count;
547 struct dm_dev *dev;
548 sector_t offset;
549};
550
551struct 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);