libceph: socket can close in any connection state
A connection's socket can close for any reason, independent of the state of the connection (and without irrespective of the connection mutex). As a result, the connectino can be in pretty much any state at the time its socket is closed. Handle those other cases at the top of con_work(). Pull this whole block of code into a separate function to reduce the clutter. Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
@@ -2273,6 +2273,35 @@ static void queue_con(struct ceph_connection *con)
|
|||||||
(void) queue_con_delay(con, 0);
|
(void) queue_con_delay(con, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool con_sock_closed(struct ceph_connection *con)
|
||||||
|
{
|
||||||
|
if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#define CASE(x) \
|
||||||
|
case CON_STATE_ ## x: \
|
||||||
|
con->error_msg = "socket closed (con state " #x ")"; \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (con->state) {
|
||||||
|
CASE(CLOSED);
|
||||||
|
CASE(PREOPEN);
|
||||||
|
CASE(CONNECTING);
|
||||||
|
CASE(NEGOTIATING);
|
||||||
|
CASE(OPEN);
|
||||||
|
CASE(STANDBY);
|
||||||
|
default:
|
||||||
|
pr_warning("%s con %p unrecognized state %lu\n",
|
||||||
|
__func__, con, con->state);
|
||||||
|
con->error_msg = "unrecognized con state";
|
||||||
|
BUG();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#undef CASE
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do some work on a connection. Drop a connection ref when we're done.
|
* Do some work on a connection. Drop a connection ref when we're done.
|
||||||
*/
|
*/
|
||||||
@@ -2284,24 +2313,8 @@ static void con_work(struct work_struct *work)
|
|||||||
|
|
||||||
mutex_lock(&con->mutex);
|
mutex_lock(&con->mutex);
|
||||||
restart:
|
restart:
|
||||||
if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) {
|
if (con_sock_closed(con))
|
||||||
switch (con->state) {
|
|
||||||
case CON_STATE_CONNECTING:
|
|
||||||
con->error_msg = "connection failed";
|
|
||||||
break;
|
|
||||||
case CON_STATE_NEGOTIATING:
|
|
||||||
con->error_msg = "negotiation failed";
|
|
||||||
break;
|
|
||||||
case CON_STATE_OPEN:
|
|
||||||
con->error_msg = "socket closed";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dout("unrecognized con state %d\n", (int)con->state);
|
|
||||||
con->error_msg = "unrecognized con state";
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
goto fault;
|
goto fault;
|
||||||
}
|
|
||||||
|
|
||||||
if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) {
|
if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) {
|
||||||
dout("con_work %p backing off\n", con);
|
dout("con_work %p backing off\n", con);
|
||||||
|
Reference in New Issue
Block a user