drbd: Starting with protocol 96 we can allow app-IO while receiving the bitmap

* C_STARTING_SYNC_S, C_STARTING_SYNC_T In these states the bitmap gets
  written to disk. Locking out of app-IO is done by using the
  drbd_queue_bitmap_io() and drbd_bitmap_io() functions these days.
  It is no longer necessary to lock out app-IO based on the connection
  state.
  App-IO that may come in after the BITMAP_IO flag got cleared before the
  state transition to C_SYNC_(SOURCE|TARGET) does not get mirrored, sets
  a bit in the local bitmap, that is already set, therefore changes nothing.

* C_WF_BITMAP_S In this state we send updates (P_OUT_OF_SYNC packets).
  With that we make sure they have the same number of bits when going
  into the C_SYNC_(SOURCE|TARGET) connection state.

* C_UNCONNECTED: The receiver starts, no need to lock out IO.

* C_DISCONNECTING: in drbd_disconnect() we had a wait_event()
  to wait until ap_bio_cnt reaches 0. Removed that.

* C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE
  C_PROTOCOL_ERROR, C_TEAR_DOWN: Same as C_DISCONNECTING

* C_WF_REPORT_PARAMS: IO still possible since that is still
  like C_WF_CONNECTION.

And we do not need to send barriers in C_WF_BITMAP_S connection state.

Allow concurrent accesses to the bitmap when receiving the bitmap.
Everything gets ORed anyways.

A drbd_free_tl_hash() is in after_state_chg_work(). At that point
all the work items of the last connections must have been processed.

Introduced a call to drbd_free_tl_hash() into drbd_free_mdev()
for paranoia reasons.

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 eff0fbf..4cb8247 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -142,7 +142,7 @@
 
 	/* before we can signal completion to the upper layers,
 	 * we may need to close the current epoch */
-	if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD &&
+	if (mdev->state.conn >= C_WF_BITMAP_T && mdev->state.conn < C_AHEAD &&
 	    req->epoch == mdev->newest_tle->br_number)
 		queue_barrier(mdev);
 
@@ -757,6 +757,23 @@
 	return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr);
 }
 
+static int drbd_should_do_remote(struct drbd_conf *mdev)
+{
+	union drbd_state s = mdev->state;
+
+	return s.pdsk == D_UP_TO_DATE ||
+		(s.pdsk >= D_INCONSISTENT &&
+		 s.conn >= C_WF_BITMAP_T &&
+		 s.conn < C_AHEAD);
+}
+static int drbd_should_send_oos(struct drbd_conf *mdev)
+{
+	union drbd_state s = mdev->state;
+
+	return s.pdsk >= D_INCONSISTENT &&
+		(s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S);
+}
+
 static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
 {
 	const int rw = bio_rw(bio);
@@ -828,12 +845,9 @@
 		drbd_al_begin_io(mdev, sector);
 	}
 
-	remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
-			    (mdev->state.pdsk >= D_INCONSISTENT &&
-			     mdev->state.conn >= C_CONNECTED &&
-			     mdev->state.conn < C_AHEAD));
-	send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD &&
-		    mdev->state.pdsk >= D_INCONSISTENT);
+	remote = remote && drbd_should_do_remote(mdev);
+	send_oos = rw == WRITE && drbd_should_send_oos(mdev);
+	D_ASSERT(!(remote && send_oos));
 
 	if (!(local || remote) && !is_susp(mdev->state)) {
 		if (__ratelimit(&drbd_ratelimit_state))
@@ -873,12 +887,9 @@
 	}
 
 	if (remote || send_oos) {
-		remote = (mdev->state.pdsk == D_UP_TO_DATE ||
-			    (mdev->state.pdsk >= D_INCONSISTENT &&
-			     mdev->state.conn >= C_CONNECTED &&
-			     mdev->state.conn < C_AHEAD));
-		send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD &&
-			    mdev->state.pdsk >= D_INCONSISTENT);
+		remote = drbd_should_do_remote(mdev);
+		send_oos = rw == WRITE && drbd_should_send_oos(mdev);
+		D_ASSERT(!(remote && send_oos));
 
 		if (!(remote || send_oos))
 			dev_warn(DEV, "lost connection while grabbing the req_lock!\n");