diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/messenger.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 973c16c20c42..66f6f56bcb23 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -2244,22 +2244,33 @@ bad_tag: | |||
2244 | 2244 | ||
2245 | 2245 | ||
2246 | /* | 2246 | /* |
2247 | * Atomically queue work on a connection. Bump @con reference to | 2247 | * Atomically queue work on a connection after the specified delay. |
2248 | * avoid races with connection teardown. | 2248 | * Bump @con reference to avoid races with connection teardown. |
2249 | * Returns 0 if work was queued, or an error code otherwise. | ||
2249 | */ | 2250 | */ |
2250 | static void queue_con(struct ceph_connection *con) | 2251 | static int queue_con_delay(struct ceph_connection *con, unsigned long delay) |
2251 | { | 2252 | { |
2252 | if (!con->ops->get(con)) { | 2253 | if (!con->ops->get(con)) { |
2253 | dout("queue_con %p ref count 0\n", con); | 2254 | dout("%s %p ref count 0\n", __func__, con); |
2254 | return; | 2255 | |
2256 | return -ENOENT; | ||
2255 | } | 2257 | } |
2256 | 2258 | ||
2257 | if (!queue_delayed_work(ceph_msgr_wq, &con->work, 0)) { | 2259 | if (!queue_delayed_work(ceph_msgr_wq, &con->work, delay)) { |
2258 | dout("queue_con %p - already queued\n", con); | 2260 | dout("%s %p - already queued\n", __func__, con); |
2259 | con->ops->put(con); | 2261 | con->ops->put(con); |
2260 | } else { | 2262 | |
2261 | dout("queue_con %p\n", con); | 2263 | return -EBUSY; |
2262 | } | 2264 | } |
2265 | |||
2266 | dout("%s %p %lu\n", __func__, con, delay); | ||
2267 | |||
2268 | return 0; | ||
2269 | } | ||
2270 | |||
2271 | static void queue_con(struct ceph_connection *con) | ||
2272 | { | ||
2273 | (void) queue_con_delay(con, 0); | ||
2263 | } | 2274 | } |
2264 | 2275 | ||
2265 | /* | 2276 | /* |
@@ -2294,14 +2305,11 @@ restart: | |||
2294 | 2305 | ||
2295 | if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { | 2306 | if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { |
2296 | dout("con_work %p backing off\n", con); | 2307 | dout("con_work %p backing off\n", con); |
2297 | if (queue_delayed_work(ceph_msgr_wq, &con->work, | 2308 | ret = queue_con_delay(con, round_jiffies_relative(con->delay)); |
2298 | round_jiffies_relative(con->delay))) { | 2309 | if (ret) { |
2299 | dout("con_work %p backoff %lu\n", con, con->delay); | ||
2300 | mutex_unlock(&con->mutex); | ||
2301 | return; | ||
2302 | } else { | ||
2303 | dout("con_work %p FAILED to back off %lu\n", con, | 2310 | dout("con_work %p FAILED to back off %lu\n", con, |
2304 | con->delay); | 2311 | con->delay); |
2312 | BUG_ON(ret == -ENOENT); | ||
2305 | set_bit(CON_FLAG_BACKOFF, &con->flags); | 2313 | set_bit(CON_FLAG_BACKOFF, &con->flags); |
2306 | } | 2314 | } |
2307 | goto done; | 2315 | goto done; |