[Drbd-dev] [DRBD][PATCH] drbd_bitfild_endian.patch

Maxim Uvarov muvarov at ru.mvista.com
Mon Nov 26 20:28:18 CET 2007


Lars Ellenberg wrote:

>On Mon, Nov 26, 2007 at 04:32:44PM +0000, Maxim Uvarov wrote:
>  
>
>>Hello all,
>>
>>We have found that drbd  state is passed incorrectly between machines  
>>with different endianness.
>>Attached patch fixes this problem by converting bitfild to int.
>>
>>Replacing all bitfileds (both in kernel and userland) isn't safe way 
>>(there are
>>about hundred lines to replace). Maybe adding converter from bitfield to 
>>int32
>>is appropriate solution ? Then sending state we do 
>>"drbd_state_to_int(state)"
>>and then receive we restore state by "int_to_drbd_state(i)". only 9 lines of
>>kernel code was changed (No need to change userspace). Additional 
>>overhead is
>>neglible.
>>    
>>
>
>right you are.
>but how about this instead:
>
>diff --git a/drbd/linux/drbd.h b/drbd/linux/drbd.h
>index b6ea313..ecf3a27 100644
>--- a/drbd/linux/drbd.h
>+++ b/drbd/linux/drbd.h
>@@ -28,6 +28,7 @@
> #include <linux/drbd_config.h>
> 
> #include <asm/types.h>
>+#include <asm/byteorder.h>
> 
> #ifdef __KERNEL__
> #include <linux/types.h>
>@@ -176,18 +177,39 @@ typedef enum {
> 	disk_mask=15
> } drbd_disks_t;
> 
>+/* bitfields are not endian safe.
>+ * pointed out by Maxim Uvarov <muvarov at ru.mvista.com>
>+ * even though we transmit as "cpu_to_be32(state)",
>+ * the offsets of the bitfields still need to be swapped
>+ * on different endianess.
>+ */
> typedef union {
> 	struct {
>-		unsigned role : 2 ;   // 3/4      primary/secondary/unknown
>-		unsigned peer : 2 ;   // 3/4      primary/secondary/unknown
>-		unsigned conn : 5 ;   // 17/32    cstates
>-		unsigned disk : 4 ;   // 8/16     from Diskless to UpToDate
>-		unsigned pdsk : 4 ;   // 8/16     from Diskless to UpToDate
>-		unsigned susp : 1 ;   // 2/2      IO suspended  no/yes
>-		unsigned aftr_isp : 1 ; // isp .. imposed sync pause
>+#if defined(__LITTLE_ENDIAN)
>+		unsigned role : 2 ;   /* 3/4      primary/secondary/unknown */
>+		unsigned peer : 2 ;   /* 3/4      primary/secondary/unknown */
>+		unsigned conn : 5 ;   /* 17/32    cstates */
>+		unsigned disk : 4 ;   /* 8/16     from Diskless to UpToDate */
>+		unsigned pdsk : 4 ;   /* 8/16     from Diskless to UpToDate */
>+		unsigned susp : 1 ;   /* 2/2      IO suspended  no/yes */
>+		unsigned aftr_isp : 1 ; /* isp .. imposed sync pause */
> 		unsigned peer_isp : 1 ;
> 		unsigned user_isp : 1 ;
>-		unsigned _pad : 11;   // 0        unused
>+		unsigned _pad : 11;   /* 0        unused */
>+#elif defined(__BIG_ENDIAN)
>+		unsigned _pad : 11;   /* 0        unused */
>+		unsigned user_isp : 1 ;
>+		unsigned peer_isp : 1 ;
>+		unsigned aftr_isp : 1 ; /* isp .. imposed sync pause */
>+		unsigned susp : 1 ;   /* 2/2      IO suspended  no/yes */
>+		unsigned pdsk : 4 ;   /* 8/16     from Diskless to UpToDate */
>+		unsigned disk : 4 ;   /* 8/16     from Diskless to UpToDate */
>+		unsigned conn : 5 ;   /* 17/32    cstates */
>+		unsigned peer : 2 ;   /* 3/4      primary/secondary/unknown */
>+		unsigned role : 2 ;   /* 3/4      primary/secondary/unknown */
>+#else
>+# error "this endianess is not supported"
>+#endif
> 	};
> 	unsigned int i;
> } drbd_state_t;
>
>
>  
>
Actually I did it at first time  but condition was  
__BIG_ENDIAN_BITFIELD. It require also changes
in default settings. And define _BITFIELD in user space. And  this 
version was denied by our architect with comment:
<cut>
Sending bit fields like this, unfortunately, is not portable. There is no
guarantee of bitfield layout event between compiler versions, let alone 
between
different architectures even of the same endian-ness.
</cut>

So it's not good idea to depend on compiler version.





More information about the drbd-dev mailing list