* [PATCH 10/20] libdtrace: retain descriptors for cached module BTF IDs
@ 2026-10-30 19:36 Kris Van Hees
2026-11-06 12:59 ` Nix
0 siblings, 1 reply; 3+ messages in thread
From: Kris Van Hees @ 2026-10-30 19:36 UTC (permalink / raw)
To: dtrace, dtrace-devel
---
libdtrace/dt_btf.c | 79 ++++++++++++++++++++++++++++++--
libdtrace/dt_impl.h | 1 +
libdtrace/dt_open.c | 1 +
test/triggers/module-discovery.c | 11 +++++
4 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
index 617b0128..727e5f54 100644
--- a/libdtrace/dt_btf.c
+++ b/libdtrace/dt_btf.c
@@ -1479,17 +1479,67 @@ dt_btf_lookup_name_kind(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name,
return id;
}
+/*
+ * Retain a descriptor as well as the ID: otherwise an unloaded object's ID
+ * could be reused and a later enumeration could mistake it for a cached one.
+ * Only IDs assigned to modules are retained, bounding descriptor use by the
+ * number of modules discovered by this handle.
+ */
+typedef struct dt_btf_id {
+ dt_hentry_t he;
+ uint32_t id;
+ int fd;
+} dt_btf_id_t;
+
+static uint32_t
+dt_btf_id_hval(const dt_btf_id_t *entry)
+{
+ return entry->id;
+}
+
+static int
+dt_btf_id_cmp(const dt_btf_id_t *a, const dt_btf_id_t *b)
+{
+ return a->id != b->id;
+}
+
+DEFINE_HE_STD_LINK_FUNCS(dt_btf_id, dt_btf_id_t, he)
+
+static void *
+dt_btf_id_release(dt_btf_id_t *head, dt_btf_id_t *entry)
+{
+ head = dt_btf_id_del(head, entry);
+ close(entry->fd);
+ free(entry);
+ return head;
+}
+
+static dt_htab_ops_t dt_btf_id_ops = {
+ .hval = (htab_hval_fn)dt_btf_id_hval,
+ .cmp = (htab_cmp_fn)dt_btf_id_cmp,
+ .add = (htab_add_fn)dt_btf_id_add,
+ .del = (htab_del_fn)dt_btf_id_release,
+ .next = (htab_next_fn)dt_btf_id_next
+};
+
int
dt_btf_get_module_ids(dtrace_hdl_t *dtp)
{
uint32_t id = 0;
+ if (dtp->dt_btf_ids == NULL) {
+ dtp->dt_btf_ids = dt_htab_create(&dt_btf_id_ops);
+ if (dtp->dt_btf_ids == NULL)
+ return dt_set_errno(dtp, EDT_NOMEM);
+ }
+
for (;;) {
int rc, fd;
btf_info_t info;
char name[PATH_MAX];
uint32_t size = sizeof(info);
dt_module_t *dmp;
+ dt_btf_id_t tmpl, *entry;
rc = dt_bpf_btf_get_next_id(id, &id);
if (rc) {
@@ -1501,6 +1551,10 @@ dt_btf_get_module_ids(dtrace_hdl_t *dtp)
return dt_set_errno(dtp, errno);
}
+ tmpl.id = id;
+ if (dt_htab_lookup(dtp->dt_btf_ids, &tmpl) != NULL)
+ continue;
+
fd = dt_bpf_btf_get_fd_by_id(id);
if (fd < 0) {
if (errno == ENOENT)
@@ -1513,14 +1567,31 @@ dt_btf_get_module_ids(dtrace_hdl_t *dtp)
info.name = (uint64_t)name;
info.name_len = sizeof(name);
rc = dt_bpf_btf_get_info_by_fd(fd, &info, &size);
- close(fd);
- if (rc)
- return dt_set_errno(dtp, errno);
+ if (rc) {
+ int err = errno;
+
+ close(fd);
+ return dt_set_errno(dtp, err);
+ }
dmp = dt_module_lookup_by_name(dtp, name);
- if (dmp == NULL || dmp->dm_btf_id != 0)
+ if (!info.kernel_btf || dmp == NULL || dmp->dm_btf_id != 0) {
+ close(fd);
continue;
+ }
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ close(fd);
+ return dt_set_errno(dtp, EDT_NOMEM);
+ }
+ entry->id = id;
+ entry->fd = fd;
+ if (dt_htab_insert(dtp->dt_btf_ids, entry) != 0) {
+ close(fd);
+ free(entry);
+ return dt_set_errno(dtp, EDT_NOMEM);
+ }
dmp->dm_btf_id = id;
}
}
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index f89ce2bc..972fceaf 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -314,6 +314,7 @@ struct dtrace_hdl {
ctf_archive_t *dt_ctfa; /* ctf archive for the entire kernel tree */
void *dt_ctfa_data; /* backing data for dt_ctfa */
char *dt_btf_path; /* path to vmlinux.btf */
+ dt_htab_t *dt_btf_ids; /* retained module BTF IDs and descriptors */
dt_htab_t *dt_kernpaths; /* hash table of dt_kern_path_t's */
dt_module_t *dt_exec; /* pointer to executable module */
dt_module_t *dt_cdefs; /* pointer to C dynamic type module */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 245ccb70..8291b87d 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1313,6 +1313,7 @@ dtrace_close(dtrace_hdl_t *dtp)
dtp->dt_kernsyms = NULL;
dt_htab_destroy(dtp->dt_mods);
dt_htab_destroy(dtp->dt_kernpaths);
+ dt_htab_destroy(dtp->dt_btf_ids);
if (dtp->dt_ctfa != NULL)
ctf_arc_close(dtp->dt_ctfa);
diff --git a/test/triggers/module-discovery.c b/test/triggers/module-discovery.c
index 0b09ae2b..d05d2bab 100644
--- a/test/triggers/module-discovery.c
+++ b/test/triggers/module-discovery.c
@@ -22,6 +22,7 @@
static const char *symbols;
static int kallsyms;
static uint32_t btf_generation, btf_id;
+static int btf_queries;
extern FILE *__real_fopen64(const char *, const char *);
@@ -78,6 +79,8 @@ __wrap_dt_bpf_btf_get_info_by_fd(int fd, btf_info_t *info, uint32_t *size)
if (symbols == NULL)
return __real_dt_bpf_btf_get_info_by_fd(fd, info, size);
+ btf_queries++;
+ info->kernel_btf = 1;
snprintf((char *)(uintptr_t)info->name, info->name_len, "%s",
names[btf_id - btf_generation - 1]);
return 0;
@@ -171,6 +174,14 @@ check_discovery(int fallback)
}
CHECK(count == 2 && found_first == 1 && found_second == 1);
+ /* Cached IDs are pinned; enumeration only queries unassigned reload IDs. */
+ btf_queries = 0;
+ CHECK(dtrace_update(dtp) == 0);
+ CHECK(btf_queries == 2);
+ btf_queries = 0;
+ CHECK(dtrace_update(dtp) == 0);
+ CHECK(btf_queries == 2);
+
/* Disappearance and reappearance at a new address do not replace metadata. */
for (i = 0; i < 4; i++) {
symbols = i % 2 == 0 ? "" : fallback ?
--
2.52.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 10/20] libdtrace: retain descriptors for cached module BTF IDs
2026-10-30 19:36 [PATCH 10/20] libdtrace: retain descriptors for cached module BTF IDs Kris Van Hees
@ 2026-11-06 12:59 ` Nix
2026-11-07 15:59 ` Kris Van Hees
0 siblings, 1 reply; 3+ messages in thread
From: Nix @ 2026-11-06 12:59 UTC (permalink / raw)
To: Kris Van Hees; +Cc: dtrace, dtrace-devel
On 30 Oct 2026, Kris Van Hees outgrape:
> ---
> libdtrace/dt_btf.c | 79 ++++++++++++++++++++++++++++++--
> libdtrace/dt_impl.h | 1 +
> libdtrace/dt_open.c | 1 +
> test/triggers/module-discovery.c | 11 +++++
> 4 files changed, 88 insertions(+), 4 deletions(-)
>
> diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
> index 617b0128..727e5f54 100644
> --- a/libdtrace/dt_btf.c
> +++ b/libdtrace/dt_btf.c
> @@ -1479,17 +1479,67 @@ dt_btf_lookup_name_kind(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name,
> return id;
> }
>
> +/*
> + * Retain a descriptor as well as the ID: otherwise an unloaded object's ID
> + * could be reused and a later enumeration could mistake it for a cached one.
> + * Only IDs assigned to modules are retained, bounding descriptor use by the
> + * number of modules discovered by this handle.
> + */
I suppose just not reusing IDs in general, and having them only
increment, would end up using too many? (I can't remember under what
circumstances they're reused, but I didn't think it was *common*.)
How it interacts with the earlier change to never remove dt_modules when
their corresponding kernel module is unloaded is unclear to me -- is
this the bit that ensures that an unloaded module never gets reused (and
instead we load a new one if the module is reloaded into the kernel), or
what?
--
NULL && (void)
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 10/20] libdtrace: retain descriptors for cached module BTF IDs
2026-11-06 12:59 ` Nix
@ 2026-11-07 15:59 ` Kris Van Hees
0 siblings, 0 replies; 3+ messages in thread
From: Kris Van Hees @ 2026-11-07 15:59 UTC (permalink / raw)
To: Nix; +Cc: dtrace, dtrace-devel
On Fri, Nov 06, 2026 at 12:59:41PM +0000, Nix wrote:
> On 30 Oct 2026, Kris Van Hees outgrape:
>
> > ---
> > libdtrace/dt_btf.c | 79 ++++++++++++++++++++++++++++++--
> > libdtrace/dt_impl.h | 1 +
> > libdtrace/dt_open.c | 1 +
> > test/triggers/module-discovery.c | 11 +++++
> > 4 files changed, 88 insertions(+), 4 deletions(-)
> >
> > diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
> > index 617b0128..727e5f54 100644
> > --- a/libdtrace/dt_btf.c
> > +++ b/libdtrace/dt_btf.c
> > @@ -1479,17 +1479,67 @@ dt_btf_lookup_name_kind(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name,
> > return id;
> > }
> >
> > +/*
> > + * Retain a descriptor as well as the ID: otherwise an unloaded object's ID
> > + * could be reused and a later enumeration could mistake it for a cached one.
> > + * Only IDs assigned to modules are retained, bounding descriptor use by the
> > + * number of modules discovered by this handle.
> > + */
>
> I suppose just not reusing IDs in general, and having them only
> increment, would end up using too many? (I can't remember under what
> circumstances they're reused, but I didn't think it was *common*.)
The thing is that we have no control over the IDs... They are provided
by the BTF subsystem, and we should not make any assumptions about them
in terms of wether they could be reused or not.
> How it interacts with the earlier change to never remove dt_modules when
> their corresponding kernel module is unloaded is unclear to me -- is
> this the bit that ensures that an unloaded module never gets reused (and
> instead we load a new one if the module is reloaded into the kernel), or
> what?
This really has to do with the way the BTF subsystem handles modules and
associates IDs with them. OUr own view of modules is independent from
that.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-07 16:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30 19:36 [PATCH 10/20] libdtrace: retain descriptors for cached module BTF IDs Kris Van Hees
2026-11-06 12:59 ` Nix
2026-11-07 15:59 ` Kris Van Hees
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.