[PATCH 2/3] fprintf: Show statistics about members with flexible arrays

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

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" <gustavoars@xxxxxxxxxx>
Cc: Willy Tarreau <w@xxxxxx>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
 dwarves_fprintf.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 0d642a318fd836ef..e16a6b4da65ed2cd 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1502,6 +1502,8 @@ struct member_types_holes {
 	uint16_t nr_with_bit_holes;
 	uint16_t total_nr_holes;
 	uint16_t total_nr_bit_holes;
+	uint16_t nr_flexible_array_members;
+	uint16_t nr_embedded_flexible_array_members;
 	uint32_t sum_paddings;
 	uint32_t sum_bit_paddings;
 };
@@ -1540,11 +1542,13 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
 
 	if (has_flexible_array) {
 		printed += fprintf(fp, " a flexible array");
+		++holes->nr_flexible_array_members;
 		first = false;
 	}
 
 	if (has_embedded_flexible_array) {
 		printed += fprintf(fp, "%s embedded flexible array(s)", first ? "" : ",");
+		++holes->nr_embedded_flexible_array_members;
 		first = false;
 	}
 
@@ -1985,6 +1989,22 @@ next_member:
 		}
 		printed += fprintf(fp, " */\n");
 	}
+	if (member_types_holes.nr_flexible_array_members > 0 ||
+	    member_types_holes.nr_embedded_flexible_array_members > 0) {
+		printed += fprintf(fp, "%.*s/* flexible array members: ",
+				   cconf.indent, tabs);
+
+		if (member_types_holes.nr_flexible_array_members > 0)
+			printed += fprintf(fp, "end: %u", member_types_holes.nr_flexible_array_members);
+
+		if (member_types_holes.nr_embedded_flexible_array_members > 0) {
+			printed += fprintf(fp, "%smiddle: %u",
+					   member_types_holes.nr_flexible_array_members ? ", " : "",
+					   member_types_holes.nr_embedded_flexible_array_members);
+		}
+
+		printed += fprintf(fp, " */\n");
+	}
 	cacheline = (cconf.base_offset + type->size) % conf_fprintf__cacheline_size(conf);
 	if (cacheline != 0)
 		printed += fprintf(fp, "%.*s/* last cacheline: %u bytes */\n",
-- 
2.46.0





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux