[bpf-next,v1,1/4] bpf: Support reporting BPF htab map's used size for monitoring

Message ID 20221105025146.238209-2-horenchuang@bytedance.com
State New
Headers
Series Add BPF htab map's used size for monitoring |

Commit Message

Ho-Ren (Jack) Chuang Nov. 5, 2022, 2:51 a.m. UTC
  Expose BPF htab map's used size by counting accessed or allocated/freed
elements to userspace.

Leverage the htab->count value for both preallocated and
dynamically allocated maps. Expose the value to a new field
"used_entries" in a userspace struct bpf_map_info  to allow monitoring.
Support hash table type (BPF_MAP_TYPE_HASH).

Signed-off-by: Ho-Ren (Jack) Chuang <horenchuang@bytedance.com>
---
 include/linux/bpf.h      |  1 +
 include/uapi/linux/bpf.h |  1 +
 kernel/bpf/hashtab.c     | 19 +++++++++++++++++++
 kernel/bpf/syscall.c     |  2 ++
 4 files changed, 23 insertions(+)
  

Comments

kernel test robot Nov. 5, 2022, 4:14 a.m. UTC | #1
Hi Ho-Ren,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Ho-Ren-Jack-Chuang/Add-BPF-htab-map-s-used-size-for-monitoring/20221105-105421
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20221105025146.238209-2-horenchuang%40bytedance.com
patch subject: [PATCH bpf-next v1 1/4] bpf: Support reporting BPF htab map's used size for monitoring
config: m68k-allyesconfig
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/3188e1adf82d93738d5e5496ee87bbd9411d8465
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Ho-Ren-Jack-Chuang/Add-BPF-htab-map-s-used-size-for-monitoring/20221105-105421
        git checkout 3188e1adf82d93738d5e5496ee87bbd9411d8465
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash kernel/bpf/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/bpf/hashtab.c:2181:5: warning: no previous prototype for 'htab_map_get_used_elem' [-Wmissing-prototypes]
    2181 | u32 htab_map_get_used_elem(struct bpf_map *map)
         |     ^~~~~~~~~~~~~~~~~~~~~~


vim +/htab_map_get_used_elem +2181 kernel/bpf/hashtab.c

  2180	
> 2181	u32 htab_map_get_used_elem(struct bpf_map *map)
  2182	{
  2183		struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
  2184	
  2185		/* The elem count may temporarily go beyond the max after
  2186		 * inc_elem_count() but before dec_elem_count().
  2187		 */
  2188		if (htab->use_percpu_counter)
  2189			return min_t(u32, htab->map.max_entries,
  2190					percpu_counter_sum(&htab->pcount) +
  2191								atomic_read(&htab->count));
  2192		else
  2193			return min_t(u32, htab->map.max_entries,
  2194								atomic_read(&htab->count));
  2195	}
  2196
  

Patch

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 9e7d46d16032..82ee14139b69 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -97,6 +97,7 @@  struct bpf_map_ops {
 	int (*map_pop_elem)(struct bpf_map *map, void *value);
 	int (*map_peek_elem)(struct bpf_map *map, void *value);
 	void *(*map_lookup_percpu_elem)(struct bpf_map *map, void *key, u32 cpu);
+	u32 (*map_get_used_elem)(struct bpf_map *map);
 
 	/* funcs called by prog_array and perf_event_array map */
 	void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 17f61338f8f8..63659368cf0e 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6215,6 +6215,7 @@  struct bpf_map_info {
 	__u32 id;
 	__u32 key_size;
 	__u32 value_size;
+	__u32 used_entries;
 	__u32 max_entries;
 	__u32 map_flags;
 	char  name[BPF_OBJ_NAME_LEN];
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index ed3f8a53603b..bc9c00b92e57 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -913,6 +913,7 @@  static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
 	if (htab_is_prealloc(htab)) {
 		check_and_free_fields(htab, l);
 		__pcpu_freelist_push(&htab->freelist, &l->fnode);
+		dec_elem_count(htab);
 	} else {
 		dec_elem_count(htab);
 		htab_elem_free(htab, l);
@@ -994,6 +995,7 @@  static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
 			if (!l)
 				return ERR_PTR(-E2BIG);
 			l_new = container_of(l, struct htab_elem, fnode);
+			inc_elem_count(htab);
 		}
 	} else {
 		if (is_map_full(htab))
@@ -2186,6 +2188,22 @@  static int bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_f
 	return num_elems;
 }
 
+u32 htab_map_get_used_elem(struct bpf_map *map)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+
+	/* The elem count may temporarily go beyond the max after
+	 * inc_elem_count() but before dec_elem_count().
+	 */
+	if (htab->use_percpu_counter)
+		return min_t(u32, htab->map.max_entries,
+				percpu_counter_sum(&htab->pcount) +
+							atomic_read(&htab->count));
+	else
+		return min_t(u32, htab->map.max_entries,
+							atomic_read(&htab->count));
+}
+
 BTF_ID_LIST_SINGLE(htab_map_btf_ids, struct, bpf_htab)
 const struct bpf_map_ops htab_map_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -2202,6 +2220,7 @@  const struct bpf_map_ops htab_map_ops = {
 	.map_seq_show_elem = htab_map_seq_show_elem,
 	.map_set_for_each_callback_args = map_set_for_each_callback_args,
 	.map_for_each_callback = bpf_for_each_hash_elem,
+	.map_get_used_elem = htab_map_get_used_elem,
 	BATCH_OPS(htab),
 	.map_btf_id = &htab_map_btf_ids[0],
 	.iter_seq_info = &iter_seq_info,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 7b373a5e861f..ea4828bb22ac 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -4203,6 +4203,8 @@  static int bpf_map_get_info_by_fd(struct file *file,
 	info.map_flags = map->map_flags;
 	info.map_extra = map->map_extra;
 	memcpy(info.name, map->name, sizeof(map->name));
+	if (map->ops->map_get_used_elem)
+		info.used_entries = map->ops->map_get_used_elem(map);
 
 	if (map->btf) {
 		info.btf_id = btf_obj_id(map->btf);