Re: [PATCH] [v2] smp: fix smp_call_function_single_async prototype

From: Arnd Bergmann
Date: Thu May 06 2021 - 04:31:55 EST


On Thu, May 6, 2021 at 10:14 AM Huang, Ying <ying.huang@xxxxxxxxx> wrote:
>
> Arnd Bergmann <arnd@xxxxxxxxxx> writes:
>
> > On Thu, May 6, 2021 at 3:20 AM Huang, Ying <ying.huang@xxxxxxxxx> wrote:
> >>
> >> Arnd Bergmann <arnd@xxxxxxxxxx> writes:
> >>
> >> > From: Arnd Bergmann <arnd@xxxxxxxx>
> >> >
> >> > As of commit 966a967116e6 ("smp: Avoid using two cache lines for struct
> >> > call_single_data"), the smp code prefers 32-byte aligned call_single_data
> >> > objects for performance reasons, but the block layer includes an instance
> >> > of this structure in the main 'struct request' that is more senstive
> >> > to size than to performance here, see 4ccafe032005 ("block: unalign
> >> > call_single_data in struct request").
> >> >
> >> > The result is a violation of the calling conventions that clang correctly
> >> > points out:
> >> >
> >> > block/blk-mq.c:630:39: warning: passing 8-byte aligned argument to 32-byte aligned parameter 2 of 'smp_call_function_single_async' may result in an unaligned pointer access [-Walign-mismatch]
> >> > smp_call_function_single_async(cpu, &rq->csd);
> >>
> >> Can this be silenced by
> >>
> >> smp_call_function_single_async(cpu, (call_single_data_t *)&rq->csd);
> >
> > Probably, but casting from smaller alignment to larger alignment is undefined
> > behavior
>
> We cannot avoid type cast in Linux kernel, such as container_of(), is
> there some difference here?

container_of() does not cause any alignment problems. Assuming the outer
structure is aligned correctly, then the inner structure also is.

> > and I'd rather not go there in case this triggers some runtime
> > misbehavior or ubsan check in the future. Making the function accept a
> > pointer with the smaller alignment avoids getting into undefined behavior
> > and doesn't require a cast.
>
> In its raw form as above, this looks bad. If we encapsulate it, it may
> look better, for example,
>
> static inline int __smp_call_function_single_async(int cpu, struct __call_single_data *csd)
> {
> smp_call_function_single_async(cpu, (call_single_data_t *)csd);
> }
>
> Then, we can do
>
> __smp_call_function_single_async(cpu, &rq->csd);

Same problem, it's still calling a function that expects stricter alignment.
It would work if we do it the other way around though:

static inline int smp_call_function_single_async(int cpu,
call_single_data_t *csd)
{
return __smp_call_function_single_async(cpu, csd);
}

That should even work without the cast.

Arnd