Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools lib bpf: Collect map definition in bpf_object

This patch collects more information from maps sections in BPF object
files into 'struct bpf_object', enables later patches access those
information (such as the type and size of the map).

In this patch, a new handler 'struct bpf_map' is extracted in parallel
with bpf_object and bpf_program. Its iterator and accessor is also
created.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1448614067-197576-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Wang Nan and committed by
Arnaldo Carvalho de Melo
9d759a9b 03905048

+148 -60
+127 -60
tools/lib/bpf/libbpf.c
··· 163 163 bpf_program_clear_priv_t clear_priv; 164 164 }; 165 165 166 + struct bpf_map { 167 + int fd; 168 + struct bpf_map_def def; 169 + void *priv; 170 + bpf_map_clear_priv_t clear_priv; 171 + }; 172 + 166 173 static LIST_HEAD(bpf_objects_list); 167 174 168 175 struct bpf_object { 169 176 char license[64]; 170 177 u32 kern_version; 171 - void *maps_buf; 172 - size_t maps_buf_sz; 173 178 174 179 struct bpf_program *programs; 175 180 size_t nr_programs; 176 - int *map_fds; 177 - /* 178 - * This field is required because maps_buf will be freed and 179 - * maps_buf_sz will be set to 0 after loaded. 180 - */ 181 - size_t nr_map_fds; 181 + struct bpf_map *maps; 182 + size_t nr_maps; 183 + 182 184 bool loaded; 183 185 184 186 /* ··· 491 489 bpf_object__init_maps(struct bpf_object *obj, void *data, 492 490 size_t size) 493 491 { 494 - if (size == 0) { 492 + size_t nr_maps; 493 + int i; 494 + 495 + nr_maps = size / sizeof(struct bpf_map_def); 496 + if (!data || !nr_maps) { 495 497 pr_debug("%s doesn't need map definition\n", 496 498 obj->path); 497 499 return 0; 498 500 } 499 501 500 - obj->maps_buf = malloc(size); 501 - if (!obj->maps_buf) { 502 - pr_warning("malloc maps failed: %s\n", obj->path); 502 + pr_debug("maps in %s: %zd bytes\n", obj->path, size); 503 + 504 + obj->maps = calloc(nr_maps, sizeof(obj->maps[0])); 505 + if (!obj->maps) { 506 + pr_warning("alloc maps for object failed\n"); 503 507 return -ENOMEM; 504 508 } 509 + obj->nr_maps = nr_maps; 505 510 506 - obj->maps_buf_sz = size; 507 - memcpy(obj->maps_buf, data, size); 508 - pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size); 511 + for (i = 0; i < nr_maps; i++) { 512 + struct bpf_map_def *def = &obj->maps[i].def; 513 + 514 + /* 515 + * fill all fd with -1 so won't close incorrect 516 + * fd (fd=0 is stdin) when failure (zclose won't close 517 + * negative fd)). 518 + */ 519 + obj->maps[i].fd = -1; 520 + 521 + /* Save map definition into obj->maps */ 522 + *def = ((struct bpf_map_def *)data)[i]; 523 + } 509 524 return 0; 510 525 } 511 526 ··· 707 688 bpf_object__create_maps(struct bpf_object *obj) 708 689 { 709 690 unsigned int i; 710 - size_t nr_maps; 711 - int *pfd; 712 691 713 - nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def); 714 - if (!obj->maps_buf || !nr_maps) { 715 - pr_debug("don't need create maps for %s\n", 716 - obj->path); 717 - return 0; 718 - } 692 + for (i = 0; i < obj->nr_maps; i++) { 693 + struct bpf_map_def *def = &obj->maps[i].def; 694 + int *pfd = &obj->maps[i].fd; 719 695 720 - obj->map_fds = malloc(sizeof(int) * nr_maps); 721 - if (!obj->map_fds) { 722 - pr_warning("realloc perf_bpf_map_fds failed\n"); 723 - return -ENOMEM; 724 - } 725 - obj->nr_map_fds = nr_maps; 726 - 727 - /* fill all fd with -1 */ 728 - memset(obj->map_fds, -1, sizeof(int) * nr_maps); 729 - 730 - pfd = obj->map_fds; 731 - for (i = 0; i < nr_maps; i++) { 732 - struct bpf_map_def def; 733 - 734 - def = *(struct bpf_map_def *)(obj->maps_buf + 735 - i * sizeof(struct bpf_map_def)); 736 - 737 - *pfd = bpf_create_map(def.type, 738 - def.key_size, 739 - def.value_size, 740 - def.max_entries); 696 + *pfd = bpf_create_map(def->type, 697 + def->key_size, 698 + def->value_size, 699 + def->max_entries); 741 700 if (*pfd < 0) { 742 701 size_t j; 743 702 int err = *pfd; ··· 723 726 pr_warning("failed to create map: %s\n", 724 727 strerror(errno)); 725 728 for (j = 0; j < i; j++) 726 - zclose(obj->map_fds[j]); 727 - obj->nr_map_fds = 0; 728 - zfree(&obj->map_fds); 729 + zclose(obj->maps[j].fd); 729 730 return err; 730 731 } 731 732 pr_debug("create map: fd=%d\n", *pfd); 732 - pfd++; 733 733 } 734 734 735 - zfree(&obj->maps_buf); 736 - obj->maps_buf_sz = 0; 737 735 return 0; 738 736 } 739 737 740 738 static int 741 - bpf_program__relocate(struct bpf_program *prog, int *map_fds) 739 + bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) 742 740 { 743 741 int i; 744 742 ··· 753 761 return -LIBBPF_ERRNO__RELOC; 754 762 } 755 763 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 756 - insns[insn_idx].imm = map_fds[map_idx]; 764 + insns[insn_idx].imm = obj->maps[map_idx].fd; 757 765 } 758 766 759 767 zfree(&prog->reloc_desc); ··· 772 780 for (i = 0; i < obj->nr_programs; i++) { 773 781 prog = &obj->programs[i]; 774 782 775 - err = bpf_program__relocate(prog, obj->map_fds); 783 + err = bpf_program__relocate(prog, obj); 776 784 if (err) { 777 785 pr_warning("failed to relocate '%s'\n", 778 786 prog->section_name); ··· 796 804 Elf_Data *data = obj->efile.reloc[i].data; 797 805 int idx = shdr->sh_info; 798 806 struct bpf_program *prog; 799 - size_t nr_maps = obj->maps_buf_sz / 800 - sizeof(struct bpf_map_def); 807 + size_t nr_maps = obj->nr_maps; 801 808 802 809 if (shdr->sh_type != SHT_REL) { 803 810 pr_warning("internal error at %d\n", __LINE__); ··· 1041 1050 if (!obj) 1042 1051 return -EINVAL; 1043 1052 1044 - for (i = 0; i < obj->nr_map_fds; i++) 1045 - zclose(obj->map_fds[i]); 1046 - zfree(&obj->map_fds); 1047 - obj->nr_map_fds = 0; 1053 + for (i = 0; i < obj->nr_maps; i++) 1054 + zclose(obj->maps[i].fd); 1048 1055 1049 1056 for (i = 0; i < obj->nr_programs; i++) 1050 1057 bpf_program__unload(&obj->programs[i]); ··· 1085 1096 bpf_object__elf_finish(obj); 1086 1097 bpf_object__unload(obj); 1087 1098 1088 - zfree(&obj->maps_buf); 1099 + for (i = 0; i < obj->nr_maps; i++) { 1100 + if (obj->maps[i].clear_priv) 1101 + obj->maps[i].clear_priv(&obj->maps[i], 1102 + obj->maps[i].priv); 1103 + obj->maps[i].priv = NULL; 1104 + obj->maps[i].clear_priv = NULL; 1105 + } 1106 + zfree(&obj->maps); 1107 + obj->nr_maps = 0; 1089 1108 1090 1109 if (obj->programs && obj->nr_programs) { 1091 1110 for (i = 0; i < obj->nr_programs; i++) ··· 1247 1250 } 1248 1251 1249 1252 return fd; 1253 + } 1254 + 1255 + int bpf_map__get_fd(struct bpf_map *map) 1256 + { 1257 + if (!map) 1258 + return -EINVAL; 1259 + 1260 + return map->fd; 1261 + } 1262 + 1263 + int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef) 1264 + { 1265 + if (!map || !pdef) 1266 + return -EINVAL; 1267 + 1268 + *pdef = map->def; 1269 + return 0; 1270 + } 1271 + 1272 + int bpf_map__set_private(struct bpf_map *map, void *priv, 1273 + bpf_map_clear_priv_t clear_priv) 1274 + { 1275 + if (!map) 1276 + return -EINVAL; 1277 + 1278 + if (map->priv) { 1279 + if (map->clear_priv) 1280 + map->clear_priv(map, map->priv); 1281 + } 1282 + 1283 + map->priv = priv; 1284 + map->clear_priv = clear_priv; 1285 + return 0; 1286 + } 1287 + 1288 + int bpf_map__get_private(struct bpf_map *map, void **ppriv) 1289 + { 1290 + if (!map) 1291 + return -EINVAL; 1292 + 1293 + if (ppriv) 1294 + *ppriv = map->priv; 1295 + return 0; 1296 + } 1297 + 1298 + struct bpf_map * 1299 + bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) 1300 + { 1301 + size_t idx; 1302 + struct bpf_map *s, *e; 1303 + 1304 + if (!obj || !obj->maps) 1305 + return NULL; 1306 + 1307 + s = obj->maps; 1308 + e = obj->maps + obj->nr_maps; 1309 + 1310 + if (prev == NULL) 1311 + return s; 1312 + 1313 + if ((prev < s) || (prev >= e)) { 1314 + pr_warning("error in %s: map handler doesn't belong to object\n", 1315 + __func__); 1316 + return NULL; 1317 + } 1318 + 1319 + idx = (prev - obj->maps) + 1; 1320 + if (idx >= obj->nr_maps) 1321 + return NULL; 1322 + return &obj->maps[idx]; 1250 1323 }
+21
tools/lib/bpf/libbpf.h
··· 165 165 unsigned int max_entries; 166 166 }; 167 167 168 + /* 169 + * There is another 'struct bpf_map' in include/linux/map.h. However, 170 + * it is not a uapi header so no need to consider name clash. 171 + */ 172 + struct bpf_map; 173 + 174 + struct bpf_map * 175 + bpf_map__next(struct bpf_map *map, struct bpf_object *obj); 176 + #define bpf_map__for_each(pos, obj) \ 177 + for ((pos) = bpf_map__next(NULL, (obj)); \ 178 + (pos) != NULL; \ 179 + (pos) = bpf_map__next((pos), (obj))) 180 + 181 + int bpf_map__get_fd(struct bpf_map *map); 182 + int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef); 183 + 184 + typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 185 + int bpf_map__set_private(struct bpf_map *map, void *priv, 186 + bpf_map_clear_priv_t clear_priv); 187 + int bpf_map__get_private(struct bpf_map *map, void **ppriv); 188 + 168 189 #endif