]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
include: Endian fix for shared kernel/user headers
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 2 Sep 2019 19:21:17 +0000 (21:21 +0200)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Wed, 2 Oct 2019 16:29:50 +0000 (18:29 +0200)
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>
src/include/ceph_fs.h
src/include/msgr.h
src/include/rados.h
src/include/rbd_types.h
src/include/types.h
src/mds/locks.c

index fd12b9f12541a16ce84b7f713a2e1ae473e164c0..1c73ff377bc08c0666c65142267d48551e138aab 100644 (file)
 #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
@@ -710,6 +731,7 @@ int ceph_flags_to_mode(int flags);
 #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 */
@@ -951,4 +973,10 @@ struct ceph_mds_snap_realm {
 } __attribute__ ((packed));
 /* followed by my snap list, then prior parent snap list */
 
+#ifndef __KERNEL__
+#undef __le16
+#undef __le32
+#undef __le64
+#endif
+
 #endif
index 4029443d0a4e588b5288c92ba50b511220134a70..bda8108082475f8a13b67920cc41658acc204060 100644 (file)
@@ -7,6 +7,14 @@
 
 #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.
  */
@@ -236,5 +244,10 @@ struct ceph_msg_footer {
 #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
index 53320d65410c619ac75152159737e2803a40ed7e..6cf951f2d8fab5e727fdaabf9106ddee89c48115 100644 (file)
@@ -9,6 +9,14 @@
 #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
  */
@@ -663,5 +671,10 @@ struct ceph_osd_reply_head {
        struct ceph_osd_op ops[0];  /* ops[], object */
 } __attribute__ ((packed));
 
+#ifndef __KERNEL__
+#undef __le16
+#undef __le32
+#undef __le64
+#endif
 
 #endif
index 94799ab6f1de60016409529ec5ef7ecbe1651c5d..4401a36c8ba9c6fcf53b1769834cb94ca72d6b64 100644 (file)
 #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 {
@@ -138,11 +138,11 @@ 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));
 
index 04c62e3897407f1ae396395e197e84220cb25343..1ae1527758de3b5fdd361e30b2b16ba2ed0be6f0 100644 (file)
 #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
index c788407fb0af450b7e8844b8becbe3fe798a192d..fad782ba6a093464db0631db1b1166ce288e2ea6 100644 (file)
@@ -8,9 +8,18 @@ typedef char bool;
 #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 },