Commit 67cb85fd authored by Thomas Gleixner's avatar Thomas Gleixner

ia64/salinfo: Replace racy task affinity logic

Some of the file operations in /proc/sal require to run code on the
requested cpu. This is achieved by temporarily setting the affinity of the
calling user space thread to the requested CPU and reset it to the original
affinity afterwards.

That's racy vs. CPU hotplug and concurrent affinity settings for that
thread resulting in code executing on the wrong CPU and overwriting the
new affinity setting.

Replace it by using work_on_cpu_safe() which guarantees to run the code on
the requested CPU or to fail in case the CPU is offline.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-ia64@vger.kernel.org
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Len Brown <lenb@kernel.org>
Link: http://lkml.kernel.org/r/20170412201042.341863457@linutronix.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 0e8d6a93
...@@ -179,14 +179,14 @@ struct salinfo_platform_oemdata_parms { ...@@ -179,14 +179,14 @@ struct salinfo_platform_oemdata_parms {
const u8 *efi_guid; const u8 *efi_guid;
u8 **oemdata; u8 **oemdata;
u64 *oemdata_size; u64 *oemdata_size;
int ret;
}; };
static void static long
salinfo_platform_oemdata_cpu(void *context) salinfo_platform_oemdata_cpu(void *context)
{ {
struct salinfo_platform_oemdata_parms *parms = context; struct salinfo_platform_oemdata_parms *parms = context;
parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
return salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
} }
static void static void
...@@ -380,16 +380,7 @@ salinfo_log_release(struct inode *inode, struct file *file) ...@@ -380,16 +380,7 @@ salinfo_log_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static void static long
call_on_cpu(int cpu, void (*fn)(void *), void *arg)
{
cpumask_t save_cpus_allowed = current->cpus_allowed;
set_cpus_allowed_ptr(current, cpumask_of(cpu));
(*fn)(arg);
set_cpus_allowed_ptr(current, &save_cpus_allowed);
}
static void
salinfo_log_read_cpu(void *context) salinfo_log_read_cpu(void *context)
{ {
struct salinfo_data *data = context; struct salinfo_data *data = context;
...@@ -399,6 +390,7 @@ salinfo_log_read_cpu(void *context) ...@@ -399,6 +390,7 @@ salinfo_log_read_cpu(void *context)
/* Clear corrected errors as they are read from SAL */ /* Clear corrected errors as they are read from SAL */
if (rh->severity == sal_log_severity_corrected) if (rh->severity == sal_log_severity_corrected)
ia64_sal_clear_state_info(data->type); ia64_sal_clear_state_info(data->type);
return 0;
} }
static void static void
...@@ -430,7 +422,7 @@ salinfo_log_new_read(int cpu, struct salinfo_data *data) ...@@ -430,7 +422,7 @@ salinfo_log_new_read(int cpu, struct salinfo_data *data)
spin_unlock_irqrestore(&data_saved_lock, flags); spin_unlock_irqrestore(&data_saved_lock, flags);
if (!data->saved_num) if (!data->saved_num)
call_on_cpu(cpu, salinfo_log_read_cpu, data); work_on_cpu_safe(cpu, salinfo_log_read_cpu, data);
if (!data->log_size) { if (!data->log_size) {
data->state = STATE_NO_DATA; data->state = STATE_NO_DATA;
cpumask_clear_cpu(cpu, &data->cpu_event); cpumask_clear_cpu(cpu, &data->cpu_event);
...@@ -459,11 +451,13 @@ salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *p ...@@ -459,11 +451,13 @@ salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *p
return simple_read_from_buffer(buffer, count, ppos, buf, bufsize); return simple_read_from_buffer(buffer, count, ppos, buf, bufsize);
} }
static void static long
salinfo_log_clear_cpu(void *context) salinfo_log_clear_cpu(void *context)
{ {
struct salinfo_data *data = context; struct salinfo_data *data = context;
ia64_sal_clear_state_info(data->type); ia64_sal_clear_state_info(data->type);
return 0;
} }
static int static int
...@@ -486,7 +480,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) ...@@ -486,7 +480,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
rh = (sal_log_record_header_t *)(data->log_buffer); rh = (sal_log_record_header_t *)(data->log_buffer);
/* Corrected errors have already been cleared from SAL */ /* Corrected errors have already been cleared from SAL */
if (rh->severity != sal_log_severity_corrected) if (rh->severity != sal_log_severity_corrected)
call_on_cpu(cpu, salinfo_log_clear_cpu, data); work_on_cpu_safe(cpu, salinfo_log_clear_cpu, data);
/* clearing a record may make a new record visible */ /* clearing a record may make a new record visible */
salinfo_log_new_read(cpu, data); salinfo_log_new_read(cpu, data);
if (data->state == STATE_LOG_RECORD) { if (data->state == STATE_LOG_RECORD) {
...@@ -531,9 +525,8 @@ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, lo ...@@ -531,9 +525,8 @@ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, lo
.oemdata = &data->oemdata, .oemdata = &data->oemdata,
.oemdata_size = &data->oemdata_size .oemdata_size = &data->oemdata_size
}; };
call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms); count = work_on_cpu_safe(cpu, salinfo_platform_oemdata_cpu,
if (parms.ret) &parms);
count = parms.ret;
} else } else
data->oemdata_size = 0; data->oemdata_size = 0;
} else } else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment