All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kumar Kartikeya Dwivedi" <memxor@gmail.com>
To: <bot+bpf-ci@kernel.org>, <bpf@vger.kernel.org>
Cc: <andrii@kernel.org>, <ast@kernel.org>, <daniel@iogearbox.net>,
	<eddyz87@gmail.com>, <emil@etsalapatis.com>, <kkd@meta.com>,
	<kernel-team@meta.com>, <martin.lau@kernel.org>,
	<yonghong.song@linux.dev>, <clm@meta.com>,
	<ihor.solodrai@linux.dev>
Subject: Re: [PATCH bpf-next v5 1/3] bpf: Show more useful info in stack depth stats
Date: Tue, 04 Aug 2026 11:48:39 +0200	[thread overview]
Message-ID: <DKG2CR8JD0F6.1MUAY6BVAIHLZ@gmail.com> (raw)
In-Reply-To: <89233ff19ba231586f1785f43c58f90c0d0ff756a8ff2e0232c475cfaea0b599@mail.kernel.org>

On Tue Aug 4, 2026 at 11:31 AM CEST, bot+bpf-ci wrote:
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index b274004fccfd9..80c249906fd39 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -18777,15 +18777,21 @@ static void print_verification_stats(struct bpf_verifier_env *env)
>>  	if (env->log.level & BPF_LOG_STATS) {
>>  		verbose(env, "verification time %lld usec\n",
>>  			div_u64(env->verification_time, 1000));
>> -		verbose(env, "stack depth %d", env->subprog_info[0].stack_depth);
>> -		for (i = 1; i < subprog_cnt; i++)
>> -			verbose(env, "+%d", env->subprog_info[i].stack_depth);
>> -		verbose(env, " max %d\n", env->max_stack_depth);
>> -		verbose(env, "insns processed %d", env->subprog_info[0].insn_processed);
>> -		for (i = 1; i < subprog_cnt; i++)
>> -			if (bpf_subprog_is_global(env, i))
>> -				verbose(env, "+%d", env->subprog_info[i].insn_processed);
>> -		verbose(env, "\n");
>> +		verbose(env, "stack depth max %d\n", env->max_stack_depth);
>> +		for (i = 0; i < subprog_cnt; i++) {
>> +			const char *name = env->subprog_info[i].name;
>> +
>> +			if (!name || !name[0])
>> +				name = "<unknown>";
>> +			if (i == 0)
>> +				verbose(env, "prog (%s) insns %d stack %d\n", name,
>> +					env->subprog_info[i].insn_processed,
>> +					env->subprog_info[i].stack_depth);
>> +			else
>> +				verbose(env, "subprog %d (%s) insns %d stack %d\n", i, name,
>> +					env->subprog_info[i].insn_processed,
>> +					env->subprog_info[i].stack_depth);
>> +		}
>>  	}
>
> The new loop prints insns %d for every subprogram, but
> subprog_info[i].insn_processed is only ever written for the main program
> and for global subprograms. The old code encoded exactly that with an
> explicit filter:
>
> kernel/bpf/verifier.c (old):
>     verbose(env, "insns processed %d", env->subprog_info[0].insn_processed);
>     for (i = 1; i < subprog_cnt; i++)
>         if (bpf_subprog_is_global(env, i))          /* <-- filter removed */
>             verbose(env, "+%d", env->subprog_info[i].insn_processed);
>
> The only two writers are do_check_main() and do_check_subprogs(). The
> latter is reached only after:
>
> kernel/bpf/verifier.c:18711
>     if (!bpf_subprog_is_global(env, i))
>         continue;
>
> and the whole function returns early at:
>
> kernel/bpf/check_btf.c:1070
>     if (!aux->func_info)
>         return 0;
>
> env is kvzalloc'd, so for every static subprogram, callback (bpf_loop,
> timer), and every subprogram of a program loaded without BTF func_info,
> insn_processed is structurally always 0. Those instructions were counted
> into the caller's record, because static subprogs are verified inline as
> part of the calling frame.
>
> Does this mean that for any program using static subprograms or callbacks
> the new per-subprog insns field shows 0 rather than where verifier work is
> actually spent?
>
> The patch's own new expectations confirm this. Every "subprog N (...) insns"
> line added in this commit is for a non-global subprogram (dummy_loop_callback,
> cumulative_stack_depth_subprog, timer_cb1, subprog1, subprog2), and each
> uses the permissive {{[0-9]+}} regex that matches 0.
>
> This directly contradicts the stated purpose: "it is hard to see where
> verifier work is spent". Either the bpf_subprog_is_global() filter should
> be kept (omit the field, or the whole record, for subprograms that are not
> independently verified), or the field should be marked as not-measured
> (e.g. insns -) so that 0 is not mistaken for a real measurement.
>

This is valid, and should be considered.

> Related coverage loss from the same root cause:
>
>> diff --git a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
>> index 67dc352addfd7..1755f133f0205 100644
>> --- a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
>> +++ b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
>> @@ -52,7 +52,7 @@ __msg("('global_calls_good_only') is global and assumed valid.")
>>  /* eventually global_good() is transitively validated as well */
>>  __msg("Validating global_good() func")
>>  __msg("('global_good') is safe for any args that match its prototype")
>> -__msg("insns processed {{[0-9]+\\+[0-9]+\\+[0-9]+$}}")
>> +__msg("prog (chained_global_func_calls_success) insns {{[0-9]+}} stack")
>
> The old anchored pattern asserted that exactly three independent counts
> were emitted (main + global_calls_good_only + global_good). The
> replacement checks only the main-program record and asserts nothing about
> the two global subprogram records. Could the one test that actually
> validated per-global-subprog instruction accounting be preserved?
>
>
> The BPF_LOG_STATS payload grows roughly an order of magnitude per
> subprogram, which can turn a previously-succeeding program load into
> -ENOSPC for callers that pass their own fixed log buffer.
>
> Old stats output scaled at about 4 bytes per subprogram ("+%d" for the
> stack chain, plus "+%d" only for global subprogs). New output emits a full
> line per subprogram: "subprog %d (%s) insns %d stack %d\n", roughly 40-50
> bytes plus the BTF name, which btf_name_valid_identifier() bounds only by
> KSYM_NAME_LEN == 512. With BPF_MAX_SUBPROGS == 256 permitted subprograms
> the stats section goes from under ~2 KB to well over ~12 KB, and far more
> with long function names.
>
> Does this matter? Looking at the load path:
>
> kernel/bpf/log.c:45-58 bpf_vlog_update_len_max()
>     tracks the required size in log->len_max.
>
> kernel/bpf/log.c:295 bpf_vlog_finalize()
>     returns -ENOSPC when log->ubuf && log->len_max > log->len_total.
>
> kernel/bpf/verifier.c:20397-20402 bpf_check()
>     err = bpf_log_attr_finalize(attr_log, &env->log);
>     if (err) ret = err;
>     if (ret) goto err_release_maps;
>
> so the successful verification is turned into a failed BPF_PROG_LOAD.
>
> A userspace loader that sets log_level = 4 (stats only) with a modest,
> fixed log_buf sized against the old output will start failing to load
> multi-subprogram programs after this change. libbpf only auto-retries with
> a larger buffer when it owns the buffer:
>
> tools/lib/bpf/libbpf.c:8064-8071
>     if (own_log_buf && errno == ENOSPC ...)
>
> so callers supplying their own log_buf get the failure.
>
> Could the number of per-subprog records be bounded, or emitted only above
> some log level, to avoid the behaviour change for stats-only callers?
>

This is a stretch. In practice, we won't have such small buffers.

>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/30891720984


  reply	other threads:[~2026-08-04  9:48 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-04  8:11 [PATCH bpf-next v5 0/3] Improve stack depth verification stats output Kumar Kartikeya Dwivedi
2026-08-04  8:11 ` [PATCH bpf-next v5 1/3] bpf: Show more useful info in stack depth stats Kumar Kartikeya Dwivedi
2026-08-04  8:22   ` sashiko-bot
2026-08-04  8:40     ` Kumar Kartikeya Dwivedi
2026-08-04  9:31   ` bot+bpf-ci
2026-08-04  9:48     ` Kumar Kartikeya Dwivedi [this message]
2026-08-04  8:11 ` [PATCH bpf-next v5 2/3] selftests/bpf: Adjust veristat stack depth parsing Kumar Kartikeya Dwivedi
2026-08-04  8:11 ` [PATCH bpf-next v5 3/3] selftests/bpf: Test stack depth stats without BTF subprog names Kumar Kartikeya Dwivedi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DKG2CR8JD0F6.1MUAY6BVAIHLZ@gmail.com \
    --to=memxor@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bot+bpf-ci@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=clm@meta.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=kernel-team@meta.com \
    --cc=kkd@meta.com \
    --cc=martin.lau@kernel.org \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.