Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4c8b3ba authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds
Browse files

[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: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f0b04115
Loading
Loading
Loading
Loading
+32 −31
Original line number Diff line number Diff line
@@ -106,12 +106,42 @@ struct region {
	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
 */
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)
@@ -539,35 +569,6 @@ static void rh_start_recovery(struct region_hash *rh)
	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.
 */
@@ -1113,7 +1114,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
	struct mirror *m;
	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) {
		queue_bio(ms, bio, rw);