diff options
author | David S. Miller <davem@davemloft.net> | 2018-08-02 10:55:32 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-02 10:55:32 -0700 |
commit | 89b1698c93a9dee043154f33d96bca9964e705f1 (patch) | |
tree | dd9dcb1965baae8edcf0b496aaa6a70609b6fc11 /tools/lib | |
parent | ffd7ce3cd9c294f1ff49ec02cdbd1bc7cb913db6 (diff) | |
parent | e30cb13c5a09ff5f043a6570c32e49b063bea6a1 (diff) | |
download | lwn-89b1698c93a9dee043154f33d96bca9964e705f1.tar.gz lwn-89b1698c93a9dee043154f33d96bca9964e705f1.zip |
Merge ra.kernel.org:/pub/scm/linux/kernel/git/davem/net
The BTF conflicts were simple overlapping changes.
The virtio_net conflict was an overlap of a fix of statistics counter,
happening alongisde a move over to a bonafide statistics structure
rather than counting value on the stack.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/bpf/btf.c | 46 | ||||
-rw-r--r-- | tools/lib/bpf/btf.h | 10 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 87 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 4 |
4 files changed, 84 insertions, 63 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 03161be094b4..1622a309f169 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -2,7 +2,6 @@ /* Copyright (c) 2018 Facebook */ #include <stdlib.h> -#include <stdint.h> #include <string.h> #include <unistd.h> #include <errno.h> @@ -32,17 +31,25 @@ struct btf { struct btf_type **types; const char *strings; void *nohdr_data; - uint32_t nr_types; - uint32_t types_size; - uint32_t data_size; + __u32 nr_types; + __u32 types_size; + __u32 data_size; int fd; }; +static const char *btf_name_by_offset(const struct btf *btf, __u32 offset) +{ + if (offset < btf->hdr->str_len) + return &btf->strings[offset]; + else + return NULL; +} + static int btf_add_type(struct btf *btf, struct btf_type *t) { if (btf->types_size - btf->nr_types < 2) { struct btf_type **new_types; - u32 expand_by, new_size; + __u32 expand_by, new_size; if (btf->types_size == BTF_MAX_NR_TYPES) return -E2BIG; @@ -69,7 +76,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t) static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log) { const struct btf_header *hdr = btf->hdr; - u32 meta_left; + __u32 meta_left; if (btf->data_size < sizeof(struct btf_header)) { elog("BTF header not found\n"); @@ -148,7 +155,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) while (next_type < end_type) { struct btf_type *t = next_type; - uint16_t vlen = BTF_INFO_VLEN(t->info); + __u16 vlen = BTF_INFO_VLEN(t->info); int err; next_type += sizeof(*t); @@ -187,6 +194,14 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) return 0; } +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id) +{ + if (type_id > btf->nr_types) + return NULL; + + return btf->types[type_id]; +} + static bool btf_type_is_void(const struct btf_type *t) { return t == &btf_void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD; @@ -197,7 +212,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t) return !t || btf_type_is_void(t); } -static int64_t btf_type_size(const struct btf_type *t) +static __s64 btf_type_size(const struct btf_type *t) { switch (BTF_INFO_KIND(t->info)) { case BTF_KIND_INT: @@ -214,12 +229,12 @@ static int64_t btf_type_size(const struct btf_type *t) #define MAX_RESOLVE_DEPTH 32 -int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) +__s64 btf__resolve_size(const struct btf *btf, __u32 type_id) { const struct btf_array *array; const struct btf_type *t; - uint32_t nelems = 1; - int64_t size = -1; + __u32 nelems = 1; + __s64 size = -1; int i; t = btf__type_by_id(btf, type_id); @@ -279,9 +294,9 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id) return type_id; } -int32_t btf__find_by_name(const struct btf *btf, const char *type_name) +__s32 btf__find_by_name(const struct btf *btf, const char *type_name) { - uint32_t i; + __u32 i; if (!strcmp(type_name, "void")) return 0; @@ -310,10 +325,9 @@ void btf__free(struct btf *btf) free(btf); } -struct btf *btf__new(uint8_t *data, uint32_t size, - btf_print_fn_t err_log) +struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log) { - uint32_t log_buf_size = 0; + __u32 log_buf_size = 0; char *log_buf = NULL; struct btf *btf; int err; diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 24f361d99a5e..dd8a86eab8ca 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -4,19 +4,21 @@ #ifndef __BPF_BTF_H #define __BPF_BTF_H -#include <stdint.h> +#include <linux/types.h> #define BTF_ELF_SEC ".BTF" struct btf; +struct btf_type; typedef int (*btf_print_fn_t)(const char *, ...) __attribute__((format(printf, 1, 2))); void btf__free(struct btf *btf); -struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log); -int32_t btf__find_by_name(const struct btf *btf, const char *type_name); -int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id); +struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log); +__s32 btf__find_by_name(const struct btf *btf, const char *type_name); +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id); +__s64 btf__resolve_size(const struct btf *btf, __u32 type_id); int btf__resolve_type(const struct btf *btf, __u32 type_id); int btf__fd(const struct btf *btf); const char *btf__name_by_offset(const struct btf *btf, __u32 offset); diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 955f8eafbf41..26e9527ee464 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -37,6 +37,7 @@ #include <linux/err.h> #include <linux/kernel.h> #include <linux/bpf.h> +#include <linux/btf.h> #include <linux/list.h> #include <linux/limits.h> #include <sys/stat.h> @@ -170,8 +171,8 @@ struct bpf_map { size_t offset; int map_ifindex; struct bpf_map_def def; - uint32_t btf_key_type_id; - uint32_t btf_value_type_id; + __u32 btf_key_type_id; + __u32 btf_value_type_id; void *priv; bpf_map_clear_priv_t clear_priv; }; @@ -969,68 +970,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) { + const struct btf_type *container_type; + const struct btf_member *key, *value; struct bpf_map_def *def = &map->def; const size_t max_name = 256; - int64_t key_size, value_size; - int32_t key_id, value_id; - char name[max_name]; + char container_name[max_name]; + __s64 key_size, value_size; + __s32 container_id; - /* Find key type by name from BTF */ - if (snprintf(name, max_name, "%s_key", map->name) == max_name) { - pr_warning("map:%s length of BTF key_type:%s_key is too long\n", + if (snprintf(container_name, max_name, "____btf_map_%s", map->name) == + max_name) { + pr_warning("map:%s length of '____btf_map_%s' is too long\n", map->name, map->name); return -EINVAL; } - key_id = btf__find_by_name(btf, name); - if (key_id < 0) { - pr_debug("map:%s key_type:%s cannot be found in BTF\n", - map->name, name); - return key_id; + container_id = btf__find_by_name(btf, container_name); + if (container_id < 0) { + pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n", + map->name, container_name); + return container_id; } - key_size = btf__resolve_size(btf, key_id); - if (key_size < 0) { - pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", - map->name, name); - return key_size; + container_type = btf__type_by_id(btf, container_id); + if (!container_type) { + pr_warning("map:%s cannot find BTF type for container_id:%u\n", + map->name, container_id); + return -EINVAL; } - if (def->key_size != key_size) { - pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", - map->name, name, (unsigned int)key_size, def->key_size); + if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT || + BTF_INFO_VLEN(container_type->info) < 2) { + pr_warning("map:%s container_name:%s is an invalid container struct\n", + map->name, container_name); return -EINVAL; } - /* Find value type from BTF */ - if (snprintf(name, max_name, "%s_value", map->name) == max_name) { - pr_warning("map:%s length of BTF value_type:%s_value is too long\n", - map->name, map->name); - return -EINVAL; + key = (struct btf_member *)(container_type + 1); + value = key + 1; + + key_size = btf__resolve_size(btf, key->type); + if (key_size < 0) { + pr_warning("map:%s invalid BTF key_type_size\n", + map->name); + return key_size; } - value_id = btf__find_by_name(btf, name); - if (value_id < 0) { - pr_debug("map:%s value_type:%s cannot be found in BTF\n", - map->name, name); - return value_id; + if (def->key_size != key_size) { + pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n", + map->name, (__u32)key_size, def->key_size); + return -EINVAL; } - value_size = btf__resolve_size(btf, value_id); + value_size = btf__resolve_size(btf, value->type); if (value_size < 0) { - pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", - map->name, name); + pr_warning("map:%s invalid BTF value_type_size\n", map->name); return value_size; } if (def->value_size != value_size) { - pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", - map->name, name, (unsigned int)value_size, def->value_size); + pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n", + map->name, (__u32)value_size, def->value_size); return -EINVAL; } - map->btf_key_type_id = key_id; - map->btf_value_type_id = value_id; + map->btf_key_type_id = key->type; + map->btf_value_type_id = value->type; return 0; } @@ -2141,12 +2146,12 @@ const char *bpf_map__name(struct bpf_map *map) return map ? map->name : NULL; } -uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map) +__u32 bpf_map__btf_key_type_id(const struct bpf_map *map) { return map ? map->btf_key_type_id : 0; } -uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map) +__u32 bpf_map__btf_value_type_id(const struct bpf_map *map) { return map ? map->btf_value_type_id : 0; } @@ -2333,8 +2338,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size, volatile struct perf_event_mmap_page *header = mem; __u64 data_tail = header->data_tail; __u64 data_head = header->data_head; + int ret = LIBBPF_PERF_EVENT_ERROR; void *base, *begin, *end; - int ret; asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */ if (data_head == data_tail) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 1f8fc2060460..413778a93499 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -254,8 +254,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj); int bpf_map__fd(struct bpf_map *map); const struct bpf_map_def *bpf_map__def(struct bpf_map *map); const char *bpf_map__name(struct bpf_map *map); -uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map); -uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map); +__u32 bpf_map__btf_key_type_id(const struct bpf_map *map); +__u32 bpf_map__btf_value_type_id(const struct bpf_map *map); typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); int bpf_map__set_priv(struct bpf_map *map, void *priv, |