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