After manually failing some paths and then reinstating them, the
following pattern of events has been observed:

[1535664.790944] localhost multipathd[26335]: mpathc: reinstate path 8:48 
(operator)
[1535664.791422] localhost multipathd[26335]: mpathc: devmap event #4
[1535664.793140] localhost kernel: device-mapper: multipath: 254:6: Reinstating 
path 8:48.
[1535665.219024] localhost multipathd[26335]: mpathc: reload [0 125829120 
multipath 1 queue_if_no_path 1 alua 2 1 queue-length 0 2 1 8:144 1 8:240 1 
queue-length 0 2 1 8:48 1 65:80 1]
[1535665.290268] localhost multipathd[26335]: sync_map_state: failing sdd state 
2 dmstate 2
[1535665.292442] localhost kernel: device-mapper: multipath: 254:6: Failing 
path 8:48.
[1535669.291320] localhost multipathd[26335]: sdd: tur state = up
[1535669.291531] localhost multipathd[26335]: mpathc: sdd - tur checker reports 
path is up
[1535669.291531] localhost multipathd[26335]: 8:48: reinstated

We see that sdd (8:48) is first reinstated, then failed again during
the reload operation, and finally reinstated in the checker.

This happens because multipathd doesn't update the internal path state when it
calls dm_reinstate_path(). If sync_map_state() is called, it will see the path
in PATH_DOWN state and fail the path again.

Fix it by setting pp->state to PATH_UNCHECKED.

Signed-off-by: Martin Wilck <mwi...@suse.com>
---
 multipathd/cli_handlers.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 4bcc82a..fcb8775 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1115,6 +1115,18 @@ cli_reinstate(void * v, struct strbuf *reply, void * 
data)
                pp->mpp->alias, pp->dev_t);
 
        checker_enable(&pp->checker);
+
+       /*
+        * A path previously failed by the operator will be in PATH_DOWN state
+        * (set by update_multipath()).
+        * After the path has been reinstated in the kernel, and before
+        * the checker updates the path state, we may need to reload
+        * the map (e.g. for failback, while handling a dm event).
+        * If the path is still in PATH_DOWN state at that time, 
sync_map_state()
+        * will call dm_fail_path() again.
+        * Avoid that by setting the state to PATH_UNCHECKED.
+        */
+       pp->state = PATH_UNCHECKED;
        pp->tick = 1;
        return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
 }
-- 
2.50.0


Reply via email to