diff options
| author | Kiyoshi Ueda <k-ueda@ct.jp.nec.com> | 2006-12-08 05:41:10 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:29:09 -0500 |
| commit | 45e157206c732613d1c07e8ceeb1a3e497fb2abf (patch) | |
| tree | 327d36f8aea80f3a7fed4bb43232155dd4835145 | |
| parent | 2e93ccc1933d08d32d9bde3784c3823e67b9b030 (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.c | 34 |
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: | |||
| 282 | m->current_pg = NULL; | 282 | m->current_pg = NULL; |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | /* | ||
| 286 | * Check whether bios must be queued in the device-mapper core rather | ||
| 287 | * than here in the target. | ||
| 288 | * | ||
| 289 | * m->lock must be held on entry. | ||
| 290 | * | ||
| 291 | * If m->queue_if_no_path and m->saved_queue_if_no_path hold the | ||
| 292 | * same value then we are not between multipath_presuspend() | ||
| 293 | * and multipath_resume() calls and we have no need to check | ||
| 294 | * for the DMF_NOFLUSH_SUSPENDING flag. | ||
| 295 | */ | ||
| 296 | static int __must_push_back(struct multipath *m) | ||
| 297 | { | ||
| 298 | return (m->queue_if_no_path != m->saved_queue_if_no_path && | ||
| 299 | dm_noflush_suspending(m->ti)); | ||
| 300 | } | ||
| 301 | |||
| 285 | static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, | 302 | static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, |
| 286 | unsigned was_queued) | 303 | unsigned was_queued) |
| 287 | { | 304 | { |
| @@ -311,10 +328,12 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, | |||
| 311 | queue_work(kmultipathd, &m->process_queued_ios); | 328 | queue_work(kmultipathd, &m->process_queued_ios); |
| 312 | pgpath = NULL; | 329 | pgpath = NULL; |
| 313 | r = DM_MAPIO_SUBMITTED; | 330 | r = DM_MAPIO_SUBMITTED; |
| 314 | } else if (!pgpath) | 331 | } else if (pgpath) |
| 315 | r = -EIO; /* Failed */ | ||
| 316 | else | ||
| 317 | bio->bi_bdev = pgpath->path.dev->bdev; | 332 | bio->bi_bdev = pgpath->path.dev->bdev; |
| 333 | else if (__must_push_back(m)) | ||
| 334 | r = DM_MAPIO_REQUEUE; | ||
| 335 | else | ||
| 336 | r = -EIO; /* Failed */ | ||
| 318 | 337 | ||
| 319 | mpio->pgpath = pgpath; | 338 | mpio->pgpath = pgpath; |
| 320 | 339 | ||
| @@ -374,6 +393,8 @@ static void dispatch_queued_ios(struct multipath *m) | |||
| 374 | bio_endio(bio, bio->bi_size, r); | 393 | bio_endio(bio, bio->bi_size, r); |
| 375 | else if (r == DM_MAPIO_REMAPPED) | 394 | else if (r == DM_MAPIO_REMAPPED) |
| 376 | generic_make_request(bio); | 395 | generic_make_request(bio); |
| 396 | else if (r == DM_MAPIO_REQUEUE) | ||
| 397 | bio_endio(bio, bio->bi_size, -EIO); | ||
| 377 | 398 | ||
| 378 | bio = next; | 399 | bio = next; |
| 379 | } | 400 | } |
| @@ -783,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio, | |||
| 783 | map_context->ptr = mpio; | 804 | map_context->ptr = mpio; |
| 784 | bio->bi_rw |= (1 << BIO_RW_FAILFAST); | 805 | bio->bi_rw |= (1 << BIO_RW_FAILFAST); |
| 785 | r = map_io(m, bio, mpio, 0); | 806 | r = map_io(m, bio, mpio, 0); |
| 786 | if (r < 0) | 807 | if (r < 0 || r == DM_MAPIO_REQUEUE) |
| 787 | mempool_free(mpio, m->mpio_pool); | 808 | mempool_free(mpio, m->mpio_pool); |
| 788 | 809 | ||
| 789 | return r; | 810 | return r; |
| @@ -1007,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio, | |||
| 1007 | 1028 | ||
| 1008 | spin_lock_irqsave(&m->lock, flags); | 1029 | spin_lock_irqsave(&m->lock, flags); |
| 1009 | if (!m->nr_valid_paths) { | 1030 | if (!m->nr_valid_paths) { |
| 1010 | if (!m->queue_if_no_path) { | 1031 | if (__must_push_back(m)) { |
| 1032 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1033 | return DM_ENDIO_REQUEUE; | ||
| 1034 | } else if (!m->queue_if_no_path) { | ||
| 1011 | spin_unlock_irqrestore(&m->lock, flags); | 1035 | spin_unlock_irqrestore(&m->lock, flags); |
| 1012 | return -EIO; | 1036 | return -EIO; |
| 1013 | } else { | 1037 | } else { |
