--- diff/drivers/md/dm-mpath.c	2004-02-18 15:51:06.000000000 +0000
+++ source/drivers/md/dm-mpath.c	2004-02-23 09:45:05.000000000 +0000
@@ -219,7 +219,7 @@ static struct path *get_current_path(str
 	return path;
 }
 
-static int map_io(struct multipath *m, struct bio *bio)
+static int map_io(struct multipath *m, struct bio *bio, union map_info *map_context)
 {
 	struct path *path;
 
@@ -228,6 +228,7 @@ static int map_io(struct multipath *m, s
 		return -EIO;
 
 	bio->bi_bdev = path->dev->bdev;
+	map_context->ptr = path;
 	return 0;
 }
 
@@ -570,8 +571,8 @@ static void fail_path(struct path *path)
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
 			    int error, union map_info *map_context)
 {
-	struct path *path;
 	struct multipath *m = (struct multipath *) ti->private;
+	struct path *path = (struct path *) map_context->ptr;
 
 	if (error) {
 		spin_lock(&m->lock);
@@ -581,7 +582,6 @@ static int multipath_end_io(struct dm_ta
 		}
 		spin_unlock(&m->lock);
 
-		path = find_path(m, bio->bi_bdev);
 		fail_path(path);
 
 		/* queue for the daemon to resubmit */
--- diff/drivers/md/dm.c	2004-02-18 16:07:19.000000000 +0000
+++ source/drivers/md/dm.c	2004-02-20 14:46:35.000000000 +0000
@@ -271,6 +271,43 @@ static inline void dec_pending(struct dm
 	}
 }
 
+static void restore_bio(struct target_io *tio, struct bio *bio)
+{
+	unsigned idx;
+	unsigned size, offset, len;
+	struct orig_bio = tio->io->bio;
+	struct bio_vec *bvec, *o_bvec;
+
+	bio->bi_sector = tio->bi_sector;
+	bio->bi_bdev = tio->bi_bdev;
+	bio->bi_size = tio->bi_size;
+	bio->bi_idx = tio->bi_idx;
+
+	/* skip bvecs preceeding this bio */
+	bvec = bio->bi_io_vec;
+	o_bvec = orig_bio->bi_io_vec;
+
+	offset = to_bytes(tio->bi_sector - orig_bio->bi_sector);
+	for (idx = 0, size = 0; idx < orig_bio->bi_vcnt; idx++) {
+		len = o_bvec[idx].bv_len;
+		if (size + len > offset)
+			break;
+
+		size += len;
+	}
+
+	/* adjust the offset of the first bvec in the clone */
+	delta = offset - size;
+	bvec[idx].bv_len = o_bvec[idx].bv_len - delta;
+	bvec[idx].bv_offset = o_bvec[bvec].bv_size + delta;
+
+	/* correct the rest of the clones */
+	size = delta;
+	while (++idx < bio->bi_vcnt) {
+		
+	}
+}
+
 static int clone_endio(struct bio *bio, unsigned int done, int error)
 {
 	int r = 0;
@@ -282,11 +319,13 @@ static int clone_endio(struct bio *bio, 
 		return 1;
 
 	if (endio) {
-		/* Restore bio fields. */
-		bio->bi_sector = tio->bi_sector;
-		bio->bi_bdev = tio->bi_bdev;
-		bio->bi_size = tio->bi_size;
-		bio->bi_idx = tio->bi_idx;
+		/*
+		 * The endio fn is only allowed to retry if there
+		 * was an error, so we only restore these fields
+		 * on the slow path.
+		 */
+		if (error)
+			restore_bio(tio, bio);
 
 		r = endio(tio->ti, bio, error, &tio->info);
 		if (r < 0)
@@ -344,11 +383,13 @@ static void __map_bio(struct dm_target *
 	atomic_inc(&tio->io->io_count);
 	r = ti->type->map(ti, clone, &tio->info);
 	if (r > 0) {
-		/* Save the bio info so we can restore it during endio. */
-		tio->bi_sector = clone->bi_sector;
-		tio->bi_bdev = clone->bi_bdev;
-		tio->bi_size = clone->bi_size;
-		tio->bi_idx = clone->bi_idx;
+		if (ti->type->endio) {
+			/* Save the bio info so we can restore it during endio. */
+			tio->bi_sector = clone->bi_sector;
+			tio->bi_bdev = clone->bi_bdev;
+			tio->bi_size = clone->bi_size;
+			tio->bi_idx = clone->bi_idx;
+		}
 
 		/* the bio has been remapped so dispatch it */
 		generic_make_request(clone);