PERF_SAMPLE_TYPE(TRANSACTION, "--transaction"),
PERF_SAMPLE_TYPE(CODE_PAGE_SIZE, "--code-page-size"),
PERF_SAMPLE_TYPE(DATA_PAGE_SIZE, "--data-page-size"),
+ PERF_SAMPLE_TYPE(CGROUP, "--all-cgroups"),
};
static int get_pinned_fd(const char *name);
#include "bpf-filter.h"
#include "bpf-filter-bison.h"
+extern int perf_bpf_filter_needs_path;
+
static int sample(enum perf_bpf_filter_term term)
{
+ perf_bpf_filter_needs_path = 0;
perf_bpf_filter_lval.sample.term = term;
perf_bpf_filter_lval.sample.part = 0;
return BFT_SAMPLE;
static int sample_part(enum perf_bpf_filter_term term, int part)
{
+ perf_bpf_filter_needs_path = 0;
perf_bpf_filter_lval.sample.term = term;
perf_bpf_filter_lval.sample.part = part;
return BFT_SAMPLE;
}
+static int sample_path(enum perf_bpf_filter_term term)
+{
+ perf_bpf_filter_needs_path = 1;
+ perf_bpf_filter_lval.sample.term = term;
+ perf_bpf_filter_lval.sample.part = 0;
+ return BFT_SAMPLE_PATH;
+}
+
static int operator(enum perf_bpf_filter_op op)
{
perf_bpf_filter_lval.op = op;
return BFT_NUM;
}
-static int error(const char *str)
+static int path_or_error(void)
{
- printf("perf_bpf_filter: Unexpected filter %s: %s\n", str, perf_bpf_filter_text);
- return BFT_ERROR;
+ if (!perf_bpf_filter_needs_path) {
+ printf("perf_bpf_filter: Error: Unexpected item: %s\n",
+ perf_bpf_filter_text);
+ return BFT_ERROR;
+ }
+ perf_bpf_filter_lval.path = perf_bpf_filter_text;
+ return BFT_PATH;
}
%}
num_dec [0-9]+
num_hex 0[Xx][0-9a-fA-F]+
space [ \t]+
+path [^ \t\n]+
ident [_a-zA-Z][_a-zA-Z0-9]+
%%
mem_hops { return sample_part(PBF_TERM_DATA_SRC, 8); }
uid { return sample(PBF_TERM_UID); }
gid { return sample(PBF_TERM_GID); }
+cgroup { return sample_path(PBF_TERM_CGROUP); }
"==" { return operator(PBF_OP_EQ); }
"!=" { return operator(PBF_OP_NEQ); }
"," { return ','; }
"||" { return BFT_LOGICAL_OR; }
-{ident} { return error("ident"); }
-. { return error("input"); }
+{path} { return path_or_error(); }
%%
#include <linux/compiler.h>
#include <linux/list.h>
#include "bpf-filter.h"
+#include "cgroup.h"
int perf_bpf_filter_lex(void);
+/* To indicate if the current term needs a pathname or not */
+int perf_bpf_filter_needs_path;
+
static void perf_bpf_filter_error(struct list_head *expr __maybe_unused,
char const *msg)
{
%union
{
unsigned long num;
+ char *path;
struct {
enum perf_bpf_filter_term term;
int part;
struct perf_bpf_filter_expr *expr;
}
-%token BFT_SAMPLE BFT_OP BFT_ERROR BFT_NUM BFT_LOGICAL_OR
+%token BFT_SAMPLE BFT_SAMPLE_PATH BFT_OP BFT_ERROR BFT_NUM BFT_LOGICAL_OR BFT_PATH
%type <expr> filter_term filter_expr
%destructor { free ($$); } <expr>
-%type <sample> BFT_SAMPLE
+%type <sample> BFT_SAMPLE BFT_SAMPLE_PATH
%type <op> BFT_OP
%type <num> BFT_NUM
+%type <path> BFT_PATH
%%
{
$$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, $3);
}
+|
+BFT_SAMPLE_PATH BFT_OP BFT_PATH
+{
+ struct cgroup *cgrp;
+ unsigned long cgroup_id = 0;
+
+ if ($2 != PBF_OP_EQ && $2 != PBF_OP_NEQ) {
+ printf("perf_bpf_filter: cgroup accepts '==' or '!=' only\n");
+ YYERROR;
+ }
+
+ cgrp = cgroup__new($3, /*do_open=*/false);
+ if (cgrp && read_cgroup_id(cgrp) == 0)
+ cgroup_id = cgrp->id;
+
+ $$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, cgroup_id);
+ cgroup__put(cgrp);
+}
%%
__PBF_UNUSED_TERM18 = PBF_TERM_SAMPLE_START + 18, /* SAMPLE_REGS_INTR = 1U << 18 */
PBF_TERM_PHYS_ADDR = PBF_TERM_SAMPLE_START + 19, /* SAMPLE_PHYS_ADDR = 1U << 19 */
__PBF_UNUSED_TERM20 = PBF_TERM_SAMPLE_START + 20, /* SAMPLE_AUX = 1U << 20 */
- __PBF_UNUSED_TERM21 = PBF_TERM_SAMPLE_START + 21, /* SAMPLE_CGROUP = 1U << 21 */
+ PBF_TERM_CGROUP = PBF_TERM_SAMPLE_START + 21, /* SAMPLE_CGROUP = 1U << 21 */
PBF_TERM_DATA_PAGE_SIZE = PBF_TERM_SAMPLE_START + 22, /* SAMPLE_DATA_PAGE_SIZE = 1U << 22 */
PBF_TERM_CODE_PAGE_SIZE = PBF_TERM_SAMPLE_START + 23, /* SAMPLE_CODE_PAGE_SIZE = 1U << 23 */
PBF_TERM_WEIGHT_STRUCT = PBF_TERM_SAMPLE_START + 24, /* SAMPLE_WEIGHT_STRUCT = 1U << 24 */
BUILD_CHECK_SAMPLE(DATA_SRC);
BUILD_CHECK_SAMPLE(TRANSACTION);
BUILD_CHECK_SAMPLE(PHYS_ADDR);
+ BUILD_CHECK_SAMPLE(CGROUP);
BUILD_CHECK_SAMPLE(DATA_PAGE_SIZE);
BUILD_CHECK_SAMPLE(CODE_PAGE_SIZE);
BUILD_CHECK_SAMPLE(WEIGHT_STRUCT);
return kctx->data->weight.full;
case PBF_TERM_PHYS_ADDR:
return kctx->data->phys_addr;
+ case PBF_TERM_CGROUP:
+ return kctx->data->cgroup;
case PBF_TERM_CODE_PAGE_SIZE:
return kctx->data->code_page_size;
case PBF_TERM_DATA_PAGE_SIZE:
case __PBF_UNUSED_TERM16:
case __PBF_UNUSED_TERM18:
case __PBF_UNUSED_TERM20:
- case __PBF_UNUSED_TERM21:
default:
break;
}
u32 cpu;
} cpu_entry;
u64 phys_addr;
+ u64 cgroup;
u64 data_page_size;
u64 code_page_size;
} __attribute__((__aligned__(64))) __attribute__((preserve_access_index));