aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2012-08-14 05:28:52 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-09 08:05:50 -0500
commit5af2e8ce2b463c2cc8e4a074f9d8f660ae7c1d8f (patch)
tree17e450ce313e0fa63096c61acf57536f4e40f533
parent715306f69d85f7ea21eaef4efe75b8364cfea1d5 (diff)
drbd: Fix completion of requests while the device is suspended
In various places (E.g. CONNECTION_LOST_WHILE_PENDING) the RQ_COMPLETION_SUSP mask is passed in the clear set to mod_rq_state(). The issue was that it tried to clear the RQ_COMPLETION_SUSP bit out of the state mask first, and eventuelly set it afterwards, in the drbd_req_put_completion_ref() function. Fixed that by moving the reference getting out of drbd_req_put_completion_ref() into the mod_rq_state(), before the place where the extra reference might be put. 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_req.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 266ef24b3c74..5ddb01edd933 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -304,18 +304,6 @@ static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_
304 if (!atomic_sub_and_test(put, &req->completion_ref)) 304 if (!atomic_sub_and_test(put, &req->completion_ref))
305 return 0; 305 return 0;
306 306
307 if (drbd_suspended(mdev)) {
308 /* We do not allow completion while suspended. Re-get a
309 * reference, so whatever happens when this is resumed
310 * may put and complete. */
311
312 D_ASSERT(!(req->rq_state & RQ_COMPLETION_SUSP));
313 req->rq_state |= RQ_COMPLETION_SUSP;
314 atomic_inc(&req->completion_ref);
315 return 0;
316 }
317
318 /* else */
319 drbd_req_complete(req, m); 307 drbd_req_complete(req, m);
320 308
321 if (req->rq_state & RQ_POSTPONED) { 309 if (req->rq_state & RQ_POSTPONED) {
@@ -338,6 +326,9 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
338 int c_put = 0; 326 int c_put = 0;
339 int k_put = 0; 327 int k_put = 0;
340 328
329 if (drbd_suspended(mdev) && !((s | clear) & RQ_COMPLETION_SUSP))
330 set |= RQ_COMPLETION_SUSP;
331
341 /* apply */ 332 /* apply */
342 333
343 req->rq_state &= ~clear; 334 req->rq_state &= ~clear;
@@ -366,6 +357,9 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
366 if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT)) 357 if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT))
367 atomic_add(req->i.size >> 9, &mdev->ap_in_flight); 358 atomic_add(req->i.size >> 9, &mdev->ap_in_flight);
368 359
360 if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
361 atomic_inc(&req->completion_ref);
362
369 /* progress: put references */ 363 /* progress: put references */
370 364
371 if ((s & RQ_COMPLETION_SUSP) && (clear & RQ_COMPLETION_SUSP)) 365 if ((s & RQ_COMPLETION_SUSP) && (clear & RQ_COMPLETION_SUSP))