On Fri, 2019-06-14 at 16:05 +0800, Yan, Zheng wrote:
On Fri, Jun 7, 2019 at 11:38 PM Jeff Layton <jlayton@xxxxxxxxxx> wrote:
Add a way to decode an entity_addr_t. Once CEPH_FEATURE_MSG_ADDR2 is
enabled, the server daemons will start encoding entity_addr_t
differently.
Add a new helper function that can handle either format.
Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
include/linux/ceph/decode.h | 2 +
net/ceph/Makefile | 2 +-
net/ceph/decode.c | 75 +++++++++++++++++++++++++++++++++++++
3 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 net/ceph/decode.c
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h
index a6c2a48d42e0..1c0a665bfc03 100644
--- a/include/linux/ceph/decode.h
+++ b/include/linux/ceph/decode.h
@@ -230,6 +230,8 @@ static inline void ceph_decode_addr(struct ceph_entity_addr *a)
WARN_ON(a->in_addr.ss_family == 512);
}
+extern int ceph_decode_entity_addr(void **p, void *end,
+ struct ceph_entity_addr *addr);
/*
* encoders
*/
diff --git a/net/ceph/Makefile b/net/ceph/Makefile
index db09defe27d0..59d0ba2072de 100644
--- a/net/ceph/Makefile
+++ b/net/ceph/Makefile
@@ -5,7 +5,7 @@
obj-$(CONFIG_CEPH_LIB) += libceph.o
libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
- mon_client.o \
+ mon_client.o decode.o \
cls_lock_client.o \
osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
striper.o \
diff --git a/net/ceph/decode.c b/net/ceph/decode.c
new file mode 100644
index 000000000000..27edf5d341ec
--- /dev/null
+++ b/net/ceph/decode.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/ceph/decode.h>
+
+int
+ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
+{
+ u8 marker, v, compat;
It's better to use name struct_v, struct_compat
+ u32 len;
+
+ ceph_decode_8_safe(p, end, marker, bad);
+ if (marker == 1) {
+ ceph_decode_8_safe(p, end, v, bad);
+ ceph_decode_8_safe(p, end, compat, bad);
+ if (!v || compat != 1)
+ goto bad;
+ /* FIXME: sanity check? */
+ ceph_decode_32_safe(p, end, len, bad);
+ /* type is __le32, so we must copy into place as-is */
+ ceph_decode_copy_safe(p, end, &addr->type,
+ sizeof(addr->type), bad);
+
+ /*
+ * TYPE_NONE == 0
+ * TYPE_LEGACY == 1
+ *
+ * Clients that don't support ADDR2 always send TYPE_NONE.
+ * For now, since all we support is msgr1, just set this to 0
+ * when we get a TYPE_LEGACY type.
+ */
+ if (addr->type == cpu_to_le32(1))
+ addr->type = 0;
+ } else if (marker == 0) {
+ addr->type = 0;
+ /* Skip rest of type field */
+ ceph_decode_skip_n(p, end, 3, bad);
+ } else {
versioned encoding has forward compatibility. The code should looks like
if (struct_v == 0) {
/* old format */
return;
}
if (struct_compat != 1)
goto bad
end = *p + struct_len;
if (struct_v == 1) {
....
}
if (struct_v == 2) {
...
}
*p = end;
+ goto bad;
+ }
+
+ ceph_decode_need(p, end, sizeof(addr->nonce), bad);
+ ceph_decode_copy(p, &addr->nonce, sizeof(addr->nonce));
+
+ /* addr length */
+ if (marker == 1) {
+ ceph_decode_32_safe(p, end, len, bad);
+ if (len > sizeof(addr->in_addr))
+ goto bad;
+ } else {
+ len = sizeof(addr->in_addr);
+ }
+
+ memset(&addr->in_addr, 0, sizeof(addr->in_addr));
+
+ if (len) {
+ ceph_decode_need(p, end, len, bad);
+ ceph_decode_copy(p, &addr->in_addr, len);
+
+ /*
+ * Fix up sa_family. Legacy encoding sends it in BE, addr2
+ * encoding uses LE.
+ */
+ if (marker == 1)
+ addr->in_addr.ss_family =
+ le16_to_cpu((__force __le16)addr->in_addr.ss_family);
+ else
+ addr->in_addr.ss_family =
+ be16_to_cpu((__force __be16)addr->in_addr.ss_family);
+ }
+ return 0;
+bad:
+ return -EINVAL;
+}
+EXPORT_SYMBOL(ceph_decode_entity_addr);
+
--
2.21.0
(Dropping dev@xxxxxxx from cc list since they evidently _really_ don't
want to see kernel patches there)
Something like this then on top of the original patch?
SQUASH: address Zheng's comments
Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
net/ceph/decode.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/net/ceph/decode.c b/net/ceph/decode.c
index 27edf5d341ec..5a008567d018 100644
--- a/net/ceph/decode.c
+++ b/net/ceph/decode.c
@@ -5,18 +5,20 @@
int
ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
{
- u8 marker, v, compat;
+ u8 marker, struct_v, struct_compat;
u32 len;
ceph_decode_8_safe(p, end, marker, bad);
if (marker == 1) {
- ceph_decode_8_safe(p, end, v, bad);
- ceph_decode_8_safe(p, end, compat, bad);
- if (!v || compat != 1)
+ ceph_decode_8_safe(p, end, struct_v, bad);
+ ceph_decode_8_safe(p, end, struct_compat, bad);
+ if (!struct_v || struct_compat != 1)
goto bad;
+
/* FIXME: sanity check? */
ceph_decode_32_safe(p, end, len, bad);
- /* type is __le32, so we must copy into place as-is */
+
+ /* type is defined as __le32, copy into place as-is */
ceph_decode_copy_safe(p, end, &addr->type,
sizeof(addr->type), bad);
@@ -32,17 +34,18 @@ ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
addr->type = 0;
} else if (marker == 0) {
addr->type = 0;
+ struct_v = 0;
+ struct_compat = 0;
/* Skip rest of type field */
ceph_decode_skip_n(p, end, 3, bad);
} else {
goto bad;
}
- ceph_decode_need(p, end, sizeof(addr->nonce), bad);
- ceph_decode_copy(p, &addr->nonce, sizeof(addr->nonce));
+ ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
/* addr length */
- if (marker == 1) {
+ if (struct_v > 0) {
ceph_decode_32_safe(p, end, len, bad);
if (len > sizeof(addr->in_addr))
goto bad;
@@ -60,7 +63,7 @@ ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
* Fix up sa_family. Legacy encoding sends it in BE, addr2
* encoding uses LE.
*/
- if (marker == 1)
+ if (struct_v > 0)
addr->in_addr.ss_family =
le16_to_cpu((__force __le16)addr->in_addr.ss_family);
else
--
2.21.0