aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2013-03-27 09:08:40 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-28 12:10:25 -0400
commit2bd5ed5d6713594eb2b4d234d01217d506279c7d (patch)
treeafdeb5ec00f0103f8bb43fea389e3cb18ee958c3 /drivers
parentbb45185de2e90af63a7bc48855de6f870cc216fc (diff)
drbd: Fix disconnect to keep the peer disk state if connection breaks during operation
The issue was that if the connection broke while we did the gracefull state change to C_DISCONNECTING (C_TEARDOWN), then we returned a success code from the state engine. (SS_CW_NO_NEED) The result of that is that we missed to call the fence-peer script in such a case. Fixed that by introducing a new error code (SS_OUTDATE_WO_CONN). This one should never reach back into user space. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/drbd/drbd_nl.c7
-rw-r--r--drivers/block/drbd/drbd_state.c14
-rw-r--r--drivers/block/drbd/drbd_strings.c1
3 files changed, 13 insertions, 9 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 56bafdcd943e..39e9a91a8f31 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -2198,8 +2198,11 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool for
2198 return SS_SUCCESS; 2198 return SS_SUCCESS;
2199 case SS_PRIMARY_NOP: 2199 case SS_PRIMARY_NOP:
2200 /* Our state checking code wants to see the peer outdated. */ 2200 /* Our state checking code wants to see the peer outdated. */
2201 rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING, 2201 rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING, pdsk, D_OUTDATED), 0);
2202 pdsk, D_OUTDATED), CS_VERBOSE); 2202
2203 if (rv == SS_OUTDATE_WO_CONN) /* lost connection before graceful disconnect succeeded */
2204 rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_VERBOSE);
2205
2203 break; 2206 break;
2204 case SS_CW_FAILED_BY_PEER: 2207 case SS_CW_FAILED_BY_PEER:
2205 /* The peer probably wants to see us outdated. */ 2208 /* The peer probably wants to see us outdated. */
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 22e259f34370..90c5be2b1d30 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -642,6 +642,10 @@ is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_t
642 && os.conn < C_WF_REPORT_PARAMS) 642 && os.conn < C_WF_REPORT_PARAMS)
643 rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */ 643 rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
644 644
645 if (ns.conn == C_DISCONNECTING && ns.pdsk == D_OUTDATED &&
646 os.conn < C_CONNECTED && os.pdsk > D_OUTDATED)
647 rv = SS_OUTDATE_WO_CONN;
648
645 return rv; 649 return rv;
646} 650}
647 651
@@ -1748,13 +1752,9 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
1748 if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags)) 1752 if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags))
1749 return SS_CW_FAILED_BY_PEER; 1753 return SS_CW_FAILED_BY_PEER;
1750 1754
1751 rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR; 1755 rv = conn_is_valid_transition(tconn, mask, val, 0);
1752 1756 if (rv == SS_SUCCESS && tconn->cstate == C_WF_REPORT_PARAMS)
1753 if (rv == SS_UNKNOWN_ERROR) 1757 rv = SS_UNKNOWN_ERROR; /* continue waiting */
1754 rv = conn_is_valid_transition(tconn, mask, val, 0);
1755
1756 if (rv == SS_SUCCESS)
1757 rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
1758 1758
1759 return rv; 1759 return rv;
1760} 1760}
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c
index 9a664bd27404..58e08ff2b2ce 100644
--- a/drivers/block/drbd/drbd_strings.c
+++ b/drivers/block/drbd/drbd_strings.c
@@ -89,6 +89,7 @@ static const char *drbd_state_sw_errors[] = {
89 [-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated", 89 [-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated",
90 [-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change", 90 [-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change",
91 [-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted", 91 [-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted",
92 [-SS_OUTDATE_WO_CONN] = "Need a connection for a graceful disconnect/outdate peer",
92 [-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config", 93 [-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config",
93}; 94};
94 95