diff options
author | Alex Elder <elder@inktank.com> | 2012-12-07 20:50:07 -0500 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-12-17 13:07:32 -0500 |
commit | 7bb21d68c535ad8be38e14a715632ae398b37ac1 (patch) | |
tree | 81a2f47b32640921f0f7ce90b93ef450b4ca599a /net | |
parent | b8f5c6edca34ff441e1ccdec68828e933a1b905b (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/messenger.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1041114453db..4b04ccc60db1 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -2273,6 +2273,35 @@ static void queue_con(struct ceph_connection *con) | |||
2273 | (void) queue_con_delay(con, 0); | 2273 | (void) queue_con_delay(con, 0); |
2274 | } | 2274 | } |
2275 | 2275 | ||
2276 | static bool con_sock_closed(struct ceph_connection *con) | ||
2277 | { | ||
2278 | if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) | ||
2279 | return false; | ||
2280 | |||
2281 | #define CASE(x) \ | ||
2282 | case CON_STATE_ ## x: \ | ||
2283 | con->error_msg = "socket closed (con state " #x ")"; \ | ||
2284 | break; | ||
2285 | |||
2286 | switch (con->state) { | ||
2287 | CASE(CLOSED); | ||
2288 | CASE(PREOPEN); | ||
2289 | CASE(CONNECTING); | ||
2290 | CASE(NEGOTIATING); | ||
2291 | CASE(OPEN); | ||
2292 | CASE(STANDBY); | ||
2293 | default: | ||
2294 | pr_warning("%s con %p unrecognized state %lu\n", | ||
2295 | __func__, con, con->state); | ||
2296 | con->error_msg = "unrecognized con state"; | ||
2297 | BUG(); | ||
2298 | break; | ||
2299 | } | ||
2300 | #undef CASE | ||
2301 | |||
2302 | return true; | ||
2303 | } | ||
2304 | |||
2276 | /* | 2305 | /* |
2277 | * Do some work on a connection. Drop a connection ref when we're done. | 2306 | * Do some work on a connection. Drop a connection ref when we're done. |
2278 | */ | 2307 | */ |
@@ -2284,24 +2313,8 @@ static void con_work(struct work_struct *work) | |||
2284 | 2313 | ||
2285 | mutex_lock(&con->mutex); | 2314 | mutex_lock(&con->mutex); |
2286 | restart: | 2315 | restart: |
2287 | if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { | 2316 | if (con_sock_closed(con)) |
2288 | switch (con->state) { | ||
2289 | case CON_STATE_CONNECTING: | ||
2290 | con->error_msg = "connection failed"; | ||
2291 | break; | ||
2292 | case CON_STATE_NEGOTIATING: | ||
2293 | con->error_msg = "negotiation failed"; | ||
2294 | break; | ||
2295 | case CON_STATE_OPEN: | ||
2296 | con->error_msg = "socket closed"; | ||
2297 | break; | ||
2298 | default: | ||
2299 | dout("unrecognized con state %d\n", (int)con->state); | ||
2300 | con->error_msg = "unrecognized con state"; | ||
2301 | BUG(); | ||
2302 | } | ||
2303 | goto fault; | 2317 | goto fault; |
2304 | } | ||
2305 | 2318 | ||
2306 | if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { | 2319 | if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { |
2307 | dout("con_work %p backing off\n", con); | 2320 | dout("con_work %p backing off\n", con); |