[dm-devel] [PATCH 7/7] dm: add the pushback feature to the multipath target
Kiyoshi Ueda
k-ueda at ct.jp.nec.com
Tue Oct 10 21:32:38 UTC 2006
This patch implements the feature which the multipath target returns
the pushback request if needed.
The pushback request can be accepted by the dm core only when:
1). The suspend is being issued with 'DMF_NOFLUSH_SUSPENDING' flag.
(Otherwise, the bio is returned to applications with EIO.)
>From the practical multipath usage, the pushback request should be
needed only when:
2). No valid paths.
3). queue_if_no_path is specified.
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 original queue_if_no_path value to
saved_queue_if_no_path.
So multipath target must check the conditions above to request pushback.
The check for 2) already exists in both of map_io() and do_end_io().
So this patch adds the '__PUSHBACK()' macro to check 1) and 3), and
use it after the check for 2).
Test results:
See the test results of the patch 6.
The patch is for:
2.6.18-mm2 + patch 1-6
Signed-off-by: Kiyoshi Ueda <k-ueda at ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura at ce.jp.nec.com>
diff -rupN 6-core-pushback/drivers/md/dm-mpath.c 7-mpath-pushback/drivers/md/dm-mpath.c
--- 6-core-pushback/drivers/md/dm-mpath.c 2006-10-06 13:42:29.000000000 -0400
+++ 7-mpath-pushback/drivers/md/dm-mpath.c 2006-10-06 13:49:10.000000000 -0400
@@ -282,6 +282,23 @@ failed:
m->current_pg = NULL;
}
+/*
+ * Check if multipath target needs to push back bios to device-mapper core.
+ * This macro checks if:
+ * o The device is in the process of being suspended with 'noflush' flag,
+ * because the dm core accepts pushback request only in that case.
+ * (dm_noflush_suspending() returns true only in that case.)
+ * o queue_if_no_path had been set before the suspend process has begun.
+ * (In the suspend process, the presuspend hook will have run and
+ * moved the real queue_if_no_path state into saved_queue_if_no_path.
+ * So in that case, queue_if_no_path should be 0 and
+ * saved_queue_if_no_path should be 1.)
+ *
+ * (m)->lock must be held before using this macro.
+ */
+#define __PUSHBACK(m) (!(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,9 +328,12 @@ static int map_io(struct multipath *m, s
queue_work(kmultipathd, &m->process_queued_ios);
pgpath = NULL;
r = DM_MAPIO_SUBMITTED;
- } else if (!pgpath)
+ } else if (!pgpath) {
r = -EIO; /* Failed */
- else
+
+ if (__PUSHBACK(m))
+ r = DM_MAPIO_REQUEUE;
+ } else
bio->bi_bdev = pgpath->path.dev->bdev;
mpio->pgpath = pgpath;
@@ -374,6 +394,14 @@ static void dispatch_queued_ios(struct m
bio_endio(bio, bio->bi_size, r);
else if (r == DM_MAPIO_REMAPPED)
generic_make_request(bio);
+ else if (r == DM_MAPIO_REQUEUE)
+ /*
+ * end_io handles the requeue request by
+ * returning the bio with error status.
+ * We don't return the r value to end_io,
+ * since it is probably not needed.
+ */
+ bio_endio(bio, bio->bi_size, -EIO);
bio = next;
}
@@ -781,7 +809,7 @@ static int multipath_map(struct dm_targe
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;
@@ -1005,7 +1033,10 @@ static int do_end_io(struct multipath *m
spin_lock_irqsave(&m->lock, flags);
if (!m->nr_valid_paths) {
- if (!m->queue_if_no_path) {
+ if (__PUSHBACK(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 {
More information about the dm-devel
mailing list