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>
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index f708aa1..1249672 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -263,7 +263,6 @@
 {
 	const unsigned long s = req->rq_state;
 	struct drbd_conf *mdev = req->w.mdev;
-	int rw = req->rq_state & RQ_WRITE ? WRITE : READ;
 
 	/* we must not complete the master bio, while it is
 	 *	still being processed by _drbd_send_zc_bio (drbd_send_dblock)
@@ -282,6 +281,8 @@
 		return;
 
 	if (req->master_bio) {
+		int rw = bio_rw(req->master_bio);
+
 		/* this is DATA_RECEIVED (remote read)
 		 * or protocol C P_WRITE_ACK
 		 * or protocol B P_RECV_ACK
@@ -326,7 +327,18 @@
 		/* Update disk stats */
 		_drbd_end_io_acct(mdev, req);
 
-		if (!(s & RQ_POSTPONED)) {
+		/* if READ failed,
+		 * have it be pushed back to the retry work queue,
+		 * so 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.
+		 * READA may fail.
+		 * WRITE should have used all available paths already.
+		 */
+		if (!ok && rw == READ)
+			req->rq_state |= RQ_POSTPONED;
+
+		if (!(req->rq_state & RQ_POSTPONED)) {
 			m->error = ok ? 0 : (error ?: -EIO);
 			m->bio = req->master_bio;
 			req->master_bio = NULL;
@@ -420,10 +432,7 @@
 
 	case ABORT_DISK_IO:
 		req->rq_state |= RQ_LOCAL_ABORTED;
-		if (req->rq_state & RQ_WRITE)
-			req_may_be_completed_not_susp(req, m);
-		else
-			goto goto_queue_for_net_read;
+		req_may_be_completed_not_susp(req, m);
 		break;
 
 	case WRITE_COMPLETED_WITH_ERROR:
@@ -451,20 +460,7 @@
 		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
 
 		__drbd_chk_io_error(mdev, false);
-
-	goto_queue_for_net_read:
-
-		/* no point in retrying if there is no good remote data,
-		 * or we have no connection. */
-		if (mdev->state.pdsk != D_UP_TO_DATE) {
-			req_may_be_completed_not_susp(req, m);
-			break;
-		}
-
-		/* _req_mod(req,TO_BE_SENT); oops, recursion... */
-		req->rq_state |= RQ_NET_PENDING;
-		inc_ap_pending(mdev);
-		/* fall through: _req_mod(req,QUEUE_FOR_NET_READ); */
+		break;
 
 	case QUEUE_FOR_NET_READ:
 		/* READ or READA, and
@@ -483,10 +479,9 @@
 		set_bit(UNPLUG_REMOTE, &mdev->flags);
 
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT((req->rq_state & RQ_LOCAL_MASK) == 0);
 		req->rq_state |= RQ_NET_QUEUED;
-		req->w.cb = (req->rq_state & RQ_LOCAL_MASK)
-			? w_read_retry_remote
-			: w_send_read_req;
+		req->w.cb = w_send_read_req;
 		drbd_queue_work(&mdev->tconn->data.work, &req->w);
 		break;
 
@@ -604,13 +599,7 @@
 		if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE)
 			atomic_sub(req->i.size >> 9, &mdev->ap_in_flight);
 
-		/* if it is still queued, we may not complete it here.
-		 * it will be canceled soon. */
-		if (!(req->rq_state & RQ_NET_QUEUED)) {
-			if (p)
-				goto goto_read_retry_local;
-			req_may_be_completed(req, m); /* Allowed while state.susp */
-		}
+		req_may_be_completed(req, m); /* Allowed while state.susp */
 		break;
 
 	case DISCARD_WRITE:
@@ -668,27 +657,11 @@
 
 		req->rq_state |= RQ_NET_DONE;
 
-		if (!(req->rq_state & RQ_WRITE))
-			goto goto_read_retry_local;
-
 		maybe_wakeup_conflicting_requests(req);
 		req_may_be_completed_not_susp(req, m);
 		/* else: done by HANDED_OVER_TO_NETWORK */
 		break;
 
-	goto_read_retry_local:
-		if (!drbd_may_do_local_read(mdev, req->i.sector, req->i.size)) {
-			req_may_be_completed_not_susp(req, m);
-			break;
-		}
-		D_ASSERT(!(req->rq_state & RQ_LOCAL_PENDING));
-		req->rq_state |= RQ_LOCAL_PENDING;
-
-		get_ldev(mdev);
-		req->w.cb = w_restart_disk_io;
-		drbd_queue_work(&mdev->tconn->data.work, &req->w);
-		break;
-
 	case FAIL_FROZEN_DISK_IO:
 		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
 			break;