Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Kiyoshi Ueda and committed by
Linus Torvalds
45e15720 2e93ccc1

+29 -5
+29 -5
drivers/md/dm-mpath.c
··· 282 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 302 static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, 286 303 unsigned was_queued) 287 304 { ··· 328 311 queue_work(kmultipathd, &m->process_queued_ios); 329 312 pgpath = NULL; 330 313 r = DM_MAPIO_SUBMITTED; 331 - } else if (!pgpath) 332 - r = -EIO; /* Failed */ 333 - else 314 + } else if (pgpath) 334 315 bio->bi_bdev = pgpath->path.dev->bdev; 316 + else if (__must_push_back(m)) 317 + r = DM_MAPIO_REQUEUE; 318 + else 319 + r = -EIO; /* Failed */ 335 320 336 321 mpio->pgpath = pgpath; 337 322 ··· 393 374 bio_endio(bio, bio->bi_size, r); 394 375 else if (r == DM_MAPIO_REMAPPED) 395 376 generic_make_request(bio); 377 + else if (r == DM_MAPIO_REQUEUE) 378 + bio_endio(bio, bio->bi_size, -EIO); 396 379 397 380 bio = next; 398 381 } ··· 804 783 map_context->ptr = mpio; 805 784 bio->bi_rw |= (1 << BIO_RW_FAILFAST); 806 785 r = map_io(m, bio, mpio, 0); 807 - if (r < 0) 786 + if (r < 0 || r == DM_MAPIO_REQUEUE) 808 787 mempool_free(mpio, m->mpio_pool); 809 788 810 789 return r; ··· 1028 1007 1029 1008 spin_lock_irqsave(&m->lock, flags); 1030 1009 if (!m->nr_valid_paths) { 1031 - if (!m->queue_if_no_path) { 1010 + if (__must_push_back(m)) { 1011 + spin_unlock_irqrestore(&m->lock, flags); 1012 + return DM_ENDIO_REQUEUE; 1013 + } else if (!m->queue_if_no_path) { 1032 1014 spin_unlock_irqrestore(&m->lock, flags); 1033 1015 return -EIO; 1034 1016 } else {