diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-14 08:01:50 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-05-09 04:16:04 -0400 |
commit | 2b4dd36fbae7203a0d503a6cede1f4ce17aa72ac (patch) | |
tree | 09ad826a0203980e3ae54c1917a3a6badf51b773 | |
parent | 6d7e32f56806ad58006720ed98a433b2047444da (diff) |
drbd: Immediately allow completion of IOs, that wait for IO completions on a failed disk
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_main.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 20 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 18 |
3 files changed, 37 insertions, 11 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 8e489a6d022e..16969c2b96cd 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -368,6 +368,12 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
368 | } | 368 | } |
369 | tmp = b->next; | 369 | tmp = b->next; |
370 | 370 | ||
371 | if (what == abort_disk_io) { | ||
372 | /* Only walk the TL, leave barrier objects in place */ | ||
373 | b = tmp; | ||
374 | continue; | ||
375 | } | ||
376 | |||
371 | if (n_writes) { | 377 | if (n_writes) { |
372 | if (what == resend) { | 378 | if (what == resend) { |
373 | b->n_writes = n_writes; | 379 | b->n_writes = n_writes; |
@@ -1565,6 +1571,10 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, | |||
1565 | eh = mdev->ldev->dc.on_io_error; | 1571 | eh = mdev->ldev->dc.on_io_error; |
1566 | was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags); | 1572 | was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags); |
1567 | 1573 | ||
1574 | /* Immediately allow completion of all application IO, that waits | ||
1575 | for completion from the local disk. */ | ||
1576 | tl_restart(mdev, abort_disk_io); | ||
1577 | |||
1568 | /* current state still has to be D_FAILED, | 1578 | /* current state still has to be D_FAILED, |
1569 | * there is only one way out: to D_DISKLESS, | 1579 | * there is only one way out: to D_DISKLESS, |
1570 | * and that may only happen after our put_ldev below. */ | 1580 | * and that may only happen after our put_ldev below. */ |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 4a0f314086e5..1a8aac4b0c2f 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -214,8 +214,7 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m) | |||
214 | { | 214 | { |
215 | const unsigned long s = req->rq_state; | 215 | const unsigned long s = req->rq_state; |
216 | struct drbd_conf *mdev = req->mdev; | 216 | struct drbd_conf *mdev = req->mdev; |
217 | /* only WRITES may end up here without a master bio (on barrier ack) */ | 217 | int rw = req->rq_state & RQ_WRITE ? WRITE : READ; |
218 | int rw = req->master_bio ? bio_data_dir(req->master_bio) : WRITE; | ||
219 | 218 | ||
220 | /* we must not complete the master bio, while it is | 219 | /* we must not complete the master bio, while it is |
221 | * still being processed by _drbd_send_zc_bio (drbd_send_dblock) | 220 | * still being processed by _drbd_send_zc_bio (drbd_send_dblock) |
@@ -230,7 +229,7 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m) | |||
230 | return; | 229 | return; |
231 | if (s & RQ_NET_PENDING) | 230 | if (s & RQ_NET_PENDING) |
232 | return; | 231 | return; |
233 | if (s & RQ_LOCAL_PENDING) | 232 | if (s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED)) |
234 | return; | 233 | return; |
235 | 234 | ||
236 | if (req->master_bio) { | 235 | if (req->master_bio) { |
@@ -277,6 +276,9 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m) | |||
277 | req->master_bio = NULL; | 276 | req->master_bio = NULL; |
278 | } | 277 | } |
279 | 278 | ||
279 | if (s & RQ_LOCAL_PENDING) | ||
280 | return; | ||
281 | |||
280 | if ((s & RQ_NET_MASK) == 0 || (s & RQ_NET_DONE)) { | 282 | if ((s & RQ_NET_MASK) == 0 || (s & RQ_NET_DONE)) { |
281 | /* this is disconnected (local only) operation, | 283 | /* this is disconnected (local only) operation, |
282 | * or protocol C P_WRITE_ACK, | 284 | * or protocol C P_WRITE_ACK, |
@@ -429,7 +431,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
429 | break; | 431 | break; |
430 | 432 | ||
431 | case completed_ok: | 433 | case completed_ok: |
432 | if (bio_data_dir(req->master_bio) == WRITE) | 434 | if (req->rq_state & RQ_WRITE) |
433 | mdev->writ_cnt += req->size>>9; | 435 | mdev->writ_cnt += req->size>>9; |
434 | else | 436 | else |
435 | mdev->read_cnt += req->size>>9; | 437 | mdev->read_cnt += req->size>>9; |
@@ -441,6 +443,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
441 | put_ldev(mdev); | 443 | put_ldev(mdev); |
442 | break; | 444 | break; |
443 | 445 | ||
446 | case abort_disk_io: | ||
447 | req->rq_state |= RQ_LOCAL_ABORTED; | ||
448 | if (req->rq_state & RQ_WRITE) | ||
449 | _req_may_be_done_not_susp(req, m); | ||
450 | else | ||
451 | goto goto_queue_for_net_read; | ||
452 | break; | ||
453 | |||
444 | case write_completed_with_error: | 454 | case write_completed_with_error: |
445 | req->rq_state |= RQ_LOCAL_COMPLETED; | 455 | req->rq_state |= RQ_LOCAL_COMPLETED; |
446 | req->rq_state &= ~RQ_LOCAL_PENDING; | 456 | req->rq_state &= ~RQ_LOCAL_PENDING; |
@@ -469,6 +479,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
469 | __drbd_chk_io_error(mdev, false); | 479 | __drbd_chk_io_error(mdev, false); |
470 | put_ldev(mdev); | 480 | put_ldev(mdev); |
471 | 481 | ||
482 | goto_queue_for_net_read: | ||
483 | |||
472 | /* no point in retrying if there is no good remote data, | 484 | /* no point in retrying if there is no good remote data, |
473 | * or we have no connection. */ | 485 | * or we have no connection. */ |
474 | if (mdev->state.pdsk != D_UP_TO_DATE) { | 486 | if (mdev->state.pdsk != D_UP_TO_DATE) { |
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 74c5b9f14d61..3d2111919486 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -119,18 +119,21 @@ enum drbd_req_event { | |||
119 | * same time, so we should hold the request lock anyways. | 119 | * same time, so we should hold the request lock anyways. |
120 | */ | 120 | */ |
121 | enum drbd_req_state_bits { | 121 | enum drbd_req_state_bits { |
122 | /* 210 | 122 | /* 3210 |
123 | * 000: no local possible | 123 | * 0000: no local possible |
124 | * 001: to be submitted | 124 | * 0001: to be submitted |
125 | * UNUSED, we could map: 011: submitted, completion still pending | 125 | * UNUSED, we could map: 011: submitted, completion still pending |
126 | * 110: completed ok | 126 | * 0110: completed ok |
127 | * 010: completed with error | 127 | * 0010: completed with error |
128 | * 1001: Aborted (before completion) | ||
129 | * 1x10: Aborted and completed -> free | ||
128 | */ | 130 | */ |
129 | __RQ_LOCAL_PENDING, | 131 | __RQ_LOCAL_PENDING, |
130 | __RQ_LOCAL_COMPLETED, | 132 | __RQ_LOCAL_COMPLETED, |
131 | __RQ_LOCAL_OK, | 133 | __RQ_LOCAL_OK, |
134 | __RQ_LOCAL_ABORTED, | ||
132 | 135 | ||
133 | /* 76543 | 136 | /* 87654 |
134 | * 00000: no network possible | 137 | * 00000: no network possible |
135 | * 00001: to be send | 138 | * 00001: to be send |
136 | * 00011: to be send, on worker queue | 139 | * 00011: to be send, on worker queue |
@@ -200,8 +203,9 @@ enum drbd_req_state_bits { | |||
200 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) | 203 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) |
201 | #define RQ_LOCAL_COMPLETED (1UL << __RQ_LOCAL_COMPLETED) | 204 | #define RQ_LOCAL_COMPLETED (1UL << __RQ_LOCAL_COMPLETED) |
202 | #define RQ_LOCAL_OK (1UL << __RQ_LOCAL_OK) | 205 | #define RQ_LOCAL_OK (1UL << __RQ_LOCAL_OK) |
206 | #define RQ_LOCAL_ABORTED (1UL << __RQ_LOCAL_ABORTED) | ||
203 | 207 | ||
204 | #define RQ_LOCAL_MASK ((RQ_LOCAL_OK << 1)-1) /* 0x07 */ | 208 | #define RQ_LOCAL_MASK ((RQ_LOCAL_ABORTED << 1)-1) |
205 | 209 | ||
206 | #define RQ_NET_PENDING (1UL << __RQ_NET_PENDING) | 210 | #define RQ_NET_PENDING (1UL << __RQ_NET_PENDING) |
207 | #define RQ_NET_QUEUED (1UL << __RQ_NET_QUEUED) | 211 | #define RQ_NET_QUEUED (1UL << __RQ_NET_QUEUED) |