diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-08-20 08:35:10 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 12:38:24 -0400 |
commit | 02918be2273a6b086292e0d85b740336eda46e36 (patch) | |
tree | 2ec58d863e30be994bfe6ae6feb3ab888fb5c9f0 /drivers/block/drbd | |
parent | 0b70a13dac014ec9274640b9e945bde493ba365e (diff) |
drbd: receiving of big packets, for payloads between 64kByte and 4GByte
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 389 |
2 files changed, 171 insertions, 222 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3f10efc2ac14..db7e65531afa 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -626,7 +626,7 @@ DCBP_set_pad_bits(struct p_compressed_bm *p, int n) | |||
626 | #endif | 626 | #endif |
627 | 627 | ||
628 | union p_polymorph { | 628 | union p_polymorph { |
629 | struct p_header80 header; | 629 | union p_header header; |
630 | struct p_handshake handshake; | 630 | struct p_handshake handshake; |
631 | struct p_data data; | 631 | struct p_data data; |
632 | struct p_block_ack block_ack; | 632 | struct p_block_ack block_ack; |
@@ -641,6 +641,8 @@ union p_polymorph { | |||
641 | struct p_req_state req_state; | 641 | struct p_req_state req_state; |
642 | struct p_req_state_reply req_state_reply; | 642 | struct p_req_state_reply req_state_reply; |
643 | struct p_block_req block_req; | 643 | struct p_block_req block_req; |
644 | struct p_delay_probe93 delay_probe93; | ||
645 | struct p_rs_uuid rs_uuid; | ||
644 | } __packed; | 646 | } __packed; |
645 | 647 | ||
646 | /**********************************************************************/ | 648 | /**********************************************************************/ |
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 9b3321e2c3cd..fe308644a63c 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -720,14 +720,14 @@ out: | |||
720 | static int drbd_send_fp(struct drbd_conf *mdev, | 720 | static int drbd_send_fp(struct drbd_conf *mdev, |
721 | struct socket *sock, enum drbd_packets cmd) | 721 | struct socket *sock, enum drbd_packets cmd) |
722 | { | 722 | { |
723 | struct p_header80 *h = (struct p_header80 *) &mdev->data.sbuf.header; | 723 | struct p_header80 *h = &mdev->data.sbuf.header.h80; |
724 | 724 | ||
725 | return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0); | 725 | return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0); |
726 | } | 726 | } |
727 | 727 | ||
728 | static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock) | 728 | static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock) |
729 | { | 729 | { |
730 | struct p_header80 *h = (struct p_header80 *) &mdev->data.sbuf.header; | 730 | struct p_header80 *h = &mdev->data.rbuf.header.h80; |
731 | int rr; | 731 | int rr; |
732 | 732 | ||
733 | rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0); | 733 | rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0); |
@@ -944,22 +944,27 @@ out_release_sockets: | |||
944 | return -1; | 944 | return -1; |
945 | } | 945 | } |
946 | 946 | ||
947 | static int drbd_recv_header(struct drbd_conf *mdev, struct p_header80 *h) | 947 | static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size) |
948 | { | 948 | { |
949 | union p_header *h = &mdev->data.rbuf.header; | ||
949 | int r; | 950 | int r; |
950 | 951 | ||
951 | r = drbd_recv(mdev, h, sizeof(*h)); | 952 | r = drbd_recv(mdev, h, sizeof(*h)); |
952 | |||
953 | if (unlikely(r != sizeof(*h))) { | 953 | if (unlikely(r != sizeof(*h))) { |
954 | dev_err(DEV, "short read expecting header on sock: r=%d\n", r); | 954 | dev_err(DEV, "short read expecting header on sock: r=%d\n", r); |
955 | return FALSE; | 955 | return FALSE; |
956 | }; | 956 | } |
957 | h->command = be16_to_cpu(h->command); | 957 | |
958 | h->length = be16_to_cpu(h->length); | 958 | if (likely(h->h80.magic == BE_DRBD_MAGIC)) { |
959 | if (unlikely(h->magic != BE_DRBD_MAGIC)) { | 959 | *cmd = be16_to_cpu(h->h80.command); |
960 | *packet_size = be16_to_cpu(h->h80.length); | ||
961 | } else if (h->h95.magic == BE_DRBD_MAGIC_BIG) { | ||
962 | *cmd = be16_to_cpu(h->h95.command); | ||
963 | *packet_size = be32_to_cpu(h->h95.length); | ||
964 | } else { | ||
960 | dev_err(DEV, "magic?? on data m: 0x%lx c: %d l: %d\n", | 965 | dev_err(DEV, "magic?? on data m: 0x%lx c: %d l: %d\n", |
961 | (long)be32_to_cpu(h->magic), | 966 | (long)be32_to_cpu(h->h80.magic), |
962 | h->command, h->length); | 967 | h->h80.command, h->h80.length); |
963 | return FALSE; | 968 | return FALSE; |
964 | } | 969 | } |
965 | mdev->last_received = jiffies; | 970 | mdev->last_received = jiffies; |
@@ -1266,17 +1271,12 @@ int w_e_reissue(struct drbd_conf *mdev, struct drbd_work *w, int cancel) __relea | |||
1266 | return 1; | 1271 | return 1; |
1267 | } | 1272 | } |
1268 | 1273 | ||
1269 | static int receive_Barrier(struct drbd_conf *mdev, struct p_header80 *h) | 1274 | static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
1270 | { | 1275 | { |
1271 | int rv, issue_flush; | 1276 | int rv, issue_flush; |
1272 | struct p_barrier *p = (struct p_barrier *)h; | 1277 | struct p_barrier *p = &mdev->data.rbuf.barrier; |
1273 | struct drbd_epoch *epoch; | 1278 | struct drbd_epoch *epoch; |
1274 | 1279 | ||
1275 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; | ||
1276 | |||
1277 | rv = drbd_recv(mdev, h->payload, h->length); | ||
1278 | ERR_IF(rv != h->length) return FALSE; | ||
1279 | |||
1280 | inc_unacked(mdev); | 1280 | inc_unacked(mdev); |
1281 | 1281 | ||
1282 | if (mdev->net_conf->wire_protocol != DRBD_PROT_C) | 1282 | if (mdev->net_conf->wire_protocol != DRBD_PROT_C) |
@@ -1570,21 +1570,12 @@ fail: | |||
1570 | return FALSE; | 1570 | return FALSE; |
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | static int receive_DataReply(struct drbd_conf *mdev, struct p_header80 *h) | 1573 | static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
1574 | { | 1574 | { |
1575 | struct drbd_request *req; | 1575 | struct drbd_request *req; |
1576 | sector_t sector; | 1576 | sector_t sector; |
1577 | unsigned int header_size, data_size; | ||
1578 | int ok; | 1577 | int ok; |
1579 | struct p_data *p = (struct p_data *)h; | 1578 | struct p_data *p = &mdev->data.rbuf.data; |
1580 | |||
1581 | header_size = sizeof(*p) - sizeof(*h); | ||
1582 | data_size = h->length - header_size; | ||
1583 | |||
1584 | ERR_IF(data_size == 0) return FALSE; | ||
1585 | |||
1586 | if (drbd_recv(mdev, h->payload, header_size) != header_size) | ||
1587 | return FALSE; | ||
1588 | 1579 | ||
1589 | sector = be64_to_cpu(p->sector); | 1580 | sector = be64_to_cpu(p->sector); |
1590 | 1581 | ||
@@ -1610,20 +1601,11 @@ static int receive_DataReply(struct drbd_conf *mdev, struct p_header80 *h) | |||
1610 | return ok; | 1601 | return ok; |
1611 | } | 1602 | } |
1612 | 1603 | ||
1613 | static int receive_RSDataReply(struct drbd_conf *mdev, struct p_header80 *h) | 1604 | static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
1614 | { | 1605 | { |
1615 | sector_t sector; | 1606 | sector_t sector; |
1616 | unsigned int header_size, data_size; | ||
1617 | int ok; | 1607 | int ok; |
1618 | struct p_data *p = (struct p_data *)h; | 1608 | struct p_data *p = &mdev->data.rbuf.data; |
1619 | |||
1620 | header_size = sizeof(*p) - sizeof(*h); | ||
1621 | data_size = h->length - header_size; | ||
1622 | |||
1623 | ERR_IF(data_size == 0) return FALSE; | ||
1624 | |||
1625 | if (drbd_recv(mdev, h->payload, header_size) != header_size) | ||
1626 | return FALSE; | ||
1627 | 1609 | ||
1628 | sector = be64_to_cpu(p->sector); | 1610 | sector = be64_to_cpu(p->sector); |
1629 | D_ASSERT(p->block_id == ID_SYNCER); | 1611 | D_ASSERT(p->block_id == ID_SYNCER); |
@@ -1767,23 +1749,14 @@ static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq) | |||
1767 | } | 1749 | } |
1768 | 1750 | ||
1769 | /* mirrored write */ | 1751 | /* mirrored write */ |
1770 | static int receive_Data(struct drbd_conf *mdev, struct p_header80 *h) | 1752 | static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
1771 | { | 1753 | { |
1772 | sector_t sector; | 1754 | sector_t sector; |
1773 | struct drbd_epoch_entry *e; | 1755 | struct drbd_epoch_entry *e; |
1774 | struct p_data *p = (struct p_data *)h; | 1756 | struct p_data *p = &mdev->data.rbuf.data; |
1775 | int header_size, data_size; | ||
1776 | int rw = WRITE; | 1757 | int rw = WRITE; |
1777 | u32 dp_flags; | 1758 | u32 dp_flags; |
1778 | 1759 | ||
1779 | header_size = sizeof(*p) - sizeof(*h); | ||
1780 | data_size = h->length - header_size; | ||
1781 | |||
1782 | ERR_IF(data_size == 0) return FALSE; | ||
1783 | |||
1784 | if (drbd_recv(mdev, h->payload, header_size) != header_size) | ||
1785 | return FALSE; | ||
1786 | |||
1787 | if (!get_ldev(mdev)) { | 1760 | if (!get_ldev(mdev)) { |
1788 | if (__ratelimit(&drbd_ratelimit_state)) | 1761 | if (__ratelimit(&drbd_ratelimit_state)) |
1789 | dev_err(DEV, "Can not write mirrored data block " | 1762 | dev_err(DEV, "Can not write mirrored data block " |
@@ -2066,20 +2039,15 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev) | |||
2066 | } | 2039 | } |
2067 | 2040 | ||
2068 | 2041 | ||
2069 | static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | 2042 | static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int digest_size) |
2070 | { | 2043 | { |
2071 | sector_t sector; | 2044 | sector_t sector; |
2072 | const sector_t capacity = drbd_get_capacity(mdev->this_bdev); | 2045 | const sector_t capacity = drbd_get_capacity(mdev->this_bdev); |
2073 | struct drbd_epoch_entry *e; | 2046 | struct drbd_epoch_entry *e; |
2074 | struct digest_info *di = NULL; | 2047 | struct digest_info *di = NULL; |
2075 | struct p_block_req *p = (struct p_block_req *)h; | 2048 | int size; |
2076 | const int brps = sizeof(*p)-sizeof(*h); | ||
2077 | int size, digest_size; | ||
2078 | unsigned int fault_type; | 2049 | unsigned int fault_type; |
2079 | 2050 | struct p_block_req *p = &mdev->data.rbuf.block_req; | |
2080 | |||
2081 | if (drbd_recv(mdev, h->payload, brps) != brps) | ||
2082 | return FALSE; | ||
2083 | 2051 | ||
2084 | sector = be64_to_cpu(p->sector); | 2052 | sector = be64_to_cpu(p->sector); |
2085 | size = be32_to_cpu(p->blksize); | 2053 | size = be32_to_cpu(p->blksize); |
@@ -2099,9 +2067,9 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | |||
2099 | if (__ratelimit(&drbd_ratelimit_state)) | 2067 | if (__ratelimit(&drbd_ratelimit_state)) |
2100 | dev_err(DEV, "Can not satisfy peer's read request, " | 2068 | dev_err(DEV, "Can not satisfy peer's read request, " |
2101 | "no local data.\n"); | 2069 | "no local data.\n"); |
2102 | drbd_send_ack_rp(mdev, h->command == P_DATA_REQUEST ? P_NEG_DREPLY : | 2070 | drbd_send_ack_rp(mdev, cmd == P_DATA_REQUEST ? P_NEG_DREPLY : |
2103 | P_NEG_RS_DREPLY , p); | 2071 | P_NEG_RS_DREPLY , p); |
2104 | return drbd_drain_block(mdev, h->length - brps); | 2072 | return TRUE; |
2105 | } | 2073 | } |
2106 | 2074 | ||
2107 | /* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD | 2075 | /* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD |
@@ -2113,7 +2081,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | |||
2113 | return FALSE; | 2081 | return FALSE; |
2114 | } | 2082 | } |
2115 | 2083 | ||
2116 | switch (h->command) { | 2084 | switch (cmd) { |
2117 | case P_DATA_REQUEST: | 2085 | case P_DATA_REQUEST: |
2118 | e->w.cb = w_e_end_data_req; | 2086 | e->w.cb = w_e_end_data_req; |
2119 | fault_type = DRBD_FAULT_DT_RD; | 2087 | fault_type = DRBD_FAULT_DT_RD; |
@@ -2128,7 +2096,6 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | |||
2128 | case P_OV_REPLY: | 2096 | case P_OV_REPLY: |
2129 | case P_CSUM_RS_REQUEST: | 2097 | case P_CSUM_RS_REQUEST: |
2130 | fault_type = DRBD_FAULT_RS_RD; | 2098 | fault_type = DRBD_FAULT_RS_RD; |
2131 | digest_size = h->length - brps ; | ||
2132 | di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO); | 2099 | di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO); |
2133 | if (!di) | 2100 | if (!di) |
2134 | goto out_free_e; | 2101 | goto out_free_e; |
@@ -2142,10 +2109,10 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | |||
2142 | if (drbd_recv(mdev, di->digest, digest_size) != digest_size) | 2109 | if (drbd_recv(mdev, di->digest, digest_size) != digest_size) |
2143 | goto out_free_e; | 2110 | goto out_free_e; |
2144 | 2111 | ||
2145 | if (h->command == P_CSUM_RS_REQUEST) { | 2112 | if (cmd == P_CSUM_RS_REQUEST) { |
2146 | D_ASSERT(mdev->agreed_pro_version >= 89); | 2113 | D_ASSERT(mdev->agreed_pro_version >= 89); |
2147 | e->w.cb = w_e_end_csum_rs_req; | 2114 | e->w.cb = w_e_end_csum_rs_req; |
2148 | } else if (h->command == P_OV_REPLY) { | 2115 | } else if (cmd == P_OV_REPLY) { |
2149 | e->w.cb = w_e_end_ov_reply; | 2116 | e->w.cb = w_e_end_ov_reply; |
2150 | dec_rs_pending(mdev); | 2117 | dec_rs_pending(mdev); |
2151 | /* drbd_rs_begin_io done when we sent this request, | 2118 | /* drbd_rs_begin_io done when we sent this request, |
@@ -2173,7 +2140,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header80 *h) | |||
2173 | 2140 | ||
2174 | default: | 2141 | default: |
2175 | dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n", | 2142 | dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n", |
2176 | cmdname(h->command)); | 2143 | cmdname(cmd)); |
2177 | fault_type = DRBD_FAULT_MAX; | 2144 | fault_type = DRBD_FAULT_MAX; |
2178 | goto out_free_e; | 2145 | goto out_free_e; |
2179 | } | 2146 | } |
@@ -2756,20 +2723,13 @@ static int cmp_after_sb(enum drbd_after_sb_p peer, enum drbd_after_sb_p self) | |||
2756 | return 1; | 2723 | return 1; |
2757 | } | 2724 | } |
2758 | 2725 | ||
2759 | static int receive_protocol(struct drbd_conf *mdev, struct p_header80 *h) | 2726 | static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
2760 | { | 2727 | { |
2761 | struct p_protocol *p = (struct p_protocol *)h; | 2728 | struct p_protocol *p = &mdev->data.rbuf.protocol; |
2762 | int header_size, data_size; | ||
2763 | int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p; | 2729 | int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p; |
2764 | int p_want_lose, p_two_primaries, cf; | 2730 | int p_want_lose, p_two_primaries, cf; |
2765 | char p_integrity_alg[SHARED_SECRET_MAX] = ""; | 2731 | char p_integrity_alg[SHARED_SECRET_MAX] = ""; |
2766 | 2732 | ||
2767 | header_size = sizeof(*p) - sizeof(*h); | ||
2768 | data_size = h->length - header_size; | ||
2769 | |||
2770 | if (drbd_recv(mdev, h->payload, header_size) != header_size) | ||
2771 | return FALSE; | ||
2772 | |||
2773 | p_proto = be32_to_cpu(p->protocol); | 2733 | p_proto = be32_to_cpu(p->protocol); |
2774 | p_after_sb_0p = be32_to_cpu(p->after_sb_0p); | 2734 | p_after_sb_0p = be32_to_cpu(p->after_sb_0p); |
2775 | p_after_sb_1p = be32_to_cpu(p->after_sb_1p); | 2735 | p_after_sb_1p = be32_to_cpu(p->after_sb_1p); |
@@ -2862,10 +2822,10 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev, | |||
2862 | return tfm; | 2822 | return tfm; |
2863 | } | 2823 | } |
2864 | 2824 | ||
2865 | static int receive_SyncParam(struct drbd_conf *mdev, struct p_header80 *h) | 2825 | static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size) |
2866 | { | 2826 | { |
2867 | int ok = TRUE; | 2827 | int ok = TRUE; |
2868 | struct p_rs_param_95 *p = (struct p_rs_param_95 *)h; | 2828 | struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95; |
2869 | unsigned int header_size, data_size, exp_max_sz; | 2829 | unsigned int header_size, data_size, exp_max_sz; |
2870 | struct crypto_hash *verify_tfm = NULL; | 2830 | struct crypto_hash *verify_tfm = NULL; |
2871 | struct crypto_hash *csums_tfm = NULL; | 2831 | struct crypto_hash *csums_tfm = NULL; |
@@ -2879,29 +2839,29 @@ static int receive_SyncParam(struct drbd_conf *mdev, struct p_header80 *h) | |||
2879 | : apv <= 94 ? sizeof(struct p_rs_param_89) | 2839 | : apv <= 94 ? sizeof(struct p_rs_param_89) |
2880 | : /* apv >= 95 */ sizeof(struct p_rs_param_95); | 2840 | : /* apv >= 95 */ sizeof(struct p_rs_param_95); |
2881 | 2841 | ||
2882 | if (h->length > exp_max_sz) { | 2842 | if (packet_size > exp_max_sz) { |
2883 | dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n", | 2843 | dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n", |
2884 | h->length, exp_max_sz); | 2844 | packet_size, exp_max_sz); |
2885 | return FALSE; | 2845 | return FALSE; |
2886 | } | 2846 | } |
2887 | 2847 | ||
2888 | if (apv <= 88) { | 2848 | if (apv <= 88) { |
2889 | header_size = sizeof(struct p_rs_param) - sizeof(*h); | 2849 | header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80); |
2890 | data_size = h->length - header_size; | 2850 | data_size = packet_size - header_size; |
2891 | } else if (apv <= 94) { | 2851 | } else if (apv <= 94) { |
2892 | header_size = sizeof(struct p_rs_param_89) - sizeof(*h); | 2852 | header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80); |
2893 | data_size = h->length - header_size; | 2853 | data_size = packet_size - header_size; |
2894 | D_ASSERT(data_size == 0); | 2854 | D_ASSERT(data_size == 0); |
2895 | } else { | 2855 | } else { |
2896 | header_size = sizeof(struct p_rs_param_95) - sizeof(*h); | 2856 | header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80); |
2897 | data_size = h->length - header_size; | 2857 | data_size = packet_size - header_size; |
2898 | D_ASSERT(data_size == 0); | 2858 | D_ASSERT(data_size == 0); |
2899 | } | 2859 | } |
2900 | 2860 | ||
2901 | /* initialize verify_alg and csums_alg */ | 2861 | /* initialize verify_alg and csums_alg */ |
2902 | memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX); | 2862 | memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX); |
2903 | 2863 | ||
2904 | if (drbd_recv(mdev, h->payload, header_size) != header_size) | 2864 | if (drbd_recv(mdev, &p->head.payload, header_size) != header_size) |
2905 | return FALSE; | 2865 | return FALSE; |
2906 | 2866 | ||
2907 | mdev->sync_conf.rate = be32_to_cpu(p->rate); | 2867 | mdev->sync_conf.rate = be32_to_cpu(p->rate); |
@@ -3032,19 +2992,15 @@ static void warn_if_differ_considerably(struct drbd_conf *mdev, | |||
3032 | (unsigned long long)a, (unsigned long long)b); | 2992 | (unsigned long long)a, (unsigned long long)b); |
3033 | } | 2993 | } |
3034 | 2994 | ||
3035 | static int receive_sizes(struct drbd_conf *mdev, struct p_header80 *h) | 2995 | static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3036 | { | 2996 | { |
3037 | struct p_sizes *p = (struct p_sizes *)h; | 2997 | struct p_sizes *p = &mdev->data.rbuf.sizes; |
3038 | enum determine_dev_size dd = unchanged; | 2998 | enum determine_dev_size dd = unchanged; |
3039 | unsigned int max_seg_s; | 2999 | unsigned int max_seg_s; |
3040 | sector_t p_size, p_usize, my_usize; | 3000 | sector_t p_size, p_usize, my_usize; |
3041 | int ldsc = 0; /* local disk size changed */ | 3001 | int ldsc = 0; /* local disk size changed */ |
3042 | enum dds_flags ddsf; | 3002 | enum dds_flags ddsf; |
3043 | 3003 | ||
3044 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; | ||
3045 | if (drbd_recv(mdev, h->payload, h->length) != h->length) | ||
3046 | return FALSE; | ||
3047 | |||
3048 | p_size = be64_to_cpu(p->d_size); | 3004 | p_size = be64_to_cpu(p->d_size); |
3049 | p_usize = be64_to_cpu(p->u_size); | 3005 | p_usize = be64_to_cpu(p->u_size); |
3050 | 3006 | ||
@@ -3148,16 +3104,12 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header80 *h) | |||
3148 | return TRUE; | 3104 | return TRUE; |
3149 | } | 3105 | } |
3150 | 3106 | ||
3151 | static int receive_uuids(struct drbd_conf *mdev, struct p_header80 *h) | 3107 | static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3152 | { | 3108 | { |
3153 | struct p_uuids *p = (struct p_uuids *)h; | 3109 | struct p_uuids *p = &mdev->data.rbuf.uuids; |
3154 | u64 *p_uuid; | 3110 | u64 *p_uuid; |
3155 | int i; | 3111 | int i; |
3156 | 3112 | ||
3157 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; | ||
3158 | if (drbd_recv(mdev, h->payload, h->length) != h->length) | ||
3159 | return FALSE; | ||
3160 | |||
3161 | p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO); | 3113 | p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO); |
3162 | 3114 | ||
3163 | for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++) | 3115 | for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++) |
@@ -3241,16 +3193,12 @@ static union drbd_state convert_state(union drbd_state ps) | |||
3241 | return ms; | 3193 | return ms; |
3242 | } | 3194 | } |
3243 | 3195 | ||
3244 | static int receive_req_state(struct drbd_conf *mdev, struct p_header80 *h) | 3196 | static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3245 | { | 3197 | { |
3246 | struct p_req_state *p = (struct p_req_state *)h; | 3198 | struct p_req_state *p = &mdev->data.rbuf.req_state; |
3247 | union drbd_state mask, val; | 3199 | union drbd_state mask, val; |
3248 | int rv; | 3200 | int rv; |
3249 | 3201 | ||
3250 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; | ||
3251 | if (drbd_recv(mdev, h->payload, h->length) != h->length) | ||
3252 | return FALSE; | ||
3253 | |||
3254 | mask.i = be32_to_cpu(p->mask); | 3202 | mask.i = be32_to_cpu(p->mask); |
3255 | val.i = be32_to_cpu(p->val); | 3203 | val.i = be32_to_cpu(p->val); |
3256 | 3204 | ||
@@ -3271,21 +3219,15 @@ static int receive_req_state(struct drbd_conf *mdev, struct p_header80 *h) | |||
3271 | return TRUE; | 3219 | return TRUE; |
3272 | } | 3220 | } |
3273 | 3221 | ||
3274 | static int receive_state(struct drbd_conf *mdev, struct p_header80 *h) | 3222 | static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3275 | { | 3223 | { |
3276 | struct p_state *p = (struct p_state *)h; | 3224 | struct p_state *p = &mdev->data.rbuf.state; |
3277 | enum drbd_conns nconn, oconn; | 3225 | enum drbd_conns nconn, oconn; |
3278 | union drbd_state ns, peer_state; | 3226 | union drbd_state ns, peer_state; |
3279 | enum drbd_disk_state real_peer_disk; | 3227 | enum drbd_disk_state real_peer_disk; |
3280 | enum chg_state_flags cs_flags; | 3228 | enum chg_state_flags cs_flags; |
3281 | int rv; | 3229 | int rv; |
3282 | 3230 | ||
3283 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) | ||
3284 | return FALSE; | ||
3285 | |||
3286 | if (drbd_recv(mdev, h->payload, h->length) != h->length) | ||
3287 | return FALSE; | ||
3288 | |||
3289 | peer_state.i = be32_to_cpu(p->state); | 3231 | peer_state.i = be32_to_cpu(p->state); |
3290 | 3232 | ||
3291 | real_peer_disk = peer_state.disk; | 3233 | real_peer_disk = peer_state.disk; |
@@ -3395,9 +3337,9 @@ static int receive_state(struct drbd_conf *mdev, struct p_header80 *h) | |||
3395 | return TRUE; | 3337 | return TRUE; |
3396 | } | 3338 | } |
3397 | 3339 | ||
3398 | static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header80 *h) | 3340 | static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3399 | { | 3341 | { |
3400 | struct p_rs_uuid *p = (struct p_rs_uuid *)h; | 3342 | struct p_rs_uuid *p = &mdev->data.rbuf.rs_uuid; |
3401 | 3343 | ||
3402 | wait_event(mdev->misc_wait, | 3344 | wait_event(mdev->misc_wait, |
3403 | mdev->state.conn == C_WF_SYNC_UUID || | 3345 | mdev->state.conn == C_WF_SYNC_UUID || |
@@ -3406,10 +3348,6 @@ static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header80 *h) | |||
3406 | 3348 | ||
3407 | /* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */ | 3349 | /* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */ |
3408 | 3350 | ||
3409 | ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE; | ||
3410 | if (drbd_recv(mdev, h->payload, h->length) != h->length) | ||
3411 | return FALSE; | ||
3412 | |||
3413 | /* Here the _drbd_uuid_ functions are right, current should | 3351 | /* Here the _drbd_uuid_ functions are right, current should |
3414 | _not_ be rotated into the history */ | 3352 | _not_ be rotated into the history */ |
3415 | if (get_ldev_if_state(mdev, D_NEGOTIATING)) { | 3353 | if (get_ldev_if_state(mdev, D_NEGOTIATING)) { |
@@ -3428,14 +3366,14 @@ static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header80 *h) | |||
3428 | enum receive_bitmap_ret { OK, DONE, FAILED }; | 3366 | enum receive_bitmap_ret { OK, DONE, FAILED }; |
3429 | 3367 | ||
3430 | static enum receive_bitmap_ret | 3368 | static enum receive_bitmap_ret |
3431 | receive_bitmap_plain(struct drbd_conf *mdev, struct p_header80 *h, | 3369 | receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size, |
3432 | unsigned long *buffer, struct bm_xfer_ctx *c) | 3370 | unsigned long *buffer, struct bm_xfer_ctx *c) |
3433 | { | 3371 | { |
3434 | unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset); | 3372 | unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset); |
3435 | unsigned want = num_words * sizeof(long); | 3373 | unsigned want = num_words * sizeof(long); |
3436 | 3374 | ||
3437 | if (want != h->length) { | 3375 | if (want != data_size) { |
3438 | dev_err(DEV, "%s:want (%u) != h->length (%u)\n", __func__, want, h->length); | 3376 | dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size); |
3439 | return FAILED; | 3377 | return FAILED; |
3440 | } | 3378 | } |
3441 | if (want == 0) | 3379 | if (want == 0) |
@@ -3571,12 +3509,13 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev, | |||
3571 | in order to be agnostic to the 32 vs 64 bits issue. | 3509 | in order to be agnostic to the 32 vs 64 bits issue. |
3572 | 3510 | ||
3573 | returns 0 on failure, 1 if we successfully received it. */ | 3511 | returns 0 on failure, 1 if we successfully received it. */ |
3574 | static int receive_bitmap(struct drbd_conf *mdev, struct p_header80 *h) | 3512 | static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3575 | { | 3513 | { |
3576 | struct bm_xfer_ctx c; | 3514 | struct bm_xfer_ctx c; |
3577 | void *buffer; | 3515 | void *buffer; |
3578 | enum receive_bitmap_ret ret; | 3516 | enum receive_bitmap_ret ret; |
3579 | int ok = FALSE; | 3517 | int ok = FALSE; |
3518 | struct p_header80 *h = &mdev->data.rbuf.header.h80; | ||
3580 | 3519 | ||
3581 | wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); | 3520 | wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); |
3582 | 3521 | ||
@@ -3596,21 +3535,21 @@ static int receive_bitmap(struct drbd_conf *mdev, struct p_header80 *h) | |||
3596 | }; | 3535 | }; |
3597 | 3536 | ||
3598 | do { | 3537 | do { |
3599 | if (h->command == P_BITMAP) { | 3538 | if (cmd == P_BITMAP) { |
3600 | ret = receive_bitmap_plain(mdev, h, buffer, &c); | 3539 | ret = receive_bitmap_plain(mdev, data_size, buffer, &c); |
3601 | } else if (h->command == P_COMPRESSED_BITMAP) { | 3540 | } else if (cmd == P_COMPRESSED_BITMAP) { |
3602 | /* MAYBE: sanity check that we speak proto >= 90, | 3541 | /* MAYBE: sanity check that we speak proto >= 90, |
3603 | * and the feature is enabled! */ | 3542 | * and the feature is enabled! */ |
3604 | struct p_compressed_bm *p; | 3543 | struct p_compressed_bm *p; |
3605 | 3544 | ||
3606 | if (h->length > BM_PACKET_PAYLOAD_BYTES) { | 3545 | if (data_size > BM_PACKET_PAYLOAD_BYTES) { |
3607 | dev_err(DEV, "ReportCBitmap packet too large\n"); | 3546 | dev_err(DEV, "ReportCBitmap packet too large\n"); |
3608 | goto out; | 3547 | goto out; |
3609 | } | 3548 | } |
3610 | /* use the page buff */ | 3549 | /* use the page buff */ |
3611 | p = buffer; | 3550 | p = buffer; |
3612 | memcpy(p, h, sizeof(*h)); | 3551 | memcpy(p, h, sizeof(*h)); |
3613 | if (drbd_recv(mdev, p->head.payload, h->length) != h->length) | 3552 | if (drbd_recv(mdev, p->head.payload, data_size) != data_size) |
3614 | goto out; | 3553 | goto out; |
3615 | if (p->head.length <= (sizeof(*p) - sizeof(p->head))) { | 3554 | if (p->head.length <= (sizeof(*p) - sizeof(p->head))) { |
3616 | dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", p->head.length); | 3555 | dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", p->head.length); |
@@ -3618,17 +3557,17 @@ static int receive_bitmap(struct drbd_conf *mdev, struct p_header80 *h) | |||
3618 | } | 3557 | } |
3619 | ret = decode_bitmap_c(mdev, p, &c); | 3558 | ret = decode_bitmap_c(mdev, p, &c); |
3620 | } else { | 3559 | } else { |
3621 | dev_warn(DEV, "receive_bitmap: h->command neither ReportBitMap nor ReportCBitMap (is 0x%x)", h->command); | 3560 | dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd); |
3622 | goto out; | 3561 | goto out; |
3623 | } | 3562 | } |
3624 | 3563 | ||
3625 | c.packets[h->command == P_BITMAP]++; | 3564 | c.packets[cmd == P_BITMAP]++; |
3626 | c.bytes[h->command == P_BITMAP] += sizeof(struct p_header80) + h->length; | 3565 | c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size; |
3627 | 3566 | ||
3628 | if (ret != OK) | 3567 | if (ret != OK) |
3629 | break; | 3568 | break; |
3630 | 3569 | ||
3631 | if (!drbd_recv_header(mdev, h)) | 3570 | if (!drbd_recv_header(mdev, &cmd, &data_size)) |
3632 | goto out; | 3571 | goto out; |
3633 | } while (ret == OK); | 3572 | } while (ret == OK); |
3634 | if (ret == FAILED) | 3573 | if (ret == FAILED) |
@@ -3659,17 +3598,16 @@ static int receive_bitmap(struct drbd_conf *mdev, struct p_header80 *h) | |||
3659 | return ok; | 3598 | return ok; |
3660 | } | 3599 | } |
3661 | 3600 | ||
3662 | static int receive_skip_(struct drbd_conf *mdev, struct p_header80 *h, int silent) | 3601 | static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3663 | { | 3602 | { |
3664 | /* TODO zero copy sink :) */ | 3603 | /* TODO zero copy sink :) */ |
3665 | static char sink[128]; | 3604 | static char sink[128]; |
3666 | int size, want, r; | 3605 | int size, want, r; |
3667 | 3606 | ||
3668 | if (!silent) | 3607 | dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n", |
3669 | dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n", | 3608 | cmd, data_size); |
3670 | h->command, h->length); | ||
3671 | 3609 | ||
3672 | size = h->length; | 3610 | size = data_size; |
3673 | while (size > 0) { | 3611 | while (size > 0) { |
3674 | want = min_t(int, size, sizeof(sink)); | 3612 | want = min_t(int, size, sizeof(sink)); |
3675 | r = drbd_recv(mdev, sink, want); | 3613 | r = drbd_recv(mdev, sink, want); |
@@ -3679,17 +3617,7 @@ static int receive_skip_(struct drbd_conf *mdev, struct p_header80 *h, int silen | |||
3679 | return size == 0; | 3617 | return size == 0; |
3680 | } | 3618 | } |
3681 | 3619 | ||
3682 | static int receive_skip(struct drbd_conf *mdev, struct p_header80 *h) | 3620 | static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) |
3683 | { | ||
3684 | return receive_skip_(mdev, h, 0); | ||
3685 | } | ||
3686 | |||
3687 | static int receive_skip_silent(struct drbd_conf *mdev, struct p_header80 *h) | ||
3688 | { | ||
3689 | return receive_skip_(mdev, h, 1); | ||
3690 | } | ||
3691 | |||
3692 | static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header80 *h) | ||
3693 | { | 3621 | { |
3694 | if (mdev->state.disk >= D_INCONSISTENT) | 3622 | if (mdev->state.disk >= D_INCONSISTENT) |
3695 | drbd_kick_lo(mdev); | 3623 | drbd_kick_lo(mdev); |
@@ -3701,73 +3629,91 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header80 *h) | |||
3701 | return TRUE; | 3629 | return TRUE; |
3702 | } | 3630 | } |
3703 | 3631 | ||
3704 | typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header80 *); | 3632 | typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); |
3705 | 3633 | ||
3706 | static drbd_cmd_handler_f drbd_default_handler[] = { | 3634 | struct data_cmd { |
3707 | [P_DATA] = receive_Data, | 3635 | int expect_payload; |
3708 | [P_DATA_REPLY] = receive_DataReply, | 3636 | size_t pkt_size; |
3709 | [P_RS_DATA_REPLY] = receive_RSDataReply, | 3637 | drbd_cmd_handler_f function; |
3710 | [P_BARRIER] = receive_Barrier, | 3638 | }; |
3711 | [P_BITMAP] = receive_bitmap, | 3639 | |
3712 | [P_COMPRESSED_BITMAP] = receive_bitmap, | 3640 | static struct data_cmd drbd_cmd_handler[] = { |
3713 | [P_UNPLUG_REMOTE] = receive_UnplugRemote, | 3641 | [P_DATA] = { 1, sizeof(struct p_data), receive_Data }, |
3714 | [P_DATA_REQUEST] = receive_DataRequest, | 3642 | [P_DATA_REPLY] = { 1, sizeof(struct p_data), receive_DataReply }, |
3715 | [P_RS_DATA_REQUEST] = receive_DataRequest, | 3643 | [P_RS_DATA_REPLY] = { 1, sizeof(struct p_data), receive_RSDataReply } , |
3716 | [P_SYNC_PARAM] = receive_SyncParam, | 3644 | [P_BARRIER] = { 0, sizeof(struct p_barrier), receive_Barrier } , |
3717 | [P_SYNC_PARAM89] = receive_SyncParam, | 3645 | [P_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } , |
3718 | [P_PROTOCOL] = receive_protocol, | 3646 | [P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } , |
3719 | [P_UUIDS] = receive_uuids, | 3647 | [P_UNPLUG_REMOTE] = { 0, sizeof(struct p_header80), receive_UnplugRemote }, |
3720 | [P_SIZES] = receive_sizes, | 3648 | [P_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest }, |
3721 | [P_STATE] = receive_state, | 3649 | [P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest }, |
3722 | [P_STATE_CHG_REQ] = receive_req_state, | 3650 | [P_SYNC_PARAM] = { 1, sizeof(struct p_header80), receive_SyncParam }, |
3723 | [P_SYNC_UUID] = receive_sync_uuid, | 3651 | [P_SYNC_PARAM89] = { 1, sizeof(struct p_header80), receive_SyncParam }, |
3724 | [P_OV_REQUEST] = receive_DataRequest, | 3652 | [P_PROTOCOL] = { 1, sizeof(struct p_protocol), receive_protocol }, |
3725 | [P_OV_REPLY] = receive_DataRequest, | 3653 | [P_UUIDS] = { 0, sizeof(struct p_uuids), receive_uuids }, |
3726 | [P_CSUM_RS_REQUEST] = receive_DataRequest, | 3654 | [P_SIZES] = { 0, sizeof(struct p_sizes), receive_sizes }, |
3727 | [P_DELAY_PROBE] = receive_skip_silent, | 3655 | [P_STATE] = { 0, sizeof(struct p_state), receive_state }, |
3656 | [P_STATE_CHG_REQ] = { 0, sizeof(struct p_req_state), receive_req_state }, | ||
3657 | [P_SYNC_UUID] = { 0, sizeof(struct p_rs_uuid), receive_sync_uuid }, | ||
3658 | [P_OV_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest }, | ||
3659 | [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, | ||
3660 | [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, | ||
3661 | [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, | ||
3728 | /* anything missing from this table is in | 3662 | /* anything missing from this table is in |
3729 | * the asender_tbl, see get_asender_cmd */ | 3663 | * the asender_tbl, see get_asender_cmd */ |
3730 | [P_MAX_CMD] = NULL, | 3664 | [P_MAX_CMD] = { 0, 0, NULL }, |
3731 | }; | 3665 | }; |
3732 | 3666 | ||
3733 | static drbd_cmd_handler_f *drbd_cmd_handler = drbd_default_handler; | 3667 | /* All handler functions that expect a sub-header get that sub-heder in |
3734 | static drbd_cmd_handler_f *drbd_opt_cmd_handler; | 3668 | mdev->data.rbuf.header.head.payload. |
3669 | |||
3670 | Usually in mdev->data.rbuf.header.head the callback can find the usual | ||
3671 | p_header, but they may not rely on that. Since there is also p_header95 ! | ||
3672 | */ | ||
3735 | 3673 | ||
3736 | static void drbdd(struct drbd_conf *mdev) | 3674 | static void drbdd(struct drbd_conf *mdev) |
3737 | { | 3675 | { |
3738 | drbd_cmd_handler_f handler; | 3676 | union p_header *header = &mdev->data.rbuf.header; |
3739 | struct p_header80 *header = &mdev->data.rbuf.header; | 3677 | unsigned int packet_size; |
3678 | enum drbd_packets cmd; | ||
3679 | size_t shs; /* sub header size */ | ||
3680 | int rv; | ||
3740 | 3681 | ||
3741 | while (get_t_state(&mdev->receiver) == Running) { | 3682 | while (get_t_state(&mdev->receiver) == Running) { |
3742 | drbd_thread_current_set_cpu(mdev); | 3683 | drbd_thread_current_set_cpu(mdev); |
3743 | if (!drbd_recv_header(mdev, header)) { | 3684 | if (!drbd_recv_header(mdev, &cmd, &packet_size)) |
3744 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); | 3685 | goto err_out; |
3745 | break; | 3686 | |
3687 | if (unlikely(cmd >= P_MAX_CMD || !drbd_cmd_handler[cmd].function)) { | ||
3688 | dev_err(DEV, "unknown packet type %d, l: %d!\n", cmd, packet_size); | ||
3689 | goto err_out; | ||
3746 | } | 3690 | } |
3747 | 3691 | ||
3748 | if (header->command < P_MAX_CMD) | 3692 | shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header); |
3749 | handler = drbd_cmd_handler[header->command]; | 3693 | rv = drbd_recv(mdev, &header->h80.payload, shs); |
3750 | else if (P_MAY_IGNORE < header->command | 3694 | if (unlikely(rv != shs)) { |
3751 | && header->command < P_MAX_OPT_CMD) | 3695 | dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); |
3752 | handler = drbd_opt_cmd_handler[header->command-P_MAY_IGNORE]; | 3696 | goto err_out; |
3753 | else if (header->command > P_MAX_OPT_CMD) | 3697 | } |
3754 | handler = receive_skip; | ||
3755 | else | ||
3756 | handler = NULL; | ||
3757 | 3698 | ||
3758 | if (unlikely(!handler)) { | 3699 | if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) { |
3759 | dev_err(DEV, "unknown packet type %d, l: %d!\n", | 3700 | dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size); |
3760 | header->command, header->length); | 3701 | goto err_out; |
3761 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); | ||
3762 | break; | ||
3763 | } | 3702 | } |
3764 | if (unlikely(!handler(mdev, header))) { | 3703 | |
3704 | rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs); | ||
3705 | |||
3706 | if (unlikely(!rv)) { | ||
3765 | dev_err(DEV, "error receiving %s, l: %d!\n", | 3707 | dev_err(DEV, "error receiving %s, l: %d!\n", |
3766 | cmdname(header->command), header->length); | 3708 | cmdname(cmd), packet_size); |
3767 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); | 3709 | goto err_out; |
3768 | break; | ||
3769 | } | 3710 | } |
3770 | } | 3711 | } |
3712 | |||
3713 | if (0) { | ||
3714 | err_out: | ||
3715 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); | ||
3716 | } | ||
3771 | } | 3717 | } |
3772 | 3718 | ||
3773 | void drbd_flush_workqueue(struct drbd_conf *mdev) | 3719 | void drbd_flush_workqueue(struct drbd_conf *mdev) |
@@ -3980,27 +3926,28 @@ static int drbd_do_handshake(struct drbd_conf *mdev) | |||
3980 | { | 3926 | { |
3981 | /* ASSERT current == mdev->receiver ... */ | 3927 | /* ASSERT current == mdev->receiver ... */ |
3982 | struct p_handshake *p = &mdev->data.rbuf.handshake; | 3928 | struct p_handshake *p = &mdev->data.rbuf.handshake; |
3983 | const int expect = sizeof(struct p_handshake) | 3929 | const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80); |
3984 | -sizeof(struct p_header80); | 3930 | unsigned int length; |
3931 | enum drbd_packets cmd; | ||
3985 | int rv; | 3932 | int rv; |
3986 | 3933 | ||
3987 | rv = drbd_send_handshake(mdev); | 3934 | rv = drbd_send_handshake(mdev); |
3988 | if (!rv) | 3935 | if (!rv) |
3989 | return 0; | 3936 | return 0; |
3990 | 3937 | ||
3991 | rv = drbd_recv_header(mdev, &p->head); | 3938 | rv = drbd_recv_header(mdev, &cmd, &length); |
3992 | if (!rv) | 3939 | if (!rv) |
3993 | return 0; | 3940 | return 0; |
3994 | 3941 | ||
3995 | if (p->head.command != P_HAND_SHAKE) { | 3942 | if (cmd != P_HAND_SHAKE) { |
3996 | dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n", | 3943 | dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n", |
3997 | cmdname(p->head.command), p->head.command); | 3944 | cmdname(cmd), cmd); |
3998 | return -1; | 3945 | return -1; |
3999 | } | 3946 | } |
4000 | 3947 | ||
4001 | if (p->head.length != expect) { | 3948 | if (length != expect) { |
4002 | dev_err(DEV, "expected HandShake length: %u, received: %u\n", | 3949 | dev_err(DEV, "expected HandShake length: %u, received: %u\n", |
4003 | expect, p->head.length); | 3950 | expect, length); |
4004 | return -1; | 3951 | return -1; |
4005 | } | 3952 | } |
4006 | 3953 | ||
@@ -4058,10 +4005,11 @@ static int drbd_do_auth(struct drbd_conf *mdev) | |||
4058 | char *response = NULL; | 4005 | char *response = NULL; |
4059 | char *right_response = NULL; | 4006 | char *right_response = NULL; |
4060 | char *peers_ch = NULL; | 4007 | char *peers_ch = NULL; |
4061 | struct p_header80 p; | ||
4062 | unsigned int key_len = strlen(mdev->net_conf->shared_secret); | 4008 | unsigned int key_len = strlen(mdev->net_conf->shared_secret); |
4063 | unsigned int resp_size; | 4009 | unsigned int resp_size; |
4064 | struct hash_desc desc; | 4010 | struct hash_desc desc; |
4011 | enum drbd_packets cmd; | ||
4012 | unsigned int length; | ||
4065 | int rv; | 4013 | int rv; |
4066 | 4014 | ||
4067 | desc.tfm = mdev->cram_hmac_tfm; | 4015 | desc.tfm = mdev->cram_hmac_tfm; |
@@ -4081,33 +4029,33 @@ static int drbd_do_auth(struct drbd_conf *mdev) | |||
4081 | if (!rv) | 4029 | if (!rv) |
4082 | goto fail; | 4030 | goto fail; |
4083 | 4031 | ||
4084 | rv = drbd_recv_header(mdev, &p); | 4032 | rv = drbd_recv_header(mdev, &cmd, &length); |
4085 | if (!rv) | 4033 | if (!rv) |
4086 | goto fail; | 4034 | goto fail; |
4087 | 4035 | ||
4088 | if (p.command != P_AUTH_CHALLENGE) { | 4036 | if (cmd != P_AUTH_CHALLENGE) { |
4089 | dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n", | 4037 | dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n", |
4090 | cmdname(p.command), p.command); | 4038 | cmdname(cmd), cmd); |
4091 | rv = 0; | 4039 | rv = 0; |
4092 | goto fail; | 4040 | goto fail; |
4093 | } | 4041 | } |
4094 | 4042 | ||
4095 | if (p.length > CHALLENGE_LEN*2) { | 4043 | if (length > CHALLENGE_LEN * 2) { |
4096 | dev_err(DEV, "expected AuthChallenge payload too big.\n"); | 4044 | dev_err(DEV, "expected AuthChallenge payload too big.\n"); |
4097 | rv = -1; | 4045 | rv = -1; |
4098 | goto fail; | 4046 | goto fail; |
4099 | } | 4047 | } |
4100 | 4048 | ||
4101 | peers_ch = kmalloc(p.length, GFP_NOIO); | 4049 | peers_ch = kmalloc(length, GFP_NOIO); |
4102 | if (peers_ch == NULL) { | 4050 | if (peers_ch == NULL) { |
4103 | dev_err(DEV, "kmalloc of peers_ch failed\n"); | 4051 | dev_err(DEV, "kmalloc of peers_ch failed\n"); |
4104 | rv = -1; | 4052 | rv = -1; |
4105 | goto fail; | 4053 | goto fail; |
4106 | } | 4054 | } |
4107 | 4055 | ||
4108 | rv = drbd_recv(mdev, peers_ch, p.length); | 4056 | rv = drbd_recv(mdev, peers_ch, length); |
4109 | 4057 | ||
4110 | if (rv != p.length) { | 4058 | if (rv != length) { |
4111 | dev_err(DEV, "short read AuthChallenge: l=%u\n", rv); | 4059 | dev_err(DEV, "short read AuthChallenge: l=%u\n", rv); |
4112 | rv = 0; | 4060 | rv = 0; |
4113 | goto fail; | 4061 | goto fail; |
@@ -4122,7 +4070,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) | |||
4122 | } | 4070 | } |
4123 | 4071 | ||
4124 | sg_init_table(&sg, 1); | 4072 | sg_init_table(&sg, 1); |
4125 | sg_set_buf(&sg, peers_ch, p.length); | 4073 | sg_set_buf(&sg, peers_ch, length); |
4126 | 4074 | ||
4127 | rv = crypto_hash_digest(&desc, &sg, sg.length, response); | 4075 | rv = crypto_hash_digest(&desc, &sg, sg.length, response); |
4128 | if (rv) { | 4076 | if (rv) { |
@@ -4135,18 +4083,18 @@ static int drbd_do_auth(struct drbd_conf *mdev) | |||
4135 | if (!rv) | 4083 | if (!rv) |
4136 | goto fail; | 4084 | goto fail; |
4137 | 4085 | ||
4138 | rv = drbd_recv_header(mdev, &p); | 4086 | rv = drbd_recv_header(mdev, &cmd, &length); |
4139 | if (!rv) | 4087 | if (!rv) |
4140 | goto fail; | 4088 | goto fail; |
4141 | 4089 | ||
4142 | if (p.command != P_AUTH_RESPONSE) { | 4090 | if (cmd != P_AUTH_RESPONSE) { |
4143 | dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n", | 4091 | dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n", |
4144 | cmdname(p.command), p.command); | 4092 | cmdname(cmd), cmd); |
4145 | rv = 0; | 4093 | rv = 0; |
4146 | goto fail; | 4094 | goto fail; |
4147 | } | 4095 | } |
4148 | 4096 | ||
4149 | if (p.length != resp_size) { | 4097 | if (length != resp_size) { |
4150 | dev_err(DEV, "expected AuthResponse payload of wrong size\n"); | 4098 | dev_err(DEV, "expected AuthResponse payload of wrong size\n"); |
4151 | rv = 0; | 4099 | rv = 0; |
4152 | goto fail; | 4100 | goto fail; |
@@ -4474,9 +4422,8 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h) | |||
4474 | return TRUE; | 4422 | return TRUE; |
4475 | } | 4423 | } |
4476 | 4424 | ||
4477 | static int got_something_to_ignore_m(struct drbd_conf *mdev, struct p_header80 *h) | 4425 | static int got_skip(struct drbd_conf *mdev, struct p_header80 *h) |
4478 | { | 4426 | { |
4479 | /* IGNORE */ | ||
4480 | return TRUE; | 4427 | return TRUE; |
4481 | } | 4428 | } |
4482 | 4429 | ||
@@ -4504,7 +4451,7 @@ static struct asender_cmd *get_asender_cmd(int cmd) | |||
4504 | [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck }, | 4451 | [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck }, |
4505 | [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply }, | 4452 | [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply }, |
4506 | [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync }, | 4453 | [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync }, |
4507 | [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), got_something_to_ignore_m }, | 4454 | [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), got_skip }, |
4508 | [P_MAX_CMD] = { 0, NULL }, | 4455 | [P_MAX_CMD] = { 0, NULL }, |
4509 | }; | 4456 | }; |
4510 | if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL) | 4457 | if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL) |
@@ -4515,7 +4462,7 @@ static struct asender_cmd *get_asender_cmd(int cmd) | |||
4515 | int drbd_asender(struct drbd_thread *thi) | 4462 | int drbd_asender(struct drbd_thread *thi) |
4516 | { | 4463 | { |
4517 | struct drbd_conf *mdev = thi->mdev; | 4464 | struct drbd_conf *mdev = thi->mdev; |
4518 | struct p_header80 *h = &mdev->meta.rbuf.header; | 4465 | struct p_header80 *h = &mdev->meta.rbuf.header.h80; |
4519 | struct asender_cmd *cmd = NULL; | 4466 | struct asender_cmd *cmd = NULL; |
4520 | 4467 | ||
4521 | int rv, len; | 4468 | int rv, len; |