From patchwork Mon Sep 7 16:36:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1359103 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=isovalent.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=isovalent-com.20150623.gappssmtp.com header.i=@isovalent-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=Fk8rzZu7; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BlYx80mlXz9sR4 for ; Tue, 8 Sep 2020 02:42:52 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730964AbgIGQmu (ORCPT ); Mon, 7 Sep 2020 12:42:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730909AbgIGQgn (ORCPT ); Mon, 7 Sep 2020 12:36:43 -0400 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1631DC061575 for ; Mon, 7 Sep 2020 09:36:42 -0700 (PDT) Received: by mail-wr1-x442.google.com with SMTP id m6so16452585wrn.0 for ; Mon, 07 Sep 2020 09:36:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=w1o8W2B7Zhme6wXQ+MUTOwcBEeetzzjkb46yP9OL+9Y=; b=Fk8rzZu74dzkud4w0RH5Tq8dgt5syuBgJ0kA77yLP2SixiisbRuNRjUk45JBTd5v5G CLGr5Q4XC4pMMXQIAyhiaGdT/eWrEKRI2GTYCF9ACIklsxlw9fPHZgPhtKyvLQxmAPDt V1q5IKg8HvrMrX57Rns5CPXbWavAPn6a69nAmOmKZgnY5IW/s+56XQz/HDEwlb2RgQC2 4Byth4ZekzJneVL+6I1KZUPoBHZTtrIPt7+MzYX6GNcqGT/bn0DqHwCIbYi0aSkgC5xk bBKG7OpFwxUhkAO8th0nH+ZWoJh1I8PAlxykD3+6jKRSWfFzNA1fAPxFrXTEOqb5Rx7t GrEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=w1o8W2B7Zhme6wXQ+MUTOwcBEeetzzjkb46yP9OL+9Y=; b=Xk2aNWp15gfHjgzyROftP4ooienOHPw7fnzUW8n6M8wzOUjLbRTRbIDKv97GDO4iEc 9P6R0Od0nM+DeBwDaptmoenZLqwToEnkSbQEwgll+1LCqlsYGaLQiTIsbdW1AyQy8328 0IYt+hmpDz+0RFk+vdGIsE3AGLva1S1ClsZokDLa7F418wUbCh77vv/EO8Bk0LfxJtYS ihy0nZBG82Eu5sZfFfgAbh+RigpV2k/wZpbofULpmYiAwBuZCr1QUWEIPMQ1hn8rMmjv ts3Bcfv1+nU5n+Oaz5zWnKjsqY5gtXvTqaB1O0hMBtLXCCePq5/PG/C358YBBx0NjthS KkoA== X-Gm-Message-State: AOAM530JPMV6YlQq4CwXMX+nbLUd/9APfO58bjGvRkVPJsFiQ0kXcgtC STzfIihIdQYCpunOrsVaxFlTUA== X-Google-Smtp-Source: ABdhPJx/YhoGx9+d1gk+CLtrXEOer35LvJlBjS9IhQXG+fqw3H36DLFpDYSzCbtWr8BrBfgOJTg3nA== X-Received: by 2002:a5d:668b:: with SMTP id l11mr18448771wru.89.1599496601559; Mon, 07 Sep 2020 09:36:41 -0700 (PDT) Received: from localhost.localdomain ([194.35.119.17]) by smtp.gmail.com with ESMTPSA id p11sm26443677wma.11.2020.09.07.09.36.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Sep 2020 09:36:40 -0700 (PDT) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, Andrii Nakryiko , Quentin Monnet Subject: [PATCH bpf-next v2 1/2] tools: bpftool: clean up function to dump map entry Date: Mon, 7 Sep 2020 17:36:33 +0100 Message-Id: <20200907163634.27469-2-quentin@isovalent.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200907163634.27469-1-quentin@isovalent.com> References: <20200907163634.27469-1-quentin@isovalent.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The function used to dump a map entry in bpftool is a bit difficult to follow, as a consequence to earlier refactorings. There is a variable ("num_elems") which does not appear to be necessary, and the error handling would look cleaner if moved to its own function. Let's clean it up. No functional change. v2: - v1 was erroneously removing the check on fd maps in an attempt to get support for outer map dumps. This is already working. Instead, v2 focuses on cleaning up the dump_map_elem() function, to avoid similar confusion in the future. Signed-off-by: Quentin Monnet --- tools/bpf/bpftool/map.c | 101 +++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index bc0071228f88..c8159cb4fb1e 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -213,8 +213,9 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key, jsonw_end_object(json_wtr); } -static void print_entry_error(struct bpf_map_info *info, unsigned char *key, - const char *error_msg) +static void +print_entry_error_msg(struct bpf_map_info *info, unsigned char *key, + const char *error_msg) { int msg_size = strlen(error_msg); bool single_line, break_names; @@ -232,6 +233,40 @@ static void print_entry_error(struct bpf_map_info *info, unsigned char *key, printf("\n"); } +static void +print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno) +{ + /* For prog_array maps or arrays of maps, failure to lookup the value + * means there is no entry for that key. Do not print an error message + * in that case. + */ + if (map_is_map_of_maps(map_info->type) || + map_is_map_of_progs(map_info->type)) + return; + + if (json_output) { + jsonw_start_object(json_wtr); /* entry */ + jsonw_name(json_wtr, "key"); + print_hex_data_json(key, map_info->key_size); + jsonw_name(json_wtr, "value"); + jsonw_start_object(json_wtr); /* error */ + jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); + jsonw_end_object(json_wtr); /* error */ + jsonw_end_object(json_wtr); /* entry */ + } else { + const char *msg = NULL; + + if (lookup_errno == ENOENT) + msg = ""; + else if (lookup_errno == ENOSPC && + map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) + msg = ""; + + print_entry_error_msg(map_info, key, + msg ? : strerror(lookup_errno)); + } +} + static void print_entry_plain(struct bpf_map_info *info, unsigned char *key, unsigned char *value) { @@ -713,56 +748,23 @@ static int dump_map_elem(int fd, void *key, void *value, struct bpf_map_info *map_info, struct btf *btf, json_writer_t *btf_wtr) { - int num_elems = 0; - int lookup_errno; - - if (!bpf_map_lookup_elem(fd, key, value)) { - if (json_output) { - print_entry_json(map_info, key, value, btf); - } else { - if (btf) { - struct btf_dumper d = { - .btf = btf, - .jw = btf_wtr, - .is_plain_text = true, - }; - - do_dump_btf(&d, map_info, key, value); - } else { - print_entry_plain(map_info, key, value); - } - num_elems++; - } - return num_elems; + if (bpf_map_lookup_elem(fd, key, value)) { + print_entry_error(map_info, key, errno); + return -1; } - /* lookup error handling */ - lookup_errno = errno; - - if (map_is_map_of_maps(map_info->type) || - map_is_map_of_progs(map_info->type)) - return 0; - if (json_output) { - jsonw_start_object(json_wtr); - jsonw_name(json_wtr, "key"); - print_hex_data_json(key, map_info->key_size); - jsonw_name(json_wtr, "value"); - jsonw_start_object(json_wtr); - jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); - jsonw_end_object(json_wtr); - jsonw_end_object(json_wtr); - } else { - const char *msg = NULL; - - if (lookup_errno == ENOENT) - msg = ""; - else if (lookup_errno == ENOSPC && - map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) - msg = ""; + print_entry_json(map_info, key, value, btf); + } else if (btf) { + struct btf_dumper d = { + .btf = btf, + .jw = btf_wtr, + .is_plain_text = true, + }; - print_entry_error(map_info, key, - msg ? : strerror(lookup_errno)); + do_dump_btf(&d, map_info, key, value); + } else { + print_entry_plain(map_info, key, value); } return 0; @@ -873,7 +875,8 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, err = 0; break; } - num_elems += dump_map_elem(fd, key, value, info, btf, wtr); + if (!dump_map_elem(fd, key, value, info, btf, wtr)) + num_elems++; prev_key = key; } From patchwork Mon Sep 7 16:36:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1359082 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=isovalent.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=isovalent-com.20150623.gappssmtp.com header.i=@isovalent-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=LzeUHCuP; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BlYpp5lbJz9sRK for ; Tue, 8 Sep 2020 02:37:22 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730914AbgIGQgz (ORCPT ); Mon, 7 Sep 2020 12:36:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730517AbgIGQgp (ORCPT ); Mon, 7 Sep 2020 12:36:45 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCF74C061573 for ; Mon, 7 Sep 2020 09:36:44 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id x23so4974061wmi.3 for ; Mon, 07 Sep 2020 09:36:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WYfb4HWcJBJMQdB3pqwUW7b6FRg6vrPe0DE1icCl/CA=; b=LzeUHCuPZgMZRfyTCiGhiPj0Iflpe7PNnruPAN6w9rHEYIgOofCgNsdottEDdUZzzx v/3N/z9QhGEzjWwnnKEqg2yuQhCAcmfNPd3T5Nb7/gdcmoLt28bhjz9L1Z+ZnueZ5pQy iEUrx/9VJ8m2qX5lCYxk634Sq9sDLqPGx9bV8usWHXuZiP5Jc++p3W4bkeJ6YVcGg1aN fRExS71wkvoWj5cYfjbUXefTIllrBfeECeQuwaKCbf+Rk1uNmurp9dUaLyDEwpX2IZuQ KcEn9APPEJFSMQq3ZIOd88E81HeovixVVvsaNsBGCT3E2IPNTkA8W6yI1wPSXueLaQZ8 R7xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WYfb4HWcJBJMQdB3pqwUW7b6FRg6vrPe0DE1icCl/CA=; b=KCwiW7N+FcWAy4GGAcFI9r4Sdpt0LX3dMwAOoCzAFbN63Rvo0TfooPEeNXQbnimtMH ibwA1DUVrokOSkQTgFkEtbrNOjkqkrNNvYCVwLpAgwhyC+jXPbw+kkWVVfnp7PnSVZBw iUj74otZ/jjuaLllI7FUEcr3rq1iij6tT27UAhWcKq9LzKkHxpVllF0PtCwU+sF4uduk 9OIWMckcWTu1G/67WsbbQJntn3ap4v10VmUBYaIHjz9DhL3KpblvTbesAqluVD4Zu1Ks qyrR6jAbm9OAC8kz4YImkZAm3QWvk3ueR6Od1vfDFyNWvTQ7kZMglSr+3s7ACHyvlAf9 5fVA== X-Gm-Message-State: AOAM531x62wfG8XLHK/hrGzEptAvfACmDaSlzFa8xTMXkyzldA2F3EAU zOBxStIJ+5czO9tBOTeB1Mh+mg== X-Google-Smtp-Source: ABdhPJxgf3Ms4f6Cfdx5mGCULGYbEwJdDPdE2IxsiiANVmfaw0JFm5LRMCB3noqsG9vKJF8bqxJ+hg== X-Received: by 2002:a1c:234d:: with SMTP id j74mr125626wmj.157.1599496602801; Mon, 07 Sep 2020 09:36:42 -0700 (PDT) Received: from localhost.localdomain ([194.35.119.17]) by smtp.gmail.com with ESMTPSA id p11sm26443677wma.11.2020.09.07.09.36.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Sep 2020 09:36:42 -0700 (PDT) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, Andrii Nakryiko , Quentin Monnet , Andrii Nakryiko Subject: [PATCH bpf-next v2 2/2] tools: bpftool: add "inner_map" to "bpftool map create" outer maps Date: Mon, 7 Sep 2020 17:36:34 +0100 Message-Id: <20200907163634.27469-3-quentin@isovalent.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200907163634.27469-1-quentin@isovalent.com> References: <20200907163634.27469-1-quentin@isovalent.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org There is no support for creating maps of types array-of-map or hash-of-map in bpftool. This is because the kernel needs an inner_map_fd to collect metadata on the inner maps to be supported by the new map, but bpftool does not provide a way to pass this file descriptor. Add a new optional "inner_map" keyword that can be used to pass a reference to a map, retrieve a fd to that map, and pass it as the inner_map_fd. Add related documentation and bash completion. Note that we can reference the inner map by its name, meaning we can have several times the keyword "name" with different meanings (mandatory outer map name, and possibly a name to use to find the inner_map_fd). The bash completion will offer it just once, and will not suggest "name" on the following command: # bpftool map create /sys/fs/bpf/my_outer_map type hash_of_maps \ inner_map name my_inner_map [TAB] Fixing that specific case seems too convoluted. Completion will work as expected, however, if the outer map name comes first and the "inner_map name ..." is passed second. Signed-off-by: Quentin Monnet Acked-by: Andrii Nakryiko --- .../bpf/bpftool/Documentation/bpftool-map.rst | 10 +++- tools/bpf/bpftool/bash-completion/bpftool | 22 ++++++++- tools/bpf/bpftool/map.c | 48 +++++++++++++------ 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 083db6c2fc67..ca9d62d7e0bd 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -23,7 +23,8 @@ MAP COMMANDS | **bpftool** **map** { **show** | **list** } [*MAP*] | **bpftool** **map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* \ -| **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**dev** *NAME*] +| **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**inner_map** *MAP*] \ +| [**dev** *NAME*] | **bpftool** **map dump** *MAP* | **bpftool** **map update** *MAP* [**key** *DATA*] [**value** *VALUE*] [*UPDATE_FLAGS*] | **bpftool** **map lookup** *MAP* [**key** *DATA*] @@ -67,7 +68,7 @@ DESCRIPTION maps. On such kernels bpftool will automatically emit this information as well. - **bpftool map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**dev** *NAME*] + **bpftool map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**inner_map** *MAP*] [**dev** *NAME*] Create a new map with given parameters and pin it to *bpffs* as *FILE*. @@ -75,6 +76,11 @@ DESCRIPTION desired flags, e.g. 1024 for **BPF_F_MMAPABLE** (see bpf.h UAPI header for existing flags). + To create maps of type array-of-maps or hash-of-maps, the + **inner_map** keyword must be used to pass an inner map. The + kernel needs it to collect metadata related to the inner maps + that the new map will work with. + Keyword **dev** expects a network interface name, and is used to request hardware offload for the map. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 7b68e3c0a5fb..3f1da30c4da6 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -709,9 +709,26 @@ _bpftool() "$cur" ) ) return 0 ;; - key|value|flags|name|entries) + key|value|flags|entries) return 0 ;; + inner_map) + COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) + return 0 + ;; + id) + _bpftool_get_map_ids + ;; + name) + case $pprev in + inner_map) + _bpftool_get_map_names + ;; + *) + return 0 + ;; + esac + ;; *) _bpftool_once_attr 'type' _bpftool_once_attr 'key' @@ -719,6 +736,9 @@ _bpftool() _bpftool_once_attr 'entries' _bpftool_once_attr 'name' _bpftool_once_attr 'flags' + if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then + _bpftool_once_attr 'inner_map' + fi _bpftool_once_attr 'dev' return 0 ;; diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index c8159cb4fb1e..7370fdd57de3 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -1250,7 +1250,7 @@ static int do_create(int argc, char **argv) { struct bpf_create_map_attr attr = { NULL, }; const char *pinfile; - int err, fd; + int err = -1, fd; if (!REQ_ARGS(7)) return -1; @@ -1265,13 +1265,13 @@ static int do_create(int argc, char **argv) if (attr.map_type) { p_err("map type already specified"); - return -1; + goto exit; } attr.map_type = map_type_from_str(*argv); if ((int)attr.map_type < 0) { p_err("unrecognized map type: %s", *argv); - return -1; + goto exit; } NEXT_ARG(); } else if (is_prefix(*argv, "name")) { @@ -1280,43 +1280,56 @@ static int do_create(int argc, char **argv) } else if (is_prefix(*argv, "key")) { if (parse_u32_arg(&argc, &argv, &attr.key_size, "key size")) - return -1; + goto exit; } else if (is_prefix(*argv, "value")) { if (parse_u32_arg(&argc, &argv, &attr.value_size, "value size")) - return -1; + goto exit; } else if (is_prefix(*argv, "entries")) { if (parse_u32_arg(&argc, &argv, &attr.max_entries, "max entries")) - return -1; + goto exit; } else if (is_prefix(*argv, "flags")) { if (parse_u32_arg(&argc, &argv, &attr.map_flags, "flags")) - return -1; + goto exit; } else if (is_prefix(*argv, "dev")) { NEXT_ARG(); if (attr.map_ifindex) { p_err("offload device already specified"); - return -1; + goto exit; } attr.map_ifindex = if_nametoindex(*argv); if (!attr.map_ifindex) { p_err("unrecognized netdevice '%s': %s", *argv, strerror(errno)); - return -1; + goto exit; } NEXT_ARG(); + } else if (is_prefix(*argv, "inner_map")) { + struct bpf_map_info info = {}; + __u32 len = sizeof(info); + int inner_map_fd; + + NEXT_ARG(); + if (!REQ_ARGS(2)) + usage(); + inner_map_fd = map_parse_fd_and_info(&argc, &argv, + &info, &len); + if (inner_map_fd < 0) + return -1; + attr.inner_map_fd = inner_map_fd; } else { p_err("unknown arg %s", *argv); - return -1; + goto exit; } } if (!attr.name) { p_err("map name not specified"); - return -1; + goto exit; } set_max_rlimit(); @@ -1324,17 +1337,22 @@ static int do_create(int argc, char **argv) fd = bpf_create_map_xattr(&attr); if (fd < 0) { p_err("map create failed: %s", strerror(errno)); - return -1; + goto exit; } err = do_pin_fd(fd, pinfile); close(fd); if (err) - return err; + goto exit; if (json_output) jsonw_null(json_wtr); - return 0; + +exit: + if (attr.inner_map_fd > 0) + close(attr.inner_map_fd); + + return err; } static int do_pop_dequeue(int argc, char **argv) @@ -1420,7 +1438,7 @@ static int do_help(int argc, char **argv) "Usage: %1$s %2$s { show | list } [MAP]\n" " %1$s %2$s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n" " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n" - " [dev NAME]\n" + " [inner_map MAP] [dev NAME]\n" " %1$s %2$s dump MAP\n" " %1$s %2$s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n" " %1$s %2$s lookup MAP [key DATA]\n"