Subject: XFRM structures binary compability

From: <[email-masked]>
Date: Mon, 12 Jan 2009 14:54:46 +0100

Hello,

I face a problem due to binary incompatibility of XFRM structures.

I use XFRM interface to create IPsec SAs. My user application is compiled as 32bit binary.
It works properly when running against 32bit kernel. However when I've run it on 64bit kernel, netlink returns an error (EINVAL).
I use Fedora for both 32 and 64-bit environment.

I'm aware that it is due to incompatibility (different alignment and padding) of XFRM structures passed between user space and kernel
(defined here for user space: /usr/include/linux/xfrm.h)
My question is: shall not the structures be designed to be the same in 32 and 64bit environment?
I think a padding should be added to meet the more strict alignment rules (i.e. 64bit environment).

I used pahole tool (available in dwarves package) to display structure alignment (see attachment).
pahole_32.txt - structures from 32bit binary
pahole_64.txt - structures from 64bit binary

What causes my trouble is "xfrm_usersa_info" which is padded with 7 bytes at the end in 64-bit,
so that the whole structure is 224 bytes in 64bit application against 220 bytes in 32bit (just 3-byte padding).
An explicit 7-byte padding in the structure would cure the case, IMHO.

Thanks for your comments.

Jiri Klimes

PS: 
David Miller: thanks for pointing me to the correct list.

struct xfrm_userpolicy_id {
	struct xfrm_selector       sel;                  /*     0    56 */
	__u32                      index;                /*    56     4 */
	__u8                       dir;                  /*    60     1 */

	/* size: 64, cachelines: 1 */
	/* padding: 3 */
};	/* definitions: 1 */

struct xfrm_userpolicy_info {
	struct xfrm_selector       sel;                  /*     0    56 */
	struct xfrm_lifetime_cfg   lft;                  /*    56    64 */
	/* --- cacheline 1 boundary (64 bytes) was 56 bytes ago --- */
	struct xfrm_lifetime_cur   curlft;               /*   120    32 */
	/* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
	__u32                      priority;             /*   152     4 */
	__u32                      index;                /*   156     4 */
	__u8                       dir;                  /*   160     1 */
	__u8                       action;               /*   161     1 */
	__u8                       flags;                /*   162     1 */
	__u8                       share;                /*   163     1 */

	/* size: 164, cachelines: 3 */
	/* last cacheline: 36 bytes */
};	/* definitions: 1 */

struct xfrm_usersa_id {
	xfrm_address_t             daddr;                /*     0    16 */
	__be32                     spi;                  /*    16     4 */
	__u16                      family;               /*    20     2 */
	__u8                       proto;                /*    22     1 */

	/* size: 24, cachelines: 1 */
	/* padding: 1 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct xfrm_usersa_info {
	struct xfrm_selector       sel;                  /*     0    56 */
	struct xfrm_id             id;                   /*    56    24 */

	/* XXX last struct has 3 bytes of padding */

	/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
	xfrm_address_t             saddr;                /*    80    16 */
	struct xfrm_lifetime_cfg   lft;                  /*    96    64 */
	/* --- cacheline 2 boundary (128 bytes) was 32 bytes ago --- */
	struct xfrm_lifetime_cur   curlft;               /*   160    32 */
	/* --- cacheline 3 boundary (192 bytes) --- */
	struct xfrm_stats          stats;                /*   192    12 */
	__u32                      seq;                  /*   204     4 */
	__u32                      reqid;                /*   208     4 */
	__u16                      family;               /*   212     2 */
	__u8                       mode;                 /*   214     1 */
	__u8                       replay_window;        /*   215     1 */
	__u8                       flags;                /*   216     1 */

	/* size: 220, cachelines: 4 */
	/* padding: 3 */
	/* paddings: 1, sum paddings: 3 */
	/* last cacheline: 28 bytes */
};	/* definitions: 1 */

struct xfrm_encap_tmpl {
	__u16                      encap_type;           /*     0     2 */
	__be16                     encap_sport;          /*     2     2 */
	__be16                     encap_dport;          /*     4     2 */

	/* XXX 2 bytes hole, try to pack */

	xfrm_address_t             encap_oa;             /*     8    16 */

	/* size: 24, cachelines: 1 */
	/* sum members: 22, holes: 1, sum holes: 2 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct xfrm_user_tmpl {
	struct xfrm_id             id;                   /*     0    24 */

	/* XXX last struct has 3 bytes of padding */

	__u16                      family;               /*    24     2 */

	/* XXX 2 bytes hole, try to pack */

	xfrm_address_t             saddr;                /*    28    16 */
	__u32                      reqid;                /*    44     4 */
	__u8                       mode;                 /*    48     1 */
	__u8                       share;                /*    49     1 */
	__u8                       optional;             /*    50     1 */

	/* XXX 1 byte hole, try to pack */

	__u32                      aalgos;               /*    52     4 */
	__u32                      ealgos;               /*    56     4 */
	__u32                      calgos;               /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */

	/* size: 64, cachelines: 1 */
	/* sum members: 61, holes: 2, sum holes: 3 */
	/* paddings: 1, sum paddings: 3 */
};	/* definitions: 1 */

struct xfrm_stats {
	__u32                      replay_window;        /*     0     4 */
	__u32                      replay;               /*     4     4 */
	__u32                      integrity_failed;     /*     8     4 */

	/* size: 12, cachelines: 1 */
	/* last cacheline: 12 bytes */
};	/* definitions: 1 */

struct xfrm_algo {
	char                       alg_name[64];         /*     0    64 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	unsigned int               alg_key_len;          /*    64     4 */
	char                       alg_key[0];           /*    68     0 */

	/* size: 68, cachelines: 2 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct xfrm_lifetime_cur {
	__u64                      bytes;                /*     0     8 */
	__u64                      packets;              /*     8     8 */
	__u64                      add_time;             /*    16     8 */
	__u64                      use_time;             /*    24     8 */

	/* size: 32, cachelines: 1 */
	/* last cacheline: 32 bytes */
};	/* definitions: 1 */

struct xfrm_lifetime_cfg {
	__u64                      soft_byte_limit;      /*     0     8 */
	__u64                      hard_byte_limit;      /*     8     8 */
	__u64                      soft_packet_limit;    /*    16     8 */
	__u64                      hard_packet_limit;    /*    24     8 */
	__u64                      soft_add_expires_seconds; /*    32     8 */
	__u64                      hard_add_expires_seconds; /*    40     8 */
	__u64                      soft_use_expires_seconds; /*    48     8 */
	__u64                      hard_use_expires_seconds; /*    56     8 */
	/* --- cacheline 1 boundary (64 bytes) --- */

	/* size: 64, cachelines: 1 */
};	/* definitions: 1 */

struct xfrm_selector {
	xfrm_address_t             daddr;                /*     0    16 */
	xfrm_address_t             saddr;                /*    16    16 */
	__be16                     dport;                /*    32     2 */
	__be16                     dport_mask;           /*    34     2 */
	__be16                     sport;                /*    36     2 */
	__be16                     sport_mask;           /*    38     2 */
	__u16                      family;               /*    40     2 */
	__u8                       prefixlen_d;          /*    42     1 */
	__u8                       prefixlen_s;          /*    43     1 */
	__u8                       proto;                /*    44     1 */

	/* XXX 3 bytes hole, try to pack */

	int                        ifindex;              /*    48     4 */
	uid_t                      user;                 /*    52     4 */

	/* size: 56, cachelines: 1 */
	/* sum members: 53, holes: 1, sum holes: 3 */
	/* last cacheline: 56 bytes */
};	/* definitions: 1 */

struct xfrm_id {
	xfrm_address_t             daddr;                /*     0    16 */
	__be32                     spi;                  /*    16     4 */
	__u8                       proto;                /*    20     1 */

	/* size: 24, cachelines: 1 */
	/* padding: 3 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct rtattr {
	short unsigned int         rta_len;              /*     0     2 */
	short unsigned int         rta_type;             /*     2     2 */

	/* size: 4, cachelines: 1 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct nlmsgerr {
	int                        error;                /*     0     4 */
	struct nlmsghdr            msg;                  /*     4    16 */

	/* size: 20, cachelines: 1 */
	/* last cacheline: 20 bytes */
};	/* definitions: 1 */

struct nlmsghdr {
	__u32                      nlmsg_len;            /*     0     4 */
	__u16                      nlmsg_type;           /*     4     2 */
	__u16                      nlmsg_flags;          /*     6     2 */
	__u32                      nlmsg_seq;            /*     8     4 */
	__u32                      nlmsg_pid;            /*    12     4 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct sockaddr_nl {
	sa_family_t                nl_family;            /*     0     2 */
	short unsigned int         nl_pad;               /*     2     2 */
	__u32                      nl_pid;               /*     4     4 */
	__u32                      nl_groups;            /*     8     4 */

	/* size: 12, cachelines: 1 */
	/* last cacheline: 12 bytes */
};	/* definitions: 1 */

struct sockaddr_in6 {
	sa_family_t                sin6_family;          /*     0     2 */
	in_port_t                  sin6_port;            /*     2     2 */
	uint32_t                   sin6_flowinfo;        /*     4     4 */
	struct in6_addr            sin6_addr;            /*     8    16 */
	uint32_t                   sin6_scope_id;        /*    24     4 */

	/* size: 28, cachelines: 1 */
	/* last cacheline: 28 bytes */
};	/* definitions: 1 */

struct sockaddr_in {
	sa_family_t                sin_family;           /*     0     2 */
	in_port_t                  sin_port;             /*     2     2 */
	struct in_addr             sin_addr;             /*     4     4 */
	unsigned char              sin_zero[8];          /*     8     8 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct in6_addr {
	union {
		uint8_t            u6_addr8[16];         /*          16 */
		uint16_t           u6_addr16[8];         /*          16 */
		uint32_t           u6_addr32[4];         /*          16 */
	} in6_u;                                         /*     0    16 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct in_addr {
	in_addr_t                  s_addr;               /*     0     4 */

	/* size: 4, cachelines: 1 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct msghdr {
	void *                     msg_name;             /*     0     4 */
	socklen_t                  msg_namelen;          /*     4     4 */
	struct iovec *             msg_iov;              /*     8     4 */
	size_t                     msg_iovlen;           /*    12     4 */
	void *                     msg_control;          /*    16     4 */
	size_t                     msg_controllen;       /*    20     4 */
	int                        msg_flags;            /*    24     4 */

	/* size: 28, cachelines: 1 */
	/* last cacheline: 28 bytes */
};	/* definitions: 1 */

struct sockaddr {
	sa_family_t                sa_family;            /*     0     2 */
	char                       sa_data[14];          /*     2    14 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct iovec {
	void *                     iov_base;             /*     0     4 */
	size_t                     iov_len;              /*     4     4 */

	/* size: 8, cachelines: 1 */
	/* last cacheline: 8 bytes */
};	/* definitions: 1 */

struct _IO_marker {
	struct _IO_marker *        _next;                /*     0     4 */
	struct _IO_FILE *          _sbuf;                /*     4     4 */
	int                        _pos;                 /*     8     4 */

	/* size: 12, cachelines: 1 */
	/* last cacheline: 12 bytes */
};	/* definitions: 1 */

struct _IO_FILE {
	int                        _flags;               /*     0     4 */
	char *                     _IO_read_ptr;         /*     4     4 */
	char *                     _IO_read_end;         /*     8     4 */
	char *                     _IO_read_base;        /*    12     4 */
	char *                     _IO_write_base;       /*    16     4 */
	char *                     _IO_write_ptr;        /*    20     4 */
	char *                     _IO_write_end;        /*    24     4 */
	char *                     _IO_buf_base;         /*    28     4 */
	char *                     _IO_buf_end;          /*    32     4 */
	char *                     _IO_save_base;        /*    36     4 */
	char *                     _IO_backup_base;      /*    40     4 */
	char *                     _IO_save_end;         /*    44     4 */
	struct _IO_marker *        _markers;             /*    48     4 */
	struct _IO_FILE *          _chain;               /*    52     4 */
	int                        _fileno;              /*    56     4 */
	int                        _flags2;              /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	__off_t                    _old_offset;          /*    64     4 */
	short unsigned int         _cur_column;          /*    68     2 */
	signed char                _vtable_offset;       /*    70     1 */
	char                       _shortbuf[1];         /*    71     1 */
	_IO_lock_t *               _lock;                /*    72     4 */
	__off64_t                  _offset;              /*    76     8 */
	void *                     __pad1;               /*    84     4 */
	void *                     __pad2;               /*    88     4 */
	void *                     __pad3;               /*    92     4 */
	void *                     __pad4;               /*    96     4 */
	size_t                     __pad5;               /*   100     4 */
	int                        _mode;                /*   104     4 */
	char                       _unused2[40];         /*   108    40 */
	/* --- cacheline 2 boundary (128 bytes) was 20 bytes ago --- */

	/* size: 148, cachelines: 3 */
	/* last cacheline: 20 bytes */
};	/* definitions: 1 */

struct xfrm_userpolicy_id {
	struct xfrm_selector       sel;                  /*     0    56 */
	__u32                      index;                /*    56     4 */
	__u8                       dir;                  /*    60     1 */

	/* size: 64, cachelines: 1 */
	/* padding: 3 */
};	/* definitions: 1 */

struct xfrm_userpolicy_info {
	struct xfrm_selector       sel;                  /*     0    56 */
	struct xfrm_lifetime_cfg   lft;                  /*    56    64 */
	/* --- cacheline 1 boundary (64 bytes) was 56 bytes ago --- */
	struct xfrm_lifetime_cur   curlft;               /*   120    32 */
	/* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
	__u32                      priority;             /*   152     4 */
	__u32                      index;                /*   156     4 */
	__u8                       dir;                  /*   160     1 */
	__u8                       action;               /*   161     1 */
	__u8                       flags;                /*   162     1 */
	__u8                       share;                /*   163     1 */

	/* size: 168, cachelines: 3 */
	/* padding: 4 */
	/* last cacheline: 40 bytes */
};	/* definitions: 1 */

struct xfrm_usersa_id {
	xfrm_address_t             daddr;                /*     0    16 */
	__be32                     spi;                  /*    16     4 */
	__u16                      family;               /*    20     2 */
	__u8                       proto;                /*    22     1 */

	/* size: 24, cachelines: 1 */
	/* padding: 1 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct xfrm_usersa_info {
	struct xfrm_selector       sel;                  /*     0    56 */
	struct xfrm_id             id;                   /*    56    24 */

	/* XXX last struct has 3 bytes of padding */

	/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
	xfrm_address_t             saddr;                /*    80    16 */
	struct xfrm_lifetime_cfg   lft;                  /*    96    64 */
	/* --- cacheline 2 boundary (128 bytes) was 32 bytes ago --- */
	struct xfrm_lifetime_cur   curlft;               /*   160    32 */
	/* --- cacheline 3 boundary (192 bytes) --- */
	struct xfrm_stats          stats;                /*   192    12 */
	__u32                      seq;                  /*   204     4 */
	__u32                      reqid;                /*   208     4 */
	__u16                      family;               /*   212     2 */
	__u8                       mode;                 /*   214     1 */
	__u8                       replay_window;        /*   215     1 */
	__u8                       flags;                /*   216     1 */

	/* size: 224, cachelines: 4 */
	/* padding: 7 */
	/* paddings: 1, sum paddings: 3 */
	/* last cacheline: 32 bytes */
};	/* definitions: 1 */

struct xfrm_encap_tmpl {
	__u16                      encap_type;           /*     0     2 */
	__be16                     encap_sport;          /*     2     2 */
	__be16                     encap_dport;          /*     4     2 */

	/* XXX 2 bytes hole, try to pack */

	xfrm_address_t             encap_oa;             /*     8    16 */

	/* size: 24, cachelines: 1 */
	/* sum members: 22, holes: 1, sum holes: 2 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct xfrm_user_tmpl {
	struct xfrm_id             id;                   /*     0    24 */

	/* XXX last struct has 3 bytes of padding */

	__u16                      family;               /*    24     2 */

	/* XXX 2 bytes hole, try to pack */

	xfrm_address_t             saddr;                /*    28    16 */
	__u32                      reqid;                /*    44     4 */
	__u8                       mode;                 /*    48     1 */
	__u8                       share;                /*    49     1 */
	__u8                       optional;             /*    50     1 */

	/* XXX 1 byte hole, try to pack */

	__u32                      aalgos;               /*    52     4 */
	__u32                      ealgos;               /*    56     4 */
	__u32                      calgos;               /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */

	/* size: 64, cachelines: 1 */
	/* sum members: 61, holes: 2, sum holes: 3 */
	/* paddings: 1, sum paddings: 3 */
};	/* definitions: 1 */

struct xfrm_stats {
	__u32                      replay_window;        /*     0     4 */
	__u32                      replay;               /*     4     4 */
	__u32                      integrity_failed;     /*     8     4 */

	/* size: 12, cachelines: 1 */
	/* last cacheline: 12 bytes */
};	/* definitions: 1 */

struct xfrm_algo {
	char                       alg_name[64];         /*     0    64 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	unsigned int               alg_key_len;          /*    64     4 */
	char                       alg_key[0];           /*    68     0 */

	/* size: 68, cachelines: 2 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct xfrm_lifetime_cur {
	__u64                      bytes;                /*     0     8 */
	__u64                      packets;              /*     8     8 */
	__u64                      add_time;             /*    16     8 */
	__u64                      use_time;             /*    24     8 */

	/* size: 32, cachelines: 1 */
	/* last cacheline: 32 bytes */
};	/* definitions: 1 */

struct xfrm_lifetime_cfg {
	__u64                      soft_byte_limit;      /*     0     8 */
	__u64                      hard_byte_limit;      /*     8     8 */
	__u64                      soft_packet_limit;    /*    16     8 */
	__u64                      hard_packet_limit;    /*    24     8 */
	__u64                      soft_add_expires_seconds; /*    32     8 */
	__u64                      hard_add_expires_seconds; /*    40     8 */
	__u64                      soft_use_expires_seconds; /*    48     8 */
	__u64                      hard_use_expires_seconds; /*    56     8 */
	/* --- cacheline 1 boundary (64 bytes) --- */

	/* size: 64, cachelines: 1 */
};	/* definitions: 1 */

struct xfrm_selector {
	xfrm_address_t             daddr;                /*     0    16 */
	xfrm_address_t             saddr;                /*    16    16 */
	__be16                     dport;                /*    32     2 */
	__be16                     dport_mask;           /*    34     2 */
	__be16                     sport;                /*    36     2 */
	__be16                     sport_mask;           /*    38     2 */
	__u16                      family;               /*    40     2 */
	__u8                       prefixlen_d;          /*    42     1 */
	__u8                       prefixlen_s;          /*    43     1 */
	__u8                       proto;                /*    44     1 */

	/* XXX 3 bytes hole, try to pack */

	int                        ifindex;              /*    48     4 */
	uid_t                      user;                 /*    52     4 */

	/* size: 56, cachelines: 1 */
	/* sum members: 53, holes: 1, sum holes: 3 */
	/* last cacheline: 56 bytes */
};	/* definitions: 1 */

struct xfrm_id {
	xfrm_address_t             daddr;                /*     0    16 */
	__be32                     spi;                  /*    16     4 */
	__u8                       proto;                /*    20     1 */

	/* size: 24, cachelines: 1 */
	/* padding: 3 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct rtattr {
	short unsigned int         rta_len;              /*     0     2 */
	short unsigned int         rta_type;             /*     2     2 */

	/* size: 4, cachelines: 1 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct nlmsgerr {
	int                        error;                /*     0     4 */
	struct nlmsghdr            msg;                  /*     4    16 */

	/* size: 20, cachelines: 1 */
	/* last cacheline: 20 bytes */
};	/* definitions: 1 */

struct nlmsghdr {
	__u32                      nlmsg_len;            /*     0     4 */
	__u16                      nlmsg_type;           /*     4     2 */
	__u16                      nlmsg_flags;          /*     6     2 */
	__u32                      nlmsg_seq;            /*     8     4 */
	__u32                      nlmsg_pid;            /*    12     4 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct sockaddr_nl {
	sa_family_t                nl_family;            /*     0     2 */
	short unsigned int         nl_pad;               /*     2     2 */
	__u32                      nl_pid;               /*     4     4 */
	__u32                      nl_groups;            /*     8     4 */

	/* size: 12, cachelines: 1 */
	/* last cacheline: 12 bytes */
};	/* definitions: 1 */

struct sockaddr_in6 {
	sa_family_t                sin6_family;          /*     0     2 */
	in_port_t                  sin6_port;            /*     2     2 */
	uint32_t                   sin6_flowinfo;        /*     4     4 */
	struct in6_addr            sin6_addr;            /*     8    16 */
	uint32_t                   sin6_scope_id;        /*    24     4 */

	/* size: 28, cachelines: 1 */
	/* last cacheline: 28 bytes */
};	/* definitions: 1 */

struct sockaddr_in {
	sa_family_t                sin_family;           /*     0     2 */
	in_port_t                  sin_port;             /*     2     2 */
	struct in_addr             sin_addr;             /*     4     4 */
	unsigned char              sin_zero[8];          /*     8     8 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct in6_addr {
	union {
		uint8_t            __u6_addr8[16];       /*          16 */
		uint16_t           __u6_addr16[8];       /*          16 */
		uint32_t           __u6_addr32[4];       /*          16 */
	} __in6_u;                                       /*     0    16 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct in_addr {
	in_addr_t                  s_addr;               /*     0     4 */

	/* size: 4, cachelines: 1 */
	/* last cacheline: 4 bytes */
};	/* definitions: 1 */

struct msghdr {
	void *                     msg_name;             /*     0     8 */
	socklen_t                  msg_namelen;          /*     8     4 */

	/* XXX 4 bytes hole, try to pack */

	struct iovec *             msg_iov;              /*    16     8 */
	size_t                     msg_iovlen;           /*    24     8 */
	void *                     msg_control;          /*    32     8 */
	size_t                     msg_controllen;       /*    40     8 */
	int                        msg_flags;            /*    48     4 */

	/* size: 56, cachelines: 1 */
	/* sum members: 48, holes: 1, sum holes: 4 */
	/* padding: 4 */
	/* last cacheline: 56 bytes */
};	/* definitions: 1 */

struct sockaddr {
	sa_family_t                sa_family;            /*     0     2 */
	char                       sa_data[14];          /*     2    14 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct iovec {
	void *                     iov_base;             /*     0     8 */
	size_t                     iov_len;              /*     8     8 */

	/* size: 16, cachelines: 1 */
	/* last cacheline: 16 bytes */
};	/* definitions: 1 */

struct _IO_marker {
	struct _IO_marker *        _next;                /*     0     8 */
	struct _IO_FILE *          _sbuf;                /*     8     8 */
	int                        _pos;                 /*    16     4 */

	/* size: 24, cachelines: 1 */
	/* padding: 4 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */

struct _IO_FILE {
	int                        _flags;               /*     0     4 */

	/* XXX 4 bytes hole, try to pack */

	char *                     _IO_read_ptr;         /*     8     8 */
	char *                     _IO_read_end;         /*    16     8 */
	char *                     _IO_read_base;        /*    24     8 */
	char *                     _IO_write_base;       /*    32     8 */
	char *                     _IO_write_ptr;        /*    40     8 */
	char *                     _IO_write_end;        /*    48     8 */
	char *                     _IO_buf_base;         /*    56     8 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	char *                     _IO_buf_end;          /*    64     8 */
	char *                     _IO_save_base;        /*    72     8 */
	char *                     _IO_backup_base;      /*    80     8 */
	char *                     _IO_save_end;         /*    88     8 */
	struct _IO_marker *        _markers;             /*    96     8 */
	struct _IO_FILE *          _chain;               /*   104     8 */
	int                        _fileno;              /*   112     4 */
	int                        _flags2;              /*   116     4 */
	__off_t                    _old_offset;          /*   120     8 */
	/* --- cacheline 2 boundary (128 bytes) --- */
	short unsigned int         _cur_column;          /*   128     2 */
	signed char                _vtable_offset;       /*   130     1 */
	char                       _shortbuf[1];         /*   131     1 */

	/* XXX 4 bytes hole, try to pack */

	_IO_lock_t *               _lock;                /*   136     8 */
	__off64_t                  _offset;              /*   144     8 */
	void *                     __pad1;               /*   152     8 */
	void *                     __pad2;               /*   160     8 */
	void *                     __pad3;               /*   168     8 */
	void *                     __pad4;               /*   176     8 */
	size_t                     __pad5;               /*   184     8 */
	/* --- cacheline 3 boundary (192 bytes) --- */
	int                        _mode;                /*   192     4 */
	char                       _unused2[20];         /*   196    20 */

	/* size: 216, cachelines: 4 */
	/* sum members: 208, holes: 2, sum holes: 8 */
	/* last cacheline: 24 bytes */
};	/* definitions: 1 */