[PATCH 08/11] dm: mpath: use noflush suspending

From: Alasdair G Kergon
Date: Wed Nov 22 2006 - 14:04:41 EST


From: Kiyoshi Ueda <k-ueda@xxxxxxxxxxxxx>

This patch implements 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@xxxxxxxxxxxxx>
Signed-off-by: Jun'ichi Nomura <j-nomura@xxxxxxxxxxxxx>
Signed-off-by: Alasdair G Kergon <agk@xxxxxxxxxx>
Cc: dm-devel@xxxxxxxxxx

Index: linux-2.6.19-rc6/drivers/md/dm-mpath.c
===================================================================
--- linux-2.6.19-rc6.orig/drivers/md/dm-mpath.c 2006-11-22 17:26:58.000000000 +0000
+++ linux-2.6.19-rc6/drivers/md/dm-mpath.c 2006-11-22 17:27:00.000000000 +0000
@@ -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, s
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 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;
}
@@ -781,7 +802,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 +1026,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 (__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 {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/