diff options
Diffstat (limited to 'drivers/md')
-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 { |