The attached patch should fix the race that could occur when an io is
resubmitted and other io is being mapped at the same time. It should
replace the patch here
http://lists.sistina.com/pipermail/dm-devel/2003-December/000354.html
because the current_path access needs to be performed under the
path_lock too.
mike
Mike Christie
mikenc@xxxxxxxxxx
--- linux-2.6.0-test10-udm3.orig/drivers/md/dm-mpath.c 2003-12-26 21:12:44.936116516 -0800
+++ linux-2.6.0-test10-udm3/drivers/md/dm-mpath.c 2003-12-26 21:37:56.127234374 -0800
@@ -650,18 +650,10 @@ static struct path *__find_path(struct m
return NULL;
}
-static int __resubmit_io(struct multipath *m, struct bio *bio)
+static void __resubmit_io(struct multipath *m, struct bio *bio)
{
- int r;
unsigned long flags;
- r = __choose_path(m);
- if (r)
- return r;
-
- /* remap */
- bio->bi_bdev = m->current_path->dev->bdev;
-
/* queue for the daemon to resubmit */
spin_lock_irqsave(&m->failed_lock, flags);
bio->bi_next = m->failed_ios;
@@ -669,27 +661,32 @@ static int __resubmit_io(struct multipat
spin_unlock_irqrestore(&m->failed_lock, flags);
dm_daemon_wake(&_kmpathd);
- return 1; /* io not complete */
}
static int multipath_end_io(struct dm_target *ti, struct bio *bio,
int error, union map_info *map_context)
{
- int r = 0;
+ struct path *path;
struct multipath *m = (struct multipath *) ti->private;
- if (error) {
- struct path *path;
+ if (!error)
+ return 0;
- spin_lock(&m->path_lock);
- path = __find_path(m, bio->bi_bdev);
- __fail_path(path);
+ spin_lock(&m->path_lock);
+ path = __find_path(m, bio->bi_bdev);
+ __fail_path(path);
+ if (__choose_path(m)) {
spin_unlock(&m->path_lock);
-
- r = __resubmit_io(m, bio);
+ return -EIO;
}
- return r;
+ /* remap */
+ bio->bi_bdev = m->current_path->dev->bdev;
+ spin_unlock(&m->path_lock);
+
+ __resubmit_io(m, bio);
+ /* io not complete */
+ return 1;
}
static void lock_path(struct path *p) {down(&p->test_lock);}