bcachefs: omit alignment attribute on big endian struct bkey

This is needed for building Rust bindings on big endian architectures
like s390x. Currently this is only done in userspace, but it might
happen in-kernel in the future. When creating a Rust binding for struct
bkey, the "packed" attribute is needed to get a type with the correct
member offsets in the big endian case. However, rustc does not allow
types to have both a "packed" and "align" attribute. Thus, in order to
get a Rust type compatible with the C type, we must omit the "aligned"
attribute in C.

This does not affect the struct's size or member offsets, only its
toplevel alignment, which should be an acceptable impact.

The little endian version can have the "align" attribute because the
"packed" attr is redundant, and rust-bindgen will omit the "packed" attr
when an "align" attr is present and it can do so without changing a
type's layout

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Thomas Bertschinger 2024-02-15 19:44:21 -07:00 committed by Kent Overstreet
parent 6e9d0558b1
commit b07ce72626
1 changed files with 35 additions and 2 deletions

View File

@ -189,7 +189,11 @@ struct bversion {
__u32 hi;
__u64 lo;
#endif
} __packed __aligned(4);
} __packed
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
__aligned(4)
#endif
;
struct bkey {
/* Size of combined key and value, in u64s */
@ -222,7 +226,36 @@ struct bkey {
__u8 pad[1];
#endif
} __packed __aligned(8);
} __packed
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/*
* The big-endian version of bkey can't be compiled by rustc with the "aligned"
* attr since it doesn't allow types to have both "packed" and "aligned" attrs.
* So for Rust compatibility, don't include this. It can be included in the LE
* version because the "packed" attr is redundant in that case.
*
* History: (quoting Kent)
*
* Specifically, when i was designing bkey, I wanted the header to be no
* bigger than necessary so that bkey_packed could use the rest. That means that
* decently offten extent keys will fit into only 8 bytes, instead of spilling over
* to 16.
*
* But packed_bkey treats the part after the header - the packed section -
* as a single multi word, variable length integer. And bkey, the unpacked
* version, is just a special case version of a bkey_packed; all the packed
* bkey code will work on keys in any packed format, the in-memory
* representation of an unpacked key also is just one type of packed key...
*
* So that constrains the key part of a bkig endian bkey to start right
* after the header.
*
* If we ever do a bkey_v2 and need to expand the hedaer by another byte for
* some reason - that will clean up this wart.
*/
__aligned(8)
#endif
;
struct bkey_packed {
__u64 _data[0];