All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Fastabend <john.fastabend@gmail.com>
To: bpf@vger.kernel.org
Cc: john.fastabend@gmail.com, daniel@iogearbox.net
Subject: [PATCH bpf-next 1/2] libbpf: add bpf_map__reuse_fd_from_loader_ctx() to allow shared maps
Date: Fri, 26 Jun 2026 14:51:12 -0700	[thread overview]
Message-ID: <20260626215113.52273-1-john.fastabend@gmail.com> (raw)

This lets the gen_loader use a map that may already be loaded/pinned on
the target system. When we are loading many signed programs on the target
we often need them to share maps to communicate/pass data between the
programs.

Note it is slightly complicated by needing to ensure on error/close that
we only emit_sys_close_blob() for map ids that are not these shared
type otherwise we could close a shared map unintentionally. To track this
we added a borrowed_fd_array.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
 tools/lib/bpf/bpf_gen_internal.h |  2 ++
 tools/lib/bpf/gen_loader.c       | 50 ++++++++++++++++++++++++++++++--
 tools/lib/bpf/libbpf.c           | 11 +++++++
 tools/lib/bpf/libbpf.h           |  1 +
 tools/lib/bpf/libbpf.map         |  1 +
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/tools/lib/bpf/bpf_gen_internal.h b/tools/lib/bpf/bpf_gen_internal.h
index 49af4260b8e6..e555c3165105 100644
--- a/tools/lib/bpf/bpf_gen_internal.h
+++ b/tools/lib/bpf/bpf_gen_internal.h
@@ -50,6 +50,7 @@ struct bpf_gen {
 	struct ksym_desc *ksyms;
 	__u32 nr_ksyms;
 	int fd_array;
+	int borrowed_fd_array;
 	int nr_fd_array;
 	int hash_insn_offset[SHA256_DWORD_SIZE];
 };
@@ -62,6 +63,7 @@ void bpf_gen__map_create(struct bpf_gen *gen,
 			 enum bpf_map_type map_type, const char *map_name,
 			 __u32 key_size, __u32 value_size, __u32 max_entries,
 			 struct bpf_map_create_opts *map_attr, int map_idx);
+void bpf_gen__map_reuse_fd(struct bpf_gen *gen, int map_idx);
 void bpf_gen__prog_load(struct bpf_gen *gen,
 			enum bpf_prog_type prog_type, const char *prog_name,
 			const char *license, struct bpf_insn *insns, size_t insn_cnt,
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index c7f2d2ac7bb3..1cb00e0244b5 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -47,6 +47,11 @@ static int blob_fd_array_off(struct bpf_gen *gen, int index)
 	return gen->fd_array + index * sizeof(int);
 }
 
+static int blob_borrowed_fd_array_off(struct bpf_gen *gen, int index)
+{
+	return gen->borrowed_fd_array + index * sizeof(int);
+}
+
 static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
 {
 	size_t off = gen->insn_cur - gen->insn_start;
@@ -111,6 +116,7 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in
 
 static int add_data(struct bpf_gen *gen, const void *data, __u32 size);
 static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off);
+static void emit_sys_close_owned_blob(struct bpf_gen *gen, int map_idx);
 static void emit_signature_match(struct bpf_gen *gen);
 
 void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)
@@ -119,6 +125,7 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps
 	int i;
 
 	gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
+	gen->borrowed_fd_array = add_data(gen, NULL, nr_maps * sizeof(int));
 	gen->log_level = log_level;
 	/* save ctx pointer into R6 */
 	emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
@@ -137,9 +144,10 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps
 			      /* size of cleanup code below (including map fd cleanup) */
 			      (nr_progs_sz / 4) * 3 + 2 +
 			      /* 6 insns for emit_sys_close_blob,
+			       * 4 insns for borrowed fd check,
 			       * 6 insns for debug_regs in emit_sys_close_blob
 			       */
-			      nr_maps * (6 + (gen->log_level ? 6 : 0))));
+			      nr_maps * (10 + (gen->log_level ? 6 : 0))));
 
 	/* remember the label where all error branches will jump to */
 	gen->cleanup_label = gen->insn_cur - gen->insn_start;
@@ -150,7 +158,7 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps
 		emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
 	}
 	for (i = 0; i < nr_maps; i++)
-		emit_sys_close_blob(gen, blob_fd_array_off(gen, i));
+		emit_sys_close_owned_blob(gen, i);
 	/* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
 	emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
 	emit(gen, BPF_EXIT_INSN());
@@ -377,6 +385,17 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
 	__emit_sys_close(gen);
 }
 
+static void emit_sys_close_owned_blob(struct bpf_gen *gen, int map_idx)
+{
+	int close_insn_cnt = 6 + (gen->log_level ? 6 : 0);
+
+	emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
+					 0, 0, 0, blob_borrowed_fd_array_off(gen, map_idx)));
+	emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0));
+	emit(gen, BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, close_insn_cnt));
+	emit_sys_close_blob(gen, blob_fd_array_off(gen, map_idx));
+}
+
 static void compute_sha_update_offsets(struct bpf_gen *gen);
 
 int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
@@ -460,6 +479,11 @@ void bpf_gen__free(struct bpf_gen *gen)
 	_val;							\
 })
 
+static void set_blob_borrowed_fd_array_off(struct bpf_gen *gen, int index)
+{
+	*(__u32 *)(gen->data_start + blob_borrowed_fd_array_off(gen, index)) = tgt_endian(1);
+}
+
 static void compute_sha_update_offsets(struct bpf_gen *gen)
 {
 	__u64 sha[SHA256_DWORD_SIZE];
@@ -596,6 +620,28 @@ void bpf_gen__map_create(struct bpf_gen *gen,
 		emit_sys_close_stack(gen, stack_off(inner_map_fd));
 }
 
+void bpf_gen__map_reuse_fd(struct bpf_gen *gen, int map_idx)
+{
+	int idx;
+
+	if (map_idx != gen->nr_maps) {
+		gen->error = -EDOM;
+		return;
+	}
+
+	idx = add_map_fd(gen);
+	if (gen->error)
+		return;
+
+	set_blob_borrowed_fd_array_off(gen, idx);
+	move_ctx2blob(gen, blob_fd_array_off(gen, idx), 4,
+		      sizeof(struct bpf_loader_ctx) +
+		      sizeof(struct bpf_map_desc) * map_idx +
+		      offsetof(struct bpf_map_desc, map_fd),
+		      false);
+	pr_debug("gen: map_reuse_fd idx %d\n", map_idx);
+}
+
 static void emit_signature_match(struct bpf_gen *gen)
 {
 	__s64 off;
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 7162146280a8..af1553e9d4df 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5085,6 +5085,15 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd)
 	return libbpf_err(err);
 }
 
+int bpf_map__reuse_fd_from_loader_ctx(struct bpf_map *map)
+{
+	if (map_is_created(map))
+		return libbpf_err(-EBUSY);
+
+	map->reused = true;
+	return 0;
+}
+
 __u32 bpf_map__max_entries(const struct bpf_map *map)
 {
 	return map->def.max_entries;
@@ -5659,6 +5668,8 @@ bpf_object__create_maps(struct bpf_object *obj)
 		}
 
 		if (map->reused) {
+			if (obj->gen_loader)
+				bpf_gen__map_reuse_fd(obj->gen_loader, map - obj->maps);
 			pr_debug("map '%s': skipping creation (preset fd=%d)\n",
 				 map->name, map->fd);
 		} else {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index b965ad571540..4145a16c8963 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -1135,6 +1135,7 @@ LIBBPF_API bool bpf_map__autoattach(const struct bpf_map *map);
  */
 LIBBPF_API int bpf_map__fd(const struct bpf_map *map);
 LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
+LIBBPF_API int bpf_map__reuse_fd_from_loader_ctx(struct bpf_map *map);
 /* get map name */
 LIBBPF_API const char *bpf_map__name(const struct bpf_map *map);
 /* get/set map type */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index b731df19ae69..d6c2f1d75cda 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -458,6 +458,7 @@ LIBBPF_1.7.0 {
 
 LIBBPF_1.8.0 {
 	global:
+		bpf_map__reuse_fd_from_loader_ctx;
 		bpf_program__attach_tracing_multi;
 		bpf_program__clone;
 		btf__new_empty_opts;
-- 
2.53.0


             reply	other threads:[~2026-06-26 21:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-26 21:51 John Fastabend [this message]
2026-06-26 21:51 ` [PATCH bpf-next 2/2] libbpf: selftest for bpf_map__reuse_fd_from_loader_ctx() John Fastabend

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260626215113.52273-1-john.fastabend@gmail.com \
    --to=john.fastabend@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.