drbd: Implemented receiving of new style packets on meta socket

Now drbd communication with protocol 100 actually works.
Replaced the remaining p_header80 with p_header where we
no longer know which header it is.

In the places where p_header80 is still in use, it is on
purpose, because we know that it is an old style header
there.

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_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 8f5a241..c0435c4 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -926,18 +926,9 @@
 	return -1;
 }
 
-static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
+static bool decode_header(struct drbd_conf *mdev, struct p_header *h, enum drbd_packets *cmd,
+			  unsigned int *packet_size)
 {
-	struct p_header *h = &mdev->tconn->data.rbuf.header;
-	int r;
-
-	r = drbd_recv(mdev, h, sizeof(*h));
-	if (unlikely(r != sizeof(*h))) {
-		if (!signal_pending(current))
-			dev_warn(DEV, "short read expecting header on sock: r=%d\n", r);
-		return false;
-	}
-
 	if (h->h80.magic == cpu_to_be32(DRBD_MAGIC)) {
 		*cmd = be16_to_cpu(h->h80.command);
 		*packet_size = be16_to_cpu(h->h80.length);
@@ -951,9 +942,25 @@
 		    be16_to_cpu(h->h80.length));
 		return false;
 	}
+	return true;
+}
+
+static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
+{
+	struct p_header *h = &mdev->tconn->data.rbuf.header;
+	int r;
+
+	r = drbd_recv(mdev, h, sizeof(*h));
+	if (unlikely(r != sizeof(*h))) {
+		if (!signal_pending(current))
+			dev_warn(DEV, "short read expecting header on sock: r=%d\n", r);
+		return false;
+	}
+
+	r = decode_header(mdev, h, cmd, packet_size);
 	mdev->tconn->last_received = jiffies;
 
-	return true;
+	return r;
 }
 
 static void drbd_flush(struct drbd_conf *mdev)
@@ -2807,14 +2814,14 @@
 	}
 
 	if (apv <= 88) {
-		header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80);
+		header_size = sizeof(struct p_rs_param) - sizeof(struct p_header);
 		data_size   = packet_size  - header_size;
 	} else if (apv <= 94) {
-		header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80);
+		header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header);
 		data_size   = packet_size  - header_size;
 		D_ASSERT(data_size == 0);
 	} else {
-		header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80);
+		header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header);
 		data_size   = packet_size  - header_size;
 		D_ASSERT(data_size == 0);
 	}
@@ -3524,7 +3531,7 @@
 	void *buffer;
 	int err;
 	int ok = false;
-	struct p_header80 *h = &mdev->tconn->data.rbuf.header.h80;
+	struct p_header *h = &mdev->tconn->data.rbuf.header;
 
 	drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED);
 	/* you are supposed to send additional out-of-sync information
@@ -3571,7 +3578,7 @@
 		}
 
 		c.packets[cmd == P_BITMAP]++;
-		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
+		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header) + data_size;
 
 		if (err <= 0) {
 			if (err < 0)
@@ -3670,13 +3677,13 @@
 	[P_DATA_REPLY]	    = { 1, sizeof(struct p_data), receive_DataReply },
 	[P_RS_DATA_REPLY]   = { 1, sizeof(struct p_data), receive_RSDataReply } ,
 	[P_BARRIER]	    = { 0, sizeof(struct p_barrier), receive_Barrier } ,
-	[P_BITMAP]	    = { 1, sizeof(struct p_header80), receive_bitmap } ,
-	[P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
-	[P_UNPLUG_REMOTE]   = { 0, sizeof(struct p_header80), receive_UnplugRemote },
+	[P_BITMAP]	    = { 1, sizeof(struct p_header), receive_bitmap } ,
+	[P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header), receive_bitmap } ,
+	[P_UNPLUG_REMOTE]   = { 0, sizeof(struct p_header), receive_UnplugRemote },
 	[P_DATA_REQUEST]    = { 0, sizeof(struct p_block_req), receive_DataRequest },
 	[P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
-	[P_SYNC_PARAM]	    = { 1, sizeof(struct p_header80), receive_SyncParam },
-	[P_SYNC_PARAM89]    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_SYNC_PARAM]	    = { 1, sizeof(struct p_header), receive_SyncParam },
+	[P_SYNC_PARAM89]    = { 1, sizeof(struct p_header), receive_SyncParam },
 	[P_PROTOCOL]        = { 1, sizeof(struct p_protocol), receive_protocol },
 	[P_UUIDS]	    = { 0, sizeof(struct p_uuids), receive_uuids },
 	[P_SIZES]	    = { 0, sizeof(struct p_sizes), receive_sizes },
@@ -4184,9 +4191,9 @@
 
 /* ********* acknowledge sender ******** */
 
-static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_RqSReply(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_req_state_reply *p = (struct p_req_state_reply *)h;
+	struct p_req_state_reply *p = &mdev->tconn->meta.rbuf.req_state_reply;
 
 	int retcode = be32_to_cpu(p->retcode);
 
@@ -4202,13 +4209,13 @@
 	return true;
 }
 
-static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_Ping(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
 	return drbd_send_ping_ack(mdev);
 
 }
 
-static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_PingAck(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
 	/* restore idle timeout */
 	mdev->tconn->meta.socket->sk->sk_rcvtimeo = mdev->tconn->net_conf->ping_int*HZ;
@@ -4218,9 +4225,9 @@
 	return true;
 }
 
-static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_IsInSync(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 
@@ -4263,9 +4270,9 @@
 	return true;
 }
 
-static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_BlockAck(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 	enum drbd_req_event what;
@@ -4277,7 +4284,7 @@
 		dec_rs_pending(mdev);
 		return true;
 	}
-	switch (be16_to_cpu(h->command)) {
+	switch (cmd) {
 	case P_RS_WRITE_ACK:
 		D_ASSERT(mdev->tconn->net_conf->wire_protocol == DRBD_PROT_C);
 		what = WRITE_ACKED_BY_PEER_AND_SIS;
@@ -4304,9 +4311,9 @@
 					     what, false);
 }
 
-static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegAck(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 	sector_t sector = be64_to_cpu(p->sector);
 	int size = be32_to_cpu(p->blksize);
 	bool missing_ok = mdev->tconn->net_conf->wire_protocol == DRBD_PROT_A ||
@@ -4337,9 +4344,9 @@
 	return true;
 }
 
-static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegDReply(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 	sector_t sector = be64_to_cpu(p->sector);
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
@@ -4351,11 +4358,11 @@
 					     NEG_ACKED, false);
 }
 
-static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegRSDReply(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
 	sector_t sector;
 	int size;
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 
 	sector = be64_to_cpu(p->sector);
 	size = be32_to_cpu(p->blksize);
@@ -4366,7 +4373,7 @@
 
 	if (get_ldev_if_state(mdev, D_FAILED)) {
 		drbd_rs_complete_io(mdev, sector);
-		switch (be16_to_cpu(h->command)) {
+		switch (cmd) {
 		case P_NEG_RS_DREPLY:
 			drbd_rs_failed_io(mdev, sector, size);
 		case P_RS_CANCEL:
@@ -4382,9 +4389,9 @@
 	return true;
 }
 
-static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_BarrierAck(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_barrier_ack *p = (struct p_barrier_ack *)h;
+	struct p_barrier_ack *p = &mdev->tconn->meta.rbuf.barrier_ack;
 
 	tl_release(mdev, p->barrier, be32_to_cpu(p->set_size));
 
@@ -4398,9 +4405,9 @@
 	return true;
 }
 
-static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_OVResult(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = &mdev->tconn->meta.rbuf.block_ack;
 	struct drbd_work *w;
 	sector_t sector;
 	int size;
@@ -4442,14 +4449,14 @@
 	return true;
 }
 
-static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_skip(struct drbd_conf *mdev, enum drbd_packets cmd)
 {
 	return true;
 }
 
 struct asender_cmd {
 	size_t pkt_size;
-	int (*process)(struct drbd_conf *mdev, struct p_header80 *h);
+	int (*process)(struct drbd_conf *mdev, enum drbd_packets cmd);
 };
 
 static struct asender_cmd *get_asender_cmd(int cmd)
@@ -4458,8 +4465,8 @@
 		/* anything missing from this table is in
 		 * the drbd_cmd_handler (drbd_default_handler) table,
 		 * see the beginning of drbdd() */
-	[P_PING]	    = { sizeof(struct p_header80), got_Ping },
-	[P_PING_ACK]	    = { sizeof(struct p_header80), got_PingAck },
+	[P_PING]	    = { sizeof(struct p_header), got_Ping },
+	[P_PING_ACK]	    = { sizeof(struct p_header), got_PingAck },
 	[P_RECV_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_WRITE_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_RS_WRITE_ACK]    = { sizeof(struct p_block_ack), got_BlockAck },
@@ -4483,15 +4490,16 @@
 int drbd_asender(struct drbd_thread *thi)
 {
 	struct drbd_conf *mdev = thi->mdev;
-	struct p_header80 *h = &mdev->tconn->meta.rbuf.header.h80;
+	struct p_header *h = &mdev->tconn->meta.rbuf.header;
 	struct asender_cmd *cmd = NULL;
 
-	int rv, len;
+	int rv;
 	void *buf    = h;
 	int received = 0;
-	int expect   = sizeof(struct p_header80);
-	int empty;
+	int expect   = sizeof(struct p_header);
 	int ping_timeout_active = 0;
+	int empty, pkt_size;
+	enum drbd_packets cmd_nr;
 
 	sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
 
@@ -4581,30 +4589,25 @@
 		}
 
 		if (received == expect && cmd == NULL) {
-			if (unlikely(h->magic != cpu_to_be32(DRBD_MAGIC))) {
-				dev_err(DEV, "magic?? on meta m: 0x%08x c: %d l: %d\n",
-				    be32_to_cpu(h->magic),
-				    be16_to_cpu(h->command),
-				    be16_to_cpu(h->length));
+			if (!decode_header(mdev, h, &cmd_nr, &pkt_size))
 				goto reconnect;
-			}
-			cmd = get_asender_cmd(be16_to_cpu(h->command));
-			len = be16_to_cpu(h->length);
+			cmd = get_asender_cmd(cmd_nr);
 			if (unlikely(cmd == NULL)) {
-				dev_err(DEV, "unknown command?? on meta m: 0x%08x c: %d l: %d\n",
-				    be32_to_cpu(h->magic),
-				    be16_to_cpu(h->command),
-				    be16_to_cpu(h->length));
+				dev_err(DEV, "unknown command %d on meta (l: %d)\n",
+					cmd_nr, pkt_size);
 				goto disconnect;
 			}
 			expect = cmd->pkt_size;
-			if (!expect(len == expect - sizeof(struct p_header80)))
+			if (pkt_size != expect - sizeof(struct p_header)) {
+				dev_err(DEV, "Wrong packet size on meta (c: %d, l: %d)\n",
+					cmd_nr, pkt_size);
 				goto reconnect;
+			}
 		}
 		if (received == expect) {
 			mdev->tconn->last_received = jiffies;
 			D_ASSERT(cmd != NULL);
-			if (!cmd->process(mdev, h))
+			if (!cmd->process(mdev, cmd_nr))
 				goto reconnect;
 
 			/* the idle_timeout (ping-int)
@@ -4614,7 +4617,7 @@
 
 			buf	 = h;
 			received = 0;
-			expect	 = sizeof(struct p_header80);
+			expect	 = sizeof(struct p_header);
 			cmd	 = NULL;
 		}
 	}