[DTrace-devel] [PATCH v3] Allow arbitrary tracefs mount points
Eugene Loh
eugene.loh at oracle.com
Tue Nov 12 20:06:32 UTC 2024
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
though:
*) There are cases -- e.g., uprobe_create(), uprobe_detach(), and
dt_prov_dtrace.c's attach() -- where indentation is being changed
gratuitously on some declaration lines.
*) It still seems to me that there are ten sites where we call
dt_tracefs_open(), only to turn the int fd into a FILE *f, which is what
we really want. How to simplify those ten sites is a little tricky due
to the variations among them, but I sent Nick an idea using a
preprocessor macro. Whether that idea is an improvement is a matter of
opinion, I suppose.
On 11/12/24 08:42, Nick Alcock via DTrace-devel wrote:
> So as of kernel 6.3 (upstream commit 2455f0e124d317dd08d337a75), the
> canonical tracefs location has moved to /sys/kernel/tracing. Unfortunately
> this requires an explicit mount, and a great many installations have not
> done this and perhaps never will. So if the debugfs is mounted on
> /sys/kernel/debug, it automatically makes /sys/kernel/debug/tracing appear
> as it used to, as another tracefs mount. And of course there's nothing
> special about the "canonical location": it's up to the admin, who might
> choose to remount the thing anywhere at all.
>
> To make this even more fun, it's quite possible to end up with the tracefs
> on /sys/kernel/debug/tracing, but an empty directory at /sys/kernel/tracing
> (I got that during testing with no effort at all).
>
> All this means that the existing DTrace hardwiring for tracefs/eventsfs
> locations isn't good enough. Instead, hunt for a suitable tracefs mount with
> getmntent(), and add a function to open files under that directory, allowing
> the path to be created using a printf-style format string (mimicking the
> things we used to do with EVENTSFS defines and the like). This is actually
> all we need; there is no need to ever return these paths at all, so there
> is no clogging up the code with free()s -- and actually there's a
> noticeable simplification in most cases.
>
> Tested with both in-practice-observed locations of debugfs, and the
> obviously crazy and bad-in-a-format-string path of "/%s/%s/%n" to make sure
> that is properly rejected.
>
> Bug: https://github.com/oracle/dtrace-utils/issues/111
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
> include/tracefs.h | 14 ----
> libdtrace/dt_error.c | 3 +-
> libdtrace/dt_impl.h | 3 +
> libdtrace/dt_open.c | 1 +
> libdtrace/dt_prov_dtrace.c | 27 +++----
> libdtrace/dt_prov_fbt.c | 37 ++++-----
> libdtrace/dt_prov_rawtp.c | 9 ++-
> libdtrace/dt_prov_sdt.c | 30 ++++---
> libdtrace/dt_prov_syscall.c | 27 ++++---
> libdtrace/dt_prov_uprobe.c | 41 +++++-----
> libdtrace/dt_provider.h | 1 -
> libdtrace/dt_subr.c | 80 +++++++++++++++++++
> runtest.sh | 8 ++
> test/unittest/funcs/tst.rw_.x | 7 +-
> test/unittest/providers/tst.dtrace_cleanup.sh | 9 ++-
> test/utils/clean_probes.sh | 12 ++-
> 16 files changed, 203 insertions(+), 106 deletions(-)
> delete mode 100644 include/tracefs.h
>
> diff --git a/include/tracefs.h b/include/tracefs.h
> deleted file mode 100644
> index d671f51adefc..000000000000
> --- a/include/tracefs.h
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -/*
> - * Oracle Linux DTrace; simple uprobe helper functions
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> - * Licensed under the Universal Permissive License v 1.0 as shown at
> - * http://oss.oracle.com/licenses/upl.
> - */
> -
> -#ifndef _TRACEFS_H
> -#define _TRACEFS_H
> -
> -#define TRACEFS "/sys/kernel/debug/tracing/"
> -#define EVENTSFS TRACEFS "events/"
> -
> -#endif /* _TRACEFS_H */
> diff --git a/libdtrace/dt_error.c b/libdtrace/dt_error.c
> index 213f0d9e1385..9c4a2b32888e 100644
> --- a/libdtrace/dt_error.c
> +++ b/libdtrace/dt_error.c
> @@ -98,7 +98,8 @@ static const struct {
> { EDT_READMAXSTACK, "Cannot read kernel param perf_event_max_stack" },
> { EDT_TRACEMEM, "Missing or corrupt tracemem() record" },
> { EDT_PCAP, "Missing or corrupt pcap() record" },
> - { EDT_PRINT, "Missing or corrupt print() record" }
> + { EDT_PRINT, "Missing or corrupt print() record" },
> + { EDT_TRACEFS, "Cannot find tracefs" }
> };
>
> static const int _dt_nerr = sizeof(_dt_errlist) / sizeof(_dt_errlist[0]);
> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> index 68fb8ec53c06..950cb34819aa 100644
> --- a/libdtrace/dt_impl.h
> +++ b/libdtrace/dt_impl.h
> @@ -354,6 +354,7 @@ struct dtrace_hdl {
> char *dt_module_path; /* pathname of kernel module root */
> dt_version_t dt_kernver;/* kernel version, used in the libpath */
> char *dt_dofstash_path; /* Path to the DOF stash. */
> + char *dt_tracefs_path; /* Path to tracefs. */
> uid_t dt_useruid; /* lowest non-system uid: set via -xuseruid */
> char *dt_sysslice; /* the systemd system slice: set via -xsysslice */
> uint_t dt_lazyload; /* boolean: set via -xlazyload */
> @@ -643,6 +644,7 @@ enum {
> EDT_TRACEMEM, /* missing or corrupt tracemem() record */
> EDT_PCAP, /* missing or corrupt pcap() record */
> EDT_PRINT, /* missing or corrupt print() record */
> + EDT_TRACEFS, /* cannot find tracefs */
> };
>
> /*
> @@ -713,6 +715,7 @@ extern void dt_conf_init(dtrace_hdl_t *);
>
> extern int dt_gmatch(const char *, const char *);
> extern char *dt_basename(char *);
> +extern int dt_tracefs_open(dtrace_hdl_t *, const char *fn, int flags, ...);
>
> extern ulong_t dt_popc(ulong_t);
> extern ulong_t dt_popcb(const ulong_t *, ulong_t);
> diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> index e1972aa821e7..775830f64492 100644
> --- a/libdtrace/dt_open.c
> +++ b/libdtrace/dt_open.c
> @@ -1317,6 +1317,7 @@ dtrace_close(dtrace_hdl_t *dtp)
> free(dtp->dt_cpp_argv);
> free(dtp->dt_cpp_path);
> free(dtp->dt_ld_path);
> + free(dtp->dt_tracefs_path);
> free(dtp->dt_sysslice);
> free(dtp->dt_dofstash_path);
>
> diff --git a/libdtrace/dt_prov_dtrace.c b/libdtrace/dt_prov_dtrace.c
> index 34b5d8e2467f..670954beb4c9 100644
> --- a/libdtrace/dt_prov_dtrace.c
> +++ b/libdtrace/dt_prov_dtrace.c
> @@ -23,8 +23,6 @@ static const char funname[] = "";
>
> #define PROBE_FUNC_SUFFIX "_probe"
>
> -#define UPROBE_EVENTS TRACEFS "uprobe_events"
> -
> static const dtrace_pattr_t pattr = {
> { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
> { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
> @@ -229,11 +227,9 @@ out:
> static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
> {
> if (!dt_tp_probe_has_info(prp)) {
> - char *spec;
> - char *fn;
> - FILE *f;
> - size_t len;
> - int fd, rc = -1;
> + char *spec;
> + FILE *f;
> + int fd = -1, rc = -1;
>
> /* get a uprobe specification for this probe */
> spec = uprobe_spec(getpid(), prp->desc->prb);
> @@ -241,7 +237,8 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
> return -ENOENT;
>
> /* add a uprobe */
> - fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
> + fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
> +
> if (fd != -1) {
> rc = dprintf(fd, "p:" GROUP_FMT "/%s %s\n",
> GROUP_DATA, prp->desc->prb, spec);
> @@ -252,16 +249,12 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
> return -ENOENT;
>
> /* open format file */
> - len = snprintf(NULL, 0, "%s" GROUP_FMT "/%s/format",
> - EVENTSFS, GROUP_DATA, prp->desc->prb) + 1;
> - fn = dt_alloc(dtp, len);
> - if (fn == NULL)
> + fd = dt_tracefs_open(dtp, "events/" GROUP_FMT "/%s/format",
> + O_RDONLY, GROUP_DATA, prp->desc->prb);
> + if (fd < 0)
> return -ENOENT;
>
> - snprintf(fn, len, "%s" GROUP_FMT "/%s/format",
> - EVENTSFS, GROUP_DATA, prp->desc->prb);
> - f = fopen(fn, "r");
> - dt_free(dtp, fn);
> + f = fdopen(fd, "r");
> if (f == NULL)
> return -ENOENT;
>
> @@ -296,7 +289,7 @@ static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
>
> dt_tp_probe_detach(dtp, prp);
>
> - fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
> + fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
> if (fd == -1)
> return;
>
> diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
> index 21f63ddffc73..b5c1f5d22a06 100644
> --- a/libdtrace/dt_prov_fbt.c
> +++ b/libdtrace/dt_prov_fbt.c
> @@ -43,8 +43,8 @@
> static const char prvname[] = "fbt";
> static const char modname[] = "vmlinux";
>
> -#define KPROBE_EVENTS TRACEFS "kprobe_events"
> -#define PROBE_LIST TRACEFS "available_filter_functions"
> +#define KPROBE_EVENTS "kprobe_events"
> +#define PROBE_LIST "available_filter_functions"
>
> #define FBT_GROUP_FMT GROUP_FMT "_%s"
> #define FBT_GROUP_DATA GROUP_DATA, prp->desc->prb
> @@ -65,6 +65,7 @@ static int populate(dtrace_hdl_t *dtp)
> {
> dt_provider_t *prv;
> dt_provimpl_t *impl;
> + int fd;
> FILE *f;
> char *buf = NULL;
> char *p;
> @@ -79,7 +80,11 @@ static int populate(dtrace_hdl_t *dtp)
> if (prv == NULL)
> return -1; /* errno already set */
>
> - f = fopen(PROBE_LIST, "r");
> + fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
> + if (fd < 0)
> + return 0;
> +
> + f = fdopen(fd, "r");
> if (f == NULL)
> return 0;
>
> @@ -363,16 +368,14 @@ static int kprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
> {
> if (!dt_tp_probe_has_info(prp)) {
> - char *fn;
> - FILE *f;
> - size_t len;
> - int fd, rc = -1;
> + FILE *f;
> + int fd, rc = -1;
>
> /*
> * Register the kprobe with the tracing subsystem. This will
> * create a tracepoint event.
> */
> - fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
> + fd = dt_tracefs_open(dtp, KPROBE_EVENTS, O_WRONLY | O_APPEND);
> if (fd == -1)
> return -ENOENT;
>
> @@ -383,19 +386,13 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
> if (rc == -1)
> return -ENOENT;
>
> - /* create format file name */
> - len = snprintf(NULL, 0, "%s" FBT_GROUP_FMT "/%s/format",
> - EVENTSFS, FBT_GROUP_DATA, prp->desc->fun) + 1;
> - fn = dt_alloc(dtp, len);
> - if (fn == NULL)
> + /* open format file */
> + fd = dt_tracefs_open(dtp, "events/" FBT_GROUP_FMT "/%s/format",
> + O_RDONLY, FBT_GROUP_DATA, prp->desc->fun);
> + if (fd < 0)
> return -ENOENT;
>
> - snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
> - FBT_GROUP_DATA, prp->desc->fun);
> -
> - /* open format file */
> - f = fopen(fn, "r");
> - dt_free(dtp, fn);
> + f = fdopen(fd, "r");
> if (f == NULL)
> return -ENOENT;
>
> @@ -431,7 +428,7 @@ static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
>
> dt_tp_probe_detach(dtp, prp);
>
> - fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
> + fd = dt_tracefs_open(dtp, KPROBE_EVENTS, O_WRONLY | O_APPEND);
> if (fd == -1)
> return;
>
> diff --git a/libdtrace/dt_prov_rawtp.c b/libdtrace/dt_prov_rawtp.c
> index 778a6f9cde90..6940edce6a6d 100644
> --- a/libdtrace/dt_prov_rawtp.c
> +++ b/libdtrace/dt_prov_rawtp.c
> @@ -38,7 +38,7 @@
> static const char prvname[] = "rawtp";
> static const char modname[] = "vmlinux";
>
> -#define PROBE_LIST TRACEFS "available_events"
> +#define PROBE_LIST "available_events"
>
> #define KPROBES "kprobes"
> #define SYSCALLS "syscalls"
> @@ -64,6 +64,7 @@ static const dtrace_pattr_t pattr = {
> static int populate(dtrace_hdl_t *dtp)
> {
> dt_provider_t *prv;
> + int fd;
> FILE *f;
> char *buf = NULL;
> char *p;
> @@ -73,7 +74,11 @@ static int populate(dtrace_hdl_t *dtp)
> if (prv == NULL)
> return -1; /* errno already set */
>
> - f = fopen(PROBE_LIST, "r");
> + fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
> + if (fd < 0)
> + return 0;
> +
> + f = fdopen(fd, "r");
> if (f == NULL)
> return 0;
>
> diff --git a/libdtrace/dt_prov_sdt.c b/libdtrace/dt_prov_sdt.c
> index 675e0458ca4c..7ebe010efa79 100644
> --- a/libdtrace/dt_prov_sdt.c
> +++ b/libdtrace/dt_prov_sdt.c
> @@ -36,7 +36,7 @@
> static const char prvname[] = "sdt";
> static const char modname[] = "vmlinux";
>
> -#define PROBE_LIST TRACEFS "available_events"
> +#define PROBE_LIST "available_events"
>
> #define KPROBES "kprobes"
> #define SYSCALLS "syscalls"
> @@ -62,6 +62,7 @@ static const dtrace_pattr_t pattr = {
> static int populate(dtrace_hdl_t *dtp)
> {
> dt_provider_t *prv;
> + int fd;
> FILE *f;
> char *buf = NULL;
> char *p;
> @@ -71,7 +72,11 @@ static int populate(dtrace_hdl_t *dtp)
> if (prv == NULL)
> return -1; /* errno already set */
>
> - f = fopen(PROBE_LIST, "r");
> + fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
> + if (fd < 0)
> + return 0;
> +
> + f = fdopen(fd, "r");
> if (f == NULL)
> return 0;
>
> @@ -192,16 +197,16 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> static int probe_info_tracefs(dtrace_hdl_t *dtp, const dt_probe_t *prp,
> int *argcp, dt_argdesc_t **argvp)
> {
> + int fd;
> FILE *f;
> - char *fn;
> int rc;
> const dtrace_probedesc_t *pdp = prp->desc;
>
> - if (asprintf(&fn, EVENTSFS "%s/%s/format", pdp->mod, pdp->prb) == -1)
> - return dt_set_errno(dtp, EDT_NOMEM);
> + fd = dt_tracefs_open(dtp, "events/%s/%s/format", O_RDONLY, pdp->mod, pdp->prb);
> + if (fd < 0)
> + return -ENOENT;
>
> - f = fopen(fn, "r");
> - free(fn);
> + f = fdopen(fd, "r");
> if (!f)
> return -ENOENT;
>
> @@ -223,15 +228,18 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
> int argc = 0;
> dt_argdesc_t *argv = NULL;
> dtrace_typeinfo_t sym;
> + int fd;
> FILE *f;
> uint32_t id;
>
> /* Retrieve the event id. */
> - if (asprintf(&str, EVENTSFS "%s/%s/id", prp->desc->mod, prp->desc->prb) == -1)
> - return dt_set_errno(dtp, EDT_NOMEM);
>
> - f = fopen(str, "r");
> - free(str);
> + fd = dt_tracefs_open(dtp, "events/%s/%s/id", O_RDONLY,
> + prp->desc->mod, prp->desc->prb);
> + if (fd < 0)
> + return dt_set_errno(dtp, EDT_ENABLING_ERR);
> +
> + f = fdopen(fd, "r");
> if (!f)
> return dt_set_errno(dtp, EDT_ENABLING_ERR);
>
> diff --git a/libdtrace/dt_prov_syscall.c b/libdtrace/dt_prov_syscall.c
> index 20843c6f538e..63ce3bc43ae1 100644
> --- a/libdtrace/dt_prov_syscall.c
> +++ b/libdtrace/dt_prov_syscall.c
> @@ -38,7 +38,7 @@
> static const char prvname[] = "syscall";
> static const char modname[] = "vmlinux";
>
> -#define SYSCALLSFS EVENTSFS "syscalls/"
> +#define SYSCALLSFS "events/syscalls/"
>
> /*
> * We need to skip over an extra field: __syscall_nr.
> @@ -61,7 +61,7 @@ struct syscall_data {
>
> #define SCD_ARG(n) offsetof(struct syscall_data, arg[n])
>
> -#define PROBE_LIST TRACEFS "available_events"
> +#define PROBE_LIST "available_events"
>
> #define PROV_PREFIX "syscalls:"
> #define ENTRY_PREFIX "sys_enter_"
> @@ -71,6 +71,7 @@ struct syscall_data {
> static int populate(dtrace_hdl_t *dtp)
> {
> dt_provider_t *prv;
> + int fd;
> FILE *f;
> char *buf = NULL;
> size_t n;
> @@ -79,7 +80,11 @@ static int populate(dtrace_hdl_t *dtp)
> if (prv == NULL)
> return -1; /* errno already set */
>
> - f = fopen(PROBE_LIST, "r");
> + fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
> + if (fd < 0)
> + return 0;
> +
> + f = fdopen(fd, "r");
> if (f == NULL)
> return 0;
>
> @@ -195,23 +200,21 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
> int *argcp, dt_argdesc_t **argvp)
> {
> + int fd;
> FILE *f;
> - char fn[256];
> int rc;
>
> /*
> * We know that the probe name is either "entry" or "return", so we can
> * just check the first character.
> */
> - strcpy(fn, SYSCALLSFS);
> - if (prp->desc->prb[0] == 'e')
> - strcat(fn, "sys_enter_");
> - else
> - strcat(fn, "sys_exit_");
> - strcat(fn, prp->desc->fun);
> - strcat(fn, "/format");
> + fd = dt_tracefs_open(dtp, SYSCALLSFS "/sys_%s_%s/format", O_RDONLY,
> + (prp->desc->prb[0] == 'e') ? "enter" : "exit",
> + prp->desc->fun);
> + if (fd < 0)
> + return -ENOENT;
>
> - f = fopen(fn, "r");
> + f = fdopen(fd, "r");
> if (!f)
> return -ENOENT;
>
> diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
> index 205014617586..6a02243ff572 100644
> --- a/libdtrace/dt_prov_uprobe.c
> +++ b/libdtrace/dt_prov_uprobe.c
> @@ -1116,13 +1116,13 @@ static char *uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int flags)
> * uprobe may be a uretprobe. Return the probe's name as
> * a new dynamically-allocated string, or NULL on error.
> */
> -static char *uprobe_create(dev_t dev, ino_t ino, const char *mapping_fn,
> - uint64_t addr, int flags)
> +static char *uprobe_create(dtrace_hdl_t *dtp, dev_t dev, ino_t ino,
> + const char *mapping_fn, uint64_t addr, int flags)
> {
> - int fd = -1;
> - int rc = -1;
> - char *name;
> - char *spec;
> + int fd = -1;
> + int rc = -1;
> + char *name;
> + char *spec;
>
> if (asprintf(&spec, "%s:0x%lx", mapping_fn, addr) < 0)
> return NULL;
> @@ -1132,8 +1132,8 @@ static char *uprobe_create(dev_t dev, ino_t ino, const char *mapping_fn,
> goto out;
>
> /* Add the uprobe. */
> - fd = open(TRACEFS "uprobe_events", O_WRONLY | O_APPEND);
> - if (fd == -1)
> + fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
> + if (fd < 0)
> goto out;
>
> rc = dprintf(fd, "%c:%s %s\n", flags & PP_IS_RETURN ? 'r' : 'p', name, spec);
> @@ -1153,8 +1153,8 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
> {
> dt_uprobe_t *upp = uprp->prv_data;
> tp_probe_t *tpp = upp->tp;
> + int fd;
> FILE *f;
> - char *fn;
> char *prb = NULL;
> int rc = -1;
>
> @@ -1163,7 +1163,7 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
>
> assert(upp->fn != NULL);
>
> - prb = uprobe_create(upp->dev, upp->inum, upp->fn, upp->off,
> + prb = uprobe_create(dtp, upp->dev, upp->inum, upp->fn, upp->off,
> upp->flags);
>
> /*
> @@ -1177,12 +1177,12 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
> upp->flags);
>
> /* open format file */
> - rc = asprintf(&fn, "%s%s/format", EVENTSFS, prb);
> + fd = dt_tracefs_open(dtp, "events/%s/format", O_RDONLY, prb);
> free(prb);
> - if (rc < 0)
> + if (fd < 0)
> return -ENOENT;
> - f = fopen(fn, "r");
> - free(fn);
> +
> + f = fdopen(fd, "r");
> if (f == NULL)
> return -ENOENT;
>
> @@ -1251,21 +1251,20 @@ done:
> * Destroy a uprobe for a given device and address.
> */
> static int
> -uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int flags)
> +uprobe_delete(dtrace_hdl_t *dtp, dev_t dev, ino_t ino, uint64_t addr, int flags)
> {
> - int fd = -1;
> - int rc = -1;
> - char *name;
> + int fd = -1;
> + int rc = -1;
> + char *name;
>
> name = uprobe_name(dev, ino, addr, flags);
> if (!name)
> goto out;
>
> - fd = open(TRACEFS "uprobe_events", O_WRONLY | O_APPEND);
> + fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
> if (fd == -1)
> goto out;
>
> -
> rc = dprintf(fd, "-:%s\n", name);
>
> out:
> @@ -1297,7 +1296,7 @@ static void detach(dtrace_hdl_t *dtp, const dt_probe_t *uprp)
>
> dt_tp_detach(dtp, tpp);
>
> - uprobe_delete(upp->dev, upp->inum, upp->off, upp->flags);
> + uprobe_delete(dtp, upp->dev, upp->inum, upp->off, upp->flags);
> }
>
> /*
> diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
> index 8f143dceaed7..4598a380b950 100644
> --- a/libdtrace/dt_provider.h
> +++ b/libdtrace/dt_provider.h
> @@ -12,7 +12,6 @@
> #include <dt_impl.h>
> #include <dt_ident.h>
> #include <dt_list.h>
> -#include <tracefs.h>
>
> #ifdef __cplusplus
> extern "C" {
> diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
> index d5dca164861e..f129e5591465 100644
> --- a/libdtrace/dt_subr.c
> +++ b/libdtrace/dt_subr.c
> @@ -20,6 +20,7 @@
> #include <assert.h>
> #include <limits.h>
> #include <sys/ioctl.h>
> +#include <mntent.h>
> #include <port.h>
>
> #include <dt_impl.h>
> @@ -998,3 +999,82 @@ uint32_t dt_gen_hval(const char *p, uint32_t hval, size_t len)
>
> return hval;
> }
> +
> +/*
> + * Find the tracefs and store it away in dtp.
> + */
> +static int
> +find_tracefs_path(dtrace_hdl_t *dtp)
> +{
> + FILE *mounts;
> + struct mntent *mnt;
> +
> + if ((mounts = setmntent("/proc/mounts", "r")) == NULL) {
> + dt_dprintf("Cannot open /proc/mounts: %s\n", strerror(errno));
> + return dt_set_errno(dtp, EDT_TRACEFS);
> + }
> +
> + while ((mnt = getmntent(mounts)) != NULL) {
> + /*
> + * Only accept tracefs paths that do not contain percent
> + * characters in their mounted paths, since we use this
> + * to augment a format string in dt_tracefs_vfn().
> + */
> + if ((strcmp(mnt->mnt_type, "tracefs") == 0) &&
> + (strchr(mnt->mnt_dir, '%') == NULL)) {
> + dtp->dt_tracefs_path = strdup(mnt->mnt_dir);
> + break;
> + }
> + }
> + endmntent(mounts);
> +
> + if (!dtp->dt_tracefs_path) {
> + dt_dprintf("Cannot find a suitable tracefs path.\n");
> + return dt_set_errno(dtp, EDT_TRACEFS);
> + }
> +
> + dt_dprintf("Found tracefs at %s\n", dtp->dt_tracefs_path);
> +
> + return 0;
> +}
> +
> +static char *
> +dt_tracefs_vfn(dtrace_hdl_t *dtp, const char *fn, va_list ap)
> +{
> + char *full_fn;
> + char *str;
> +
> + if (!dtp->dt_tracefs_path)
> + if (find_tracefs_path(dtp) < 0)
> + return NULL; /* errno is set for us. */
> +
> + if (asprintf(&full_fn, "%s/%s", dtp->dt_tracefs_path, fn) < 0) {
> + dt_set_errno(dtp, EDT_NOMEM);
> + return NULL;
> + }
> +
> + if (vasprintf(&str, full_fn, ap) < 0) {
> + str = NULL;
> + dt_set_errno(dtp, EDT_NOMEM);
> + }
> + free(full_fn);
> + return str;
> +}
> +
> +int
> +dt_tracefs_open(dtrace_hdl_t *dtp, const char *fn, int flags, ...)
> +{
> + va_list ap;
> + char *str;
> + int fd;
> +
> + va_start(ap, flags);
> + if ((str = dt_tracefs_vfn(dtp, fn, ap)) == NULL) {
> + va_end(ap);
> + return -1; /* errno is set for us. */
> + }
> +
> + fd = open(str, flags, 0666);
> + free(str);
> + return fd; /* errno is set for us. */
> +}
> diff --git a/runtest.sh b/runtest.sh
> index 46b532d7e161..fbf4e60c82a9 100755
> --- a/runtest.sh
> +++ b/runtest.sh
> @@ -607,6 +607,14 @@ elif ! /usr/bin/cpp -x c -fno-show-column - /dev/null < /dev/null 2>&1 | \
> export DTRACE_OPT_CPPARGS="-fno-show-column"
> fi
>
> +# Find the tracefs.
> +tracefs="$(awk '$3 == "tracefs" { print $2; exit; }' /proc/mounts)"
> +if [[ -z $tracefs ]]; then
> + echo "Cannot find any tracefs mounts in /proc/mounts. Some tests will fail." >&2
> +fi
> +
> +export tracefs
> +
> # More than one dtrace tree -> run tests for all dtraces, and verify identical
> # intermediate code is produced by each dtrace.
>
> diff --git a/test/unittest/funcs/tst.rw_.x b/test/unittest/funcs/tst.rw_.x
> index 29c581116154..5737c7575a26 100755
> --- a/test/unittest/funcs/tst.rw_.x
> +++ b/test/unittest/funcs/tst.rw_.x
> @@ -1,6 +1,11 @@
> #!/bin/sh
>
> -FUNCS=/sys/kernel/debug/tracing/available_filter_functions
> +FUNCS=${tracefs}/available_filter_functions
> +
> +if [[ ! -e $FUNCS ]]; then
> + echo no tracefs found
> + exit 1
> +fi
>
> if ! grep -qw _raw_read_lock $FUNCS; then
> echo no _raw_read_lock FBT probe due to kernel config
> diff --git a/test/unittest/providers/tst.dtrace_cleanup.sh b/test/unittest/providers/tst.dtrace_cleanup.sh
> index 4ac59ccb4315..f3e434ae76fc 100755
> --- a/test/unittest/providers/tst.dtrace_cleanup.sh
> +++ b/test/unittest/providers/tst.dtrace_cleanup.sh
> @@ -1,7 +1,7 @@
> #!/bin/bash
> #
> # Oracle Linux DTrace.
> -# Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
> +# Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
> # Licensed under the Universal Permissive License v 1.0 as shown at
> # http://oss.oracle.com/licenses/upl.
>
> @@ -14,7 +14,12 @@
> ##
>
> dtrace=$1
> -UPROBE_EVENTS=/sys/kernel/debug/tracing/uprobe_events
> +UPROBE_EVENTS=${tracefs}/uprobe_events
> +
> +if [[ ! -e $UPROBE_EVENTS ]]; then
> + echo "no tracefs/uprobe_events" >&2
> + exit 67
> +fi
>
> out=/tmp/output.$$
> $dtrace $dt_flags -n BEGIN,END &>> $out &
> diff --git a/test/utils/clean_probes.sh b/test/utils/clean_probes.sh
> index 8292b3096424..cfd100088eb7 100755
> --- a/test/utils/clean_probes.sh
> +++ b/test/utils/clean_probes.sh
> @@ -1,9 +1,13 @@
> #!/usr/bin/bash
>
> -TRACEFS=/sys/kernel/debug/tracing
> -EVENTS=${TRACEFS}/available_events
> -KPROBES=${TRACEFS}/kprobe_events
> -UPROBES=${TRACEFS}/uprobe_events
> +EVENTS=${tracefs}/available_events
> +KPROBES=${tracefs}/kprobe_events
> +UPROBES=${tracefs}/uprobe_events
> +
> +# We can't work without the tracefs: just give up quietly.
> +if [[ ! -e $EVENTS ]]; then
> + exit 0
> +fi
>
> # Check permissions
> if [[ ! -r ${EVENTS} ]]; then
More information about the DTrace-devel
mailing list