Message ID | 53A01039.2020302@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Srivatsa, On Tue, Jun 17, 2014 at 3:24 PM, Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote: > On 06/17/2014 03:03 PM, Sachin Kamat wrote: > >>> Below is an updated patch, please let me know how it goes. (You'll have to >>> revert c47a9d7cca first, and then 56e692182, before trying this patch). >> >> I am unable to apply your below patch on top of the above 2 reverts. >> Applying: CPU hotplug, smp: Execute any pending IPI callbacks before CPU offline >> fatal: corrupt patch at line 106 >> Patch failed at 0001 CPU hotplug, smp: Execute any pending IPI >> callbacks before CPU offline >> >> Even with 'patch' I get the below failures: >> patching file kernel/smp.c >> Hunk #2 FAILED at 53. >> Hunk #3 FAILED at 179. >> 2 out of 3 hunks FAILED -- saving rejects to file kernel/smp.c.rej >> > > Hmm, weird. My mailer must have screwed it up. > > Let's try again: > > [In case this also doesn't work for you, please use this git tree in which > I have reverted the 2 old commits and added this updated patch. > > git://github.com/srivatsabhat/linux.git ipi-offline-fix-v3 > ] Unfortunately the attached patch did not apply either. Nevertheless, I applied the patch from your above mentioned tree. With that patch I do not see the warnings that I mentioned in my first mail. Thanks for fixing it. Regards, Sachin.
On 06/17/2014 05:25 PM, Sachin Kamat wrote: > Hi Srivatsa, > > On Tue, Jun 17, 2014 at 3:24 PM, Srivatsa S. Bhat > <srivatsa.bhat@linux.vnet.ibm.com> wrote: >> On 06/17/2014 03:03 PM, Sachin Kamat wrote: >> >>>> Below is an updated patch, please let me know how it goes. (You'll have to >>>> revert c47a9d7cca first, and then 56e692182, before trying this patch). >>> >>> I am unable to apply your below patch on top of the above 2 reverts. >>> Applying: CPU hotplug, smp: Execute any pending IPI callbacks before CPU offline >>> fatal: corrupt patch at line 106 >>> Patch failed at 0001 CPU hotplug, smp: Execute any pending IPI >>> callbacks before CPU offline >>> >>> Even with 'patch' I get the below failures: >>> patching file kernel/smp.c >>> Hunk #2 FAILED at 53. >>> Hunk #3 FAILED at 179. >>> 2 out of 3 hunks FAILED -- saving rejects to file kernel/smp.c.rej >>> >> >> Hmm, weird. My mailer must have screwed it up. >> >> Let's try again: >> >> [In case this also doesn't work for you, please use this git tree in which >> I have reverted the 2 old commits and added this updated patch. >> >> git://github.com/srivatsabhat/linux.git ipi-offline-fix-v3 >> ] > > Unfortunately the attached patch did not apply either. Nevertheless, I > applied the > patch from your above mentioned tree. With that patch I do not see the warnings > that I mentioned in my first mail. Thanks for fixing it. > Sure, thanks for reporting the bug and testing the updated patch! By the way, I think there is some problem in the workflow that you use to copy-paste/apply the patch. I tried applying both patches (that I sent in 2 different mails) and both applied properly without any problems. Regards, Srivatsa S. Bhat
diff --git a/kernel/smp.c b/kernel/smp.c index 306f818..80c33f8 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -29,6 +29,8 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue); +static void flush_smp_call_function_queue(bool warn_cpu_offline); + static int hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -51,12 +53,27 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: + /* Fall-through to the CPU_DEAD[_FROZEN] case. */ case CPU_DEAD: case CPU_DEAD_FROZEN: free_cpumask_var(cfd->cpumask); free_percpu(cfd->csd); break; + + case CPU_DYING: + case CPU_DYING_FROZEN: + /* + * The IPIs for the smp-call-function callbacks queued by other + * CPUs might arrive late, either due to hardware latencies or + * because this CPU disabled interrupts (inside stop-machine) + * before the IPIs were sent. So flush out any pending callbacks + * explicitly (without waiting for the IPIs to arrive), to + * ensure that the outgoing CPU doesn't go offline with work + * still pending. + */ + flush_smp_call_function_queue(false); + break; #endif }; @@ -177,23 +194,47 @@ static int generic_exec_single(int cpu, struct call_single_data *csd, return 0; } -/* - * Invoked by arch to handle an IPI for call function single. Must be - * called from the arch with interrupts disabled. +/** + * generic_smp_call_function_single_interrupt - Execute SMP IPI callbacks + * + * Invoked by arch to handle an IPI for call function single. + * Must be called with interrupts disabled. */ void generic_smp_call_function_single_interrupt(void) { + flush_smp_call_function_queue(true); +} + +/** + * flush_smp_call_function_queue - Flush pending smp-call-function callbacks + * + * @warn_cpu_offline: If set to 'true', warn if callbacks were queued on an + * offline CPU. Skip this check if set to 'false'. + * + * Flush any pending smp-call-function callbacks queued on this CPU. This is + * invoked by the generic IPI handler, as well as by a CPU about to go offline, + * to ensure that all pending IPI callbacks are run before it goes completely + * offline. + * + * Loop through the call_single_queue and run all the queued callbacks. + * Must be called with interrupts disabled. + */ +static void flush_smp_call_function_queue(bool warn_cpu_offline) +{ + struct llist_head *head; struct llist_node *entry; struct call_single_data *csd, *csd_next; static bool warned; - entry = llist_del_all(&__get_cpu_var(call_single_queue)); + WARN_ON(!irqs_disabled()); + + head = &__get_cpu_var(call_single_queue); + entry = llist_del_all(head); entry = llist_reverse_order(entry); - /* - * Shouldn't receive this interrupt on a cpu that is not yet online. - */ - if (unlikely(!cpu_online(smp_processor_id()) && !warned)) { + /* There shouldn't be any pending callbacks on an offline CPU. */ + if (unlikely(warn_cpu_offline && !cpu_online(smp_processor_id()) && + !warned && !llist_empty(head))) { warned = true; WARN(1, "IPI on offline CPU %d\n", smp_processor_id());