[DTrace-devel] [PATCH 7/8] rawfbt: performance improvements
Kris Van Hees
kris.van.hees at oracle.com
Wed Mar 12 06:38:35 UTC 2025
On Wed, Mar 12, 2025 at 01:45:57AM -0400, Eugene Loh via DTrace-devel wrote:
> Preliminary comment on this one... a couple of USDT tests start to fail
> reproducibly with this patch. The explanation is weird. The tests filter
> out specific run-dependent probe ID values before checking with their .r
> results files. But because some of these probe IDs get a lot smaller
> (narrower, fewer digits) with this fbt patch, the filters break. I have a
> patch for those USDT tests. I suppose that patch should land before these
> fbt patches. So, my fault. Sorry.
>
> On 3/7/25 16:34, Kris Van Hees via DTrace-devel wrote:
> > Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> > ---
> > libdtrace/dt_prov_rawfbt.c | 223 +++++++++++++++++++++++++------------
> > 1 file changed, 151 insertions(+), 72 deletions(-)
> >
> > diff --git a/libdtrace/dt_prov_rawfbt.c b/libdtrace/dt_prov_rawfbt.c
> > index 62f2f4f0..52152655 100644
> > --- a/libdtrace/dt_prov_rawfbt.c
> > +++ b/libdtrace/dt_prov_rawfbt.c
> > @@ -44,10 +44,8 @@
> > #include "dt_pt_regs.h"
> > static const char prvname[] = "rawfbt";
> > -static const char modname[] = "vmlinux";
> > #define KPROBE_EVENTS TRACEFS "kprobe_events"
> > -#define PROBE_LIST TRACEFS "available_filter_functions"
> > #define FBT_GROUP_FMT GROUP_FMT "_%s"
> > #define FBT_GROUP_DATA GROUP_DATA, prp->desc->prb
> > @@ -61,98 +59,178 @@ static const dtrace_pattr_t pattr = {
> > };
> > /*
> > - * Scan the PROBE_LIST file and add entry and return probes for every function
> > - * that is listed.
> > + * Create the rawfbt provider.
> > */
> > static int populate(dtrace_hdl_t *dtp)
> > {
> > dt_provider_t *prv;
> > - FILE *f;
> > - char *buf = NULL;
> > - size_t len = 0;
> > - size_t n = 0;
> > - dtrace_syminfo_t sip;
> > - dtrace_probedesc_t pd;
> > prv = dt_provider_create(dtp, prvname, &dt_rawfbt, &pattr, NULL);
> > if (prv == NULL)
> > return -1; /* errno already set */
> > - f = fopen(PROBE_LIST, "r");
> > - if (f == NULL)
> > + return 0;
> > +}
> > +
> > +/* Create a probe (if it does not exist yet). */
> > +static int provide_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
> > +{
> > + dt_provider_t *prv = dt_provider_lookup(dtp, pdp->prv);
> > +
> > + if (prv == NULL)
> > return 0;
> > + if (dt_probe_lookup(dtp, pdp) != NULL)
> > + return 0;
> > +#ifdef DEBUG_FBT
Hm, something tells me I mailed ut a slightly earlier patch than I intended.
I am pretty sure I made a version of this patch without the DEBUG_FBT stuff.
> > + if (dt_tp_probe_insert(dtp, prv, pdp->prv, pdp->mod, pdp->fun, pdp->prb)) {
> > + fprintf(stderr, "%s(..., PROVIDE %s:%s:%s:%s) - ...\n", __func__, pdp->prv, pdp->mod, pdp->fun, pdp->prb);
> > + return 1;
> > + }
> > +#else
> > + if (dt_tp_probe_insert(dtp, prv, pdp->prv, pdp->mod, pdp->fun, pdp->prb))
> > + return 1;
> > +#endif
> > - while (getline(&buf, &len, f) >= 0) {
> > - char *p;
> > - const char *mod = modname;
> > - dt_probe_t *prp;
> > + return 0;
> > +}
> > - /*
> > - * Here buf is either "funcname\n" or "funcname [modname]\n".
> > - * The last line may not have a linefeed.
> > - */
> > - p = strchr(buf, '\n');
> > - if (p) {
> > - *p = '\0';
> > - if (p > buf && *(--p) == ']')
> > - *p = '\0';
> > +/*
> > + * Try to provide probes for the given probe description. The caller ensures
> > + * that the provider name in probe desxcription (if any) is a match for this
> > + * provider. When this is called, we already know that this provider matches
> > + * the provider component of the probe specification.
> > + */
> > +#define FBT_ENTRY 1
> > +#define FBT_RETURN 2
> > +
> > +static int provide(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
> > +{
> > + int n = 0;
> > + int prb = 0;
> > + dt_module_t *dmp = NULL;
> > + dt_symbol_t *sym = NULL;
> > + dt_htab_next_t *it = NULL;
> > + dtrace_probedesc_t pd;
> > +
> > + dt_modsym_mark_traceable(dtp);
Again, this should be moved lower.
> > +
> > + /*
> > + * Nothing to do if a probe name is specified and cannot match 'entry'
> > + * or 'return'.
> > + */
> > + if (dt_gmatch("entry", pdp->prb))
> > + prb |= FBT_ENTRY;
> > + if (dt_gmatch("return", pdp->prb))
> > + prb |= FBT_RETURN;
> > + if (prb == 0)
> > + return 0;
> > +
> > + /*
> > + * If we have an explicit module name, check it. If not found, we can
> > + * ignore this request.
> > + */
> > + if (pdp->mod[0] != '\0' && strchr(pdp->mod, '*') == NULL) {
> > + dmp = dt_module_lookup_by_name(dtp, pdp->mod);
> > + if (dmp == NULL)
> > + return 0;
> > + }
> > +
> > + /*
> > + * If we have an explicit function name, we start with a basic symbol
> > + * name lookup.
> > + */
> > + if (pdp->fun[0] != '\0' && strchr(pdp->fun, '*') == NULL) {
> > + /* If we have a module, use it. */
> > + if (dmp != NULL) {
> > + sym = dt_module_symbol_by_name(dtp, dmp, pdp->fun);
> > + if (sym == NULL)
> > + return 0;
> > + if (!dt_symbol_traceable(sym))
> > + return 0;
> > +
> > + pd.id = DTRACE_IDNONE;
> > + pd.prv = pdp->prv;
> > + pd.mod = dmp->dm_name;
> > + pd.fun = pdp->fun;
> > +
> > + if (prb & FBT_ENTRY) {
> > + pd.prb = "entry";
> > + n += provide_probe(dtp, &pd);
> > + }
> > + if (prb & FBT_RETURN) {
> > + pd.prb = "return";
> > + n += provide_probe(dtp, &pd);
> > + }
> > +
> > + return n;
> > }
> > - /*
> > - * Now buf is either "funcname" or "funcname [modname". If
> > - * there is no module name provided, we will use the default.
> > - */
> > - p = strchr(buf, ' ');
> > - if (p) {
> > - *p++ = '\0';
> > - if (*p == '[')
> > - p++;
> > + sym = dt_symbol_by_name(dtp, pdp->fun);
> > + while (sym != NULL) {
> > + const char *mod = dt_symbol_module(sym)->dm_name;
> > +
> > + if (dt_symbol_traceable(sym) &&
> > + dt_gmatch(mod, pdp->mod)) {
> > + pd.id = DTRACE_IDNONE;
> > + pd.prv = pdp->prv;
> > + pd.mod = mod;
> > + pd.fun = pdp->fun;
> > +
> > + if (prb & FBT_ENTRY) {
> > + pd.prb = "entry";
> > + n += provide_probe(dtp, &pd);
> > + }
> > + if (prb & FBT_RETURN) {
> > + pd.prb = "return";
> > + n += provide_probe(dtp, &pd);
> > + }
> > +
> > + }
> > + sym = dt_symbol_by_name_next(sym);
> > }
> > -#define strstarts(var, x) (strncmp(var, x, strlen (x)) == 0)
> > - /* Weed out __ftrace_invalid_address___* entries. */
> > - if (strstarts(buf, "__ftrace_invalid_address__") ||
> > - strstarts(buf, "__probestub_") ||
> > - strstarts(buf, "__traceiter_"))
> > + return n;
> > + }
> > +
> > + /*
> > + * No explicit function name. We need to go through all possible
> > + * symbol names and see if they match.
> > + */
> > + while ((sym = dt_htab_next(dtp->dt_kernsyms, &it)) != NULL) {
> > + dt_module_t *smp;
> > + const char *fun;
> > +
> > + /* Ensure the symbol can be traced. */
> > + if (!dt_symbol_traceable(sym))
> > continue;
> > -#undef strstarts
> > - /*
> > - * If we did not see a module name, perform a symbol lookup to
> > - * try to determine the module name.
> > - */
> > - if (!p) {
> > - if (dtrace_lookup_by_name(dtp, DTRACE_OBJ_KMODS, buf,
> > - NULL, &sip) == 0)
> > - mod = sip.object;
> > - } else
> > - mod = p;
> > + /* Match the function name. */
> > + fun = dt_symbol_name(sym);
> > + if (!dt_gmatch(fun, pdp->fun))
> > + continue;
> > - /*
> > - * Due to the lack of module names in
> > - * TRACEFS/available_filter_functions, there are some duplicate
> > - * function names. The kernel does not let us trace functions
> > - * that have duplicates, so we need to remove the existing one.
> > - */
> > - pd.id = DTRACE_IDNONE;
> > - pd.prv = prvname;
> > - pd.mod = mod;
> > - pd.fun = buf;
> > - pd.prb = "entry";
> > - prp = dt_probe_lookup(dtp, &pd);
> > - if (prp != NULL) {
> > - dt_probe_destroy(prp);
> > + /* Validate the module name. */
> > + smp = dt_symbol_module(sym);
> > + if (dmp) {
> > + if (smp != dmp)
> > + continue;
> > + } else if (!dt_gmatch(smp->dm_name, pdp->mod))
> > continue;
> > - }
> > - if (dt_tp_probe_insert(dtp, prv, prvname, mod, buf, "entry"))
> > - n++;
> > - if (dt_tp_probe_insert(dtp, prv, prvname, mod, buf, "return"))
> > - n++;
> > - }
> > + pd.id = DTRACE_IDNONE;
> > + pd.prv = pdp->prv;
> > + pd.mod = smp->dm_name;
> > + pd.fun = fun;
> > - free(buf);
> > - fclose(f);
> > + if (prb & FBT_ENTRY) {
> > + pd.prb = "entry";
> > + n += provide_probe(dtp, &pd);
> > + }
> > + if (prb & FBT_RETURN) {
> > + pd.prb = "return";
> > + n += provide_probe(dtp, &pd);
> > + }
> > + }
> > return n;
> > }
> > @@ -306,6 +384,7 @@ dt_provimpl_t dt_rawfbt = {
> > .name = prvname,
> > .prog_type = BPF_PROG_TYPE_KPROBE,
> > .populate = &populate,
> > + .provide = &provide,
> > .load_prog = &dt_bpf_prog_load,
> > .trampoline = &trampoline,
> > .attach = &attach,
>
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel
More information about the DTrace-devel
mailing list