]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
libbpf: Add section handlers for sleepable tracepoints
authorMykyta Yatsenko <yatsenko@meta.com>
Wed, 22 Apr 2026 19:41:10 +0000 (12:41 -0700)
committerKumar Kartikeya Dwivedi <memxor@gmail.com>
Wed, 22 Apr 2026 20:44:30 +0000 (22:44 +0200)
Add SEC_DEF entries for sleepable tracepoint variants:
  - "tp_btf.s+"     for sleepable BTF-based raw tracepoints
  - "raw_tp.s+"     for sleepable raw tracepoints
  - "raw_tracepoint.s+" (alias)
  - "tp.s+"         for sleepable classic tracepoints
  - "tracepoint.s+" (alias)

Extract sec_name_match_prefix() to share the prefix matching logic
between attach_tp() and attach_raw_tp(), eliminating duplicated
loops and hardcoded strcmp() checks for bare section names.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/bpf/20260422-sleepable_tracepoints-v13-5-99005dff21ef@meta.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
tools/lib/bpf/libbpf.c

index 83aae7a39d36def2eefee36f0c6e12a3bec03748..ab2071fdd3e8b39a1f5215c0e14052568f2da72b 100644 (file)
@@ -10018,11 +10018,16 @@ static const struct bpf_sec_def section_defs[] = {
        SEC_DEF("netkit/peer",          SCHED_CLS, BPF_NETKIT_PEER, SEC_NONE),
        SEC_DEF("tracepoint+",          TRACEPOINT, 0, SEC_NONE, attach_tp),
        SEC_DEF("tp+",                  TRACEPOINT, 0, SEC_NONE, attach_tp),
+       SEC_DEF("tracepoint.s+",        TRACEPOINT, 0, SEC_SLEEPABLE, attach_tp),
+       SEC_DEF("tp.s+",                TRACEPOINT, 0, SEC_SLEEPABLE, attach_tp),
        SEC_DEF("raw_tracepoint+",      RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
        SEC_DEF("raw_tp+",              RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
+       SEC_DEF("raw_tracepoint.s+",    RAW_TRACEPOINT, 0, SEC_SLEEPABLE, attach_raw_tp),
+       SEC_DEF("raw_tp.s+",            RAW_TRACEPOINT, 0, SEC_SLEEPABLE, attach_raw_tp),
        SEC_DEF("raw_tracepoint.w+",    RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
        SEC_DEF("raw_tp.w+",            RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
        SEC_DEF("tp_btf+",              TRACING, BPF_TRACE_RAW_TP, SEC_ATTACH_BTF, attach_trace),
+       SEC_DEF("tp_btf.s+",            TRACING, BPF_TRACE_RAW_TP, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_trace),
        SEC_DEF("fentry+",              TRACING, BPF_TRACE_FENTRY, SEC_ATTACH_BTF, attach_trace),
        SEC_DEF("fmod_ret+",            TRACING, BPF_MODIFY_RETURN, SEC_ATTACH_BTF, attach_trace),
        SEC_DEF("fexit+",               TRACING, BPF_TRACE_FEXIT, SEC_ATTACH_BTF, attach_trace),
@@ -13152,25 +13157,61 @@ struct bpf_link *bpf_program__attach_tracepoint(const struct bpf_program *prog,
        return bpf_program__attach_tracepoint_opts(prog, tp_category, tp_name, NULL);
 }
 
+/*
+ * Match section name against a prefix array. Returns pointer past
+ * "prefix/" on match, empty string for bare sections (exact prefix
+ * match), or NULL if no prefix matches.
+ */
+static const char *sec_name_match_prefix(const char *sec_name,
+                                        const char *const *prefixes,
+                                        size_t n)
+{
+       size_t i;
+
+       for (i = 0; i < n; i++) {
+               size_t pfx_len;
+
+               if (!str_has_pfx(sec_name, prefixes[i]))
+                       continue;
+
+               pfx_len = strlen(prefixes[i]);
+               if (sec_name[pfx_len] == '\0')
+                       return sec_name + pfx_len;
+
+               if (sec_name[pfx_len] != '/' || sec_name[pfx_len + 1] == '\0')
+                       continue;
+
+               return sec_name + pfx_len + 1;
+       }
+       return NULL;
+}
+
 static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link)
 {
+       static const char *const prefixes[] = {
+               "tp.s",
+               "tp",
+               "tracepoint.s",
+               "tracepoint",
+       };
        char *sec_name, *tp_cat, *tp_name;
+       const char *match;
 
        *link = NULL;
 
-       /* no auto-attach for SEC("tp") or SEC("tracepoint") */
-       if (strcmp(prog->sec_name, "tp") == 0 || strcmp(prog->sec_name, "tracepoint") == 0)
+       match = sec_name_match_prefix(prog->sec_name, prefixes, ARRAY_SIZE(prefixes));
+       if (!match) {
+               pr_warn("prog '%s': invalid section name '%s'\n", prog->name, prog->sec_name);
+               return -EINVAL;
+       }
+       if (!match[0]) /* bare section name no autoattach */
                return 0;
 
        sec_name = strdup(prog->sec_name);
        if (!sec_name)
                return -ENOMEM;
 
-       /* extract "tp/<category>/<name>" or "tracepoint/<category>/<name>" */
-       if (str_has_pfx(prog->sec_name, "tp/"))
-               tp_cat = sec_name + sizeof("tp/") - 1;
-       else
-               tp_cat = sec_name + sizeof("tracepoint/") - 1;
+       tp_cat = sec_name + (match - prog->sec_name);
        tp_name = strchr(tp_cat, '/');
        if (!tp_name) {
                free(sec_name);
@@ -13234,37 +13275,22 @@ static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf
                "raw_tracepoint",
                "raw_tp.w",
                "raw_tracepoint.w",
+               "raw_tp.s",
+               "raw_tracepoint.s",
        };
-       size_t i;
-       const char *tp_name = NULL;
+       const char *match;
 
        *link = NULL;
 
-       for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
-               size_t pfx_len;
-
-               if (!str_has_pfx(prog->sec_name, prefixes[i]))
-                       continue;
-
-               pfx_len = strlen(prefixes[i]);
-               /* no auto-attach case of, e.g., SEC("raw_tp") */
-               if (prog->sec_name[pfx_len] == '\0')
-                       return 0;
-
-               if (prog->sec_name[pfx_len] != '/')
-                       continue;
-
-               tp_name = prog->sec_name + pfx_len + 1;
-               break;
-       }
-
-       if (!tp_name) {
-               pr_warn("prog '%s': invalid section name '%s'\n",
-                       prog->name, prog->sec_name);
+       match = sec_name_match_prefix(prog->sec_name, prefixes, ARRAY_SIZE(prefixes));
+       if (!match) {
+               pr_warn("prog '%s': invalid section name '%s'\n", prog->name, prog->sec_name);
                return -EINVAL;
        }
+       if (!match[0])
+               return 0;
 
-       *link = bpf_program__attach_raw_tracepoint(prog, tp_name);
+       *link = bpf_program__attach_raw_tracepoint(prog, match);
        return libbpf_get_error(*link);
 }