Endian swapping is done differently in kernel space vs. user space,
but a few header files are shared between those two user cases.
Current code attempts to handle this by re-defining __le16/32/64
before pulling those headers into user space, but this is not
consistenly done: when ceph_fs.h is included via types.h, the
redefinition happens, but when ceph_fs.h is directly included,
the redefinition does not happen.
Fix this by performing the same redefinition directly *in* those
shared headers, when included by user space.
Note that the redefines where also in effect for rbd_types.h,
which is *not* shared with the kernel, so in the file I'm simply
replacing __le16/32/64 with ceph_le16/32/64 in-line.
Also note that it is now no longer possible to include any of
the three files using the redefined macros in C code (as they
make use of C++ features). However, this currently happens in
exactly one file, src/mds/locks.c, which only uses a few CEPH_CAP_...
constants from the header. To fix this, I've simply duplicated
those definitions, which are unchangeable ABI constants anyway.
Fixes (partially): https://tracker.ceph.com/issues/41605
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
(cherry picked from commit
743ed43a785795412cdda16e3d25b12cb9228a32)
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
#include "msgr.h"
#include "rados.h"
+/*
+ * The data structures defined here are shared between Linux kernel and
+ * user space. Also, those data structures are maintained always in
+ * little-endian byte order, even on big-endian systems. This is handled
+ * differently in kernel vs. user space. For use as kernel headers, the
+ * little-endian fields need to use the __le16/__le32/__le64 types. These
+ * are markers that indicate endian conversion routines must be used
+ * whenever such fields are accessed, which can be verified by checker
+ * tools like "sparse". For use as user-space headers, the little-endian
+ * fields instead use types ceph_le16/ceph_le32/ceph_le64, which are C++
+ * classes that implement automatic endian conversion on every access.
+ * To still allow for header sharing, this file uses the __le types, but
+ * redefines those to the ceph_ types when compiled in user space.
+ */
+#ifndef __KERNEL__
+#include "byteorder.h"
+#define __le16 ceph_le16
+#define __le32 ceph_le32
+#define __le64 ceph_le64
+#endif
+
/*
* subprotocol versions. when specific messages types or high-level
* protocols change, bump the affected components. we keep rev
#define CEPH_CAP_PIN 1 /* no specific capabilities beyond the pin */
/* generic cap bits */
+/* note: these definitions are duplicated in mds/locks.c */
#define CEPH_CAP_GSHARED 1 /* client can reads */
#define CEPH_CAP_GEXCL 2 /* client can read and update */
#define CEPH_CAP_GCACHE 4 /* (file) client can cache reads */
} __attribute__ ((packed));
/* followed by my snap list, then prior parent snap list */
+#ifndef __KERNEL__
+#undef __le16
+#undef __le32
+#undef __le64
+#endif
+
#endif
#include "include/int_types.h"
+/* See comment in ceph_fs.h. */
+#ifndef __KERNEL__
+#include "byteorder.h"
+#define __le16 ceph_le16
+#define __le32 ceph_le32
+#define __le64 ceph_le64
+#endif
+
/*
* Data types for message passing layer used by Ceph.
*/
#define CEPH_MSG_FOOTER_NOCRC (1<<1) /* no data crc */
#define CEPH_MSG_FOOTER_SIGNED (1<<2) /* msg was signed */
+#ifndef __KERNEL__
+#undef __le16
+#undef __le32
+#undef __le64
+#endif
#endif
#include <string.h>
#include "msgr.h"
+/* See comment in ceph_fs.h. */
+#ifndef __KERNEL__
+#include "byteorder.h"
+#define __le16 ceph_le16
+#define __le32 ceph_le32
+#define __le64 ceph_le64
+#endif
+
/*
* fs id
*/
struct ceph_osd_op ops[0]; /* ops[], object */
} __attribute__ ((packed));
+#ifndef __KERNEL__
+#undef __le16
+#undef __le32
+#undef __le64
+#endif
#endif
#define RBD_MIRROR_PEER_CONFIG_KEY_PREFIX "rbd/mirror/peer/"
struct rbd_info {
- __le64 max_id;
+ ceph_le64 max_id;
} __attribute__ ((packed));
struct rbd_obj_snap_ondisk {
- __le64 id;
- __le64 image_size;
+ ceph_le64 id;
+ ceph_le64 image_size;
} __attribute__((packed));
struct rbd_obj_header_ondisk {
__u8 comp_type;
__u8 unused;
} __attribute__((packed)) options;
- __le64 image_size;
- __le64 snap_seq;
- __le32 snap_count;
- __le32 reserved;
- __le64 snap_names_len;
+ ceph_le64 image_size;
+ ceph_le64 snap_seq;
+ ceph_le32 snap_count;
+ ceph_le32 reserved;
+ ceph_le64 snap_names_len;
struct rbd_obj_snap_ondisk snaps[0];
} __attribute__((packed));
#include <fcntl.h>
#include <string.h>
-// <macro hackery>
-// temporarily remap __le* to ceph_le* for benefit of shared kernel/userland headers
-#define __le16 ceph_le16
-#define __le32 ceph_le32
-#define __le64 ceph_le64
#include "ceph_fs.h"
#include "ceph_frag.h"
#include "rbd_types.h"
-#undef __le16
-#undef __le32
-#undef __le64
-// </macro hackery>
-
#ifdef __cplusplus
#ifndef _BACKWARD_BACKWARD_WARNING_H
#include <string.h>
#include <fcntl.h>
-#include "include/ceph_fs.h"
#include "locks.h"
+/* Duplicated from ceph_fs.h, which we cannot include into a C file. */
+#define CEPH_CAP_GSHARED 1 /* client can reads */
+#define CEPH_CAP_GEXCL 2 /* client can read and update */
+#define CEPH_CAP_GCACHE 4 /* (file) client can cache reads */
+#define CEPH_CAP_GRD 8 /* (file) client can read */
+#define CEPH_CAP_GWR 16 /* (file) client can write */
+#define CEPH_CAP_GBUFFER 32 /* (file) client can buffer writes */
+#define CEPH_CAP_GWREXTEND 64 /* (file) client can extend EOF */
+#define CEPH_CAP_GLAZYIO 128 /* (file) client can perform lazy io */
+
static const struct sm_state_t simplelock[LOCK_MAX] = {
// stable loner rep state r rp rd wr fwr l x caps,other
[LOCK_SYNC] = { 0, false, LOCK_SYNC, ANY, 0, ANY, 0, 0, ANY, 0, CEPH_CAP_GSHARED,0,0,CEPH_CAP_GSHARED },