Registering struct_ops types from modules.
Subsystems (4)
RFC 1/1 Registering struct_ops types from modules.
From: Kui-Feng Lee <[email protected]>
Resend to remove noise!
Given the current constraints of the current implementation, struct_ops cannot be registered dynamically. This presents a significant limitation for modules like fuse-bpf, which seeks to implement a new struct_ops type. To address this issue, here it proposes the introduction of a new API. This API will enable the registering of new struct_ops types from modules.
The following code is an example of how to implement a new struct_ops type in a module with the proposed API. It adds a new type bpf_testmod_ops in the bpf_testmod module. And, call register_bpf_struct_ops() and unregister_bpf_struct_ops() when init and exit the module.
A module may forget or be unable to call unregister_bpf_struct_ops(). That may cause tragedies. So, the bpf_struct_ops subsystem should handle it automatically, as a fallback, when the module registered a struct_ops type is unloaded.
--- .../selftests/bpf/bpf_testmod/bpf_testmod.c | 58 +++++++++++++++++++ .../selftests/bpf/bpf_testmod/bpf_testmod.h | 5 ++ .../bpf/prog_tests/test_struct_ops_module.c | 49 ++++++++++++++++ .../selftests/bpf/progs/struct_ops_module.c | 27 +++++++++ 9 files changed, 170 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c create mode 100644 tools/testing/selftests/bpf/progs/struct_ops_module.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +58 -0
@@ -1,5 +1,6 @@// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2020 Facebook */ +#include <linux/bpf.h> #include <linux/btf.h> #include <linux/btf_ids.h> #include <linux/error-injection.h>
@@ -517,11 +518,62 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_test_static_unused_arg) BTF_ID_FLAGS(func, bpf_kfunc_call_test_offset) BTF_SET8_END(bpf_testmod_check_kfunc_ids) +#ifdef CONFIG_DEBUG_INFO_BTF_MODULES + +static int bpf_testmod_ops_init (struct btf *btf) +{ +return 0 ; +} + +static bool bpf_testmod_ops_is_valid_access (int off,int size, +enum bpf_access_type type, +const struct bpf_prog *prog, +struct bpf_insn_access_aux *info) +{ +return 0 ; +} + +static int bpf_testmod_ops_init_member (const struct btf_type *t, +const struct btf_member *member, +void *kdata,const void *udata) +{ +return 0 ; +} +static const struct btf_kfunc_id_set bpf_testmod_kfunc_set = { .owner =THIS_MODULE , .set = &bpf_testmod_check_kfunc_ids, }; +static const struct bpf_verifier_ops bpf_testmod_verifier_ops = { + .is_valid_access = bpf_testmod_ops_is_valid_access, +}; + +static int bpf_dummy_reg (void *kdata) +{ +return 0 ; +} + +static void bpf_dummy_unreg (void *kdata) +{ +} + +struct bpf_struct_ops bpf_bpf_testmod_ops = { + .verifier_ops = &bpf_testmod_verifier_ops, + .init = bpf_testmod_ops_init, + .init_member = bpf_testmod_ops_init_member, + .reg = bpf_dummy_reg, + .unreg = bpf_dummy_unreg, + .name ="bpf_testmod_ops" , +}; + +static struct bpf_struct_ops_mod bpf_testmod_struct_ops = { + .owner =THIS_MODULE , + .st_ops = &bpf_bpf_testmod_ops, +}; + +#endif /* CONFIG_DEBUG_INFO_BTF_MODULES */ +extern int bpf_fentry_test1 (int a);static int bpf_testmod_init (void )
@@ -532,6 +584,9 @@ static int bpf_testmod_init(void) ret = ret ?:register_btf_kfunc_id_set (BPF_PROG_TYPE_SCHED_CLS , &bpf_testmod_kfunc_set); ret = ret ?:register_btf_kfunc_id_set (BPF_PROG_TYPE_TRACING , &bpf_testmod_kfunc_set); ret = ret ?:register_btf_kfunc_id_set (BPF_PROG_TYPE_SYSCALL , &bpf_testmod_kfunc_set); +#ifdef CONFIG_DEBUG_INFO_BTF_MODULES + ret = ret ?:register_bpf_struct_ops (&bpf_testmod_struct_ops); +#endif if (ret <0 )return ret;if (bpf_fentry_test1 (0 ) <0 )
@@ -541,6 +596,9 @@ static int bpf_testmod_init(void)static void bpf_testmod_exit (void ) { +#ifdef CONFIG_DEBUG_INFO_BTF_MODULES +unregister_bpf_struct_ops (&bpf_testmod_struct_ops); +#endif return sysfs_remove_bin_file (kernel_kobj, &bin_attr_bpf_testmod_file); }
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h +5 -0
@@ -28,4 +28,9 @@ struct bpf_iter_testmod_seq { int cnt; }; +struct bpf_testmod_ops { +int (*test_1)(void ); +int (*test_2)(int a,int b); +}; +#endif /* _BPF_TESTMOD_H */
tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c new file +49 -0
49 lines not on this page · raw message
tools/testing/selftests/bpf/progs/struct_ops_module.c new file +27 -0
@@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ +#include <vmlinux.h> +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include "../bpf_testmod/bpf_testmod.h" + +char _license[] SEC("license") = "GPL"; + +SEC("struct_ops/test_1") +int BPF_PROG (test_1 ) +{ +return 0xdeadbeef ; +} + +SEC("struct_ops/test_2") +int BPF_PROG (test_2 ,int a,int b) +{ +return a + b; +} + +SEC(".struct_ops.link") +struct bpf_testmod_ops testmod_1 = { + .test_1 = (void *)test_1, + .test_2 = (void *)test_2, +}; +
Signature · 1 line
2.34.1
Quoted 12 lines · On Thu, Sep 7, 2023 at 1:32 PM <[email protected]> wrote:
From: Kui-Feng Lee <[email protected]>
Resend to remove noise!
Given the current constraints of the current implementation,
struct_opscannot be registered dynamically. This presents a significant limitation for modules like fuse-bpf, which seeks to implement a newstruct_opstype. To address this issue, here it proposes the introduction of a new API. This API will enable the registering of newstruct_opstypes from modules.
Quoted 4 lines
The following code is an example of how to implement a new
struct_opstype in a module with the proposed API. It adds a new typebpf_testmod_opsin thebpf_testmodmodule. And, callregister_bpf_struct_ops()andunregister_bpf_struct_ops()when init and exit the module.
register_bpf_struct_ops() api implementation is missing in the diff.
Quoted 13 lines · Alexei Starovoitov
Quoted 12 lines · On Thu, Sep 7, 2023 at 1:32 PM <[email protected]> wrote:
From: Kui-Feng Lee <[email protected]>
Resend to remove noise!
Given the current constraints of the current implementation,
struct_opscannot be registered dynamically. This presents a significant limitation for modules like fuse-bpf, which seeks to implement a newstruct_opstype. To address this issue, here it proposes the introduction of a new API. This API will enable the registering of newstruct_opstypes from modules.
Quoted 6 lines
Quoted 4 lines
The following code is an example of how to implement a new
struct_opstype in a module with the proposed API. It adds a new typebpf_testmod_opsin thebpf_testmodmodule. And, callregister_bpf_struct_ops()andunregister_bpf_struct_ops()when init and exit the module.
register_bpf_struct_ops()api implementation is missing in the diff.
Sorry for the confusion!
The purpose of this RFC to check how people think about the API itself.