smp: Fix smp_call_function_single_async prototype
As of commit966a967116
("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, see4ccafe0320
("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); It does seem that the usage of the call_single_data without cache line alignment should still be allowed by the smp code, so just change the function prototype so it accepts both, but leave the default alignment unchanged for the other users. This seems better to me than adding a local hack to shut up an otherwise correct warning in the caller. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Jens Axboe <axboe@kernel.dk> Link: https://lkml.kernel.org/r/20210505211300.3174456-1-arnd@kernel.org
This commit is contained in:
parent
635de956a7
commit
1139aeb1c5
|
@ -53,7 +53,7 @@ int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
|
|||
void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func,
|
||||
void *info, bool wait, const struct cpumask *mask);
|
||||
|
||||
int smp_call_function_single_async(int cpu, call_single_data_t *csd);
|
||||
int smp_call_function_single_async(int cpu, struct __call_single_data *csd);
|
||||
|
||||
/*
|
||||
* Call a function on all processors
|
||||
|
|
26
kernel/smp.c
26
kernel/smp.c
|
@ -211,7 +211,7 @@ static u64 cfd_seq_inc(unsigned int src, unsigned int dst, unsigned int type)
|
|||
} while (0)
|
||||
|
||||
/* Record current CSD work for current CPU, NULL to erase. */
|
||||
static void __csd_lock_record(call_single_data_t *csd)
|
||||
static void __csd_lock_record(struct __call_single_data *csd)
|
||||
{
|
||||
if (!csd) {
|
||||
smp_mb(); /* NULL cur_csd after unlock. */
|
||||
|
@ -226,13 +226,13 @@ static void __csd_lock_record(call_single_data_t *csd)
|
|||
/* Or before unlock, as the case may be. */
|
||||
}
|
||||
|
||||
static __always_inline void csd_lock_record(call_single_data_t *csd)
|
||||
static __always_inline void csd_lock_record(struct __call_single_data *csd)
|
||||
{
|
||||
if (static_branch_unlikely(&csdlock_debug_enabled))
|
||||
__csd_lock_record(csd);
|
||||
}
|
||||
|
||||
static int csd_lock_wait_getcpu(call_single_data_t *csd)
|
||||
static int csd_lock_wait_getcpu(struct __call_single_data *csd)
|
||||
{
|
||||
unsigned int csd_type;
|
||||
|
||||
|
@ -282,7 +282,7 @@ static const char *csd_lock_get_type(unsigned int type)
|
|||
return (type >= ARRAY_SIZE(seq_type)) ? "?" : seq_type[type];
|
||||
}
|
||||
|
||||
static void csd_lock_print_extended(call_single_data_t *csd, int cpu)
|
||||
static void csd_lock_print_extended(struct __call_single_data *csd, int cpu)
|
||||
{
|
||||
struct cfd_seq_local *seq = &per_cpu(cfd_seq_local, cpu);
|
||||
unsigned int srccpu = csd->node.src;
|
||||
|
@ -321,7 +321,7 @@ static void csd_lock_print_extended(call_single_data_t *csd, int cpu)
|
|||
* the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,
|
||||
* so waiting on other types gets much less information.
|
||||
*/
|
||||
static bool csd_lock_wait_toolong(call_single_data_t *csd, u64 ts0, u64 *ts1, int *bug_id)
|
||||
static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *ts1, int *bug_id)
|
||||
{
|
||||
int cpu = -1;
|
||||
int cpux;
|
||||
|
@ -387,7 +387,7 @@ static bool csd_lock_wait_toolong(call_single_data_t *csd, u64 ts0, u64 *ts1, in
|
|||
* previous function call. For multi-cpu calls its even more interesting
|
||||
* as we'll have to ensure no other cpu is observing our csd.
|
||||
*/
|
||||
static void __csd_lock_wait(call_single_data_t *csd)
|
||||
static void __csd_lock_wait(struct __call_single_data *csd)
|
||||
{
|
||||
int bug_id = 0;
|
||||
u64 ts0, ts1;
|
||||
|
@ -401,7 +401,7 @@ static void __csd_lock_wait(call_single_data_t *csd)
|
|||
smp_acquire__after_ctrl_dep();
|
||||
}
|
||||
|
||||
static __always_inline void csd_lock_wait(call_single_data_t *csd)
|
||||
static __always_inline void csd_lock_wait(struct __call_single_data *csd)
|
||||
{
|
||||
if (static_branch_unlikely(&csdlock_debug_enabled)) {
|
||||
__csd_lock_wait(csd);
|
||||
|
@ -431,17 +431,17 @@ static void __smp_call_single_queue_debug(int cpu, struct llist_node *node)
|
|||
#else
|
||||
#define cfd_seq_store(var, src, dst, type)
|
||||
|
||||
static void csd_lock_record(call_single_data_t *csd)
|
||||
static void csd_lock_record(struct __call_single_data *csd)
|
||||
{
|
||||
}
|
||||
|
||||
static __always_inline void csd_lock_wait(call_single_data_t *csd)
|
||||
static __always_inline void csd_lock_wait(struct __call_single_data *csd)
|
||||
{
|
||||
smp_cond_load_acquire(&csd->node.u_flags, !(VAL & CSD_FLAG_LOCK));
|
||||
}
|
||||
#endif
|
||||
|
||||
static __always_inline void csd_lock(call_single_data_t *csd)
|
||||
static __always_inline void csd_lock(struct __call_single_data *csd)
|
||||
{
|
||||
csd_lock_wait(csd);
|
||||
csd->node.u_flags |= CSD_FLAG_LOCK;
|
||||
|
@ -454,7 +454,7 @@ static __always_inline void csd_lock(call_single_data_t *csd)
|
|||
smp_wmb();
|
||||
}
|
||||
|
||||
static __always_inline void csd_unlock(call_single_data_t *csd)
|
||||
static __always_inline void csd_unlock(struct __call_single_data *csd)
|
||||
{
|
||||
WARN_ON(!(csd->node.u_flags & CSD_FLAG_LOCK));
|
||||
|
||||
|
@ -501,7 +501,7 @@ void __smp_call_single_queue(int cpu, struct llist_node *node)
|
|||
* for execution on the given CPU. data must already have
|
||||
* ->func, ->info, and ->flags set.
|
||||
*/
|
||||
static int generic_exec_single(int cpu, call_single_data_t *csd)
|
||||
static int generic_exec_single(int cpu, struct __call_single_data *csd)
|
||||
{
|
||||
if (cpu == smp_processor_id()) {
|
||||
smp_call_func_t func = csd->func;
|
||||
|
@ -784,7 +784,7 @@ EXPORT_SYMBOL(smp_call_function_single);
|
|||
* NOTE: Be careful, there is unfortunately no current debugging facility to
|
||||
* validate the correctness of this serialization.
|
||||
*/
|
||||
int smp_call_function_single_async(int cpu, call_single_data_t *csd)
|
||||
int smp_call_function_single_async(int cpu, struct __call_single_data *csd)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
|
|||
}
|
||||
EXPORT_SYMBOL(smp_call_function_single);
|
||||
|
||||
int smp_call_function_single_async(int cpu, call_single_data_t *csd)
|
||||
int smp_call_function_single_async(int cpu, struct __call_single_data *csd)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
|
Loading…
Reference in New Issue