summaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-11-27 03:47:35 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-11-27 19:57:09 -0500
commit9d759a9b4ac2690077d8b21258e6e95c3e34bfa9 (patch)
tree184e9f95a010e1a883e83962189b742173ffd30a /tools/lib
parent039050482573e168690d365b8ea1d4f599ebbbd8 (diff)
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>
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/libbpf.c187
-rw-r--r--tools/lib/bpf/libbpf.h21
2 files changed, 148 insertions, 60 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e3f4c3379f14..f50982579aa8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -163,22 +163,24 @@ struct bpf_program {
163 bpf_program_clear_priv_t clear_priv; 163 bpf_program_clear_priv_t clear_priv;
164}; 164};
165 165
166struct bpf_map {
167 int fd;
168 struct bpf_map_def def;
169 void *priv;
170 bpf_map_clear_priv_t clear_priv;
171};
172
166static LIST_HEAD(bpf_objects_list); 173static LIST_HEAD(bpf_objects_list);
167 174
168struct bpf_object { 175struct bpf_object {
169 char license[64]; 176 char license[64];
170 u32 kern_version; 177 u32 kern_version;
171 void *maps_buf;
172 size_t maps_buf_sz;
173 178
174 struct bpf_program *programs; 179 struct bpf_program *programs;
175 size_t nr_programs; 180 size_t nr_programs;
176 int *map_fds; 181 struct bpf_map *maps;
177 /* 182 size_t nr_maps;
178 * This field is required because maps_buf will be freed and 183
179 * maps_buf_sz will be set to 0 after loaded.
180 */
181 size_t nr_map_fds;
182 bool loaded; 184 bool loaded;
183 185
184 /* 186 /*
@@ -489,21 +491,38 @@ static int
489bpf_object__init_maps(struct bpf_object *obj, void *data, 491bpf_object__init_maps(struct bpf_object *obj, void *data,
490 size_t size) 492 size_t size)
491{ 493{
492 if (size == 0) { 494 size_t nr_maps;
495 int i;
496
497 nr_maps = size / sizeof(struct bpf_map_def);
498 if (!data || !nr_maps) {
493 pr_debug("%s doesn't need map definition\n", 499 pr_debug("%s doesn't need map definition\n",
494 obj->path); 500 obj->path);
495 return 0; 501 return 0;
496 } 502 }
497 503
498 obj->maps_buf = malloc(size); 504 pr_debug("maps in %s: %zd bytes\n", obj->path, size);
499 if (!obj->maps_buf) { 505
500 pr_warning("malloc maps failed: %s\n", obj->path); 506 obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
507 if (!obj->maps) {
508 pr_warning("alloc maps for object failed\n");
501 return -ENOMEM; 509 return -ENOMEM;
502 } 510 }
511 obj->nr_maps = nr_maps;
512
513 for (i = 0; i < nr_maps; i++) {
514 struct bpf_map_def *def = &obj->maps[i].def;
503 515
504 obj->maps_buf_sz = size; 516 /*
505 memcpy(obj->maps_buf, data, size); 517 * fill all fd with -1 so won't close incorrect
506 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size); 518 * fd (fd=0 is stdin) when failure (zclose won't close
519 * negative fd)).
520 */
521 obj->maps[i].fd = -1;
522
523 /* Save map definition into obj->maps */
524 *def = ((struct bpf_map_def *)data)[i];
525 }
507 return 0; 526 return 0;
508} 527}
509 528
@@ -688,37 +707,15 @@ static int
688bpf_object__create_maps(struct bpf_object *obj) 707bpf_object__create_maps(struct bpf_object *obj)
689{ 708{
690 unsigned int i; 709 unsigned int i;
691 size_t nr_maps;
692 int *pfd;
693
694 nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def);
695 if (!obj->maps_buf || !nr_maps) {
696 pr_debug("don't need create maps for %s\n",
697 obj->path);
698 return 0;
699 }
700 710
701 obj->map_fds = malloc(sizeof(int) * nr_maps); 711 for (i = 0; i < obj->nr_maps; i++) {
702 if (!obj->map_fds) { 712 struct bpf_map_def *def = &obj->maps[i].def;
703 pr_warning("realloc perf_bpf_map_fds failed\n"); 713 int *pfd = &obj->maps[i].fd;
704 return -ENOMEM;
705 }
706 obj->nr_map_fds = nr_maps;
707
708 /* fill all fd with -1 */
709 memset(obj->map_fds, -1, sizeof(int) * nr_maps);
710 714
711 pfd = obj->map_fds; 715 *pfd = bpf_create_map(def->type,
712 for (i = 0; i < nr_maps; i++) { 716 def->key_size,
713 struct bpf_map_def def; 717 def->value_size,
714 718 def->max_entries);
715 def = *(struct bpf_map_def *)(obj->maps_buf +
716 i * sizeof(struct bpf_map_def));
717
718 *pfd = bpf_create_map(def.type,
719 def.key_size,
720 def.value_size,
721 def.max_entries);
722 if (*pfd < 0) { 719 if (*pfd < 0) {
723 size_t j; 720 size_t j;
724 int err = *pfd; 721 int err = *pfd;
@@ -726,22 +723,17 @@ bpf_object__create_maps(struct bpf_object *obj)
726 pr_warning("failed to create map: %s\n", 723 pr_warning("failed to create map: %s\n",
727 strerror(errno)); 724 strerror(errno));
728 for (j = 0; j < i; j++) 725 for (j = 0; j < i; j++)
729 zclose(obj->map_fds[j]); 726 zclose(obj->maps[j].fd);
730 obj->nr_map_fds = 0;
731 zfree(&obj->map_fds);
732 return err; 727 return err;
733 } 728 }
734 pr_debug("create map: fd=%d\n", *pfd); 729 pr_debug("create map: fd=%d\n", *pfd);
735 pfd++;
736 } 730 }
737 731
738 zfree(&obj->maps_buf);
739 obj->maps_buf_sz = 0;
740 return 0; 732 return 0;
741} 733}
742 734
743static int 735static int
744bpf_program__relocate(struct bpf_program *prog, int *map_fds) 736bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
745{ 737{
746 int i; 738 int i;
747 739
@@ -761,7 +753,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds)
761 return -LIBBPF_ERRNO__RELOC; 753 return -LIBBPF_ERRNO__RELOC;
762 } 754 }
763 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 755 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
764 insns[insn_idx].imm = map_fds[map_idx]; 756 insns[insn_idx].imm = obj->maps[map_idx].fd;
765 } 757 }
766 758
767 zfree(&prog->reloc_desc); 759 zfree(&prog->reloc_desc);
@@ -780,7 +772,7 @@ bpf_object__relocate(struct bpf_object *obj)
780 for (i = 0; i < obj->nr_programs; i++) { 772 for (i = 0; i < obj->nr_programs; i++) {
781 prog = &obj->programs[i]; 773 prog = &obj->programs[i];
782 774
783 err = bpf_program__relocate(prog, obj->map_fds); 775 err = bpf_program__relocate(prog, obj);
784 if (err) { 776 if (err) {
785 pr_warning("failed to relocate '%s'\n", 777 pr_warning("failed to relocate '%s'\n",
786 prog->section_name); 778 prog->section_name);
@@ -804,8 +796,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
804 Elf_Data *data = obj->efile.reloc[i].data; 796 Elf_Data *data = obj->efile.reloc[i].data;
805 int idx = shdr->sh_info; 797 int idx = shdr->sh_info;
806 struct bpf_program *prog; 798 struct bpf_program *prog;
807 size_t nr_maps = obj->maps_buf_sz / 799 size_t nr_maps = obj->nr_maps;
808 sizeof(struct bpf_map_def);
809 800
810 if (shdr->sh_type != SHT_REL) { 801 if (shdr->sh_type != SHT_REL) {
811 pr_warning("internal error at %d\n", __LINE__); 802 pr_warning("internal error at %d\n", __LINE__);
@@ -1050,10 +1041,8 @@ int bpf_object__unload(struct bpf_object *obj)
1050 if (!obj) 1041 if (!obj)
1051 return -EINVAL; 1042 return -EINVAL;
1052 1043
1053 for (i = 0; i < obj->nr_map_fds; i++) 1044 for (i = 0; i < obj->nr_maps; i++)
1054 zclose(obj->map_fds[i]); 1045 zclose(obj->maps[i].fd);
1055 zfree(&obj->map_fds);
1056 obj->nr_map_fds = 0;
1057 1046
1058 for (i = 0; i < obj->nr_programs; i++) 1047 for (i = 0; i < obj->nr_programs; i++)
1059 bpf_program__unload(&obj->programs[i]); 1048 bpf_program__unload(&obj->programs[i]);
@@ -1096,7 +1085,15 @@ void bpf_object__close(struct bpf_object *obj)
1096 bpf_object__elf_finish(obj); 1085 bpf_object__elf_finish(obj);
1097 bpf_object__unload(obj); 1086 bpf_object__unload(obj);
1098 1087
1099 zfree(&obj->maps_buf); 1088 for (i = 0; i < obj->nr_maps; i++) {
1089 if (obj->maps[i].clear_priv)
1090 obj->maps[i].clear_priv(&obj->maps[i],
1091 obj->maps[i].priv);
1092 obj->maps[i].priv = NULL;
1093 obj->maps[i].clear_priv = NULL;
1094 }
1095 zfree(&obj->maps);
1096 obj->nr_maps = 0;
1100 1097
1101 if (obj->programs && obj->nr_programs) { 1098 if (obj->programs && obj->nr_programs) {
1102 for (i = 0; i < obj->nr_programs; i++) 1099 for (i = 0; i < obj->nr_programs; i++)
@@ -1251,3 +1248,73 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
1251 1248
1252 return fd; 1249 return fd;
1253} 1250}
1251
1252int bpf_map__get_fd(struct bpf_map *map)
1253{
1254 if (!map)
1255 return -EINVAL;
1256
1257 return map->fd;
1258}
1259
1260int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
1261{
1262 if (!map || !pdef)
1263 return -EINVAL;
1264
1265 *pdef = map->def;
1266 return 0;
1267}
1268
1269int bpf_map__set_private(struct bpf_map *map, void *priv,
1270 bpf_map_clear_priv_t clear_priv)
1271{
1272 if (!map)
1273 return -EINVAL;
1274
1275 if (map->priv) {
1276 if (map->clear_priv)
1277 map->clear_priv(map, map->priv);
1278 }
1279
1280 map->priv = priv;
1281 map->clear_priv = clear_priv;
1282 return 0;
1283}
1284
1285int bpf_map__get_private(struct bpf_map *map, void **ppriv)
1286{
1287 if (!map)
1288 return -EINVAL;
1289
1290 if (ppriv)
1291 *ppriv = map->priv;
1292 return 0;
1293}
1294
1295struct bpf_map *
1296bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
1297{
1298 size_t idx;
1299 struct bpf_map *s, *e;
1300
1301 if (!obj || !obj->maps)
1302 return NULL;
1303
1304 s = obj->maps;
1305 e = obj->maps + obj->nr_maps;
1306
1307 if (prev == NULL)
1308 return s;
1309
1310 if ((prev < s) || (prev >= e)) {
1311 pr_warning("error in %s: map handler doesn't belong to object\n",
1312 __func__);
1313 return NULL;
1314 }
1315
1316 idx = (prev - obj->maps) + 1;
1317 if (idx >= obj->nr_maps)
1318 return NULL;
1319 return &obj->maps[idx];
1320}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 949df4b346cf..ef631255dfaa 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -165,4 +165,25 @@ struct bpf_map_def {
165 unsigned int max_entries; 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 */
172struct bpf_map;
173
174struct bpf_map *
175bpf_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
181int bpf_map__get_fd(struct bpf_map *map);
182int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
183
184typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
185int bpf_map__set_private(struct bpf_map *map, void *priv,
186 bpf_map_clear_priv_t clear_priv);
187int bpf_map__get_private(struct bpf_map *map, void **ppriv);
188
168#endif 189#endif