[Devel] [PATCH hci-8.1 3/6] ve/printk: Specify ve in printks

Vladimir Riabchun vladimir.riabchun at virtuozzo.com
Sat Oct 3 16:49:44 MSK 2026



On 10/2/26 23:36, no-reply at sashiko.virtuozzo.com wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> - [Medium] printk: host-log decision in ve_vprintk() uses get_exec_env() instead of the explicit ve
> - [Low] printk: ve_printk_ratelimited() passes get_exec_env() as explicit ve, bypassing in_task() guard
> - [Low] printk: !CONFIG_PRINTK stub ve_printk_deferred() keeps stale __printf(2, 3) attribute
> --
> 
> commit 59948e2d94e2f343f89f9252383a061f24bb4a33
> Author: Vladimir Riabchun <vladimir.riabchun at virtuozzo.com>
> 
> ve/printk: Specify ve in printks
> 
> This commit adds ve_printk helpers that take an explicit VE, so callers
> where get_exec_env() is unreliable can name the VE to log to. The
> ve_ratelimit() and ve_net_ratelimit() helpers now require a VE argument,
> and the netfilter callers pass net->owner_ve.
> 
> Link: https://virtuozzo.atlassian.net/browse/VSTOR-146839
> 
>> diff --git a/include/linux/printk.h b/include/linux/printk.h
>> --- a/include/linux/printk.h
>> +++ b/include/linux/printk.h
> 
> [ ... ]
> 
>>   static inline __printf(3, 4) __cold
>> +int __ve_printk(int dst, struct ve_struct *ve, const char *s, ...)
>> +{
>> +	return 0;
>> +}
>>   static inline __printf(2, 3) __cold
>> -int ve_printk_deferred(int dst, const char *s, ...)
>> +int ve_printk_deferred(int dst, struct ve_struct *ve, const char *s, ...)
>>   {
>>   	return 0;
>>   }
> 
> [Severity: Low]
> The stub ve_printk_deferred() gained the struct ve_struct *ve parameter,
> so the format string is now argument 3. It still carries
> __printf(2, 3), while the real prototype was updated to __printf(3, 4).
> 
> With the old attribute, GCC treats the ve pointer as the format string.
> Could this produce a -Wformat warning (an error under -Werror) at call
> sites such as __ve_ratelimit() in lib/ratelimit.c when building with
> CONFIG_PRINTK=n?
> 
> Should the stub use __printf(3, 4) to match?

Yes, correct. Will fix in v2.

> 
> [ ... ]
> 
>> @@ -747,7 +761,8 @@ struct pi_entry {
>>   				      DEFAULT_RATELIMIT_BURST);		\
>>   									\
>> -	if (ve_ratelimit(dst, &_rs))					\
>> +	WARN_ON_ONCE((dst & VE_LOG) && !in_task());			\
>> +	if (ve_ratelimit(dst, get_exec_env(), &_rs))			\
>>   		ve_printk(dst, fmt, ##__VA_ARGS__);			\
>>   })
> 
> [Severity: Low]
> Here get_exec_env() is passed as an explicit VE. When
> ve_printk_ratelimited(VE_LOG, ...) runs from softirq, the interval-reset
> path in __ve_ratelimit() calls:
> 
> __ve_ratelimit()
>    ve_printk_deferred(dst, ve, KERN_WARNING "%s: %d callbacks suppressed\n", ...)
> 
> With a non-NULL ve, ve_vprintk_deferred() computes ve_provided as true,
> so this check is skipped:
> 
> 	if (!ve_provided && WARN_ON_ONCE(!in_task()))
> 		goto done;
> 
> Can the "callbacks suppressed" message then be written to the log of
> whichever VE belongs to the interrupted task? The in_task() guard no
> longer protects this path.

True. Will fix in v2 by passing ve0 value here in IRQ case.

> 
> Would it be better to keep passing NULL here, or to use a variant that
> keeps the guard?
> 
>> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
>> --- a/kernel/printk/printk.c
>> +++ b/kernel/printk/printk.c
> 
> [ ... ]
> 
>> -static asmlinkage int ve_vprintk(int dst, const char *fmt, va_list args)
>> +static asmlinkage int ve_vprintk(int dst, struct ve_struct *ve,
>> +				const char *fmt, va_list args)
>>   {
>>   	va_list args2;
>> -	int r = 0;
>> +	int r = 0, ve_provided = (ve != NULL);
>>   
>>   	WARN_ON_ONCE(!dst || (dst & ~VE_LOG_BOTH));
>>   
>> +	if (!ve)
>> +		ve = get_exec_env();
>> +
>>   	va_copy(args2, args);
>>   	if (ve_is_super(get_exec_env()) || (dst & VE0_LOG))
>>   		r = vprintk(fmt, args);
> 
> [Severity: Medium]
> The host-log decision here still uses ve_is_super(get_exec_env()), while
> the per-VE branch below uses ve_is_super(ve). When an explicit ve is
> passed, can the two destinations disagree?
> 
> Take net_velog_ratelimited(net->owner_ve, ...) called from a netfilter
> softirq path such as xt_TCPMSS or nf_conntrack allocation:
> 
> - If a container-owned VE_LOG-only message is emitted while the softirq
>    interrupted a VE0 task, ve_is_super(get_exec_env()) is true. The
>    message is then also printed to the host log.
> 
> - If a VE0-owned message is emitted while the softirq interrupted a
>    container task, ve_is_super(get_exec_env()) is false. If dst has no
>    VE0_LOG, the host branch is skipped. The per-VE branch is skipped too,
>    since ve_is_super(ve) is true. The message is lost.
> 
> Should this test use ve_is_super(ve) instead of get_exec_env()?

True, missed it. Will fix in v2. Next one as well.

> 
> [ ... ]
> 
>> +static asmlinkage int ve_vprintk_deferred(int dst, struct ve_struct *ve,
>> +					const char *fmt, va_list args)
>>   {
>>   	va_list args2;
>> -	int r = 0;
>> +	int r = 0, ve_provided = (ve != NULL);
>>   
>>   	WARN_ON_ONCE(!dst || (dst & ~VE_LOG_BOTH));
>>   
>> +	if (!ve)
>> +		ve = get_exec_env();
>> +
>>   	va_copy(args2, args);
>>   	if (ve_is_super(get_exec_env()) || (dst & VE0_LOG))
>>   		r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
> 
> [Severity: Medium]
> The deferred variant has the same issue. __ve_ratelimit() calls
> ve_printk_deferred() from arbitrary contexts with an explicit ve, but the
> host-log condition still looks at get_exec_env().
> 
> Can the "callbacks suppressed" message go to the host log, or be dropped,
> based on the interrupted task's VE rather than the ve passed in?
> 
> Should this use ve_is_super(ve) as well?
> 

-- 
Best regards, Riabchun Vladimir
Linux Kernel Developer, Virtuozzo



More information about the Devel mailing list