Introduces a new command to the main bpf syscall to return the number of entries in a map. Returns EOPNOTSUPP if the relevant map operation is not implemented. Co-developed-by: Nick Zavaritsky <mejedi@xxxxxxxxx> Signed-off-by: Nick Zavaritsky <mejedi@xxxxxxxxx> Signed-off-by: Charalampos Stylianopoulos <charalampos.stylianopoulos@xxxxxxxxx> --- include/uapi/linux/bpf.h | 17 +++++++++++++++++ kernel/bpf/syscall.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2acf9b336371..f5c7adea1387 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -903,6 +903,17 @@ union bpf_iter_link_info { * A new file descriptor (a nonnegative integer), or -1 if an * error occurred (in which case, *errno* is set appropriately). * + * BPF_MAP_GET_NUM_ENTRIES + * Description + * Get the number of entries currently present in the map. + * + * This operation is supported only for a subset of maps. If the + * map is not supported, the operation returns **EOPNOTSUPP**. + * + * Return + * Returns zero on success. On error, -1 is returned and *errno* + * is set appropriately. + * * NOTES * eBPF objects (maps and programs) can be shared between processes. * @@ -958,6 +969,7 @@ enum bpf_cmd { BPF_LINK_DETACH, BPF_PROG_BIND_MAP, BPF_TOKEN_CREATE, + BPF_MAP_GET_NUM_ENTRIES, __MAX_BPF_CMD, }; @@ -1837,6 +1849,11 @@ union bpf_attr { __u32 bpffs_fd; } token_create; + struct { /* struct used by BPF_MAP_GET_NUM_ENTRIES command*/ + __u32 map_fd; + __u32 num_entries; + } map_get_num_entries; + } __attribute__((aligned(8))); /* The description below is an attempt at providing documentation to eBPF diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 4e88797fdbeb..a31a63a4aa5d 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -5748,6 +5748,35 @@ static int token_create(union bpf_attr *attr) return bpf_token_create(attr); } +#define BPF_MAP_GET_NUM_ENTRIES_LAST_FIELD map_get_num_entries.num_entries + +static int bpf_get_num_entries(union bpf_attr *attr, union bpf_attr __user *uattr) +{ + __u32 num_entries = 0; + struct bpf_map *map; + + if (CHECK_ATTR(BPF_MAP_GET_NUM_ENTRIES)) + return -EINVAL; + + + CLASS(fd, f)(attr->map_fd); + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); + + if (!map->ops->map_num_entries) + return -EOPNOTSUPP; + + num_entries = map->ops->map_num_entries(map); + if (num_entries < 0) + return num_entries; + + if (put_user(num_entries, &uattr->map_get_num_entries.num_entries)) + return -EFAULT; + + return 0; +} + static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size) { union bpf_attr attr; @@ -5884,6 +5913,9 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size) case BPF_TOKEN_CREATE: err = token_create(&attr); break; + case BPF_MAP_GET_NUM_ENTRIES: + err = bpf_get_num_entries(&attr, uattr.user); + break; default: err = -EINVAL; break; -- 2.43.0