Re: [RFC][PATCH v2 02/11] stop_machine: Accumulate error code rather than overwrite

Borislav Petkov <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <20260809020424.GBanfgKG9iaIyIV0ko@fat_crate.local>
On Tue, Mar 31, 2026 at 01:42:40AM +0000, Chang S. Bae wrote:
> cpu_stopper_thread() invokes a stop function and collects its error code
> in struct cpu_stop_done. In the multi stop-machine case, it is shared
> data, but currently an arbitrary error is recorded as overwriting.
> 
> With different errors, accumulating error code instead can distinguish a
> multi-error condition as bits are cumulatively set.
> 
> Convert the error recoding to accumulate return values.

"recording"

> 
> Suggested-by: Borislav Petkov <[email protected]>
> Signed-off-by: Chang S. Bae <[email protected]>
> Link: https://lore.kernel.org/lkml/20260304163335.GDaahe3wdnqxSC2yfw@fat_crate.local
> ---
> V1 -> V2: New patch
> 
> While tried to explain its benefit here, I considered this change
> deserves more discussions to ensure its impact, so RFC.
> ---
>  include/linux/stop_machine.h | 12 ++++++------
>  kernel/stop_machine.c        | 10 +++++-----
>  2 files changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
> index c753dd53e79d..2f986555113a 100644
> --- a/include/linux/stop_machine.h
> +++ b/include/linux/stop_machine.h
> @@ -124,9 +124,9 @@ static inline void print_stop_info(const char *log_lvl, struct task_struct *task
>   * the possibility of blocking in cpus_read_lock() means that the caller
>   * cannot usefully rely on this serialization.
>   *
> - * Return: 0 if all invocations of @fn return zero.  Otherwise, the
> - * value returned by an arbitrarily chosen member of the set of calls to
> - * @fn that returned non-zero.
> + * Return: 0 if all invocations of @fn return zero.  Otherwise, an
> + * accumulated return value from all invocation of @fn that returned

"The return value is generated by OR-ing in all return values of @fn."

Just keep it simpler.

> + * non-zero.
>   */
>  int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
>  
> @@ -154,9 +154,9 @@ int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *
>   *
>   * Context: Must be called from within a cpus_read_lock() protected region.
>   *
> - * Return: 0 if all invocations of @fn return zero.  Otherwise, the
> - * value returned by an arbitrarily chosen member of the set of calls to
> - * @fn that returned non-zero.
> + * Return: 0 if all invocations of @fn return zero.  Otherwise, an
> + * accumulated return value from all invocation of @fn that returned
> + * non-zero.

Ditto.

Just simplify all occurances.

>  int stop_core_cpuslocked(unsigned int cpu, cpu_stop_fn_t fn, void *data);
>  
> diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
> index 822cf56fdc81..15268f1207e9 100644
> --- a/kernel/stop_machine.c
> +++ b/kernel/stop_machine.c
> @@ -459,7 +459,7 @@ static int __stop_cpus(const struct cpumask *cpumask,
>   * RETURNS:
>   * -ENOENT if @fn(@arg) was not executed at all because all cpus in
>   * @cpumask were offline; otherwise, 0 if all executions of @fn
> - * returned 0, any non zero return value if any returned non zero.
> + * returned 0, the accumulated value of all non-zero @fn returns.
>   */
>  static int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
>  {
> @@ -512,7 +512,7 @@ static void cpu_stopper_thread(unsigned int cpu)
>  		ret = fn(arg);
>  		if (done) {
>  			if (ret)
> -				done->ret = ret;
> +				done->ret |= ret;
>  			cpu_stop_signal_done(done);
>  		}
>  		preempt_count_dec();
> @@ -674,8 +674,8 @@ EXPORT_SYMBOL_GPL(stop_core_cpuslocked);
>   * Local CPU is inactive.  Temporarily stops all active CPUs.
>   *
>   * RETURNS:
> - * 0 if all executions of @fn returned 0, any non zero return value if any
> - * returned non zero.
> + * 0 if all executions of @fn returned 0, otherwise the accumulated value
> + * of all non-zero @fn returns.
>   */
>  int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
>  				  const struct cpumask *cpus)
> @@ -705,5 +705,5 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
>  		cpu_relax();
>  
>  	mutex_unlock(&stop_cpus_mutex);
> -	return ret ?: done.ret;
> +	return ret | done.ret;

So we might see more failures from this change as error values which were
overwritten in the past, will be returned now.

Oh well, we'll need to hamme on it some more...

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.