bpf: refactory struct_ops type initialization to a function.
authorKui-Feng Lee <thinker.li@gmail.com>
Fri, 19 Jan 2024 22:49:52 +0000 (14:49 -0800)
committerMartin KaFai Lau <martin.lau@kernel.org>
Wed, 24 Jan 2024 00:37:43 +0000 (16:37 -0800)
Move the majority of the code to bpf_struct_ops_init_one(), which can then
be utilized for the initialization of newly registered dynamically
allocated struct_ops types in the following patches.

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

index cf5c6ff..932af16 100644 (file)
@@ -137,6 +137,7 @@ struct btf_struct_metas {
 
 extern const struct file_operations btf_fops;
 
+const char *btf_get_name(const struct btf *btf);
 void btf_get(struct btf *btf);
 void btf_put(struct btf *btf);
 int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_sz);
index 02068bd..96cba76 100644 (file)
@@ -110,102 +110,111 @@ const struct bpf_prog_ops bpf_struct_ops_prog_ops = {
 
 static const struct btf_type *module_type;
 
-void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log)
+static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops,
+                                   struct btf *btf,
+                                   struct bpf_verifier_log *log)
 {
-       s32 type_id, value_id, module_id;
        const struct btf_member *member;
-       struct bpf_struct_ops *st_ops;
        const struct btf_type *t;
+       s32 type_id, value_id;
        char value_name[128];
        const char *mname;
-       u32 i, j;
+       int i;
 
-       /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */
-#define BPF_STRUCT_OPS_TYPE(_name) BTF_TYPE_EMIT(struct bpf_struct_ops_##_name);
-#include "bpf_struct_ops_types.h"
-#undef BPF_STRUCT_OPS_TYPE
+       if (strlen(st_ops->name) + VALUE_PREFIX_LEN >=
+           sizeof(value_name)) {
+               pr_warn("struct_ops name %s is too long\n",
+                       st_ops->name);
+               return;
+       }
+       sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name);
 
-       module_id = btf_find_by_name_kind(btf, "module", BTF_KIND_STRUCT);
-       if (module_id < 0) {
-               pr_warn("Cannot find struct module in btf_vmlinux\n");
+       value_id = btf_find_by_name_kind(btf, value_name,
+                                        BTF_KIND_STRUCT);
+       if (value_id < 0) {
+               pr_warn("Cannot find struct %s in %s\n",
+                       value_name, btf_get_name(btf));
                return;
        }
-       module_type = btf_type_by_id(btf, module_id);
 
-       for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) {
-               st_ops = bpf_struct_ops[i];
+       type_id = btf_find_by_name_kind(btf, st_ops->name,
+                                       BTF_KIND_STRUCT);
+       if (type_id < 0) {
+               pr_warn("Cannot find struct %s in %s\n",
+                       st_ops->name, btf_get_name(btf));
+               return;
+       }
+       t = btf_type_by_id(btf, type_id);
+       if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) {
+               pr_warn("Cannot support #%u members in struct %s\n",
+                       btf_type_vlen(t), st_ops->name);
+               return;
+       }
 
-               if (strlen(st_ops->name) + VALUE_PREFIX_LEN >=
-                   sizeof(value_name)) {
-                       pr_warn("struct_ops name %s is too long\n",
+       for_each_member(i, t, member) {
+               const struct btf_type *func_proto;
+
+               mname = btf_name_by_offset(btf, member->name_off);
+               if (!*mname) {
+                       pr_warn("anon member in struct %s is not supported\n",
                                st_ops->name);
-                       continue;
+                       break;
                }
-               sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name);
 
-               value_id = btf_find_by_name_kind(btf, value_name,
-                                                BTF_KIND_STRUCT);
-               if (value_id < 0) {
-                       pr_warn("Cannot find struct %s in btf_vmlinux\n",
-                               value_name);
-                       continue;
+               if (__btf_member_bitfield_size(t, member)) {
+                       pr_warn("bit field member %s in struct %s is not supported\n",
+                               mname, st_ops->name);
+                       break;
                }
 
-               type_id = btf_find_by_name_kind(btf, st_ops->name,
-                                               BTF_KIND_STRUCT);
-               if (type_id < 0) {
-                       pr_warn("Cannot find struct %s in btf_vmlinux\n",
-                               st_ops->name);
-                       continue;
-               }
-               t = btf_type_by_id(btf, type_id);
-               if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) {
-                       pr_warn("Cannot support #%u members in struct %s\n",
-                               btf_type_vlen(t), st_ops->name);
-                       continue;
+               func_proto = btf_type_resolve_func_ptr(btf,
+                                                      member->type,
+                                                      NULL);
+               if (func_proto &&
+                   btf_distill_func_proto(log, btf,
+                                          func_proto, mname,
+                                          &st_ops->func_models[i])) {
+                       pr_warn("Error in parsing func ptr %s in struct %s\n",
+                               mname, st_ops->name);
+                       break;
                }
+       }
 
-               for_each_member(j, t, member) {
-                       const struct btf_type *func_proto;
+       if (i == btf_type_vlen(t)) {
+               if (st_ops->init(btf)) {
+                       pr_warn("Error in init bpf_struct_ops %s\n",
+                               st_ops->name);
+               } else {
+                       st_ops->type_id = type_id;
+                       st_ops->type = t;
+                       st_ops->value_id = value_id;
+                       st_ops->value_type = btf_type_by_id(btf,
+                                                           value_id);
+               }
+       }
+}
 
-                       mname = btf_name_by_offset(btf, member->name_off);
-                       if (!*mname) {
-                               pr_warn("anon member in struct %s is not supported\n",
-                                       st_ops->name);
-                               break;
-                       }
+void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log)
+{
+       struct bpf_struct_ops *st_ops;
+       s32 module_id;
+       u32 i;
 
-                       if (__btf_member_bitfield_size(t, member)) {
-                               pr_warn("bit field member %s in struct %s is not supported\n",
-                                       mname, st_ops->name);
-                               break;
-                       }
+       /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */
+#define BPF_STRUCT_OPS_TYPE(_name) BTF_TYPE_EMIT(struct bpf_struct_ops_##_name);
+#include "bpf_struct_ops_types.h"
+#undef BPF_STRUCT_OPS_TYPE
 
-                       func_proto = btf_type_resolve_func_ptr(btf,
-                                                              member->type,
-                                                              NULL);
-                       if (func_proto &&
-                           btf_distill_func_proto(log, btf,
-                                                  func_proto, mname,
-                                                  &st_ops->func_models[j])) {
-                               pr_warn("Error in parsing func ptr %s in struct %s\n",
-                                       mname, st_ops->name);
-                               break;
-                       }
-               }
+       module_id = btf_find_by_name_kind(btf, "module", BTF_KIND_STRUCT);
+       if (module_id < 0) {
+               pr_warn("Cannot find struct module in %s\n", btf_get_name(btf));
+               return;
+       }
+       module_type = btf_type_by_id(btf, module_id);
 
-               if (j == btf_type_vlen(t)) {
-                       if (st_ops->init(btf)) {
-                               pr_warn("Error in init bpf_struct_ops %s\n",
-                                       st_ops->name);
-                       } else {
-                               st_ops->type_id = type_id;
-                               st_ops->type = t;
-                               st_ops->value_id = value_id;
-                               st_ops->value_type = btf_type_by_id(btf,
-                                                                   value_id);
-                       }
-               }
+       for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) {
+               st_ops = bpf_struct_ops[i];
+               bpf_struct_ops_init_one(st_ops, btf, log);
        }
 }
 
index 4f532b3..f8735a2 100644 (file)
@@ -1707,6 +1707,11 @@ static void btf_free_rcu(struct rcu_head *rcu)
        btf_free(btf);
 }
 
+const char *btf_get_name(const struct btf *btf)
+{
+       return btf->name;
+}
+
 void btf_get(struct btf *btf)
 {
        refcount_inc(&btf->refcnt);