diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 09:04:36 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:57:59 -0500 |
commit | 823bd832a60dcf4bf9c162112f34f2f1783d0eaa (patch) | |
tree | 6bc4707730dda8f597079008fdcc29209fcd0bd8 | |
parent | 7d4c782cbda4af0d7dc39cb8e7d50a927781aa1f (diff) |
drbd: Bugfix for the connection behavior
If we get into the C_BROKEN_PIPE cstate once, the state engine set the
thi->t_state of the receiver thread to restarting. But with the while loop
in drbdd_init() a new connection gets established. After the call into
drbdd() returns immediately since the thi->t_state is not RUNNING. The
restart of drbd_init() then resets thi->t_state to RUNNING.
I.e. after entering C_BROKEN_PIPE once, the next successful established
connection gets wasted.
The two parts of the fix:
* Do not cause the thread to restart if we detect the issue
with the sockets while we are in C_WF_CONNECTION.
* Make sure that all actions that would have set us to C_BROKEN_PIPE
happen before the state change to C_WF_REPORT_PARAMS.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_state.c | 2 |
2 files changed, 6 insertions, 6 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 8d5212194806..fff55657e0da 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -987,14 +987,9 @@ retry: | |||
987 | } | 987 | } |
988 | } | 988 | } |
989 | 989 | ||
990 | if (conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE) < SS_SUCCESS) | ||
991 | return 0; | ||
992 | |||
993 | sock->sk->sk_sndtimeo = timeout; | 990 | sock->sk->sk_sndtimeo = timeout; |
994 | sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | 991 | sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; |
995 | 992 | ||
996 | drbd_thread_start(&tconn->asender); | ||
997 | |||
998 | if (drbd_send_protocol(tconn) == -EOPNOTSUPP) | 993 | if (drbd_send_protocol(tconn) == -EOPNOTSUPP) |
999 | return -1; | 994 | return -1; |
1000 | 995 | ||
@@ -1008,6 +1003,11 @@ retry: | |||
1008 | } | 1003 | } |
1009 | rcu_read_unlock(); | 1004 | rcu_read_unlock(); |
1010 | 1005 | ||
1006 | if (conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE) < SS_SUCCESS) | ||
1007 | return 0; | ||
1008 | |||
1009 | drbd_thread_start(&tconn->asender); | ||
1010 | |||
1011 | return h; | 1011 | return h; |
1012 | 1012 | ||
1013 | out_release_sockets: | 1013 | out_release_sockets: |
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 1132d87fa284..ecc5e2761668 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -1055,7 +1055,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
1055 | drbd_thread_stop_nowait(&mdev->tconn->receiver); | 1055 | drbd_thread_stop_nowait(&mdev->tconn->receiver); |
1056 | 1056 | ||
1057 | /* Upon network failure, we need to restart the receiver. */ | 1057 | /* Upon network failure, we need to restart the receiver. */ |
1058 | if (os.conn > C_TEAR_DOWN && | 1058 | if (os.conn > C_WF_CONNECTION && |
1059 | ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT) | 1059 | ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT) |
1060 | drbd_thread_restart_nowait(&mdev->tconn->receiver); | 1060 | drbd_thread_restart_nowait(&mdev->tconn->receiver); |
1061 | 1061 | ||