bpf: refactory struct_ops type initialization to a function.
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>
This commit is contained in:
parent
b7d1af3791
commit
3b1f89e747
@ -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);
|
||||
|
@ -110,15 +110,95 @@ 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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log)
|
||||
{
|
||||
struct bpf_struct_ops *st_ops;
|
||||
s32 module_id;
|
||||
u32 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);
|
||||
@ -127,85 +207,14 @@ void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log)
|
||||
|
||||
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");
|
||||
pr_warn("Cannot find struct module in %s\n", 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];
|
||||
|
||||
if (strlen(st_ops->name) + VALUE_PREFIX_LEN >=
|
||||
sizeof(value_name)) {
|
||||
pr_warn("struct_ops name %s is too long\n",
|
||||
st_ops->name);
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for_each_member(j, 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);
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
bpf_struct_ops_init_one(st_ops, btf, log);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user