Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fprintf: Show statistics about members with flexible arrays
For instance, this one has embedded flexible arrays: $ pahole lirc_fh struct lirc_fh { struct list_head list; /* 0 16 */ struct rc_dev * rc; /* 16 8 */ int carrier_low; /* 24 4 */ /* XXX 4 bytes hole, try to pack */ struct { union { struct __kfifo kfifo; /* 32 24 */ unsigned int * type; /* 32 8 */ const unsigned int * const_type; /* 32 8 */ char * rectype; /* 32 8 */ unsigned int * ptr; /* 32 8 */ const unsigned int * ptr_const; /* 32 8 */ }; /* 32 24 */ unsigned int buf[]; /* 56 0 */ } rawir; /* 32 24 */ /* XXX last struct has a flexible array */ struct { union { struct __kfifo kfifo; /* 56 24 */ struct lirc_scancode * type; /* 56 8 */ const struct lirc_scancode * const_type; /* 56 8 */ char * rectype; /* 56 8 */ struct lirc_scancode * ptr; /* 56 8 */ const struct lirc_scancode * ptr_const; /* 56 8 */ }; /* 56 24 */ /* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */ struct lirc_scancode buf[]; /* 80 0 */ } scancodes; /* 56 24 */ /* XXX last struct has a flexible array */ wait_queue_head_t wait_poll; /* 80 24 */ u8 send_mode; /* 104 1 */ u8 rec_mode; /* 105 1 */ /* size: 112, cachelines: 2, members: 8 */ /* sum members: 102, holes: 1, sum holes: 4 */ /* padding: 6 */ /* flexible array members: end: 2 */ /* last cacheline: 48 bytes */ }; $ 'end' means that the members with flexible arrays have them in the "classical" sense, i.e. the last member of those member types is a [] member. When 'middle' appears it means another level, just like the above 'struct lirc_fh' has multiple members in its midle that are flexible arrays. If we use 'pahole --with_embedded_flexible_array' we'll see quite a few in the Linux kernel (using BTF info from /sys/kernel/btf/vmlinux, mostly available in most kernels these days), using --sizes so that we get just one line per Linux kernel struct that have embedded flexible arrays (and its sizes and number of alignment holes, as bonuses): $ pahole --sizes --with_embedded_flexible_array | head mem_cgroup 2240 10 pglist_data 175424 7 zone 1728 5 cgroup 1984 3 cgroup_root 6272 1 page_counter 192 1 cpu_hw_events 5200 6 crypto_shash 40 1 crypto_aead 40 0 crypto_ahash 48 2 $ $ pahole crypto_shash struct crypto_shash { unsigned int descsize; /* 0 4 */ /* XXX 4 bytes hole, try to pack */ struct crypto_tfm base; /* 8 32 */ /* XXX last struct has a flexible array, 1 hole */ /* size: 40, cachelines: 1, members: 2 */ /* sum members: 36, holes: 1, sum holes: 4 */ /* member types with holes: 1, total: 1 */ /* flexible array members: end: 1 */ /* last cacheline: 40 bytes */ }; $ If we expand it all: $ pahole -E crypto_shash struct crypto_shash { unsigned int descsize; /* 0 4 */ /* XXX 4 bytes hole, try to pack */ struct crypto_tfm { /* typedef refcount_t */ struct refcount_struct { /* typedef atomic_t */ struct { int counter; /* 8 4 */ } refs; /* 8 4 */ } refcnt; /* 8 4 */ /* typedef u32 -> __u32 */ unsigned int crt_flags; /* 12 4 */ int node; /* 16 4 */ /* XXX 4 bytes hole, try to pack */ void (*exit)(struct crypto_tfm *); /* 24 8 */ struct crypto_alg * __crt_alg; /* 32 8 */ void * __crt_ctx[]; /* 40 0 */ } base; /* 8 32 */ /* XXX last struct has a flexible array, 1 hole */ /* size: 40, cachelines: 1, members: 2 */ /* sum members: 36, holes: 1, sum holes: 4 */ /* member types with holes: 1, total: 1 */ /* flexible array members: end: 1 */ /* last cacheline: 40 bytes */ }; $ Interesting, but we don't see the "middle" case... Maybe 'struct cgroup'? $ pahole cgroup | tail struct cgroup * ancestors[]; /* 1984 0 */ /* size: 1984, cachelines: 31, members: 42 */ /* sum members: 1952, holes: 3, sum holes: 32 */ /* member types with holes: 3, total: 3 */ /* paddings: 1, sum paddings: 4 */ /* forced alignments: 1 */ /* flexible array members: end: 1 */ }; $ Humm, maybe some data structure embeds 'struct cgroup'? Lets see with: $ pahole --contains cgroup cgroup_root $ A-ha, finally that 'middle' stat: $ pahole cgroup_root struct cgroup_root { struct kernfs_root * kf_root; /* 0 8 */ unsigned int subsys_mask; /* 8 4 */ int hierarchy_id; /* 12 4 */ struct list_head root_list; /* 16 16 */ struct callback_head rcu; /* 32 16 */ /* XXX 16 bytes hole, try to pack */ /* --- cacheline 1 boundary (64 bytes) --- */ struct cgroup cgrp __attribute__((__aligned__(64))); /* 64 1984 */ /* XXX last struct has a flexible array, embedded flexible array(s), 3 holes */ /* --- cacheline 32 boundary (2048 bytes) --- */ struct cgroup * cgrp_ancestor_storage; /* 2048 8 */ atomic_t nr_cgrps; /* 2056 4 */ unsigned int flags; /* 2060 4 */ char release_agent_path[4096]; /* 2064 4096 */ /* --- cacheline 96 boundary (6144 bytes) was 16 bytes ago --- */ char name[64]; /* 6160 64 */ /* size: 6272, cachelines: 98, members: 11 */ /* sum members: 6208, holes: 1, sum holes: 16 */ /* padding: 48 */ /* member types with holes: 1, total: 3 */ /* forced alignments: 1, forced holes: 1, sum forced holes: 16 */ /* flexible array members: end: 1, middle: 1 */ } __attribute__((__aligned__(64))); $ Cc: "Gustavo A. R. Silva" <[email protected]> Cc: Willy Tarreau <[email protected]> Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
- Loading branch information