ceph: use fixed endian encoding for ceph_entity_addr
We exchange struct ceph_entity_addr over the wire and store it on disk.
The sockaddr_storage.ss_family field, however, is host endianness. So,
fix ss_family endianness to big endian when sending/receiving over the
wire.
Signed-off-by: Sage Weil <sage@newdream.net>
diff --git a/fs/ceph/decode.h b/fs/ceph/decode.h
index 91179fb..a382aec 100644
--- a/fs/ceph/decode.h
+++ b/fs/ceph/decode.h
@@ -76,19 +76,31 @@
* struct ceph_timespec <-> struct timespec
*/
static inline void ceph_decode_timespec(struct timespec *ts,
- struct ceph_timespec *tv)
+ const struct ceph_timespec *tv)
{
ts->tv_sec = le32_to_cpu(tv->tv_sec);
ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
}
static inline void ceph_encode_timespec(struct ceph_timespec *tv,
- struct timespec *ts)
+ const struct timespec *ts)
{
tv->tv_sec = cpu_to_le32(ts->tv_sec);
tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
}
/*
+ * sockaddr_storage <-> ceph_sockaddr
+ */
+static inline void ceph_encode_addr(struct ceph_entity_addr *a)
+{
+ a->in_addr.ss_family = htons(a->in_addr.ss_family);
+}
+static inline void ceph_decode_addr(struct ceph_entity_addr *a)
+{
+ a->in_addr.ss_family = ntohs(a->in_addr.ss_family);
+}
+
+/*
* encoders
*/
static inline void ceph_encode_64(void **p, u64 v)
diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c
index 80daea0..4226c81 100644
--- a/fs/ceph/mdsmap.c
+++ b/fs/ceph/mdsmap.c
@@ -86,6 +86,7 @@
ceph_decode_need(p, end, sizeof(addr) + 1 + sizeof(u32), bad);
ceph_decode_copy(p, &addr, sizeof(addr));
+ ceph_decode_addr(&addr);
infoversion = ceph_decode_8(p);
namelen = ceph_decode_32(p); /* skip mds name */
*p += namelen;
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index b48abc0..6ff44bb 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -12,6 +12,7 @@
#include "super.h"
#include "messenger.h"
+#include "decode.h"
/*
* Ceph uses the messenger to exchange ceph_msg messages with other
@@ -97,6 +98,12 @@
return s;
}
+static void encode_my_addr(struct ceph_messenger *msgr)
+{
+ memcpy(&msgr->my_enc_addr, &msgr->inst.addr, sizeof(msgr->my_enc_addr));
+ ceph_encode_addr(&msgr->my_enc_addr);
+}
+
/*
* work queue for all reading and writing to/from the socket.
*/
@@ -590,12 +597,12 @@
con->out_kvec[0].iov_base = CEPH_BANNER;
con->out_kvec[0].iov_len = len;
- con->out_kvec[1].iov_base = &msgr->inst.addr;
- con->out_kvec[1].iov_len = sizeof(msgr->inst.addr);
+ con->out_kvec[1].iov_base = &msgr->my_enc_addr;
+ con->out_kvec[1].iov_len = sizeof(msgr->my_enc_addr);
con->out_kvec[2].iov_base = &con->out_connect;
con->out_kvec[2].iov_len = sizeof(con->out_connect);
con->out_kvec_left = 3;
- con->out_kvec_bytes = len + sizeof(msgr->inst.addr) +
+ con->out_kvec_bytes = len + sizeof(msgr->my_enc_addr) +
sizeof(con->out_connect);
con->out_kvec_cur = con->out_kvec;
con->out_more = 0;
@@ -976,6 +983,9 @@
if (verify_hello(con) < 0)
return -1;
+ ceph_decode_addr(&con->actual_peer_addr);
+ ceph_decode_addr(&con->peer_addr_for_me);
+
/*
* Make sure the other end is who we wanted. note that the other
* end may not yet know their ip address, so if it's 0.0.0.0, give
@@ -1005,6 +1015,7 @@
&con->peer_addr_for_me.in_addr,
sizeof(con->peer_addr_for_me.in_addr));
addr_set_port(&con->msgr->inst.addr.in_addr, port);
+ encode_my_addr(con->msgr);
dout("process_connect learned my addr is %s\n",
pr_addr(&con->msgr->inst.addr.in_addr));
}
@@ -1780,6 +1791,7 @@
/* select a random nonce */
get_random_bytes(&msgr->inst.addr.nonce,
sizeof(msgr->inst.addr.nonce));
+ encode_my_addr(msgr);
dout("messenger_create %p\n", msgr);
return msgr;
@@ -1806,8 +1818,9 @@
}
/* set src+dst */
- msg->hdr.src = con->msgr->inst;
- msg->hdr.orig_src = con->msgr->inst;
+ msg->hdr.src.name = con->msgr->inst.name;
+ msg->hdr.src.addr = con->msgr->my_enc_addr;
+ msg->hdr.orig_src = msg->hdr.src;
msg->hdr.dst_erank = con->peer_addr.erank;
/* queue */
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index dcd98b6..e016fa7 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -53,6 +53,7 @@
struct ceph_messenger {
struct ceph_entity_inst inst; /* my name+address */
+ struct ceph_entity_addr my_enc_addr;
struct page *zero_page; /* used in certain error cases */
bool nocrc;
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 61263c9..95b76e7 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -59,6 +59,8 @@
m->epoch = epoch;
m->num_mon = num_mon;
ceph_decode_copy(&p, m->mon_inst, num_mon*sizeof(m->mon_inst[0]));
+ for (i = 0; i < num_mon; i++)
+ ceph_decode_addr(&m->mon_inst[i].addr);
dout("monmap_decode epoch %d, num_mon %d\n", m->epoch,
m->num_mon);
diff --git a/fs/ceph/msgr.h b/fs/ceph/msgr.h
index 9abc879..8e3ea2e 100644
--- a/fs/ceph/msgr.h
+++ b/fs/ceph/msgr.h
@@ -21,7 +21,7 @@
* whenever the wire protocol changes. try to keep this string length
* constant.
*/
-#define CEPH_BANNER "ceph v022"
+#define CEPH_BANNER "ceph v023"
#define CEPH_BANNER_MAX_LEN 30
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c
index d62e111..cd7bb26 100644
--- a/fs/ceph/osdmap.c
+++ b/fs/ceph/osdmap.c
@@ -460,6 +460,8 @@
*p += 4; /* skip length field (should match max) */
ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr));
+ for (i = 0; i < map->max_osd; i++)
+ ceph_decode_addr(&map->osd_addr[i]);
/* pg_temp */
ceph_decode_32_safe(p, end, len, bad);
@@ -619,6 +621,7 @@
struct ceph_entity_addr addr;
ceph_decode_32_safe(p, end, osd, bad);
ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad);
+ ceph_decode_addr(&addr);
pr_info("osd%d up\n", osd);
BUG_ON(osd >= map->max_osd);
map->osd_state[osd] |= CEPH_OSD_UP;