dm mpath: delay the retry of a request if the target responded as busy
authorMike Snitzer <snitzer@redhat.com>
Sat, 13 Jan 2018 00:53:40 +0000 (19:53 -0500)
committerMike Snitzer <snitzer@redhat.com>
Mon, 29 Jan 2018 18:44:54 +0000 (13:44 -0500)
Add DM_ENDIO_DELAY_REQUEUE to allow request-based multipath's
multipath_end_io() to instruct dm-rq.c:dm_done() to delay a requeue.
This is beneficial to do if BLK_STS_RESOURCE is returned from the target
(because target is busy).

Relative to blk-mq: kick the hw queues via blk_mq_requeue_work(),
indirectly from dm-rq.c:__dm_mq_kick_requeue_list(), after a delay.

For old .request_fn: use blk_delay_queue().

bio-based multipath doesn't have feature parity with request-based for
retryable error requeues; that is something that'll need fixing in the
future.

Suggested-by: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Bart Van Assche <bart.vanassche@wdc.com>
[as interpreted from Bart's "... patch looks fine to me."]

drivers/md/dm-mpath.c
drivers/md/dm-rq.c
include/linux/device-mapper.h

index 815de2b091a554c9f73c428ff641bde52ac6f3ca..a8b1ffc0cb3de91c3e22477553f90279a69b59f4 100644 (file)
@@ -1585,7 +1585,10 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
        if (error && !noretry_error(error)) {
                struct multipath *m = ti->private;
 
-               r = DM_ENDIO_REQUEUE;
+               if (error == BLK_STS_RESOURCE)
+                       r = DM_ENDIO_DELAY_REQUEUE;
+               else
+                       r = DM_ENDIO_REQUEUE;
 
                if (pgpath)
                        fail_path(pgpath);
index 9d32f25489c27ad1fc743d387e19f8fa5a67cf25..b78ff6921cfb670f325819bd45cd211f4b49cd62 100644 (file)
@@ -315,6 +315,10 @@ static void dm_done(struct request *clone, blk_status_t error, bool mapped)
                /* The target wants to requeue the I/O */
                dm_requeue_original_request(tio, false);
                break;
+       case DM_ENDIO_DELAY_REQUEUE:
+               /* The target wants to requeue the I/O after a delay */
+               dm_requeue_original_request(tio, true);
+               break;
        default:
                DMWARN("unimplemented target endio return value: %d", r);
                BUG();
index 9ba84532947d769eee1a8669ca85c3c57ff1f530..da83f64952e7d07ebccded358bb363807d49b7b5 100644 (file)
@@ -550,6 +550,7 @@ do {                                                                        \
 #define DM_ENDIO_DONE          0
 #define DM_ENDIO_INCOMPLETE    1
 #define DM_ENDIO_REQUEUE       2
+#define DM_ENDIO_DELAY_REQUEUE 3
 
 /*
  * Definitions of return values from target map function.
@@ -557,7 +558,7 @@ do {                                                                        \
 #define DM_MAPIO_SUBMITTED     0
 #define DM_MAPIO_REMAPPED      1
 #define DM_MAPIO_REQUEUE       DM_ENDIO_REQUEUE
-#define DM_MAPIO_DELAY_REQUEUE 3
+#define DM_MAPIO_DELAY_REQUEUE DM_ENDIO_DELAY_REQUEUE
 #define DM_MAPIO_KILL          4
 
 #define dm_sector_div64(x, y)( \