This patch replicates the kernel code for bpf ringbuf_map mm usage
calculation.
  $ bpftool map create /sys/fs/bpf/rb0 type ringbuf key 0 value 0 entries $((1<<24))
name rb0
Before:
  crash> bpf -m 12
   ID      BPF_MAP               BPF_MAP_TYPE           MAP_FLAGS
   12  ffff8dc4d7c0ed00             RINGBUF              00000000
       KEY_SIZE: 0  VALUE_SIZE: 0  MAX_ENTRIES: 16777216  MEMLOCK: (unknown)
       NAME: "rb0"  UID: (unused)
After:
  crash> bpf -m 12
   ID      BPF_MAP               BPF_MAP_TYPE           MAP_FLAGS
   12  ffff8dc4d7c0ed00             RINGBUF              00000000
       KEY_SIZE: 0  VALUE_SIZE: 0  MAX_ENTRIES: 16777216  MEMLOCK: 16855320
       NAME: "rb0"  UID: (unused)
Thus, the output will be the same as bpftool:
  $ bpftool map show id 12
  12: ringbuf  name rb0  flags 0x0
	key 0B  value 0B  max_entries 16777216  memlock 16855320B
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
 bpf.c     | 30 +++++++++++++++++++++++++++++-
 defs.h    |  5 +++++
 symbols.c |  5 +++++
 3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/bpf.c b/bpf.c
index 466b244..43e4ff5 100644
--- a/bpf.c
+++ b/bpf.c
@@ -121,6 +121,26 @@ static ulong bpf_map_memory_size(int map_type, uint value_size,
 	return roundup((max_entries * size), PAGESIZE());
 }
 
+/*
+ * Code replicated from kernel/bpf/ringbuf.c:ringbuf_map_mem_usage()
+*/
+static ulong ringbuf_map_mem_usage(struct bpf_info *bpf, int i)
+{
+	ulong nr_pages;
+	ulong usage = SIZE(bpf_ringbuf_map);
+	ulong rb = (ulong)(bpf->maplist[i].value) - OFFSET(bpf_ringbuf_map_map)
+			+ OFFSET(bpf_ringbuf_map_rb);
+	readmem(rb, KVADDR, &rb, sizeof(ulong), "bpf_ringbuf *",
RETURN_ON_ERROR);
+	readmem(rb + OFFSET(bpf_ringbuf_nr_pages), KVADDR, &nr_pages,
+		sizeof(ulong), "bpf_ringbuf.nr_pages", RETURN_ON_ERROR);
+	usage += (nr_pages << PAGESHIFT());
+	ulong nr_meta_pages = (OFFSET(bpf_ringbuf_consumer_pos) >> PAGESHIFT()) + 2;
+	ulong nr_data_pages = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_max_entries)) >>
PAGESHIFT();
+	usage += (nr_meta_pages + 2 * nr_data_pages) * sizeof(void *);
+
+	return usage;
+}
+
 void
 cmd_bpf(void)
 {
@@ -217,6 +237,7 @@ bpf_init(struct bpf_info *bpf)
 		STRUCT_SIZE_INIT(bpf_prog_aux, "bpf_prog_aux");
 		STRUCT_SIZE_INIT(bpf_map, "bpf_map");
 		STRUCT_SIZE_INIT(bpf_insn, "bpf_insn");
+		STRUCT_SIZE_INIT(bpf_ringbuf_map, "bpf_ringbuf_map");
 		MEMBER_OFFSET_INIT(bpf_prog_aux, "bpf_prog", "aux");
 		MEMBER_OFFSET_INIT(bpf_prog_type, "bpf_prog", "type");
 		MEMBER_OFFSET_INIT(bpf_prog_tag, "bpf_prog", "tag");
@@ -228,6 +249,10 @@ bpf_init(struct bpf_info *bpf)
 		MEMBER_OFFSET_INIT(bpf_map_map_flags, "bpf_map", "map_flags");
 		MEMBER_OFFSET_INIT(bpf_prog_aux_used_maps, "bpf_prog_aux",
"used_maps");
 		MEMBER_OFFSET_INIT(bpf_prog_aux_used_map_cnt, "bpf_prog_aux",
"used_map_cnt");
+		MEMBER_OFFSET_INIT(bpf_ringbuf_map_map, "bpf_ringbuf_map", "map");
+		MEMBER_OFFSET_INIT(bpf_ringbuf_map_rb, "bpf_ringbuf_map", "rb");
+		MEMBER_OFFSET_INIT(bpf_ringbuf_consumer_pos, "bpf_ringbuf",
"consumer_pos");
+		MEMBER_OFFSET_INIT(bpf_ringbuf_nr_pages, "bpf_ringbuf",
"nr_pages");
 		if (!VALID_STRUCT(bpf_prog) || 
 		    !VALID_STRUCT(bpf_prog_aux) ||
 		    !VALID_STRUCT(bpf_map) ||
@@ -664,7 +689,10 @@ do_map_only:
 				fprintf(fp, "%d\n", map_pages * PAGESIZE());
 			} else if ((msize = bpf_map_memory_size(type, value_size, key_size, max_entries)))
 				fprintf(fp, "%ld\n", msize);
-			else
+#define BPF_MAP_TYPE_RINGBUF (0x1BUL)
+			else if (type == BPF_MAP_TYPE_RINGBUF) {
+				fprintf(fp, "%ld\n", ringbuf_map_mem_usage(bpf, i));
+			} else
 				fprintf(fp, "(unknown)");
 
 			fprintf(fp, "     NAME: ");
diff --git a/defs.h b/defs.h
index 4fecb83..498c262 100644
--- a/defs.h
+++ b/defs.h
@@ -2274,6 +2274,10 @@ struct offset_table {                    /* stash of commonly-used
offsets */
 	long request_queue_tag_set;
 	long blk_mq_tag_set_flags;
 	long blk_mq_tag_set_shared_tags;
+	long bpf_ringbuf_map_map;
+	long bpf_ringbuf_map_rb;
+	long bpf_ringbuf_consumer_pos;
+	long bpf_ringbuf_nr_pages;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
@@ -2452,6 +2456,7 @@ struct size_table {         /* stash of commonly-used sizes */
 	long vmap_node;
 	long cpumask_t;
 	long task_struct_exit_state;
+	long bpf_ringbuf_map;
 };
 
 struct array_table {
diff --git a/symbols.c b/symbols.c
index ce0b441..19e1316 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11868,6 +11868,10 @@ dump_offset_table(char *spec, ulong makestruct)
 	fprintf(fp, "          thread_struct_gsbase: %ld\n",
OFFSET(thread_struct_gsbase));
 	fprintf(fp, "              thread_struct_fs: %ld\n",
OFFSET(thread_struct_fs));
 	fprintf(fp, "              thread_struct_gs: %ld\n",
OFFSET(thread_struct_gs));
+	fprintf(fp, "           bpf_ringbuf_map_map: %ld\n",
OFFSET(bpf_ringbuf_map_map));
+	fprintf(fp, "            bpf_ringbuf_map_rb: %ld\n",
OFFSET(bpf_ringbuf_map_rb));
+	fprintf(fp, "      bpf_ringbuf_consumer_pos: %ld\n",
OFFSET(bpf_ringbuf_consumer_pos));
+	fprintf(fp, "          bpf_ringbuf_nr_pages: %ld\n",
OFFSET(bpf_ringbuf_nr_pages));
 
 	fprintf(fp, "\n                    size_table:\n");
 	fprintf(fp, "                          page: %ld\n", SIZE(page));
@@ -12148,6 +12152,7 @@ dump_offset_table(char *spec, ulong makestruct)
 
 	fprintf(fp, "                percpu_counter: %ld\n", SIZE(percpu_counter));
 	fprintf(fp, "                     cpumask_t: %ld\n", SIZE(cpumask_t));
+	fprintf(fp, "               bpf_ringbuf_map: %ld\n", SIZE(bpf_ringbuf_map));
 
         fprintf(fp, "\n                   array_table:\n");
 	/*
-- 
2.47.0