From: Wang Nan <wangnan0@huawei.com>
To: Alexei Starovoitov <ast@kernel.org>,
Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>,
Daniel Borkmann <daniel@iogearbox.net>,
"David S. Miller" <davem@davemloft.net>,
He Kuang <hekuang@huawei.com>, Jiri Olsa <jolsa@kernel.org>,
Li Zefan <lizefan@huawei.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Namhyung Kim <namhyung@kernel.org>,
Peter Zijlstra <peterz@infradead.org>, <pi3orama@163.com>,
Will Deacon <will.deacon@arm.com>, <linux-kernel@vger.kernel.org>,
Wang Nan <wangnan0@huawei.com>
Subject: [PATCH 14/54] perf tools: Support setting different slots in a BPF map separately
Date: Mon, 25 Jan 2016 09:56:01 +0000 [thread overview]
Message-ID: <1453715801-7732-15-git-send-email-wangnan0@huawei.com> (raw)
In-Reply-To: <1453715801-7732-1-git-send-email-wangnan0@huawei.com>
This patch introduces basic facilities to support config different
slots in a BPF map one by one.
array.nr_ranges and array.ranges are introduced into 'struct
parse_events_term', where ranges is an array of indices range (start,
length) which will be configured by this config term. nr_ranges
is the size of the array. The array is passed to 'struct bpf_map_priv'.
To indicate the new type of configuration, BPF_MAP_KEY_RANGES is
added as a new key type. bpf_map_config_foreach_key() is extended to
iterate over those indices instead of all possible keys.
Code in this commit will be enabled by following commit which enables
the indices syntax for array configuration.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@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
---
tools/perf/util/bpf-loader.c | 132 ++++++++++++++++++++++++++++++++++++++---
tools/perf/util/bpf-loader.h | 1 +
tools/perf/util/parse-events.c | 33 ++++++++++-
tools/perf/util/parse-events.h | 12 ++++
4 files changed, 170 insertions(+), 8 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2893b4e..6c25de8 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -17,6 +17,7 @@
#include "llvm-utils.h"
#include "probe-event.h"
#include "probe-finder.h" // for MAX_PROBES
+#include "parse-events.h"
#include "llvm-utils.h"
#define DEFINE_PRINT_FN(name, level) \
@@ -747,6 +748,7 @@ enum bpf_map_op_type {
enum bpf_map_key_type {
BPF_MAP_KEY_ALL,
+ BPF_MAP_KEY_RANGES,
};
struct bpf_map_op {
@@ -754,6 +756,9 @@ struct bpf_map_op {
enum bpf_map_op_type op_type;
enum bpf_map_key_type key_type;
union {
+ struct parse_events_array array;
+ } k;
+ union {
u64 value;
struct perf_evsel *evsel;
} v;
@@ -779,6 +784,8 @@ bpf_map_op__free(struct bpf_map_op *op)
*/
if ((list->next != LIST_POISON1) && (list->prev != LIST_POISON2))
list_del(list);
+ if (op->key_type == BPF_MAP_KEY_RANGES)
+ parse_events__clear_array(&op->k.array);
free(op);
}
@@ -794,8 +801,30 @@ bpf_map_priv__clear(struct bpf_map *map __maybe_unused,
free(priv);
}
+static int
+bpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term,
+ const char *map_name)
+{
+ op->key_type = BPF_MAP_KEY_ALL;
+
+ if (term->array.nr_ranges) {
+ size_t memsz = term->array.nr_ranges *
+ sizeof(op->k.array.ranges[0]);
+
+ op->k.array.ranges = memdup(term->array.ranges, memsz);
+ if (!op->k.array.ranges) {
+ pr_debug("No enough memory to alloc indices for %s\n",
+ map_name);
+ return -ENOMEM;
+ }
+ op->key_type = BPF_MAP_KEY_RANGES;
+ op->k.array.nr_ranges = term->array.nr_ranges;
+ }
+ return 0;
+}
+
static struct bpf_map_op *
-bpf_map_op__alloc(struct bpf_map *map)
+bpf_map_op__alloc(struct bpf_map *map, struct parse_events_term *term)
{
struct bpf_map_op *op;
struct bpf_map_priv *priv;
@@ -829,7 +858,12 @@ bpf_map_op__alloc(struct bpf_map *map)
return ERR_PTR(-ENOMEM);
}
- op->key_type = BPF_MAP_KEY_ALL;
+ err = bpf_map_op_setkey(op, term, map_name);
+ if (err) {
+ free(op);
+ return ERR_PTR(err);
+ }
+
list_add_tail(&op->list, &priv->ops_list);
return op;
}
@@ -872,7 +906,7 @@ bpf__obj_config_map_array_value(struct bpf_map *map,
return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE;
}
- op = bpf_map_op__alloc(map);
+ op = bpf_map_op__alloc(map, term);
if (IS_ERR(op))
return PTR_ERR(op);
op->op_type = BPF_MAP_OP_SET_VALUE;
@@ -933,7 +967,7 @@ bpf__obj_config_map_array_event(struct bpf_map *map,
return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
}
- op = bpf_map_op__alloc(map);
+ op = bpf_map_op__alloc(map, term);
if (IS_ERR(op))
return PTR_ERR(op);
@@ -972,6 +1006,44 @@ struct bpf_obj_config_map_func bpf_obj_config_map_funcs[] = {
};
static int
+config_map_indices_range_check(struct parse_events_term *term,
+ struct bpf_map *map,
+ const char *map_name)
+{
+ struct parse_events_array *array = &term->array;
+ struct bpf_map_def def;
+ unsigned int i;
+ int err;
+
+ if (!array->nr_ranges)
+ return 0;
+ if (!array->ranges) {
+ pr_debug("ERROR: map %s: array->nr_ranges is %d but range array is NULL\n",
+ map_name, (int)array->nr_ranges);
+ return -BPF_LOADER_ERRNO__INTERNAL;
+ }
+
+ err = bpf_map__get_def(map, &def);
+ if (err) {
+ pr_debug("ERROR: Unable to get map definition from '%s'\n",
+ map_name);
+ return -BPF_LOADER_ERRNO__INTERNAL;
+ }
+
+ for (i = 0; i < array->nr_ranges; i++) {
+ unsigned int start = array->ranges[i].start;
+ size_t length = array->ranges[i].length;
+ unsigned int idx = start + length - 1;
+
+ if (idx >= def.max_entries) {
+ pr_debug("ERROR: index %d too large\n", idx);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG;
+ }
+ }
+ return 0;
+}
+
+static int
bpf__obj_config_map(struct bpf_object *obj,
struct parse_events_term *term,
struct perf_evlist *evlist,
@@ -1007,6 +1079,13 @@ bpf__obj_config_map(struct bpf_object *obj,
}
*key_scan_pos += map_opt - map_name;
+
+ *key_scan_pos += strlen(map_opt);
+ err = config_map_indices_range_check(term, map, map_name);
+ if (err)
+ goto out;
+ *key_scan_pos -= strlen(map_opt);
+
for (i = 0; i < ARRAY_SIZE(bpf_obj_config_map_funcs); i++) {
struct bpf_obj_config_map_func *func =
&bpf_obj_config_map_funcs[i];
@@ -1077,6 +1156,33 @@ foreach_key_array_all(map_config_func_t func,
}
static int
+foreach_key_array_ranges(map_config_func_t func, void *arg,
+ const char *name, int map_fd,
+ struct bpf_map_def *pdef,
+ struct bpf_map_op *op)
+{
+ unsigned int i, j;
+ int err;
+
+ for (i = 0; i < op->k.array.nr_ranges; i++) {
+ unsigned int start = op->k.array.ranges[i].start;
+ size_t length = op->k.array.ranges[i].length;
+
+ for (j = 0; j < length; j++) {
+ unsigned int idx = start + j;
+
+ err = func(name, map_fd, pdef, op, &idx, arg);
+ if (err) {
+ pr_debug("ERROR: failed to insert value to %s[%u]\n",
+ name, idx);
+ return err;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
bpf_map_config_foreach_key(struct bpf_map *map,
map_config_func_t func,
void *arg)
@@ -1116,13 +1222,24 @@ bpf_map_config_foreach_key(struct bpf_map *map,
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
switch (op->key_type) {
case BPF_MAP_KEY_ALL:
- return foreach_key_array_all(func, arg, name,
- map_fd, &def, op);
+ err = foreach_key_array_all(func, arg, name,
+ map_fd, &def, op);
+ if (err)
+ return err;
+ break;
+ case BPF_MAP_KEY_RANGES:
+ err = foreach_key_array_ranges(func, arg, name,
+ map_fd, &def,
+ op);
+ if (err)
+ return err;
+ break;
default:
pr_debug("ERROR: keytype for map '%s' invalid\n",
name);
return -BPF_LOADER_ERRNO__INTERNAL;
- }
+ }
+ break;
default:
pr_debug("ERROR: type of '%s' incorrect\n", name);
return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
@@ -1309,6 +1426,7 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
[ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)] = "Event dimension too large",
[ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)] = "Doesn't support inherit event",
[ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)] = "Wrong event type for map",
+ [ERRCODE_OFFSET(OBJCONF_MAP_IDX2BIG)] = "Index too large",
};
static int
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index c9ce792..30ee519 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -38,6 +38,7 @@ enum bpf_loader_errno {
BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM, /* Event dimension too large */
BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH, /* Doesn't support inherit event */
BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE, /* Wrong event type for map */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG, /* Index too large */
__BPF_LOADER_ERRNO__END,
};
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e0ac77..f229663 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -2148,8 +2148,39 @@ void parse_events__free_terms(struct list_head *terms)
{
struct parse_events_term *term, *h;
- list_for_each_entry_safe(term, h, terms, list)
+ list_for_each_entry_safe(term, h, terms, list) {
+ if (term->array.nr_ranges)
+ free(term->array.ranges);
free(term);
+ }
+}
+
+int parse_events__merge_arrays(struct parse_events_array *dest,
+ struct parse_events_array *another)
+{
+ struct parse_events_array new;
+
+ if (!dest || !another)
+ return -EINVAL;
+
+ new.nr_ranges = dest->nr_ranges + another->nr_ranges;
+ new.ranges = malloc(sizeof(new.ranges[0]) * new.nr_ranges);
+ if (!new.ranges)
+ return -ENOMEM;
+
+ memcpy(&new.ranges[0], dest->ranges,
+ sizeof(new.ranges[0]) * dest->nr_ranges);
+ memcpy(&new.ranges[dest->nr_ranges], another->ranges,
+ sizeof(new.ranges[0]) * another->nr_ranges);
+ free(dest->ranges);
+ free(another->ranges);
+ *dest = new;
+ return 0;
+}
+
+void parse_events__clear_array(struct parse_events_array *a)
+{
+ free(a->ranges);
}
void parse_events_evlist_error(struct parse_events_evlist *data,
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 20ad3c2..c34615f 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,8 +71,17 @@ enum {
PARSE_EVENTS__TERM_TYPE_INHERIT
};
+struct parse_events_array {
+ size_t nr_ranges;
+ struct {
+ unsigned int start;
+ size_t length;
+ } *ranges;
+};
+
struct parse_events_term {
char *config;
+ struct parse_events_array array;
union {
char *str;
u64 num;
@@ -117,6 +126,9 @@ int parse_events_term__sym_hw(struct parse_events_term **term,
int parse_events_term__clone(struct parse_events_term **new,
struct parse_events_term *term);
void parse_events__free_terms(struct list_head *terms);
+int parse_events__merge_arrays(struct parse_events_array *dest,
+ struct parse_events_array *another);
+void parse_events__clear_array(struct parse_events_array *a);
int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name);
--
1.8.3.4
next prev parent reply other threads:[~2016-01-25 9:58 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-25 9:55 [GIT PULL 00/54] perf tools: Bugfix, BPF improvements and overwrite ring buffer support Wang Nan
2016-01-25 9:55 ` [PATCH 01/54] perf test: Add libbpf relocation checker Wang Nan
2016-01-26 14:58 ` Arnaldo Carvalho de Melo
2016-01-26 15:07 ` Arnaldo Carvalho de Melo
2016-02-03 10:13 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 02/54] perf bpf: Check relocation target section Wang Nan
2016-02-03 10:14 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 03/54] tools build: Allow subprojects select all feature checkers Wang Nan
2016-02-03 10:14 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 04/54] perf build: Select all feature checkers for feature-dump Wang Nan
2016-02-03 10:14 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 05/54] perf build: Use feature dump file for build-test Wang Nan
2016-01-26 16:59 ` Arnaldo Carvalho de Melo
2016-01-27 2:36 ` Wangnan (F)
2016-01-27 13:54 ` Arnaldo Carvalho de Melo
2016-01-27 11:22 ` [PATCH] tools build: Check basic headers for test-compile feature checker Wang Nan
2016-01-27 13:23 ` Jiri Olsa
2016-01-27 13:55 ` Arnaldo Carvalho de Melo
2016-02-03 10:15 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 06/54] perf test: Check environment before start real BPF test Wang Nan
2016-02-03 10:18 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 07/54] perf tools: Fix symbols searching for offline module in buildid-cache Wang Nan
2016-01-25 9:55 ` [PATCH 08/54] perf test: Improve bp_signal Wang Nan
2016-02-03 10:18 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:55 ` [PATCH 09/54] perf tools: Add API to config maps in bpf object Wang Nan
2016-02-03 23:29 ` Arnaldo Carvalho de Melo
2016-02-04 12:59 ` Wangnan (F)
2016-01-25 9:55 ` [PATCH 10/54] perf tools: Enable BPF object configure syntax Wang Nan
2016-01-25 9:55 ` [PATCH 11/54] perf record: Apply config to BPF objects before recording Wang Nan
2016-01-25 9:55 ` [PATCH 12/54] perf tools: Enable passing event to BPF object Wang Nan
2016-01-25 9:56 ` [PATCH 13/54] perf tools: Support perf event alias name Wang Nan
2016-02-03 23:35 ` Arnaldo Carvalho de Melo
2016-01-25 9:56 ` Wang Nan [this message]
2016-01-25 9:56 ` [PATCH 15/54] perf tools: Enable indices setting syntax for BPF maps Wang Nan
2016-01-25 9:56 ` [PATCH 16/54] perf tools: Introduce bpf-output event Wang Nan
2016-01-25 9:56 ` [PATCH 17/54] perf data: Support converting data from bpf_perf_event_output() Wang Nan
2016-01-25 9:56 ` [PATCH 18/54] perf core: Introduce new ioctl options to pause and resume ring buffer Wang Nan
2016-01-25 9:56 ` [PATCH 19/54] perf core: Set event's default overflow_handler Wang Nan
2016-01-25 9:56 ` [PATCH 20/54] perf core: Prepare writing into ring buffer from end Wang Nan
2016-01-25 9:56 ` [PATCH 21/54] perf core: Add backward attribute to perf event Wang Nan
2016-01-25 9:56 ` [PATCH 22/54] perf core: Reduce perf event output overhead by new overflow handler Wang Nan
2016-01-25 9:56 ` [PATCH 23/54] perf tools: Introduce API to pause ring buffer Wang Nan
2016-01-25 9:56 ` [PATCH 24/54] perf tools: Only validate is_pos for tracking evsels Wang Nan
2016-01-25 9:56 ` [PATCH 25/54] perf tools: Print write_backward value in perf_event_attr__fprintf Wang Nan
2016-01-25 9:56 ` [PATCH 26/54] perf tools: Move timestamp creation to util Wang Nan
2016-02-03 10:18 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:56 ` [PATCH 27/54] perf tools: Make ordered_events reusable Wang Nan
2016-01-25 9:56 ` [PATCH 28/54] perf record: Extract synthesize code to record__synthesize() Wang Nan
2016-01-29 20:37 ` Arnaldo Carvalho de Melo
2016-01-25 9:56 ` [PATCH 29/54] perf tools: Add perf_data_file__switch() helper Wang Nan
2016-01-25 9:56 ` [PATCH 30/54] perf record: Turns auxtrace_snapshot_enable into 3 states Wang Nan
2016-01-25 9:56 ` [PATCH 31/54] perf record: Introduce record__finish_output() to finish a perf.data Wang Nan
2016-01-25 9:56 ` [PATCH 32/54] perf record: Use OPT_BOOLEAN_SET for buildid cache related options Wang Nan
2016-02-03 10:19 ` [tip:perf/core] " tip-bot for Wang Nan
2016-01-25 9:56 ` [PATCH 33/54] perf record: Add '--timestamp-filename' option to append timestamp to output filename Wang Nan
2016-01-25 9:56 ` [PATCH 34/54] perf record: Split output into multiple files via '--switch-output' Wang Nan
2016-01-25 9:56 ` [PATCH 35/54] perf record: Force enable --timestamp-filename when --switch-output is provided Wang Nan
2016-01-25 9:56 ` [PATCH 36/54] perf record: Disable buildid cache options by default in switch output mode Wang Nan
2016-01-25 9:56 ` [PATCH 37/54] perf record: Re-synthesize tracking events after output switching Wang Nan
2016-01-25 9:56 ` [PATCH 38/54] perf record: Generate tracking events for process forked by perf Wang Nan
2016-01-25 9:56 ` [PATCH 39/54] perf record: Ensure return non-zero rc when mmap fail Wang Nan
2016-01-25 9:56 ` [PATCH 40/54] perf record: Prevent reading invalid data in record__mmap_read Wang Nan
2016-01-25 9:56 ` [PATCH 41/54] perf tools: Add evlist channel helpers Wang Nan
2016-01-25 9:56 ` [PATCH 42/54] perf tools: Automatically add new channel according to evlist Wang Nan
2016-01-25 9:56 ` [PATCH 43/54] perf tools: Operate multiple channels Wang Nan
2016-01-25 9:56 ` [PATCH 44/54] perf tools: Squash overwrite setting into channel Wang Nan
2016-01-25 9:56 ` [PATCH 45/54] perf record: Don't read from and poll overwrite channel Wang Nan
2016-01-25 9:56 ` [PATCH 46/54] perf record: Don't poll on " Wang Nan
2016-01-25 9:56 ` [PATCH 47/54] perf tools: Detect avalibility of write_backward Wang Nan
2016-01-25 9:56 ` [PATCH 48/54] perf tools: Enable overwrite settings Wang Nan
2016-01-25 9:56 ` [PATCH 49/54] perf tools: Set write_backward attribut bit for overwrite events Wang Nan
2016-01-25 9:56 ` [PATCH 50/54] perf record: Toggle overwrite ring buffer for reading Wang Nan
2016-01-26 8:25 ` Wangnan (F)
2016-01-25 9:56 ` [PATCH 51/54] perf record: Rename variable to make code clear Wang Nan
2016-01-25 9:56 ` [PATCH 52/54] perf record: Read from backward ring buffer Wang Nan
2016-01-25 9:56 ` [PATCH 53/54] perf record: Allow generate tracking events at the end of output Wang Nan
2016-01-25 9:56 ` [PATCH 54/54] perf tools: Don't warn about out of order event if write_backward is used Wang Nan
2016-01-26 9:11 ` [offlist] Re: [GIT PULL 00/54] perf tools: Bugfix, BPF improvements and overwrite ring buffer support Wangnan (F)
2016-01-26 14:11 ` Arnaldo Carvalho de Melo
2016-02-05 14:01 [PATCH " Wang Nan
2016-02-05 14:01 ` [PATCH 14/54] perf tools: Support setting different slots in a BPF map separately Wang Nan
2016-02-12 14:23 ` Jiri Olsa
2016-02-12 14:34 ` pi3orama
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1453715801-7732-15-git-send-email-wangnan0@huawei.com \
--to=wangnan0@huawei.com \
--cc=acme@redhat.com \
--cc=ast@kernel.org \
--cc=brendan.d.gregg@gmail.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=hekuang@huawei.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan@huawei.com \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=pi3orama@163.com \
--cc=will.deacon@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome