drbd: Remove some fixed header size assumptions
authorAndreas Gruenbacher <agruen@linbit.com>
Wed, 30 Mar 2011 09:53:51 +0000 (11:53 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 8 Nov 2012 15:45:09 +0000 (16:45 +0100)
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_receiver.c

index ccc374cc7eaad6d6abf83fe6dd77ee3b4120e9ae..cb16783e78df14fcda1697852330d878730028fb 100644 (file)
@@ -543,19 +543,10 @@ struct p_delay_probe93 {
        u32     offset;  /* usecs the probe got sent after the reference time point */
 } __packed;
 
-/* one bitmap packet, including the p_header,
- * should fit within one _architecture independend_ page.
- * so we need to use the fixed size 4KiB page size
- * most architectures have used for a long time.
+/*
+ * Bitmap packets need to fit within a single page on the sender and receiver,
+ * so we are limited to 4 KiB (and not to PAGE_SIZE, which can be bigger).
  */
-#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header))
-#define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
-#define BM_PACKET_VLI_BYTES_MAX (4096 - sizeof(struct p_compressed_bm))
-#if (PAGE_SIZE < 4096)
-/* drbd_send_bitmap / receive_bitmap would break horribly */
-#error "PAGE_SIZE too small"
-#endif
-
 #define DRBD_SOCKET_BUFFER_SIZE 4096
 
 /**********************************************************************/
index e3dc84dcd67e22f11a023e15f629e552a4983a4d..3ecbd4908cdcb352d18cad6ad9bc37aa41092d43 100644 (file)
@@ -1100,8 +1100,9 @@ static void dcbp_set_pad_bits(struct p_compressed_bm *p, int n)
 }
 
 int fill_bitmap_rle_bits(struct drbd_conf *mdev,
-       struct p_compressed_bm *p,
-       struct bm_xfer_ctx *c)
+                        struct p_compressed_bm *p,
+                        unsigned int size,
+                        struct bm_xfer_ctx *c)
 {
        struct bitstream bs;
        unsigned long plain_bits;
@@ -1120,8 +1121,8 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
                return 0; /* nothing to do. */
 
        /* use at most thus many bytes */
-       bitstream_init(&bs, p->code, BM_PACKET_VLI_BYTES_MAX, 0);
-       memset(p->code, 0, BM_PACKET_VLI_BYTES_MAX);
+       bitstream_init(&bs, p->code, size, 0);
+       memset(p->code, 0, size);
        /* plain bits covered in this code string */
        plain_bits = 0;
 
@@ -1203,11 +1204,11 @@ static int
 send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
 {
        struct drbd_socket *sock = &mdev->tconn->data;
+       unsigned int header_size = drbd_header_size(mdev->tconn);
        struct p_compressed_bm *p = sock->sbuf;
-       unsigned long num_words;
        int len, err;
 
-       len = fill_bitmap_rle_bits(mdev, p, c);
+       len = fill_bitmap_rle_bits(mdev, p, DRBD_SOCKET_BUFFER_SIZE - sizeof(*p) /* FIXME */, c);
        if (len < 0)
                return -EIO;
 
@@ -1224,9 +1225,14 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
        } else {
                /* was not compressible.
                 * send a buffer full of plain text bits instead. */
+               unsigned int data_size;
+               unsigned long num_words;
                struct p_header *h = sock->sbuf;
-               num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
-               len = num_words * sizeof(long);
+
+               data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
+               num_words = min_t(size_t, data_size / sizeof(unsigned long),
+                                 c->bm_words - c->word_offset);
+               len = num_words * sizeof(unsigned long);
                if (len)
                        drbd_bm_get_lel(mdev, c->word_offset, num_words,
                                        (unsigned long *)h->payload);
@@ -1236,7 +1242,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
                c->bit_offset = c->word_offset * BITS_PER_LONG;
 
                c->packets[1]++;
-               c->bytes[1] += sizeof(struct p_header80) + len;
+               c->bytes[1] += header_size + len;
 
                if (c->bit_offset > c->bm_bits)
                        c->bit_offset = c->bm_bits;
@@ -2550,7 +2556,6 @@ int __init drbd_init(void)
 {
        int err;
 
-       BUILD_BUG_ON(sizeof(struct p_header80) != sizeof(struct p_header95));
        BUILD_BUG_ON(sizeof(struct p_connection_features) != 80);
 
        if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
index 40fe7199d5f782b7badd49a5a869666deb8b295e..74ed3ac263f36d792576a8c5ae01224602cdbc16 100644 (file)
@@ -3660,16 +3660,19 @@ static int receive_sync_uuid(struct drbd_tconn *tconn, struct packet_info *pi)
  * code upon failure.
  */
 static int
-receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
+receive_bitmap_plain(struct drbd_conf *mdev, unsigned int size,
                     struct p_header *h, struct bm_xfer_ctx *c)
 {
        unsigned long *buffer = (unsigned long *)h->payload;
-       unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
-       unsigned want = num_words * sizeof(long);
+       unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE -
+                                drbd_header_size(mdev->tconn);
+       unsigned int num_words = min_t(size_t, data_size / sizeof(unsigned long),
+                                      c->bm_words - c->word_offset);
+       unsigned int want = num_words * sizeof(unsigned long);
        int err;
 
-       if (want != data_size) {
-               dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
+       if (want != size) {
+               dev_err(DEV, "%s:want (%u) != size (%u)\n", __func__, want, size);
                return -EIO;
        }
        if (want == 0)
@@ -3796,11 +3799,13 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
                const char *direction, struct bm_xfer_ctx *c)
 {
        /* what would it take to transfer it "plaintext" */
-       unsigned plain = sizeof(struct p_header) *
-               ((c->bm_words+BM_PACKET_WORDS-1)/BM_PACKET_WORDS+1)
-               + c->bm_words * sizeof(long);
-       unsigned total = c->bytes[0] + c->bytes[1];
-       unsigned r;
+       unsigned int header_size = drbd_header_size(mdev->tconn);
+       unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
+       unsigned int plain =
+               header_size * (DIV_ROUND_UP(c->bm_words, data_size) + 1) +
+               c->bm_words * sizeof(unsigned long);
+       unsigned int total = c->bytes[0] + c->bytes[1];
+       unsigned int r;
 
        /* total can not be zero. but just in case: */
        if (total == 0)
@@ -3862,7 +3867,7 @@ static int receive_bitmap(struct drbd_tconn *tconn, struct packet_info *pi)
                         * and the feature is enabled! */
                        struct p_compressed_bm *p;
 
-                       if (pi->size > BM_PACKET_PAYLOAD_BYTES) {
+                       if (pi->size > DRBD_SOCKET_BUFFER_SIZE - drbd_header_size(tconn)) {
                                dev_err(DEV, "ReportCBitmap packet too large\n");
                                err = -EIO;
                                goto out;
@@ -3885,7 +3890,7 @@ static int receive_bitmap(struct drbd_tconn *tconn, struct packet_info *pi)
                }
 
                c.packets[pi->cmd == P_BITMAP]++;
-               c.bytes[pi->cmd == P_BITMAP] += sizeof(struct p_header) + pi->size;
+               c.bytes[pi->cmd == P_BITMAP] += drbd_header_size(tconn) + pi->size;
 
                if (err <= 0) {
                        if (err < 0)