aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-03-14 08:01:50 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-05-09 04:16:04 -0400
commit2b4dd36fbae7203a0d503a6cede1f4ce17aa72ac (patch)
tree09ad826a0203980e3ae54c1917a3a6badf51b773 /drivers/block
parent6d7e32f56806ad58006720ed98a433b2047444da (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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_main.c10
-rw-r--r--drivers/block/drbd/drbd_req.c20
-rw-r--r--drivers/block/drbd/drbd_req.h18
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 */
121enum drbd_req_state_bits { 121enum 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)