criu: parse information about BPF maps from procfs

This commit enables CRIU to:
(a) identify an anonymous inode as being a BPF map
(b) parse information about BPF maps from procfs

Source files modified:

* files.c - Checks anonymous inodes to see whether they are BPF maps.
If so, sets struct fdtype_ops *ops to a structure that knows how to
dump BPF maps

* proc_parse.c - Function parse_fdinfo_pid_s() now checks whether the
current file being processed is a BPF map. If so, it calls a newly
defined function parse_bpfmap() which knows how to parse information
about BPF maps from procfs

Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit is contained in:
Abhishek Vijeev 2020-07-24 17:18:32 +05:30 committed by Andrei Vagin
parent 4d5fc9fe5c
commit adf2da9bec
2 changed files with 68 additions and 0 deletions

View file

@ -48,6 +48,7 @@
#include "string.h"
#include "kerndat.h"
#include "fdstore.h"
#include "bpfmap.h"
#include "protobuf.h"
#include "util.h"
@ -539,6 +540,10 @@ static int dump_one_file(struct pid *pid, int fd, int lfd, struct fd_opts *opts,
ops = &signalfd_dump_ops;
else if (is_timerfd_link(link))
ops = &timerfd_dump_ops;
#ifdef CONFIG_HAS_LIBBPF
else if (is_bpfmap_link(link))
ops = &bpfmap_dump_ops;
#endif
else
return dump_unsupp_fd(&p, lfd, "anon", link, e);

View file

@ -1682,6 +1682,57 @@ nodata:
goto parse_err;
}
typedef struct bpfmap_fmt {
char *fmt;
void *value;
} bpfmap_fmt;
static int parse_bpfmap(struct bfd *f, char *str, BpfmapFileEntry *bpf)
{
/*
* Format is:
*
* uint32_t map_type
* uint32_t key_size
* uint32_t value_size
* uint32_t max_entries
* uint32_t map_flags
* uint64_t memlock
* uint32_t map_id
* boolean frozen
*/
bpfmap_fmt map[] = {
{"map_type: %u", &bpf->map_type },
{"key_size: %u", &bpf->key_size },
{"value_size: %u", &bpf->value_size },
{"max_entries: %u", &bpf->max_entries },
{"map_flags: %"PRIx32"", &bpf->map_flags },
{"memlock: %"PRIu64"", &bpf->memlock },
{"map_id: %u", &bpf->map_id },
{"frozen: %d", &bpf->frozen },
};
size_t n = sizeof(map) / sizeof(bpfmap_fmt);
int i;
for (i = 0; i < n; i++) {
if (sscanf(str, map[i].fmt, map[i].value) != 1)
return -1;
if (i == n - 1)
break;
str = breadline(f);
if (IS_ERR_OR_NULL(str)) {
pr_err("No data left in proc file while parsing bpfmap\n");
return -1;
}
}
return 0;
}
#define fdinfo_field(str, field) !strncmp(str, field":", sizeof(field))
static int parse_file_lock_buf(char *buf, struct file_lock *fl,
@ -2014,6 +2065,18 @@ static int parse_fdinfo_pid_s(int pid, int fd, int type, void *arg)
entry_met = true;
continue;
}
if (fdinfo_field(str, "map_type")) {
BpfmapFileEntry *bpf = arg;
if (type != FD_TYPES__BPFMAP)
goto parse_err;
ret = parse_bpfmap(&f, str, bpf);
if (ret)
goto parse_err;
entry_met = true;
continue;
}
}
exit_code = 0;