Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Bertschinger and committed by
Kent Overstreet
b07ce726 6e9d0558

+35 -2
+35 -2
fs/bcachefs/bcachefs_format.h
··· 189 189 __u32 hi; 190 190 __u64 lo; 191 191 #endif 192 - } __packed __aligned(4); 192 + } __packed 193 + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 194 + __aligned(4) 195 + #endif 196 + ; 193 197 194 198 struct bkey { 195 199 /* Size of combined key and value, in u64s */ ··· 226 222 227 223 __u8 pad[1]; 228 224 #endif 229 - } __packed __aligned(8); 225 + } __packed 226 + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 227 + /* 228 + * The big-endian version of bkey can't be compiled by rustc with the "aligned" 229 + * attr since it doesn't allow types to have both "packed" and "aligned" attrs. 230 + * So for Rust compatibility, don't include this. It can be included in the LE 231 + * version because the "packed" attr is redundant in that case. 232 + * 233 + * History: (quoting Kent) 234 + * 235 + * Specifically, when i was designing bkey, I wanted the header to be no 236 + * bigger than necessary so that bkey_packed could use the rest. That means that 237 + * decently offten extent keys will fit into only 8 bytes, instead of spilling over 238 + * to 16. 239 + * 240 + * But packed_bkey treats the part after the header - the packed section - 241 + * as a single multi word, variable length integer. And bkey, the unpacked 242 + * version, is just a special case version of a bkey_packed; all the packed 243 + * bkey code will work on keys in any packed format, the in-memory 244 + * representation of an unpacked key also is just one type of packed key... 245 + * 246 + * So that constrains the key part of a bkig endian bkey to start right 247 + * after the header. 248 + * 249 + * If we ever do a bkey_v2 and need to expand the hedaer by another byte for 250 + * some reason - that will clean up this wart. 251 + */ 252 + __aligned(8) 253 + #endif 254 + ; 230 255 231 256 struct bkey_packed { 232 257 __u64 _data[0];