Re: [PATCH bpf-next v3 2/4] bpf: Introduce __bpf_kfunc_mark_deprecated annotation

Mykyta Yatsenko
2026-04-20T14:21:14Z

On 4/18/26 6:16 PM, Kumar Kartikeya Dwivedi wrote:
> Documentation for KF_DEPRECATED documents the expectations and
> recommendations for deprecating existing kfuncs. Until now, such a flag
> never materialized. Unlike other kfunc flags, more context needs to be
> carried with such a flag, thus we introduce __bpf_kfunc_mark_deprecated
> as a replacement for the (non-existent) kfunc flag which takes a
> replacement kfunc to provide recommendations to the user.
>
> Apply it to all existing impl-suffixed kfuncs that are preserved for
> backwards compatibility for a few kernel releases, after we introduced
> versions with KF_IMPLICIT_ARGS.
>
> Note that this is only supported by LLVM-compiled kernels as of writing,
> since GCC does not support for BTF declaration tags.
>
> Cc: Vineet Gupta <vineet.gupta@linux.dev>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> ---
> Documentation/bpf/kfuncs.rst | 42 ++++++++++---------
> include/linux/bpf_verifier.h | 1 +
> include/linux/btf.h | 5 +++
> include/linux/compiler_types.h | 14 ++++++-
> kernel/bpf/helpers.c | 8 ++++
> kernel/bpf/verifier.c | 41 ++++++++++++++++++
> .../selftests/bpf/test_kmods/bpf_testmod.c | 1 +
> 7 files changed, 90 insertions(+), 22 deletions(-)
>
...
> +static void warn_for_deprecated_kfuncs(struct bpf_verifier_env *env,
> + struct bpf_kfunc_call_arg_meta *meta,
> + int insn_idx, s16 offset)
> +{
> + const struct bpf_line_info *linfo;
> + const char *replacement;
> + const struct btf_type *t;
> + struct bpf_kfunc_desc *desc;
> + const char *file;
> + int line_num;
> +
> + if (!env->prog->aux->btf)
> + return;
> +
> + t = btf_type_by_id(meta->btf, meta->func_id);
> + replacement = btf_find_decl_tag_value(meta->btf, t, -1, BPF_KFUNC_DECL_TAG_DEPRECATED);
> + if (IS_ERR(replacement) || str_is_empty(replacement))
> + return;
> +
> + desc = find_kfunc_desc(env->prog, meta->func_id, offset);
> + if (!desc || desc->warned_deprecated)
> + return;
> +
> + linfo = bpf_find_linfo(env->prog, insn_idx);
> + if (linfo) {
> + bpf_get_linfo_file_line(env->prog->aux->btf, linfo, &file, NULL, &line_num);
> + warn(env, "%s:%d (insn #%d) uses deprecated kfunc %s(), which will be removed.\n",
> + file, line_num, insn_idx, meta->func_name);
> + } else {
> + warn(env, "(insn #%d) uses deprecated kfunc %s(), which will be removed.\n",
> + insn_idx, meta->func_name);
> + }
> +
> + warn(env, "Switch to kfunc %s() instead.\n", replacement);
> + warn(env, "For older kernels, choose the correct kfunc using bpf_ksym_exists().\n");

Is it right to reference bpf_ksym_exists() macro from the verifier log,
what if user does not use bpf_helpers.h header?

> +
> + desc->warned_deprecated = true;
> +}
> +
> static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
> int *insn_idx_p)
> {
> @@ -13016,6 +13055,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>
> insn_aux->is_iter_next = bpf_is_iter_next_kfunc(&meta);
>
> + warn_for_deprecated_kfuncs(env, &meta, insn_idx, insn->off);
> +
> if (!insn->off &&
> (insn->imm == special_kfunc_list[KF_bpf_res_spin_lock] ||
> insn->imm == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])) {
> diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> index d876314a4d67..5a57a92a8f8c 100644
> --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> @@ -1252,6 +1252,7 @@ __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_assoc(struct st_ops_args *args, st
>
> __bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
> __bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
> +__bpf_kfunc_mark_deprecated(bpf_kfunc_implicit_arg_legacy)
> __bpf_kfunc int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, struct bpf_prog_aux *aux);
>
> /* hook targets */