summaryrefslogtreecommitdiff
path: root/drivers/block/drbd/drbd_state.h
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2014-11-10 17:21:11 +0100
committerJens Axboe <axboe@fb.com>2014-11-10 09:27:35 -0700
commita88215312c5ed74697973f6c9f0fce718bcf18ad (patch)
tree831cef10aa7728cff1fe109ba5f6ee8dad4e3225 /drivers/block/drbd/drbd_state.h
parentf221f4bcc5f40e2967e4596ef167bdbc987c8e9d (diff)
drbd: fix race between role change and handshake
Symptoms: If DRBD was "cleanly shut down" (all in sync, both Secondary before disconnect, identical data generation uuids), and then one side was promoted *during* the next connection handshake, the role change could confuse the handshake. The Primary would get stuck in WFBitmapS, the Secondary would log unexpected cstate (Connected) in receive_bitmap and get stuck in WFBitmapT. Fix: The test in is_valid_soft_transition wrong. It works because the not allowed actions (promote/attach) do not touch the cstate. The previous condition failed to demand a cstate change in one clause. In order to avoid deadlocks give up the state_mutex while waiting for the transient state to go away. Conflicts: drbd/drbd_state.c drbd/drbd_state.h drbd/drbd_wrappers.h 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>
Diffstat (limited to 'drivers/block/drbd/drbd_state.h')
-rw-r--r--drivers/block/drbd/drbd_state.h5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index cc41605ba21c..7f53c40823cd 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -117,6 +117,11 @@ extern enum drbd_state_rv _drbd_request_state(struct drbd_device *,
union drbd_state,
union drbd_state,
enum chg_state_flags);
+
+extern enum drbd_state_rv
+_drbd_request_state_holding_state_mutex(struct drbd_device *, union drbd_state,
+ union drbd_state, enum chg_state_flags);
+
extern enum drbd_state_rv __drbd_set_state(struct drbd_device *, union drbd_state,
enum chg_state_flags,
struct completion *done);