drbd: Do not BUG() when connection breaks in a special way
authorPhilipp Reisner <philipp.reisner@linbit.com>
Mon, 28 Apr 2014 16:43:20 +0000 (18:43 +0200)
committerJens Axboe <axboe@fb.com>
Wed, 30 Apr 2014 19:46:54 +0000 (13:46 -0600)
When a 'cluster wide' disconnect executes, the result comes back
from the peer, and immediately after that the connection breaks
then _conn_rq_cond() reported back SS_CW_SUCCESS.
Therefore _conn_request_state() calls conn_set_state(), which
has a BUG() in it.
The BUG() is hit because conn_is_valid_transition() does not like
the transaction. Which goes back to is_valid_soft_transition()
returning SS_OUTDATE_WO_CONN.

This fix is to consider an error reported by is_valid_soft_transition()
even when the peer agreed to the transaction.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/drbd/drbd_state.c

index 3796662..a5d8aae 100644 (file)
@@ -1765,19 +1765,19 @@ conn_set_state(struct drbd_connection *connection, union drbd_state mask, union
 static enum drbd_state_rv
 _conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
 {
-       enum drbd_state_rv rv;
+       enum drbd_state_rv err, rv = SS_UNKNOWN_ERROR; /* continue waiting */;
 
        if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &connection->flags))
-               return SS_CW_SUCCESS;
+               rv = SS_CW_SUCCESS;
 
        if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &connection->flags))
-               return SS_CW_FAILED_BY_PEER;
+               rv = SS_CW_FAILED_BY_PEER;
 
-       rv = conn_is_valid_transition(connection, mask, val, 0);
-       if (rv == SS_SUCCESS && connection->cstate == C_WF_REPORT_PARAMS)
-               rv = SS_UNKNOWN_ERROR; /* continue waiting */
+       err = conn_is_valid_transition(connection, mask, val, 0);
+       if (err == SS_SUCCESS && connection->cstate == C_WF_REPORT_PARAMS)
+               return rv;
 
-       return rv;
+       return err;
 }
 
 enum drbd_state_rv