"bpftool map dump" walks the map with bpf_map_get_next_key() and treats ENOENT as the end of the map. Map types that can't be iterated fail that call on the very first key: local storage and ringbuf with ENOTSUPP, bloom filter and arena with EOPNOTSUPP, queue and stack with EINVAL. bpftool then ends the walk without a word and prints what it prints for an empty map, "[]" with BTF or "Found 0 elements" without, and only the exit status tells that the map was not read. On a socket storage map that holds storage for a socket: # bpftool map dump pinned /sys/fs/bpf/sk_storage [] Ask for the first key before printing anything, and when that fails with anything but ENOENT, fail with the map type and the error instead of a dump: # bpftool map dump pinned /sys/fs/bpf/sk_storage Error: can't dump sk_storage map: Unknown error 524 # bpftool -j map dump pinned /sys/fs/bpf/sk_storage {"error":"can't dump sk_storage map: Unknown error 524"} An error later in the walk is now reported too, as "bpftool map getnext" reports it, and the element count is printed only after a complete walk. Assisted-by: LLM Signed-off-by: Maxim Skokov Acked-by: Quentin Monnet --- tools/bpf/bpftool/map.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 20d59eab09a1..b7f62fcbb6fc 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -856,6 +856,22 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, } } + /* Fail early to avoid an empty dump if map type cannot be iterated */ + if (bpf_map_get_next_key(fd, NULL, key) && errno != ENOENT) { + const char *map_type_str; + int saved_errno = errno; + + map_type_str = libbpf_bpf_map_type_str(info->type); + if (map_type_str) + p_err("can't dump %s map: %s", map_type_str, + strerror(saved_errno)); + else + p_err("can't dump map of type %u: %s", info->type, + strerror(saved_errno)); + err = -1; + goto exit_free; + } + if (wtr) { err = get_map_kv_btf(info, &btf); if (err) { @@ -883,8 +899,11 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, while (true) { err = bpf_map_get_next_key(fd, prev_key, key); if (err) { - if (errno == ENOENT) + if (errno == ENOENT) { err = 0; + break; + } + p_err("can't get next key: %s", strerror(errno)); break; } if (!dump_map_elem(fd, key, value, info, btf, wtr, @@ -897,7 +916,7 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, jsonw_end_array(wtr); /* elements */ if (show_header) jsonw_end_object(wtr); /* map object */ - } else { + } else if (!err) { printf("Found %u element%s\n", num_elems, num_elems != 1 ? "s" : ""); } -- 2.47.3