|
|
01fc30 |
commit f294197b5511537e6b14d5e1db324f4fc4fdd3f8
|
|
|
01fc30 |
Author: Dave Anderson <anderson@redhat.com>
|
|
|
01fc30 |
Date: Fri Jul 6 10:57:50 2018 -0400
|
|
|
01fc30 |
|
|
|
01fc30 |
Support for the "bpf" command on RHEL 3.10.0-913.el7 and later
|
|
|
01fc30 |
3.10-based RHEL7 kernels, which contain a backport of the upstream
|
|
|
01fc30 |
eBPF code, but still use the older, pre-4.11, IDR facility that does
|
|
|
01fc30 |
not use radix trees for linking the active bpf_prog and bpf_map
|
|
|
01fc30 |
structures. Without the patch, the command indicates "bpf: command
|
|
|
01fc30 |
not supported or applicable on this architecture or kernel".
|
|
|
01fc30 |
(anderson@redhat.com)
|
|
|
01fc30 |
|
|
|
01fc30 |
diff --git a/bpf.c b/bpf.c
|
|
|
01fc30 |
index 427263d..8871b76 100644
|
|
|
01fc30 |
--- a/bpf.c
|
|
|
01fc30 |
+++ b/bpf.c
|
|
|
01fc30 |
@@ -45,6 +45,10 @@ static void bpf_prog_gpl_compatible(char *, ulong);
|
|
|
01fc30 |
static void dump_xlated_plain(void *, unsigned int, int);
|
|
|
01fc30 |
static void print_boot_time(unsigned long long, char *, unsigned int);
|
|
|
01fc30 |
|
|
|
01fc30 |
+static int do_old_idr(int, ulong, struct radix_tree_pair *);
|
|
|
01fc30 |
+#define OLD_IDR_INIT (1)
|
|
|
01fc30 |
+#define OLD_IDR_COUNT (2)
|
|
|
01fc30 |
+#define OLD_IDR_GATHER (3)
|
|
|
01fc30 |
|
|
|
01fc30 |
#define PROG_ID (0x1)
|
|
|
01fc30 |
#define MAP_ID (0x2)
|
|
|
01fc30 |
@@ -167,7 +171,6 @@ bpf_init(struct bpf_info *bpf)
|
|
|
01fc30 |
!VALID_STRUCT(bpf_map) ||
|
|
|
01fc30 |
!VALID_STRUCT(bpf_insn) ||
|
|
|
01fc30 |
INVALID_MEMBER(bpf_prog_aux) ||
|
|
|
01fc30 |
- INVALID_MEMBER(idr_idr_rt) ||
|
|
|
01fc30 |
INVALID_MEMBER(bpf_prog_type) ||
|
|
|
01fc30 |
INVALID_MEMBER(bpf_prog_tag) ||
|
|
|
01fc30 |
INVALID_MEMBER(bpf_prog_jited_len) ||
|
|
|
01fc30 |
@@ -210,6 +213,9 @@ bpf_init(struct bpf_info *bpf)
|
|
|
01fc30 |
mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "BPF_MAP"),
|
|
|
01fc30 |
mkstring(buf3, bpf->bpf_map_map_type_size, CENTER|LJUST, "BPF_MAP_TYPE"));
|
|
|
01fc30 |
|
|
|
01fc30 |
+ if (INVALID_MEMBER(idr_idr_rt))
|
|
|
01fc30 |
+ do_old_idr(OLD_IDR_INIT, 0, NULL);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
bpf->status = TRUE;
|
|
|
01fc30 |
break;
|
|
|
01fc30 |
|
|
|
01fc30 |
@@ -220,24 +226,38 @@ bpf_init(struct bpf_info *bpf)
|
|
|
01fc30 |
command_not_supported();
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
- bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
- RADIX_TREE_COUNT, NULL);
|
|
|
01fc30 |
+ if (VALID_MEMBER(idr_idr_rt))
|
|
|
01fc30 |
+ bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
+ RADIX_TREE_COUNT, NULL);
|
|
|
01fc30 |
+ else
|
|
|
01fc30 |
+ bpf->progs = do_old_idr(OLD_IDR_COUNT, symbol_value("prog_idr"), NULL);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
if (bpf->progs) {
|
|
|
01fc30 |
len = sizeof(struct radix_tree_pair) * (bpf->progs+1);
|
|
|
01fc30 |
bpf->proglist = (struct radix_tree_pair *)GETBUF(len);
|
|
|
01fc30 |
bpf->proglist[0].index = bpf->progs;
|
|
|
01fc30 |
- bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
- RADIX_TREE_GATHER, bpf->proglist);
|
|
|
01fc30 |
+ if (VALID_MEMBER(idr_idr_rt))
|
|
|
01fc30 |
+ bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
+ RADIX_TREE_GATHER, bpf->proglist);
|
|
|
01fc30 |
+ else
|
|
|
01fc30 |
+ bpf->progs = do_old_idr(OLD_IDR_GATHER, symbol_value("prog_idr"), bpf->proglist);
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
- bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
- RADIX_TREE_COUNT, NULL);
|
|
|
01fc30 |
+ if (VALID_MEMBER(idr_idr_rt))
|
|
|
01fc30 |
+ bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
+ RADIX_TREE_COUNT, NULL);
|
|
|
01fc30 |
+ else
|
|
|
01fc30 |
+ bpf->maps = do_old_idr(OLD_IDR_COUNT, symbol_value("map_idr"), NULL);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
if (bpf->maps) {
|
|
|
01fc30 |
len = sizeof(struct radix_tree_pair) * (bpf->maps+1);
|
|
|
01fc30 |
bpf->maplist = (struct radix_tree_pair *)GETBUF(len);
|
|
|
01fc30 |
bpf->maplist[0].index = bpf->maps;
|
|
|
01fc30 |
- bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
- RADIX_TREE_GATHER, bpf->maplist);
|
|
|
01fc30 |
+ if (VALID_MEMBER(idr_idr_rt))
|
|
|
01fc30 |
+ bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
|
|
|
01fc30 |
+ RADIX_TREE_GATHER, bpf->maplist);
|
|
|
01fc30 |
+ else
|
|
|
01fc30 |
+ bpf->maps = do_old_idr(OLD_IDR_GATHER, symbol_value("map_idr"), bpf->maplist);
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
bpf->bpf_prog_buf = GETBUF(SIZE(bpf_prog));
|
|
|
01fc30 |
@@ -538,8 +558,10 @@ do_map_only:
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
bailout:
|
|
|
01fc30 |
- FREEBUF(bpf->proglist);
|
|
|
01fc30 |
- FREEBUF(bpf->maplist);
|
|
|
01fc30 |
+ if (bpf->proglist)
|
|
|
01fc30 |
+ FREEBUF(bpf->proglist);
|
|
|
01fc30 |
+ if (bpf->maplist)
|
|
|
01fc30 |
+ FREEBUF(bpf->maplist);
|
|
|
01fc30 |
FREEBUF(bpf->bpf_prog_buf);
|
|
|
01fc30 |
FREEBUF(bpf->bpf_prog_aux_buf);
|
|
|
01fc30 |
FREEBUF(bpf->bpf_map_buf);
|
|
|
01fc30 |
@@ -1255,3 +1277,50 @@ print_boot_time(unsigned long long nsecs, char *buf, unsigned int size)
|
|
|
01fc30 |
sprintf(buf, "(unknown)");
|
|
|
01fc30 |
#endif
|
|
|
01fc30 |
}
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+/*
|
|
|
01fc30 |
+ * Borrow the old (pre-radix_tree) IDR facility code used by
|
|
|
01fc30 |
+ * the ipcs command.
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+static int
|
|
|
01fc30 |
+do_old_idr(int cmd, ulong idr, struct radix_tree_pair *rtp)
|
|
|
01fc30 |
+{
|
|
|
01fc30 |
+ int i, max, cur, next_id, total = 0;
|
|
|
01fc30 |
+ ulong entry;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ switch (cmd)
|
|
|
01fc30 |
+ {
|
|
|
01fc30 |
+ case OLD_IDR_INIT:
|
|
|
01fc30 |
+ ipcs_init();
|
|
|
01fc30 |
+ break;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ case OLD_IDR_COUNT:
|
|
|
01fc30 |
+ readmem(idr + OFFSET(idr_cur), KVADDR, &cur,
|
|
|
01fc30 |
+ sizeof(int), "idr.cur", FAULT_ON_ERROR);
|
|
|
01fc30 |
+ for (total = next_id = 0; next_id < cur; next_id++) {
|
|
|
01fc30 |
+ entry = idr_find(idr, next_id);
|
|
|
01fc30 |
+ if (entry == 0)
|
|
|
01fc30 |
+ continue;
|
|
|
01fc30 |
+ total++;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+ break;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ case OLD_IDR_GATHER:
|
|
|
01fc30 |
+ max = rtp[0].index;
|
|
|
01fc30 |
+ readmem(idr + OFFSET(idr_cur), KVADDR, &cur,
|
|
|
01fc30 |
+ sizeof(int), "idr.cur", FAULT_ON_ERROR);
|
|
|
01fc30 |
+ for (i = total = next_id = 0; next_id < cur; next_id++) {
|
|
|
01fc30 |
+ entry = idr_find(idr, next_id);
|
|
|
01fc30 |
+ if (entry == 0)
|
|
|
01fc30 |
+ continue;
|
|
|
01fc30 |
+ total++;
|
|
|
01fc30 |
+ rtp[i].index = next_id;
|
|
|
01fc30 |
+ rtp[i].value = (void *)entry;
|
|
|
01fc30 |
+ if (++i == max)
|
|
|
01fc30 |
+ break;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+ break;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ return total;
|
|
|
01fc30 |
+}
|
|
|
01fc30 |
diff --git a/defs.h b/defs.h
|
|
|
01fc30 |
index e6e3850..b05aecc 100644
|
|
|
01fc30 |
--- a/defs.h
|
|
|
01fc30 |
+++ b/defs.h
|
|
|
01fc30 |
@@ -2031,6 +2031,7 @@ struct offset_table { /* stash of commonly-used offsets */
|
|
|
01fc30 |
long bpf_prog_aux_load_time;
|
|
|
01fc30 |
long bpf_prog_aux_user;
|
|
|
01fc30 |
long user_struct_uid;
|
|
|
01fc30 |
+ long idr_cur;
|
|
|
01fc30 |
};
|
|
|
01fc30 |
|
|
|
01fc30 |
struct size_table { /* stash of commonly-used sizes */
|
|
|
01fc30 |
@@ -5590,6 +5591,12 @@ enum {
|
|
|
01fc30 |
void dev_init(void);
|
|
|
01fc30 |
void dump_dev_table(void);
|
|
|
01fc30 |
|
|
|
01fc30 |
+/*
|
|
|
01fc30 |
+ * ipcs.c
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+void ipcs_init(void);
|
|
|
01fc30 |
+ulong idr_find(ulong, int);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
#ifdef ARM
|
|
|
01fc30 |
void arm_init(int);
|
|
|
01fc30 |
void arm_dump_machdep_table(ulong);
|
|
|
01fc30 |
diff --git a/ipcs.c b/ipcs.c
|
|
|
01fc30 |
index ef51fdd..80f78e4 100644
|
|
|
01fc30 |
--- a/ipcs.c
|
|
|
01fc30 |
+++ b/ipcs.c
|
|
|
01fc30 |
@@ -79,13 +79,11 @@ struct ipcs_table {
|
|
|
01fc30 |
* function declaration
|
|
|
01fc30 |
*/
|
|
|
01fc30 |
|
|
|
01fc30 |
-static void ipcs_init(void);
|
|
|
01fc30 |
static int dump_shared_memory(int, ulong, int, ulong);
|
|
|
01fc30 |
static int dump_semaphore_arrays(int, ulong, int, ulong);
|
|
|
01fc30 |
static int dump_message_queues(int, ulong, int, ulong);
|
|
|
01fc30 |
static int ipc_search_idr(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
|
|
|
01fc30 |
static int ipc_search_array(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
|
|
|
01fc30 |
-static ulong idr_find(ulong, int);
|
|
|
01fc30 |
static int dump_shm_info(ulong, int, ulong, int, int);
|
|
|
01fc30 |
static int dump_sem_info(ulong, int, ulong, int, int);
|
|
|
01fc30 |
static int dump_msg_info(ulong, int, ulong, int, int);
|
|
|
01fc30 |
@@ -101,7 +99,7 @@ static void gather_radix_tree_entries(ulong);
|
|
|
01fc30 |
*/
|
|
|
01fc30 |
static struct ipcs_table ipcs_table = { 0 };
|
|
|
01fc30 |
|
|
|
01fc30 |
-static void
|
|
|
01fc30 |
+void
|
|
|
01fc30 |
ipcs_init(void)
|
|
|
01fc30 |
{
|
|
|
01fc30 |
if (ipcs_table.init_flags & IPCS_INIT) {
|
|
|
01fc30 |
@@ -119,6 +117,7 @@ ipcs_init(void)
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(idr_layer_layer, "idr_layer", "layer");
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(idr_layer_ary, "idr_layer", "ary");
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(idr_top, "idr", "top");
|
|
|
01fc30 |
+ MEMBER_OFFSET_INIT(idr_cur, "idr", "cur");
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(ipc_id_ary_p, "ipc_id_ary", "p");
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(ipc_ids_entries, "ipc_ids", "entries");
|
|
|
01fc30 |
MEMBER_OFFSET_INIT(ipc_ids_max_id, "ipc_ids", "max_id");
|
|
|
01fc30 |
@@ -188,7 +187,10 @@ ipcs_init(void)
|
|
|
01fc30 |
ipcs_table.shm_f_op_huge_addr = -1;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
- if (BITS32())
|
|
|
01fc30 |
+ if (VALID_MEMBER(idr_layer_ary) &&
|
|
|
01fc30 |
+ get_array_length("idr_layer.ary", NULL, 0) > 64)
|
|
|
01fc30 |
+ ipcs_table.idr_bits = 8;
|
|
|
01fc30 |
+ else if (BITS32())
|
|
|
01fc30 |
ipcs_table.idr_bits = 5;
|
|
|
01fc30 |
else if (BITS64())
|
|
|
01fc30 |
ipcs_table.idr_bits = 6;
|
|
|
01fc30 |
@@ -635,7 +637,7 @@ ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(
|
|
|
01fc30 |
/*
|
|
|
01fc30 |
* search every idr_layer
|
|
|
01fc30 |
*/
|
|
|
01fc30 |
-static ulong
|
|
|
01fc30 |
+ulong
|
|
|
01fc30 |
idr_find(ulong idp, int id)
|
|
|
01fc30 |
{
|
|
|
01fc30 |
ulong idr_layer_p;
|
|
|
01fc30 |
diff --git a/symbols.c b/symbols.c
|
|
|
01fc30 |
index bf55319..8ff1430 100644
|
|
|
01fc30 |
--- a/symbols.c
|
|
|
01fc30 |
+++ b/symbols.c
|
|
|
01fc30 |
@@ -10041,6 +10041,8 @@ dump_offset_table(char *spec, ulong makestruct)
|
|
|
01fc30 |
OFFSET(idr_layers));
|
|
|
01fc30 |
fprintf(fp, " idr_top: %ld\n",
|
|
|
01fc30 |
OFFSET(idr_top));
|
|
|
01fc30 |
+ fprintf(fp, " idr_cur: %ld\n",
|
|
|
01fc30 |
+ OFFSET(idr_cur));
|
|
|
01fc30 |
fprintf(fp, " ipc_id_ary_p: %ld\n",
|
|
|
01fc30 |
OFFSET(ipc_id_ary_p));
|
|
|
01fc30 |
fprintf(fp, " ipc_ids_entries: %ld\n",
|