Thread (8 messages) 8 messages, 4 authors, 2019-06-30

Re: [PATCH v3 bpf-next 4/4] tools/bpftool: switch map event_pipe to libbpf's perf_buffer

From: Andrii Nakryiko <hidden>
Date: 2019-06-30 06:44:16
Also in: bpf

Re-sending as plain text, first time it somehow turned into HTML... :(


On Sat, Jun 29, 2019 at 11:24 AM Jakub Kicinski
[off-list ref] wrote:
On Fri, 28 Jun 2019 22:53:09 -0700, Andrii Nakryiko wrote:
quoted
      map_info_len = sizeof(map_info);
      map_fd = map_parse_fd_and_info(&argc, &argv, &map_info, &map_info_len);
-     if (map_fd < 0)
+     if (map_fd < 0) {
+             p_err("failed to get map info");
Can't do, map_parse_fd_and_info() prints an error already, we can't
have multiple errors in JSON.
Oh.. I need to be more careful with printing error in bpftool due to
this JSON business... Thanks!
quoted
              return -1;
+     }

      if (map_info.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
              p_err("map is not a perf event array");
@@ -205,7 +157,7 @@ int do_event_pipe(int argc, char **argv)
                      char *endptr;

                      NEXT_ARG();
-                     cpu = strtoul(*argv, &endptr, 0);
+                     ctx.cpu = strtoul(*argv, &endptr, 0);
                      if (*endptr) {
                              p_err("can't parse %s as CPU ID", **argv);
                              goto err_close_map;
@@ -216,7 +168,7 @@ int do_event_pipe(int argc, char **argv)
                      char *endptr;

                      NEXT_ARG();
-                     index = strtoul(*argv, &endptr, 0);
+                     ctx.idx = strtoul(*argv, &endptr, 0);
                      if (*endptr) {
                              p_err("can't parse %s as index", **argv);
                              goto err_close_map;
@@ -228,45 +180,32 @@ int do_event_pipe(int argc, char **argv)
                      goto err_close_map;
              }

-             do_all = false;
+             ctx.all_cpus = false;
      }

-     if (!do_all) {
-             if (index == -1 || cpu == -1) {
+     if (!ctx.all_cpus) {
+             if (ctx.idx == -1 || ctx.cpu == -1) {
                      p_err("cpu and index must be specified together");
                      goto err_close_map;
Now that you look at err looks like we're missing an err = -1 assignment
here?  but...
No need, see below.
quoted
              }
-
-             nfds = 1;
      } else {
-             nfds = min(get_possible_cpus(), map_info.max_entries);
-             cpu = 0;
-             index = 0;
+             ctx.cpu = 0;
+             ctx.idx = 0;
      }

-     rings = calloc(nfds, sizeof(rings[0]));
-     if (!rings)
+     opts.attr = &perf_attr;
+     opts.event_cb = print_bpf_output;
+     opts.ctx = &ctx;
+     opts.cpu_cnt = ctx.all_cpus ? 0 : 1;
+     opts.cpus = &ctx.cpu;
+     opts.map_keys = &ctx.idx;
+
+     pb = perf_buffer__new_raw(map_fd, MMAP_PAGE_CNT, &opts);
+     err = libbpf_get_error(pb);
+     if (err) {
+             p_err("failed to create perf buffer: %s (%d)",
+                   strerror(err), err);
              goto err_close_map;
-
-     pfds = calloc(nfds, sizeof(pfds[0]));
-     if (!pfds)
-             goto err_free_rings;
-
-     for (i = 0; i < nfds; i++) {
-             rings[i].cpu = cpu + i;
-             rings[i].key = index + i;
-
-             rings[i].fd = bpf_perf_event_open(map_fd, rings[i].key,
-                                               rings[i].cpu);
-             if (rings[i].fd < 0)
-                     goto err_close_fds_prev;
-
-             rings[i].mem = perf_event_mmap(rings[i].fd);
-             if (!rings[i].mem)
-                     goto err_close_fds_current;
-
-             pfds[i].fd = rings[i].fd;
-             pfds[i].events = POLLIN;
      }

      signal(SIGINT, int_exit);
@@ -277,35 +216,25 @@ int do_event_pipe(int argc, char **argv)
              jsonw_start_array(json_wtr);

      while (!stop) {
-             poll(pfds, nfds, 200);
-             for (i = 0; i < nfds; i++)
-                     perf_event_read(&rings[i], &tmp_buf, &tmp_buf_sz);
+             err = perf_buffer__poll(pb, 200);
+             if (err < 0 && err != -EINTR) {
+                     p_err("perf buffer polling failed: %s (%d)",
+                           strerror(err), err);
+                     goto err_close_pb;
+             }
      }
-     free(tmp_buf);

      if (json_output)
              jsonw_end_array(json_wtr);

-     for (i = 0; i < nfds; i++) {
-             perf_event_unmap(rings[i].mem);
-             close(rings[i].fd);
-     }
-     free(pfds);
-     free(rings);
+     perf_buffer__free(pb);
      close(map_fd);

      return 0;

-err_close_fds_prev:
-     while (i--) {
-             perf_event_unmap(rings[i].mem);
-err_close_fds_current:
-             close(rings[i].fd);
-     }
-     free(pfds);
-err_free_rings:
-     free(rings);
+err_close_pb:
+     perf_buffer__free(pb);
 err_close_map:
      close(map_fd);
-     return -1;
+     return err ? -1 : 0;
... how can we return 0 on the error path?
Good catch! I initially was going to merge success and error path, but
after seeing how many explicit `err = <something>` I had to do I
abandoned the effort, but forgot to undo this `return -1` change. I'll
return -1 unconditionally.
quoted
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help