bpf: refactor special field-type detection
authorMykyta Yatsenko <yatsenko@meta.com>
Tue, 23 Sep 2025 11:23:56 +0000 (12:23 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 23 Sep 2025 14:34:38 +0000 (07:34 -0700)
Reduce code duplication in detection of the known special field types in
map values. This refactoring helps to avoid copying a chunk of code in
the next patch of the series.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20250923112404.668720-2-mykyta.yatsenko5@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/btf.c

index 6473930..c51e16b 100644 (file)
@@ -3478,60 +3478,44 @@ btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
        return BTF_FIELD_FOUND;
 }
 
-#define field_mask_test_name(field_type, field_type_str) \
-       if (field_mask & field_type && !strcmp(name, field_type_str)) { \
-               type = field_type;                                      \
-               goto end;                                               \
-       }
-
 static int btf_get_field_type(const struct btf *btf, const struct btf_type *var_type,
-                             u32 field_mask, u32 *seen_mask,
-                             int *align, int *sz)
-{
-       int type = 0;
+                             u32 field_mask, u32 *seen_mask, int *align, int *sz)
+{
+       const struct {
+               enum btf_field_type type;
+               const char *const name;
+               const bool is_unique;
+       } field_types[] = {
+               { BPF_SPIN_LOCK, "bpf_spin_lock", true },
+               { BPF_RES_SPIN_LOCK, "bpf_res_spin_lock", true },
+               { BPF_TIMER, "bpf_timer", true },
+               { BPF_WORKQUEUE, "bpf_wq", true },
+               { BPF_LIST_HEAD, "bpf_list_head", false },
+               { BPF_LIST_NODE, "bpf_list_node", false },
+               { BPF_RB_ROOT, "bpf_rb_root", false },
+               { BPF_RB_NODE, "bpf_rb_node", false },
+               { BPF_REFCOUNT, "bpf_refcount", false },
+       };
+       int type = 0, i;
        const char *name = __btf_name_by_offset(btf, var_type->name_off);
-
-       if (field_mask & BPF_SPIN_LOCK) {
-               if (!strcmp(name, "bpf_spin_lock")) {
-                       if (*seen_mask & BPF_SPIN_LOCK)
-                               return -E2BIG;
-                       *seen_mask |= BPF_SPIN_LOCK;
-                       type = BPF_SPIN_LOCK;
-                       goto end;
-               }
-       }
-       if (field_mask & BPF_RES_SPIN_LOCK) {
-               if (!strcmp(name, "bpf_res_spin_lock")) {
-                       if (*seen_mask & BPF_RES_SPIN_LOCK)
-                               return -E2BIG;
-                       *seen_mask |= BPF_RES_SPIN_LOCK;
-                       type = BPF_RES_SPIN_LOCK;
-                       goto end;
-               }
-       }
-       if (field_mask & BPF_TIMER) {
-               if (!strcmp(name, "bpf_timer")) {
-                       if (*seen_mask & BPF_TIMER)
-                               return -E2BIG;
-                       *seen_mask |= BPF_TIMER;
-                       type = BPF_TIMER;
-                       goto end;
-               }
-       }
-       if (field_mask & BPF_WORKQUEUE) {
-               if (!strcmp(name, "bpf_wq")) {
-                       if (*seen_mask & BPF_WORKQUEUE)
+       const char *field_type_name;
+       enum btf_field_type field_type;
+       bool is_unique;
+
+       for (i = 0; i < ARRAY_SIZE(field_types); ++i) {
+               field_type = field_types[i].type;
+               field_type_name = field_types[i].name;
+               is_unique = field_types[i].is_unique;
+               if (!(field_mask & field_type) || strcmp(name, field_type_name))
+                       continue;
+               if (is_unique) {
+                       if (*seen_mask & field_type)
                                return -E2BIG;
-                       *seen_mask |= BPF_WORKQUEUE;
-                       type = BPF_WORKQUEUE;
-                       goto end;
+                       *seen_mask |= field_type;
                }
+               type = field_type;
+               goto end;
        }
-       field_mask_test_name(BPF_LIST_HEAD, "bpf_list_head");
-       field_mask_test_name(BPF_LIST_NODE, "bpf_list_node");
-       field_mask_test_name(BPF_RB_ROOT,   "bpf_rb_root");
-       field_mask_test_name(BPF_RB_NODE,   "bpf_rb_node");
-       field_mask_test_name(BPF_REFCOUNT,  "bpf_refcount");
 
        /* Only return BPF_KPTR when all other types with matchable names fail */
        if (field_mask & (BPF_KPTR | BPF_UPTR) && !__btf_type_is_struct(var_type)) {
@@ -3545,8 +3529,6 @@ end:
        return type;
 }
 
-#undef field_mask_test_name
-
 /* Repeat a number of fields for a specified number of times.
  *
  * Copy the fields starting from the first field and repeat them for