[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>
This commit is contained in:
committed by
Linus Torvalds
parent
f0b0411536
commit
e4c8b3ba34
@@ -106,12 +106,42 @@ struct region {
|
|||||||
struct bio_list delayed_bios;
|
struct bio_list delayed_bios;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* Mirror set structures.
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
struct mirror {
|
||||||
|
atomic_t error_count;
|
||||||
|
struct dm_dev *dev;
|
||||||
|
sector_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mirror_set {
|
||||||
|
struct dm_target *ti;
|
||||||
|
struct list_head list;
|
||||||
|
struct region_hash rh;
|
||||||
|
struct kcopyd_client *kcopyd_client;
|
||||||
|
|
||||||
|
spinlock_t lock; /* protects the next two lists */
|
||||||
|
struct bio_list reads;
|
||||||
|
struct bio_list writes;
|
||||||
|
|
||||||
|
/* recovery */
|
||||||
|
region_t nr_regions;
|
||||||
|
int in_sync;
|
||||||
|
|
||||||
|
struct mirror *default_mirror; /* Default mirror */
|
||||||
|
|
||||||
|
unsigned int nr_mirrors;
|
||||||
|
struct mirror mirror[0];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Conversion fns
|
* Conversion fns
|
||||||
*/
|
*/
|
||||||
static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio)
|
static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio)
|
||||||
{
|
{
|
||||||
return bio->bi_sector >> rh->region_shift;
|
return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
|
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)
|
|||||||
wake();
|
wake();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
* Mirror set structures.
|
|
||||||
*---------------------------------------------------------------*/
|
|
||||||
struct mirror {
|
|
||||||
atomic_t error_count;
|
|
||||||
struct dm_dev *dev;
|
|
||||||
sector_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mirror_set {
|
|
||||||
struct dm_target *ti;
|
|
||||||
struct list_head list;
|
|
||||||
struct region_hash rh;
|
|
||||||
struct kcopyd_client *kcopyd_client;
|
|
||||||
|
|
||||||
spinlock_t lock; /* protects the next two lists */
|
|
||||||
struct bio_list reads;
|
|
||||||
struct bio_list writes;
|
|
||||||
|
|
||||||
/* recovery */
|
|
||||||
region_t nr_regions;
|
|
||||||
int in_sync;
|
|
||||||
|
|
||||||
struct mirror *default_mirror; /* Default mirror */
|
|
||||||
|
|
||||||
unsigned int nr_mirrors;
|
|
||||||
struct mirror mirror[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Every mirror should look like this one.
|
* Every mirror should look like this one.
|
||||||
*/
|
*/
|
||||||
@@ -1113,7 +1114,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
|
|||||||
struct mirror *m;
|
struct mirror *m;
|
||||||
struct mirror_set *ms = ti->private;
|
struct mirror_set *ms = ti->private;
|
||||||
|
|
||||||
map_context->ll = bio->bi_sector >> ms->rh.region_shift;
|
map_context->ll = bio_to_region(&ms->rh, bio);
|
||||||
|
|
||||||
if (rw == WRITE) {
|
if (rw == WRITE) {
|
||||||
queue_bio(ms, bio, rw);
|
queue_bio(ms, bio, rw);
|
||||||
|
Reference in New Issue
Block a user