multipath_endio(): the call to __resubmit_io() wasn't within the lock. Renamed __resubmit_io() -> __remap_io() Lifted the submit code into multipath_endio() after a successful remap. [Mike Christie] --- diff/drivers/md/dm-mpath.c 2003-12-29 10:17:21.000000000 +0000 +++ source/drivers/md/dm-mpath.c 2004-01-02 11:03:56.000000000 +0000 @@ -650,10 +650,9 @@ return NULL; } -static int __resubmit_io(struct multipath *m, struct bio *bio) +static int __remap_io(struct multipath *m, struct bio *bio) { int r; - unsigned long flags; r = __choose_path(m); if (r) @@ -661,21 +660,14 @@ /* 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; - m->failed_ios = bio; - spin_unlock_irqrestore(&m->failed_lock, flags); - - dm_daemon_wake(&_kmpathd); - return 1; /* io not complete */ + return 0; } static int multipath_end_io(struct dm_target *ti, struct bio *bio, int error, union map_info *map_context) { int r = 0; + unsigned long flags; struct multipath *m = (struct multipath *) ti->private; if (error) { @@ -684,9 +676,19 @@ spin_lock(&m->path_lock); path = __find_path(m, bio->bi_bdev); __fail_path(path); + r = __remap_io(m, bio); spin_unlock(&m->path_lock); - r = __resubmit_io(m, bio); + if (!r) { + /* queue for the daemon to resubmit */ + spin_lock_irqsave(&m->failed_lock, flags); + bio->bi_next = m->failed_ios; + m->failed_ios = bio; + spin_unlock_irqrestore(&m->failed_lock, flags); + + dm_daemon_wake(&_kmpathd); + r = 1; /* io not complete */ + } } return r;