drbd: drbd_send_ack_dp must not rely on header information
authorLars Ellenberg <lars.ellenberg@linbit.com>
Wed, 6 Oct 2010 09:46:55 +0000 (11:46 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 14 Oct 2010 16:38:45 +0000 (18:38 +0200)
drbd commit 17c854fea474a5eb3cfa12e4fb019e46debbc4ec
drbd: receiving of big packets, for payloads between 64kByte and 4GByte
introduced a new on-the-wire packet header format.  We must no longer
assume either format, but use the result of whatever drbd_recv_header
has decoded.

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 1680939de101f092593a3cddd3f694c5dad1ba98..8ab6fed39539d0f043408d901fac0698cc5fbdb0 100644 (file)
@@ -1230,7 +1230,7 @@ extern int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
 extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
                        struct p_block_req *rp);
 extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-                       struct p_data *dp);
+                       struct p_data *dp, int data_size);
 extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
                            sector_t sector, int blksize, u64 block_id);
 extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
index e1f2c2e54f5f169ab9880e59996df16cfef4a50a..accb37d1215f0948928f8b3d7d9bd6fdd4ffbc64 100644 (file)
@@ -2193,13 +2193,14 @@ static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
        return ok;
 }
 
+/* dp->sector and dp->block_id already/still in network byte order,
+ * data_size is payload size according to dp->head,
+ * and may need to be corrected for digest size. */
 int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-                    struct p_data *dp)
+                    struct p_data *dp, int data_size)
 {
-       const int header_size = sizeof(struct p_data)
-                             - sizeof(struct p_header80);
-       int data_size  = ((struct p_header80 *)dp)->length - header_size;
-
+       data_size -= (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
+               crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
        return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
                              dp->block_id);
 }
index b5d3fa6c7a8b625e47762d7c4c8e62363a8523f7..45a2d610ca1db81e3d924ca9c946fe5d0152ac15 100644 (file)
@@ -1630,7 +1630,7 @@ static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, un
 
                ok = drbd_drain_block(mdev, data_size);
 
-               drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+               drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
        }
 
        atomic_add(data_size >> 9, &mdev->rs_sect_in);
@@ -1787,7 +1787,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
                        mdev->peer_seq++;
                spin_unlock(&mdev->peer_seq_lock);
 
-               drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+               drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
                atomic_inc(&mdev->current_epoch->epoch_size);
                return drbd_drain_block(mdev, data_size);
        }