diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2012-03-26 11:29:30 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:58:24 -0500 |
commit | 4439c400ab278378a82efb543bb3bb91b184d8db (patch) | |
tree | 8573efc9416f0a5c22899018aa93ccd064e2f992 /drivers/block/drbd | |
parent | 2415308eb94e7bddf9c9a0f210374600210274d7 (diff) |
drbd: simplify retry path of failed READ requests
If a local or remote READ request fails, just push it back to the retry
workqueue. It will re-enter __drbd_make_request, and be re-assigned to
a suitable local or remote path, or failed, if we do not have access to
good data anymore.
This obsoletes w_read_retry_remote(),
and eliminates two goto...retry blocks in __req_mod()
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 1 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 65 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 20 |
3 files changed, 19 insertions, 67 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index caeb01eef44e..ab9926e915cb 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -1439,7 +1439,6 @@ extern void drbd_csum_bio(struct drbd_conf *, struct crypto_hash *, struct bio * | |||
1439 | extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *, | 1439 | extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *, |
1440 | struct drbd_peer_request *, void *); | 1440 | struct drbd_peer_request *, void *); |
1441 | /* worker callbacks */ | 1441 | /* worker callbacks */ |
1442 | extern int w_read_retry_remote(struct drbd_work *, int); | ||
1443 | extern int w_e_end_data_req(struct drbd_work *, int); | 1442 | extern int w_e_end_data_req(struct drbd_work *, int); |
1444 | extern int w_e_end_rsdata_req(struct drbd_work *, int); | 1443 | extern int w_e_end_rsdata_req(struct drbd_work *, int); |
1445 | extern int w_e_end_csum_rs_req(struct drbd_work *, int); | 1444 | extern int w_e_end_csum_rs_req(struct drbd_work *, int); |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index f708aa1809f0..1249672519ca 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -263,7 +263,6 @@ void req_may_be_completed(struct drbd_request *req, struct bio_and_error *m) | |||
263 | { | 263 | { |
264 | const unsigned long s = req->rq_state; | 264 | const unsigned long s = req->rq_state; |
265 | struct drbd_conf *mdev = req->w.mdev; | 265 | struct drbd_conf *mdev = req->w.mdev; |
266 | int rw = req->rq_state & RQ_WRITE ? WRITE : READ; | ||
267 | 266 | ||
268 | /* we must not complete the master bio, while it is | 267 | /* we must not complete the master bio, while it is |
269 | * still being processed by _drbd_send_zc_bio (drbd_send_dblock) | 268 | * still being processed by _drbd_send_zc_bio (drbd_send_dblock) |
@@ -282,6 +281,8 @@ void req_may_be_completed(struct drbd_request *req, struct bio_and_error *m) | |||
282 | return; | 281 | return; |
283 | 282 | ||
284 | if (req->master_bio) { | 283 | if (req->master_bio) { |
284 | int rw = bio_rw(req->master_bio); | ||
285 | |||
285 | /* this is DATA_RECEIVED (remote read) | 286 | /* this is DATA_RECEIVED (remote read) |
286 | * or protocol C P_WRITE_ACK | 287 | * or protocol C P_WRITE_ACK |
287 | * or protocol B P_RECV_ACK | 288 | * or protocol B P_RECV_ACK |
@@ -326,7 +327,18 @@ void req_may_be_completed(struct drbd_request *req, struct bio_and_error *m) | |||
326 | /* Update disk stats */ | 327 | /* Update disk stats */ |
327 | _drbd_end_io_acct(mdev, req); | 328 | _drbd_end_io_acct(mdev, req); |
328 | 329 | ||
329 | if (!(s & RQ_POSTPONED)) { | 330 | /* if READ failed, |
331 | * have it be pushed back to the retry work queue, | ||
332 | * so it will re-enter __drbd_make_request, | ||
333 | * and be re-assigned to a suitable local or remote path, | ||
334 | * or failed if we do not have access to good data anymore. | ||
335 | * READA may fail. | ||
336 | * WRITE should have used all available paths already. | ||
337 | */ | ||
338 | if (!ok && rw == READ) | ||
339 | req->rq_state |= RQ_POSTPONED; | ||
340 | |||
341 | if (!(req->rq_state & RQ_POSTPONED)) { | ||
330 | m->error = ok ? 0 : (error ?: -EIO); | 342 | m->error = ok ? 0 : (error ?: -EIO); |
331 | m->bio = req->master_bio; | 343 | m->bio = req->master_bio; |
332 | req->master_bio = NULL; | 344 | req->master_bio = NULL; |
@@ -420,10 +432,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
420 | 432 | ||
421 | case ABORT_DISK_IO: | 433 | case ABORT_DISK_IO: |
422 | req->rq_state |= RQ_LOCAL_ABORTED; | 434 | req->rq_state |= RQ_LOCAL_ABORTED; |
423 | if (req->rq_state & RQ_WRITE) | 435 | req_may_be_completed_not_susp(req, m); |
424 | req_may_be_completed_not_susp(req, m); | ||
425 | else | ||
426 | goto goto_queue_for_net_read; | ||
427 | break; | 436 | break; |
428 | 437 | ||
429 | case WRITE_COMPLETED_WITH_ERROR: | 438 | case WRITE_COMPLETED_WITH_ERROR: |
@@ -451,20 +460,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
451 | D_ASSERT(!(req->rq_state & RQ_NET_MASK)); | 460 | D_ASSERT(!(req->rq_state & RQ_NET_MASK)); |
452 | 461 | ||
453 | __drbd_chk_io_error(mdev, false); | 462 | __drbd_chk_io_error(mdev, false); |
454 | 463 | break; | |
455 | goto_queue_for_net_read: | ||
456 | |||
457 | /* no point in retrying if there is no good remote data, | ||
458 | * or we have no connection. */ | ||
459 | if (mdev->state.pdsk != D_UP_TO_DATE) { | ||
460 | req_may_be_completed_not_susp(req, m); | ||
461 | break; | ||
462 | } | ||
463 | |||
464 | /* _req_mod(req,TO_BE_SENT); oops, recursion... */ | ||
465 | req->rq_state |= RQ_NET_PENDING; | ||
466 | inc_ap_pending(mdev); | ||
467 | /* fall through: _req_mod(req,QUEUE_FOR_NET_READ); */ | ||
468 | 464 | ||
469 | case QUEUE_FOR_NET_READ: | 465 | case QUEUE_FOR_NET_READ: |
470 | /* READ or READA, and | 466 | /* READ or READA, and |
@@ -483,10 +479,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
483 | set_bit(UNPLUG_REMOTE, &mdev->flags); | 479 | set_bit(UNPLUG_REMOTE, &mdev->flags); |
484 | 480 | ||
485 | D_ASSERT(req->rq_state & RQ_NET_PENDING); | 481 | D_ASSERT(req->rq_state & RQ_NET_PENDING); |
482 | D_ASSERT((req->rq_state & RQ_LOCAL_MASK) == 0); | ||
486 | req->rq_state |= RQ_NET_QUEUED; | 483 | req->rq_state |= RQ_NET_QUEUED; |
487 | req->w.cb = (req->rq_state & RQ_LOCAL_MASK) | 484 | req->w.cb = w_send_read_req; |
488 | ? w_read_retry_remote | ||
489 | : w_send_read_req; | ||
490 | drbd_queue_work(&mdev->tconn->data.work, &req->w); | 485 | drbd_queue_work(&mdev->tconn->data.work, &req->w); |
491 | break; | 486 | break; |
492 | 487 | ||
@@ -604,13 +599,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
604 | if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE) | 599 | if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE) |
605 | atomic_sub(req->i.size >> 9, &mdev->ap_in_flight); | 600 | atomic_sub(req->i.size >> 9, &mdev->ap_in_flight); |
606 | 601 | ||
607 | /* if it is still queued, we may not complete it here. | 602 | req_may_be_completed(req, m); /* Allowed while state.susp */ |
608 | * it will be canceled soon. */ | ||
609 | if (!(req->rq_state & RQ_NET_QUEUED)) { | ||
610 | if (p) | ||
611 | goto goto_read_retry_local; | ||
612 | req_may_be_completed(req, m); /* Allowed while state.susp */ | ||
613 | } | ||
614 | break; | 603 | break; |
615 | 604 | ||
616 | case DISCARD_WRITE: | 605 | case DISCARD_WRITE: |
@@ -668,27 +657,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
668 | 657 | ||
669 | req->rq_state |= RQ_NET_DONE; | 658 | req->rq_state |= RQ_NET_DONE; |
670 | 659 | ||
671 | if (!(req->rq_state & RQ_WRITE)) | ||
672 | goto goto_read_retry_local; | ||
673 | |||
674 | maybe_wakeup_conflicting_requests(req); | 660 | maybe_wakeup_conflicting_requests(req); |
675 | req_may_be_completed_not_susp(req, m); | 661 | req_may_be_completed_not_susp(req, m); |
676 | /* else: done by HANDED_OVER_TO_NETWORK */ | 662 | /* else: done by HANDED_OVER_TO_NETWORK */ |
677 | break; | 663 | break; |
678 | 664 | ||
679 | goto_read_retry_local: | ||
680 | if (!drbd_may_do_local_read(mdev, req->i.sector, req->i.size)) { | ||
681 | req_may_be_completed_not_susp(req, m); | ||
682 | break; | ||
683 | } | ||
684 | D_ASSERT(!(req->rq_state & RQ_LOCAL_PENDING)); | ||
685 | req->rq_state |= RQ_LOCAL_PENDING; | ||
686 | |||
687 | get_ldev(mdev); | ||
688 | req->w.cb = w_restart_disk_io; | ||
689 | drbd_queue_work(&mdev->tconn->data.work, &req->w); | ||
690 | break; | ||
691 | |||
692 | case FAIL_FROZEN_DISK_IO: | 665 | case FAIL_FROZEN_DISK_IO: |
693 | if (!(req->rq_state & RQ_LOCAL_COMPLETED)) | 666 | if (!(req->rq_state & RQ_LOCAL_COMPLETED)) |
694 | break; | 667 | break; |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index f10451701cdb..d7573f4b7421 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -244,26 +244,6 @@ void drbd_request_endio(struct bio *bio, int error) | |||
244 | complete_master_bio(mdev, &m); | 244 | complete_master_bio(mdev, &m); |
245 | } | 245 | } |
246 | 246 | ||
247 | int w_read_retry_remote(struct drbd_work *w, int cancel) | ||
248 | { | ||
249 | struct drbd_request *req = container_of(w, struct drbd_request, w); | ||
250 | struct drbd_conf *mdev = w->mdev; | ||
251 | |||
252 | /* We should not detach for read io-error, | ||
253 | * but try to WRITE the P_DATA_REPLY to the failed location, | ||
254 | * to give the disk the chance to relocate that block */ | ||
255 | |||
256 | spin_lock_irq(&mdev->tconn->req_lock); | ||
257 | if (cancel || mdev->state.pdsk != D_UP_TO_DATE) { | ||
258 | _req_mod(req, READ_RETRY_REMOTE_CANCELED); | ||
259 | spin_unlock_irq(&mdev->tconn->req_lock); | ||
260 | return 0; | ||
261 | } | ||
262 | spin_unlock_irq(&mdev->tconn->req_lock); | ||
263 | |||
264 | return w_send_read_req(w, 0); | ||
265 | } | ||
266 | |||
267 | void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, | 247 | void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, |
268 | struct drbd_peer_request *peer_req, void *digest) | 248 | struct drbd_peer_request *peer_req, void *digest) |
269 | { | 249 | { |