[DTrace-devel] [PATCH] Allow arbitrary tracefs mount points

Nick Alcock nick.alcock at oracle.com
Wed Nov 6 16:46:56 UTC 2024


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 return an arbitrary path under that
directory (mimicking the things we used to do with EVENTSFS defines and the
like).  Return a pointer to static (per-dtrace_hdl) storage so that we don't
need to clog up all the callers with dynamic allocation: only one path is
ever needed at any one time anyway.

Tested with both in-practice-observed locations of debugfs.

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                           |  4 ++
 libdtrace/dt_open.c                           |  2 +
 libdtrace/dt_prov_dtrace.c                    | 31 ++++++-----
 libdtrace/dt_prov_fbt.c                       | 40 ++++++++------
 libdtrace/dt_prov_rawtp.c                     | 10 ++--
 libdtrace/dt_prov_sdt.c                       | 23 +++++---
 libdtrace/dt_prov_syscall.c                   | 18 ++++---
 libdtrace/dt_prov_uprobe.c                    | 52 +++++++++++--------
 libdtrace/dt_provider.h                       |  1 -
 libdtrace/dt_subr.c                           | 52 +++++++++++++++++++
 test/unittest/funcs/tst.rw_.x                 |  7 ++-
 test/unittest/providers/tst.dtrace_cleanup.sh |  9 +++-
 test/utils/clean_probes.sh                    |  6 ++-
 15 files changed, 187 insertions(+), 85 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..f6b41bf72b9f 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_MNT, "Cannot find tracefs mount point" }
 };
 
 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..9d246cef2e7f 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -354,6 +354,8 @@ 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.  */
+	char *dt_tracefs_file;	/* See tracefs_file().  */
 	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 +645,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_MNT,	/* cannot find tracefs mount point */
 };
 
 /*
@@ -713,6 +716,7 @@ extern void dt_conf_init(dtrace_hdl_t *);
 
 extern int dt_gmatch(const char *, const char *);
 extern char *dt_basename(char *);
+extern const char *tracefs_file(dtrace_hdl_t *, const char *);
 
 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..e74b11244a35 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1317,6 +1317,8 @@ 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_tracefs_file);
 	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..221a46bd50b8 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,12 @@ 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;
+		const char	*uprobe_events;
+		char		*fn;
+		FILE		*f;
+		size_t		len;
+		int		fd = -1, rc = -1;
 
 		/* get a uprobe specification for this probe */
 		spec = uprobe_spec(getpid(), prp->desc->prb);
@@ -241,7 +240,9 @@ 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);
+		if ((uprobe_events = tracefs_file(dtp, "uprobe_events")) != NULL)
+			fd = open(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,14 +253,18 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 			return -ENOENT;
 
 		/* open format file */
+
+		if ((uprobe_events = tracefs_file(dtp, "events/")) == NULL)
+			return -ENOENT;
+
 		len = snprintf(NULL, 0, "%s" GROUP_FMT "/%s/format",
-			       EVENTSFS, GROUP_DATA, prp->desc->prb) + 1;
+			       uprobe_events, GROUP_DATA, prp->desc->prb) + 1;
 		fn = dt_alloc(dtp, len);
 		if (fn == NULL)
 			return -ENOENT;
 
 		snprintf(fn, len, "%s" GROUP_FMT "/%s/format",
-			 EVENTSFS, GROUP_DATA, prp->desc->prb);
+			 uprobe_events, GROUP_DATA, prp->desc->prb);
 		f = fopen(fn, "r");
 		dt_free(dtp, fn);
 		if (f == NULL)
@@ -289,14 +294,16 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
  */
 static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 {
-	int		fd;
+	int		fd = -1;
+	const char	*uprobe_events;
 
 	if (!dt_tp_probe_has_info(prp))
 		return;
 
 	dt_tp_probe_detach(dtp, prp);
 
-	fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+	if ((uprobe_events = tracefs_file(dtp, "uprobe_events")) != NULL)
+		fd = open(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..7d81b0f3e87d 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -7,7 +7,7 @@
  * The Function Boundary Tracing (FBT) provider for DTrace.
  *
  * FBT probes are exposed by the kernel as kprobes.  They are listed in the
- * TRACEFS/available_filter_functions file.  Some kprobes are associated with
+ * tracefs available_filter_functions file.  Some kprobes are associated with
  * a specific kernel module, while most are in the core kernel.
  *
  * Mapping from event name to DTrace probe name:
@@ -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
@@ -58,14 +58,15 @@ static const dtrace_pattr_t	pattr = {
 };
 
 /*
- * Scan the PROBE_LIST file and add entry and return probes for every function
+ * Scan the available_filter_functions file and add entry and return probes for every function
  * that is listed.
  */
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t		*prv;
 	dt_provimpl_t		*impl;
-	FILE			*f;
+	const char		*probe_list;
+	FILE			*f = NULL;
 	char			*buf = NULL;
 	char			*p;
 	const char		*mod = modname;
@@ -79,7 +80,8 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	if ((probe_list = tracefs_file(dtp, PROBE_LIST)) != NULL)
+		f = fopen(probe_list, "r");
 	if (f == NULL)
 		return 0;
 
@@ -363,16 +365,18 @@ 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;
+		const char	*kprobe_events;
+		char		*fn;
+		FILE		*f;
+		size_t		len;
+		int		fd = -1, rc = -1;
 
 		/*
 		 * Register the kprobe with the tracing subsystem.  This will
 		 * create a tracepoint event.
 		 */
-		fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
+		if ((kprobe_events = tracefs_file(dtp, KPROBE_EVENTS)) != NULL)
+			fd = open(kprobe_events, O_WRONLY | O_APPEND);
 		if (fd == -1)
 			return -ENOENT;
 
@@ -384,13 +388,17 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 			return -ENOENT;
 
 		/* create format file name */
+
+		if ((kprobe_events = tracefs_file(dtp, "events/")) == NULL)
+			return -ENOENT;
+
 		len = snprintf(NULL, 0, "%s" FBT_GROUP_FMT "/%s/format",
-			       EVENTSFS, FBT_GROUP_DATA, prp->desc->fun) + 1;
+			       kprobe_events, FBT_GROUP_DATA, prp->desc->fun) + 1;
 		fn = dt_alloc(dtp, len);
 		if (fn == NULL)
 			return -ENOENT;
 
-		snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
+		snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", kprobe_events,
 			 FBT_GROUP_DATA, prp->desc->fun);
 
 		/* open format file */
@@ -424,14 +432,16 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
  */
 static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 {
-	int		fd;
+	const char	*kprobe_events;
+	int		fd = -1;
 
 	if (!dt_tp_probe_has_info(prp))
 		return;
 
 	dt_tp_probe_detach(dtp, prp);
 
-	fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
+	if ((kprobe_events = tracefs_file(dtp, KPROBE_EVENTS)) != NULL)
+		fd = open(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..6e495afef092 100644
--- a/libdtrace/dt_prov_rawtp.c
+++ b/libdtrace/dt_prov_rawtp.c
@@ -8,7 +8,7 @@
  *
  * Raw tracepoints are exposed by the kernel tracing system to allow access to
  * untranslated arguments to their associated tracepoint events.  Each
- * tracepoint event listed in the TRACEFS/available_events file can be traced
+ * tracepoint event listed in the tracefs available_events file can be traced
  * as a raw tracepoint using the BPF program type BPF_PROG_TYPE_RAW_TRACEPOINT.
  *
  * Mapping from event name to DTrace probe name:
@@ -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,7 +64,8 @@ static const dtrace_pattr_t	pattr = {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
-	FILE		*f;
+	const char	*probe_list;
+	FILE		*f = NULL;
 	char		*buf = NULL;
 	char		*p;
 	size_t		n;
@@ -73,7 +74,8 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	if ((probe_list = tracefs_file(dtp, PROBE_LIST)) != NULL)
+		f = fopen(probe_list, "r");
 	if (f == NULL)
 		return 0;
 
diff --git a/libdtrace/dt_prov_sdt.c b/libdtrace/dt_prov_sdt.c
index 675e0458ca4c..717fd62f0c3a 100644
--- a/libdtrace/dt_prov_sdt.c
+++ b/libdtrace/dt_prov_sdt.c
@@ -7,7 +7,7 @@
  * The Statically Defined Tracepoint (SDT) provider for DTrace.
  *
  * SDT probes are exposed by the kernel as tracepoint events.  They are listed
- * in the TRACEFS/available_events file.
+ * in the tracefs available_events file.
  *
  * Mapping from event name to DTrace probe name:
  *
@@ -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,7 +62,8 @@ static const dtrace_pattr_t	pattr = {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
-	FILE		*f;
+	const char	*probe_list;
+	FILE		*f = NULL;
 	char		*buf = NULL;
 	char		*p;
 	size_t		n;
@@ -71,7 +72,8 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	if ((probe_list = tracefs_file(dtp, PROBE_LIST)) != NULL)
+		f = fopen(probe_list, "r");
 	if (f == NULL)
 		return 0;
 
@@ -192,12 +194,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)
 {
+	const char			*eventsfs;
 	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)
+	if ((eventsfs = tracefs_file(dtp, "events")) == NULL)
+		return -ENOENT;
+
+	if (asprintf(&fn, "%s/%s/%s/format", eventsfs, pdp->mod, pdp->prb) == -1)
 		return dt_set_errno(dtp, EDT_NOMEM);
 
 	f = fopen(fn, "r");
@@ -215,6 +221,7 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		      int *argcp, dt_argdesc_t **argvp)
 {
 #ifdef HAVE_LIBCTF
+	const char		*eventsfs;
 	int			rc, i;
 	char			*str;
 	ctf_dict_t		*ctfp;
@@ -227,7 +234,11 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	uint32_t		id;
 
 	/* Retrieve the event id. */
-	if (asprintf(&str, EVENTSFS "%s/%s/id", prp->desc->mod, prp->desc->prb) == -1)
+
+	if ((eventsfs = tracefs_file(dtp, "events")) == NULL)
+		return -1;			/* errno is set for us. */
+
+	if (asprintf(&str, "%s/%s/%s/id", eventsfs, prp->desc->mod, prp->desc->prb) == -1)
 		return dt_set_errno(dtp, EDT_NOMEM);
 
 	f = fopen(str, "r");
diff --git a/libdtrace/dt_prov_syscall.c b/libdtrace/dt_prov_syscall.c
index 20843c6f538e..869e8e130c42 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,7 +71,8 @@ struct syscall_data {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
-	FILE		*f;
+	const char	*probe_list;
+	FILE		*f = NULL;
 	char		*buf = NULL;
 	size_t		n;
 
@@ -79,7 +80,8 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	if ((probe_list = tracefs_file(dtp, PROBE_LIST)) != NULL)
+		f = fopen(probe_list, "r");
 	if (f == NULL)
 		return 0;
 
@@ -196,14 +198,18 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		      int *argcp, dt_argdesc_t **argvp)
 {
 	FILE		*f;
-	char		fn[256];
+	const char	*syscallsfs;
+	char		fn[PATH_MAX];
 	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 ((syscallsfs = tracefs_file(dtp, SYSCALLSFS)) == NULL)
+		return -ENOENT;
+
+	strcpy(fn, syscallsfs);
 	if (prp->desc->prb[0] == 'e')
 		strcat(fn, "sys_enter_");
 	else
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index 205014617586..f8752eaa3843 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -1116,13 +1116,14 @@ 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;
+	const char	*uprobe_events;
+	int		fd = -1;
+	int		rc = -1;
+	char		*name;
+	char		*spec;
 
 	if (asprintf(&spec, "%s:0x%lx", mapping_fn, addr) < 0)
 		return NULL;
@@ -1132,7 +1133,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 ((uprobe_events = tracefs_file(dtp, "uprobe_events")) != NULL)
+		fd = open(uprobe_events, O_WRONLY | O_APPEND);
 	if (fd == -1)
 		goto out;
 
@@ -1153,8 +1155,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;
-	FILE		*f;
-	char		*fn;
+	const char	*eventsfs;
+	FILE		*f = NULL;
 	char		*prb = NULL;
 	int		rc = -1;
 
@@ -1163,7 +1165,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 +1179,16 @@ 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);
-	free(prb);
-	if (rc < 0)
-		return -ENOENT;
-	f = fopen(fn, "r");
-	free(fn);
+	if ((eventsfs = tracefs_file(dtp, "events")) != NULL) {
+		char	*fn;
+
+		rc = asprintf(&fn, "%s/%s/format", eventsfs, prb);
+		free(prb);
+		if (rc < 0)
+			return -ENOENT;
+		f = fopen(fn, "r");
+		free(fn);
+	}
 	if (f == NULL)
 		return -ENOENT;
 
@@ -1251,17 +1257,19 @@ 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;
+	const char	*uprobe_events;
+	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);
+	if ((uprobe_events = tracefs_file(dtp, "uprobe_events")) != NULL)
+		fd = open(uprobe_events, O_WRONLY | O_APPEND);
 	if (fd == -1)
 		goto out;
 
@@ -1297,7 +1305,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..6ec03b503a66 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,54 @@ 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_MNT);
+	}
+
+	while ((mnt = getmntent(mounts)) != NULL) {
+		if (strcmp(mnt->mnt_type, "tracefs") == 0) {
+			dtp->dt_tracefs_path = strdup(mnt->mnt_dir);
+			break;
+		}
+	}
+	endmntent(mounts);
+
+	if (!dtp->dt_tracefs_path)
+		return dt_set_errno(dtp, EDT_TRACEFS_MNT);
+
+	dt_dprintf("Found tracefs at %s\n", dtp->dt_tracefs_path);
+
+	return 0;
+}
+
+/*
+ * Return the path to a tracefs file.  (Statically allocated,
+ * discarded on reuse.)
+ */
+const char *
+tracefs_file(dtrace_hdl_t *dtp, const char *fn)
+{
+	free(dtp->dt_tracefs_file);
+
+	if (!dtp->dt_tracefs_path)
+		if (find_tracefs_path(dtp) < 0)
+			return NULL;		/* errno is set for us. */
+
+	if (asprintf(&dtp->dt_tracefs_file, "%s/%s", dtp->dt_tracefs_path, fn) < 0) {
+		dtp->dt_tracefs_file = NULL;
+		dt_set_errno(dtp, EDT_NOMEM);
+		return NULL;
+	}
+	return dtp->dt_tracefs_file;
+}
diff --git a/test/unittest/funcs/tst.rw_.x b/test/unittest/funcs/tst.rw_.x
index 29c581116154..7e178778d900 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
+TRACEFS=/sys/kernel/tracing
+if [[ ! -e $TRACEFS/available_filter_functions ]]; then
+	TRACEFS=/sys/kernel/debug/tracing
+fi
+
+FUNCS=${TRACEFS}/available_filter_functions
 
 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..08b47a057783 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
+TRACEFS=/sys/kernel/tracing
+if [[ ! -e $TRACEFS/uprobe_events ]]; then
+	TRACEFS=/sys/kernel/debug/tracing
+fi
+
+UPROBE_EVENTS=${TRACEFS}/uprobe_events
 
 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..16e98b29b275 100755
--- a/test/utils/clean_probes.sh
+++ b/test/utils/clean_probes.sh
@@ -1,6 +1,10 @@
 #!/usr/bin/bash
 
-TRACEFS=/sys/kernel/debug/tracing
+TRACEFS=/sys/kernel/tracing
+if [[ ! -e $TRACEFS/available_events ]]; then
+	TRACEFS=/sys/kernel/debug/tracing
+fi
+
 EVENTS=${TRACEFS}/available_events
 KPROBES=${TRACEFS}/kprobe_events
 UPROBES=${TRACEFS}/uprobe_events
-- 
2.46.0.278.g36e3a12567




More information about the DTrace-devel mailing list