mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-21 17:37:39 +00:00
bpfmap: handle new field in fdinfo
Starting with Linux Kernel release 5.16 the fdinfo proc entry contains a map_extra field which breaks CRIU parsing of bpfmap entries. This commit adds the map_extra as a possible field to CRIU. The value of map_extra is not passed to the kernel on restore as it does not seem to be evaluated in the code paths CRIU restore is using for BPF. This fixes CRIU CI using Fedora with 5.16. See Linux commit 9330986c03006ab1d33d243b7cfe598a7a3c1baa "bpf: Add bloom filter map implementation" Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
parent
56df8aeeb5
commit
247cdc90db
@ -292,6 +292,9 @@ static int bpfmap_open(struct file_desc *d, int *new_fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bpfe->has_map_extra && bpfe->map_extra)
|
||||
pr_warn("bpfmap map_extra has non-zero value. This will not be restored.\n");
|
||||
|
||||
if (restore_bpfmap_data(bpfmap_fd, bpfe->map_id, bpfmap_data_hash_table))
|
||||
return -1;
|
||||
|
||||
|
@ -1772,6 +1772,12 @@ nodata:
|
||||
typedef struct bpfmap_fmt {
|
||||
char *fmt;
|
||||
void *value;
|
||||
/*
|
||||
* If newer kernels are adding additional entries, these entries need
|
||||
* to be marked as optional in the protobuf definition and the parsing
|
||||
* must be able to ignore it if running on an older kernel.
|
||||
*/
|
||||
protobuf_c_boolean *optional;
|
||||
} bpfmap_fmt;
|
||||
|
||||
static int parse_bpfmap(struct bfd *f, char *str, BpfmapFileEntry *bpf)
|
||||
@ -1784,27 +1790,36 @@ static int parse_bpfmap(struct bfd *f, char *str, BpfmapFileEntry *bpf)
|
||||
* uint32_t value_size
|
||||
* uint32_t max_entries
|
||||
* uint32_t map_flags
|
||||
* uint64_t map_extra
|
||||
* uint64_t memlock
|
||||
* uint32_t map_id
|
||||
* boolean frozen
|
||||
*/
|
||||
|
||||
/* This needs to be in the same order as in the fdinfo entry. */
|
||||
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 },
|
||||
{ "map_type: %u", &bpf->map_type, NULL },
|
||||
{ "key_size: %u", &bpf->key_size, NULL },
|
||||
{ "value_size: %u", &bpf->value_size, NULL },
|
||||
{ "max_entries: %u", &bpf->max_entries, NULL },
|
||||
{ "map_flags: %" PRIx32 "", &bpf->map_flags, NULL },
|
||||
{ "map_extra: %" PRIx64 "", &bpf->map_extra, &bpf->has_map_extra },
|
||||
{ "memlock: %" PRIu64 "", &bpf->memlock, NULL },
|
||||
{ "map_id: %u", &bpf->map_id, NULL },
|
||||
{ "frozen: %d", &bpf->frozen, NULL },
|
||||
};
|
||||
|
||||
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)
|
||||
bool parsing_failed = false;
|
||||
if (sscanf(str, map[i].fmt, map[i].value) != 1) {
|
||||
parsing_failed = true;
|
||||
}
|
||||
if (map[i].optional && !parsing_failed)
|
||||
*map[i].optional = true;
|
||||
if (!map[i].optional && parsing_failed)
|
||||
return -1;
|
||||
|
||||
if (i == n - 1)
|
||||
@ -1817,6 +1832,9 @@ static int parse_bpfmap(struct bfd *f, char *str, BpfmapFileEntry *bpf)
|
||||
}
|
||||
}
|
||||
|
||||
if (bpf->has_map_extra && bpf->map_extra)
|
||||
pr_warn("Non-zero value for fdinfo map_extra entry found. This will not be restored.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,4 +21,5 @@ message bpfmap_file_entry {
|
||||
required string map_name = 13;
|
||||
required uint32 ifindex = 14 [default = 0];
|
||||
optional sint32 mnt_id = 15 [default = -1];
|
||||
optional uint64 map_extra = 16;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user