core: Infer __packed__ for union struct members
I.e. check that all the structs that are embedded in a union have their natural
alignment satisfied by the size of the array they are contained in,
Before this change we ended up not marking union struct members that didn't had
natural alignment violations as __packed__ even tho they had to be to be in a
struct that didn't satisfied their natural alignment requirements, which would
violate them when said union was in an array, i.e. the second entry would have
the non __packed__ union struct member in a bad position.
E.g. Before:
$ pahole -C ceph_osd_op /home/acme/git/build/v5.1-rc4+/net/ceph/osd_client.o
struct ceph_osd_op {
__le16 op; /* 0 2 */
__le32 flags; /* 2 4 */
union {
struct {
__le64 offset; /* 6 8 */
__le64 length; /* 14 8 */
__le64 truncate_size; /* 22 8 */
__le32 truncate_seq; /* 30 4 */
} __attribute__((__packed__)) extent; /* 6 28 */
struct {
__le32 name_len; /* 6 4 */
__le32 value_len; /* 10 4 */
__u8 cmp_op; /* 14 1 */
__u8 cmp_mode; /* 15 1 */
} __attribute__((__packed__)) xattr; /* 6 10 */
struct {
__u8 class_len; /* 6 1 */
__u8 method_len; /* 7 1 */
__u8 argc; /* 8 1 */
__le32 indata_len; /* 9 4 */
} __attribute__((__packed__)) cls; /* 6 7 */
struct {
__le64 cookie; /* 6 8 */
__le64 count; /* 14 8 */
} pgls; /* 6 16 */
struct {
__le64 snapid; /* 6 8 */
} snap; /* 6 8 */
struct {
__le64 cookie; /* 6 8 */
__le64 ver; /* 14 8 */
__u8 op; /* 22 1 */
__le32 gen; /* 23 4 */
} __attribute__((__packed__)) watch; /* 6 21 */
struct {
__le64 cookie; /* 6 8 */
} notify; /* 6 8 */
struct {
__le64 offset; /* 6 8 */
__le64 length; /* 14 8 */
__le64 src_offset; /* 22 8 */
} clonerange; /* 6 24 */
struct {
__le64 expected_object_size; /* 6 8 */
__le64 expected_write_size; /* 14 8 */
} alloc_hint; /* 6 16 */
struct {
__le64 snapid; /* 6 8 */
__le64 src_version; /* 14 8 */
__u8 flags; /* 22 1 */
__le32 src_fadvise_flags; /* 23 4 */
} __attribute__((__packed__)) copy_from; /* 6 21 */
}; /* 6 28 */
__le32 payload_len; /* 34 4 */
/* size: 38, cachelines: 1, members: 4 */
/* last cacheline: 38 bytes */
} __attribute__((__packed__));
After:
$ pahole -C ceph_osd_op /home/acme/git/build/v5.1-rc4+/net/ceph/osd_client.o
struct ceph_osd_op {
__le16 op; /* 0 2 */
__le32 flags; /* 2 4 */
union {
struct {
__le64 offset; /* 6 8 */
__le64 length; /* 14 8 */
__le64 truncate_size; /* 22 8 */
__le32 truncate_seq; /* 30 4 */
} __attribute__((__packed__)) extent; /* 6 28 */
struct {
__le32 name_len; /* 6 4 */
__le32 value_len; /* 10 4 */
__u8 cmp_op; /* 14 1 */
__u8 cmp_mode; /* 15 1 */
} __attribute__((__packed__)) xattr; /* 6 10 */
struct {
__u8 class_len; /* 6 1 */
__u8 method_len; /* 7 1 */
__u8 argc; /* 8 1 */
__le32 indata_len; /* 9 4 */
} __attribute__((__packed__)) cls; /* 6 7 */
struct {
__le64 cookie; /* 6 8 */
__le64 count; /* 14 8 */
} pgls; /* 6 16 */
struct {
__le64 snapid; /* 6 8 */
} snap; /* 6 8 */
struct {
__le64 cookie; /* 6 8 */
__le64 ver; /* 14 8 */
__u8 op; /* 22 1 */
__le32 gen; /* 23 4 */
} __attribute__((__packed__)) watch; /* 6 21 */
struct {
__le64 cookie; /* 6 8 */
} notify; /* 6 8 */
struct {
__le64 offset; /* 6 8 */
__le64 length; /* 14 8 */
__le64 src_offset; /* 22 8 */
} clonerange; /* 6 24 */
struct {
__le64 expected_object_size; /* 6 8 */
__le64 expected_write_size; /* 14 8 */
} alloc_hint; /* 6 16 */
struct {
__le64 snapid; /* 6 8 */
__le64 src_version; /* 14 8 */
__u8 flags; /* 22 1 */
__le32 src_fadvise_flags; /* 23 4 */
} __attribute__((__packed__)) copy_from; /* 6 21 */
}; /* 6 28 */
__le32 payload_len; /* 34 4 */
/* size: 38, cachelines: 1, members: 4 */
/* last cacheline: 38 bytes */
} __attribute__((__packed__));
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
3 files changed