[DTrace-devel] [PATCH 06/12] Make a provider-specific attach()

eugene.loh at oracle.com eugene.loh at oracle.com
Sat Jul 11 17:38:30 PDT 2020


From: Eugene Loh <eugene.loh at oracle.com>

We used dt_bpf_attach() to attach BPF programs to probes.  This
was suitable for the tracepoint-like providers to date, which used
established event IDs to enable probes to get their file descriptors
and then attach the BPF program fd;  however, the approach is
inadequate for some other providers.

Remove dt_bpf_attach(), instead calling a provider-specific attach()
function.

Note that many providers actually are tracepoint-like.  So, they can
share a common attach() function.  That function, tp_event_attach(),
is supplied by the sdt provider in the same way as that provider
supplies the common tp_event_info() function.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_bpf.c          | 39 +++----------------------------------
 libdtrace/dt_prov_dtrace.c  |  1 +
 libdtrace/dt_prov_fbt.c     |  1 +
 libdtrace/dt_prov_sdt.c     | 34 ++++++++++++++++++++++++++++++++
 libdtrace/dt_prov_syscall.c |  1 +
 libdtrace/dt_provider.h     |  3 +++
 6 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index e7780b56..573c8357 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -317,41 +317,6 @@ dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	return rc;
 }
 
-/*
- * Attach a BPF program to a probe.
- */
-int
-dt_bpf_attach(dtrace_hdl_t *dtp, dt_probe_t *prp, int bpf_fd)
-{
-	tp_probe_t *datap = prp->prv_data;
-
-	/*
-	 * If we have not yet created a perf event for this probe, do that now
-	 * and cache the file descriptor so we only need to do this once.
-	 */
-	if (datap->event_fd == -1) {
-		int			fd;
-		struct perf_event_attr	attr = { 0, };
-
-		attr.type = PERF_TYPE_TRACEPOINT;
-		attr.sample_type = PERF_SAMPLE_RAW;
-		attr.sample_period = 1;
-		attr.wakeup_events = 1;
-		attr.config = datap->event_id;
-
-		fd = perf_event_open(&attr, -1, 0, -1, 0);
-		if (fd < 0)
-			return dt_set_errno(dtp, errno);
-
-		datap->event_fd = fd;
-	}
-
-	if (ioctl(datap->event_fd, PERF_EVENT_IOC_SET_BPF, bpf_fd) < 0)
-		return dt_set_errno(dtp, errno);
-
-	return 0;
-}
-
 int
 dt_bpf_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	    void *data)
@@ -371,7 +336,9 @@ dt_bpf_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	if (fd < 0)
 		return fd;
 
-	rc = dt_bpf_attach(dtp, prp, fd);
+	if (!prp->prov->impl->attach)
+		return -1;
+	rc = prp->prov->impl->attach(dtp, prp, fd);
 	if (rc < 0)
 		return rc;
 
diff --git a/libdtrace/dt_prov_dtrace.c b/libdtrace/dt_prov_dtrace.c
index a5dc1eb0..dcddafa3 100644
--- a/libdtrace/dt_prov_dtrace.c
+++ b/libdtrace/dt_prov_dtrace.c
@@ -317,6 +317,7 @@ dt_provimpl_t	dt_dtrace = {
 	.populate	= &populate,
 	.trampoline	= &trampoline,
 	.probe_info	= &probe_info,
+	.attach		= &tp_attach,
 	.probe_destroy	= &tp_probe_destroy,
 	.probe_fini	= &probe_fini,
 };
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index d01d1932..ceefa173 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -358,6 +358,7 @@ dt_provimpl_t	dt_fbt = {
 	.populate	= &populate,
 	.trampoline	= &trampoline,
 	.probe_info	= &probe_info,
+	.attach		= &tp_attach,
 	.probe_destroy	= &tp_probe_destroy,
 	.probe_fini	= &probe_fini,
 };
diff --git a/libdtrace/dt_prov_sdt.c b/libdtrace/dt_prov_sdt.c
index 9223951b..3d341cd3 100644
--- a/libdtrace/dt_prov_sdt.c
+++ b/libdtrace/dt_prov_sdt.c
@@ -19,13 +19,16 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
 #include <linux/bpf.h>
+#include <linux/perf_event.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <bpf_asm.h>
 
 #include "dt_impl.h"
+#include "dt_bpf.h"
 #include "dt_bpf_builtins.h"
 #include "dt_provider.h"
 #include "dt_probe.h"
@@ -239,6 +242,36 @@ done:
 	return 0;
 }
 
+int tp_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
+{
+	tp_probe_t *datap = prp->prv_data;
+
+	if (datap->event_id == -1)
+		return 0;
+
+	if (datap->event_fd == -1) {
+		int			fd;
+		struct perf_event_attr	attr = { 0, };
+
+		attr.type = PERF_TYPE_TRACEPOINT;
+		attr.sample_type = PERF_SAMPLE_RAW;
+		attr.sample_period = 1;
+		attr.wakeup_events = 1;
+		attr.config = datap->event_id;
+
+		fd = perf_event_open(&attr, -1, 0, -1, 0);
+		if (fd < 0)
+			return dt_set_errno(dtp, errno);
+
+		datap->event_fd = fd;
+	}
+
+	if (ioctl(datap->event_fd, PERF_EVENT_IOC_SET_BPF, bpf_fd) < 0)
+		return dt_set_errno(dtp, errno);
+
+	return 0;
+}
+
 int tp_probe_destroy(dtrace_hdl_t *dtp, void *datap)
 {
 	dt_free(dtp, datap);
@@ -451,6 +484,7 @@ dt_provimpl_t	dt_sdt = {
 	.prog_type	= BPF_PROG_TYPE_TRACEPOINT,
 	.populate	= &populate,
 	.trampoline	= &trampoline,
+	.attach		= &tp_attach,
 	.probe_info	= &probe_info,
 	.probe_destroy	= &tp_probe_destroy,
 	.probe_fini	= &tp_probe_fini,
diff --git a/libdtrace/dt_prov_syscall.c b/libdtrace/dt_prov_syscall.c
index 1c9145c0..ea3721db 100644
--- a/libdtrace/dt_prov_syscall.c
+++ b/libdtrace/dt_prov_syscall.c
@@ -275,6 +275,7 @@ dt_provimpl_t	dt_syscall = {
 	.populate	= &populate,
 	.trampoline	= &trampoline,
 	.probe_info	= &probe_info,
+	.attach		= &tp_attach,
 	.probe_destroy	= &tp_probe_destroy,
 	.probe_fini	= &tp_probe_fini,
 };
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index 85fe2227..1fb616a0 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -65,6 +65,8 @@ typedef struct dt_provimpl {
 			  const struct dt_probe *prp,
 			  int *argcp, dt_argdesc_t **argvp);
 	void (*trampoline)(dt_pcb_t *pcb);	/* generate BPF trampoline */
+	int (*attach)(dtrace_hdl_t *dtp,	/* attach BPF program to probe */
+		      const struct dt_probe *prp, int bpf_fd);
 	int (*probe_destroy)(dtrace_hdl_t *dtp,	/* free provider-specific data */
 			     void *datap);
 	int (*probe_fini)(dtrace_hdl_t *dtp,	/* probe cleanup */
@@ -101,6 +103,7 @@ extern struct dt_probe *tp_probe_insert(dtrace_hdl_t *dtp, dt_provider_t *prov,
 extern int tp_probe_destroy(dtrace_hdl_t *dtp, void *datap);
 extern int tp_event_info(dtrace_hdl_t *dtp, FILE *f, int skip,
 			 tp_probe_t *datap, int *argcp, dt_argdesc_t **argvp);
+extern int tp_attach(dtrace_hdl_t *dtp, const struct dt_probe *prp, int bpf_fd);
 extern int tp_probe_fini(dtrace_hdl_t *dtp, const struct dt_probe *prb);
 
 #define	DT_PROVIDER_INTF	0x1	/* provider interface declaration */
-- 
2.18.2




More information about the DTrace-devel mailing list