drbd: Introduce protocol version 100 headers
authorAndreas Gruenbacher <agruen@linbit.com>
Wed, 30 Mar 2011 14:00:17 +0000 (16:00 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 8 Nov 2012 15:45:10 +0000 (16:45 +0100)
The 8 byte header finally becomes too small. With the protocol 100 header we
have 16 bit for the volume number, proper 32 bit for the data length, and
32 bit for further extensions in the future.

Previous versions of drbd are using version 80 headers for all packets
short enough for protocol 80.  They support both header versions in
worker context, but only version 80 headers in asynchronous context.
For backwards compatibility, continue to use version 80 headers for
short packets before protocol version 100.

From protocol version 100 on, use the same header version for all
packets.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_receiver.c
include/linux/drbd.h
include/linux/drbd_genl.h
include/linux/drbd_limits.h

index 6d55bb75a081c3ec73ad2ec4a9e1c4e990127e87..bf1aad683387c0acd4703e609b06f3e745cc0c5b 100644 (file)
@@ -307,6 +307,14 @@ struct p_header95 {
        u32       length;       /* Use only 24 bits of that. Ignore the highest 8 bit. */
 } __packed;
 
+struct p_header100 {
+       u32       magic;
+       u16       volume;
+       u16       command;
+       u32       length;
+       u32       pad;
+} __packed;
+
 extern unsigned int drbd_header_size(struct drbd_tconn *tconn);
 
 /* these defines must not be changed without changing the protocol version */
index b9dcc50135c42800ee01188c27cd725f41fc9e3b..5d9112cefcd727d015e1c8b399f6af9af35f2ce9 100644 (file)
@@ -698,9 +698,15 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi)
  */
 unsigned int drbd_header_size(struct drbd_tconn *tconn)
 {
-       BUILD_BUG_ON(sizeof(struct p_header80) != sizeof(struct p_header95));
-       BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header80), 8));
-       return sizeof(struct p_header80);
+       if (tconn->agreed_pro_version >= 100) {
+               BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header100), 8));
+               return sizeof(struct p_header100);
+       } else {
+               BUILD_BUG_ON(sizeof(struct p_header80) !=
+                            sizeof(struct p_header95));
+               BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header80), 8));
+               return sizeof(struct p_header80);
+       }
 }
 
 static unsigned int prepare_header80(struct p_header80 *h, enum drbd_packet cmd, int size)
@@ -719,10 +725,24 @@ static unsigned int prepare_header95(struct p_header95 *h, enum drbd_packet cmd,
        return sizeof(struct p_header95);
 }
 
-static unsigned int prepare_header(struct drbd_tconn *tconn, int vnr, void *buffer,
-                                  enum drbd_packet cmd, int size)
+static unsigned int prepare_header100(struct p_header100 *h, enum drbd_packet cmd,
+                                     int size, int vnr)
+{
+       h->magic = cpu_to_be32(DRBD_MAGIC_100);
+       h->volume = cpu_to_be16(vnr);
+       h->command = cpu_to_be16(cmd);
+       h->length = cpu_to_be32(size);
+       h->pad = 0;
+       return sizeof(struct p_header100);
+}
+
+static unsigned int prepare_header(struct drbd_tconn *tconn, int vnr,
+                                  void *buffer, enum drbd_packet cmd, int size)
 {
-       if (tconn->agreed_pro_version >= 95)
+       if (tconn->agreed_pro_version >= 100)
+               return prepare_header100(buffer, cmd, size, vnr);
+       else if (tconn->agreed_pro_version >= 95 &&
+                size > DRBD_MAX_SIZE_H80_PACKET)
                return prepare_header95(buffer, cmd, size);
        else
                return prepare_header80(buffer, cmd, size);
index d9bb1a5c756a284a3252871c05607ae11ecf5263..0f52b88719c897847b23a200f37313ba5967431c 100644 (file)
@@ -2833,8 +2833,7 @@ int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info)
                retcode = ERR_INVALID_REQUEST;
                goto out;
        }
-       /* FIXME we need a define here */
-       if (adm_ctx.volume >= 256) {
+       if (adm_ctx.volume > DRBD_VOLUME_MAX) {
                drbd_msg_put_info("requested volume id out of range");
                retcode = ERR_INVALID_REQUEST;
                goto out;
index 7e0ab2246fb6ef470bf9e4cf41d62b9d25e8e6be..311b95453cb7e29d008ef3d2cd74773290e02661 100644 (file)
@@ -983,8 +983,18 @@ static int decode_header(struct drbd_tconn *tconn, void *header, struct packet_i
 {
        unsigned int header_size = drbd_header_size(tconn);
 
-       if (header_size == sizeof(struct p_header95) &&
-           *(__be16 *)header == cpu_to_be16(DRBD_MAGIC_BIG)) {
+       if (header_size == sizeof(struct p_header100) &&
+           *(__be32 *)header == cpu_to_be32(DRBD_MAGIC_100)) {
+               struct p_header100 *h = header;
+               if (h->pad != 0) {
+                       conn_err(tconn, "Header padding is not zero\n");
+                       return -EINVAL;
+               }
+               pi->vnr = be16_to_cpu(h->volume);
+               pi->cmd = be16_to_cpu(h->command);
+               pi->size = be32_to_cpu(h->length);
+       } else if (header_size == sizeof(struct p_header95) &&
+                  *(__be16 *)header == cpu_to_be16(DRBD_MAGIC_BIG)) {
                struct p_header95 *h = header;
 
                pi->cmd = be16_to_cpu(h->command);
index 60d308819096006abbfb778e128919aa97caa371..fe8d6ba31bcbd3f47cfd06b4ac6c4780e19ce12b 100644 (file)
@@ -341,6 +341,7 @@ enum drbd_timeout_flag {
 
 #define DRBD_MAGIC 0x83740267
 #define DRBD_MAGIC_BIG 0x835a
+#define DRBD_MAGIC_100 0x8620ec20
 
 /* how I came up with this magic?
  * base64 decode "actlog==" ;) */
index 938e8560a8333045cae588162c05e77958c522ac..10144d546a66f65a9457cb838660909375bd5bb0 100644 (file)
@@ -95,8 +95,6 @@ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply,
  * and/or the replication group (aka resource) name,
  * and the volume id within the resource. */
 GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context,
-               /* currently only 256 volumes per group,
-                * but maybe we still change that */
        __u32_field(1, GENLA_F_MANDATORY,       ctx_volume)
        __str_field(2, GENLA_F_MANDATORY,       ctx_conn_name, 128)
 )
index 659a8eb3883010ba2e872be34c7f336c0eb97bbc..7f5149bef70eb98345f94e84e3a75ee026e38d59 100644 (file)
@@ -19,6 +19,8 @@
 #define DRBD_MINOR_COUNT_MAX 256
 #define DRBD_MINOR_COUNT_DEF 32
 
+#define DRBD_VOLUME_MAX 65535
+
 #define DRBD_DIALOG_REFRESH_MIN 0
 #define DRBD_DIALOG_REFRESH_MAX 600