bpf: add struct_ops_tab to btf.
authorKui-Feng Lee <thinker.li@gmail.com>
Fri, 19 Jan 2024 22:49:55 +0000 (14:49 -0800)
committerMartin KaFai Lau <martin.lau@kernel.org>
Wed, 24 Jan 2024 00:37:44 +0000 (16:37 -0800)
Maintain a registry of registered struct_ops types in the per-btf (module)
struct_ops_tab. This registry allows for easy lookup of struct_ops types
that are registered by a specific module.

It is a preparation work for supporting kernel module struct_ops in a
latter patch. Each struct_ops will be registered under its own kernel
module btf and will be stored in the newly added btf->struct_ops_tab. The
bpf verifier and bpf syscall (e.g. prog and map cmd) can find the
struct_ops and its btf type/size/id... information from
btf->struct_ops_tab.

Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
Link: https://lore.kernel.org/r/20240119225005.668602-5-thinker.li@gmail.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
kernel/bpf/btf.c

index f8735a2ec5d4a99d60d62eed73be6f736860da3e..2e5e6ec5d965c711f07a03b53e9c0b04bd74e4c8 100644 (file)
@@ -241,6 +241,12 @@ struct btf_id_dtor_kfunc_tab {
        struct btf_id_dtor_kfunc dtors[];
 };
 
+struct btf_struct_ops_tab {
+       u32 cnt;
+       u32 capacity;
+       struct bpf_struct_ops_desc ops[];
+};
+
 struct btf {
        void *data;
        struct btf_type **types;
@@ -258,6 +264,7 @@ struct btf {
        struct btf_kfunc_set_tab *kfunc_set_tab;
        struct btf_id_dtor_kfunc_tab *dtor_kfunc_tab;
        struct btf_struct_metas *struct_meta_tab;
+       struct btf_struct_ops_tab *struct_ops_tab;
 
        /* split BTF support */
        struct btf *base_btf;
@@ -1688,11 +1695,20 @@ static void btf_free_struct_meta_tab(struct btf *btf)
        btf->struct_meta_tab = NULL;
 }
 
+static void btf_free_struct_ops_tab(struct btf *btf)
+{
+       struct btf_struct_ops_tab *tab = btf->struct_ops_tab;
+
+       kfree(tab);
+       btf->struct_ops_tab = NULL;
+}
+
 static void btf_free(struct btf *btf)
 {
        btf_free_struct_meta_tab(btf);
        btf_free_dtor_kfunc_tab(btf);
        btf_free_kfunc_set_tab(btf);
+       btf_free_struct_ops_tab(btf);
        kvfree(btf->types);
        kvfree(btf->resolved_sizes);
        kvfree(btf->resolved_ids);
@@ -8689,3 +8705,42 @@ bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log,
 
        return !strncmp(reg_name, arg_name, cmp_len);
 }
+
+static int
+btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops)
+{
+       struct btf_struct_ops_tab *tab, *new_tab;
+       int i;
+
+       tab = btf->struct_ops_tab;
+       if (!tab) {
+               tab = kzalloc(offsetof(struct btf_struct_ops_tab, ops[4]),
+                             GFP_KERNEL);
+               if (!tab)
+                       return -ENOMEM;
+               tab->capacity = 4;
+               btf->struct_ops_tab = tab;
+       }
+
+       for (i = 0; i < tab->cnt; i++)
+               if (tab->ops[i].st_ops == st_ops)
+                       return -EEXIST;
+
+       if (tab->cnt == tab->capacity) {
+               new_tab = krealloc(tab,
+                                  offsetof(struct btf_struct_ops_tab,
+                                           ops[tab->capacity * 2]),
+                                  GFP_KERNEL);
+               if (!new_tab)
+                       return -ENOMEM;
+               tab = new_tab;
+               tab->capacity *= 2;
+               btf->struct_ops_tab = tab;
+       }
+
+       tab->ops[btf->struct_ops_tab->cnt].st_ops = st_ops;
+
+       btf->struct_ops_tab->cnt++;
+
+       return 0;
+}