aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2015-07-15 07:23:24 -0400
committerMike Snitzer <snitzer@redhat.com>2016-09-29 10:57:07 -0400
commit8ff232c1a819c2e98d85974a3bff0b7b8e2970ed (patch)
treedb6ad1ed59eb2910d8b4b1050bf5fce0630882d7
parent7cd326747f46ffe1c7bff5682e97dfbcb98990ec (diff)
dm mpath: always return reservation conflict without failing over
If dm-mpath encounters an reservation conflict it should not fail the path (as communication with the target is not affected) but should rather retry on another path. However, in doing so we might be inducing a ping-pong between paths, with no guarantee of any forward progress. And arguably a reservation conflict is an unexpected error, so we should be passing it upwards to allow the application to take appropriate steps. This change resolves a show-stopper problem seen with the pNFS SCSI layout because it is trivial to hit reservation conflict based failover loops without it. Doubts were raised about the implications of this change relative to products like IBM's SVC. But there is little point withholding a fix for Linux because a proprietary product may or may not have some issues in its implementation of how it interfaces with Linux. In the future, if there is glaring evidence that this change is certainly problematic we can revisit it. Signed-off-by: Hannes Reinecke <hare@suse.de> Acked-by: Christoph Hellwig <hch@lst.de> Tested-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Mike Snitzer <snitzer@redhat.com> # tweaked header
-rw-r--r--drivers/md/dm-mpath.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index f31fa1364abc..e477af8596e2 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1530,6 +1530,14 @@ static void activate_path(struct work_struct *work)
1530static int noretry_error(int error) 1530static int noretry_error(int error)
1531{ 1531{
1532 switch (error) { 1532 switch (error) {
1533 case -EBADE:
1534 /*
1535 * EBADE signals an reservation conflict.
1536 * We shouldn't fail the path here as we can communicate with
1537 * the target. We should failover to the next path, but in
1538 * doing so we might be causing a ping-pong between paths.
1539 * So just return the reservation conflict error.
1540 */
1533 case -EOPNOTSUPP: 1541 case -EOPNOTSUPP:
1534 case -EREMOTEIO: 1542 case -EREMOTEIO:
1535 case -EILSEQ: 1543 case -EILSEQ:
@@ -1574,9 +1582,6 @@ static int do_end_io(struct multipath *m, struct request *clone,
1574 if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { 1582 if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
1575 if (!must_push_back_rq(m)) 1583 if (!must_push_back_rq(m))
1576 r = -EIO; 1584 r = -EIO;
1577 } else {
1578 if (error == -EBADE)
1579 r = error;
1580 } 1585 }
1581 } 1586 }
1582 1587
@@ -1625,9 +1630,6 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
1625 if (!must_push_back_bio(m)) 1630 if (!must_push_back_bio(m))
1626 return -EIO; 1631 return -EIO;
1627 return DM_ENDIO_REQUEUE; 1632 return DM_ENDIO_REQUEUE;
1628 } else {
1629 if (error == -EBADE)
1630 return error;
1631 } 1633 }
1632 } 1634 }
1633 1635