* so shrink_page_list() would not recurse into,
* and potentially deadlock on, this drbd worker.
*/
+ DISCONNECT_SENT, /* Currently the last bit in this 32bit word */
};
struct drbd_bitmap; /* opaque for drbd_conf */
goto abort;
}
+ if (mask.conn == C_MASK && val.conn == C_DISCONNECTING)
+ set_bit(DISCONNECT_SENT, &mdev->flags);
+
wait_event(mdev->state_wait,
(rv = _req_st_cond(mdev, mask, val)));
dev_err(DEV, "sock_recvmsg returned %d\n", rv);
break;
} else if (rv == 0) {
- dev_info(DEV, "sock was shut down by peer\n");
break;
} else {
/* signal came in, or peer/link went down,
set_fs(oldfs);
+ if (rv == 0) {
+ if (test_bit(DISCONNECT_SENT, &mdev->flags)) {
+ long t; /* time_left */
+ t = wait_event_timeout(mdev->state_wait, mdev->state.conn < C_CONNECTED,
+ mdev->net_conf->ping_timeo * HZ/10);
+ if (t)
+ goto out;
+ }
+ dev_info(DEV, "sock was shut down by peer\n");
+ }
+
if (rv != size)
drbd_force_state(mdev, NS(conn, C_BROKEN_PIPE));
+out:
return rv;
}
D_ASSERT(!mdev->data.socket);
+ clear_bit(DISCONNECT_SENT, &mdev->flags);
if (drbd_request_state(mdev, NS(conn, C_WF_CONNECTION)) < SS_SUCCESS)
return -2;
received += rv;
buf += rv;
} else if (rv == 0) {
+ if (test_bit(DISCONNECT_SENT, &mdev->flags)) {
+ long t; /* time_left */
+ t = wait_event_timeout(mdev->state_wait, mdev->state.conn < C_CONNECTED,
+ mdev->net_conf->ping_timeo * HZ/10);
+ if (t)
+ break;
+ }
dev_err(DEV, "meta connection shut down by peer.\n");
goto reconnect;
} else if (rv == -EAGAIN) {