summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKiyoshi Ueda <k-ueda@ct.jp.nec.com>2006-12-08 02:41:10 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 08:29:09 -0800
commit45e157206c732613d1c07e8ceeb1a3e497fb2abf (patch)
tree327d36f8aea80f3a7fed4bb43232155dd4835145
parent2e93ccc1933d08d32d9bde3784c3823e67b9b030 (diff)
[PATCH] dm: mpath: use noflush suspending
Implement the pushback feature for the multipath target. The pushback request is used when: 1) there are no valid paths; 2) queue_if_no_path was set; 3) a suspend is being issued with the DMF_NOFLUSH_SUSPENDING flag. Otherwise bios are returned to applications with -EIO. To check whether queue_if_no_path is specified or not, you need to check both queue_if_no_path and saved_queue_if_no_path, because presuspend saves the original queue_if_no_path value to saved_queue_if_no_path. The check for 1 already exists in both map_io() and do_end_io(). So this patch adds __must_push_back() to check 2 and 3. Test results: See the test results in the preceding patch. Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Cc: dm-devel@redhat.com Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/dm-mpath.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index d325edcbb3f5..3aa013506967 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -282,6 +282,23 @@ failed:
m->current_pg = NULL;
}
+/*
+ * Check whether bios must be queued in the device-mapper core rather
+ * than here in the target.
+ *
+ * m->lock must be held on entry.
+ *
+ * If m->queue_if_no_path and m->saved_queue_if_no_path hold the
+ * same value then we are not between multipath_presuspend()
+ * and multipath_resume() calls and we have no need to check
+ * for the DMF_NOFLUSH_SUSPENDING flag.
+ */
+static int __must_push_back(struct multipath *m)
+{
+ return (m->queue_if_no_path != m->saved_queue_if_no_path &&
+ dm_noflush_suspending(m->ti));
+}
+
static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
unsigned was_queued)
{
@@ -311,10 +328,12 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
queue_work(kmultipathd, &m->process_queued_ios);
pgpath = NULL;
r = DM_MAPIO_SUBMITTED;
- } else if (!pgpath)
- r = -EIO; /* Failed */
- else
+ } else if (pgpath)
bio->bi_bdev = pgpath->path.dev->bdev;
+ else if (__must_push_back(m))
+ r = DM_MAPIO_REQUEUE;
+ else
+ r = -EIO; /* Failed */
mpio->pgpath = pgpath;
@@ -374,6 +393,8 @@ static void dispatch_queued_ios(struct multipath *m)
bio_endio(bio, bio->bi_size, r);
else if (r == DM_MAPIO_REMAPPED)
generic_make_request(bio);
+ else if (r == DM_MAPIO_REQUEUE)
+ bio_endio(bio, bio->bi_size, -EIO);
bio = next;
}
@@ -783,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
map_context->ptr = mpio;
bio->bi_rw |= (1 << BIO_RW_FAILFAST);
r = map_io(m, bio, mpio, 0);
- if (r < 0)
+ if (r < 0 || r == DM_MAPIO_REQUEUE)
mempool_free(mpio, m->mpio_pool);
return r;
@@ -1007,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio,
spin_lock_irqsave(&m->lock, flags);
if (!m->nr_valid_paths) {
- if (!m->queue_if_no_path) {
+ if (__must_push_back(m)) {
+ spin_unlock_irqrestore(&m->lock, flags);
+ return DM_ENDIO_REQUEUE;
+ } else if (!m->queue_if_no_path) {
spin_unlock_irqrestore(&m->lock, flags);
return -EIO;
} else {