From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751267AbbHAK50 (ORCPT ); Sat, 1 Aug 2015 06:57:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33688 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751095AbbHAK5Z (ORCPT ); Sat, 1 Aug 2015 06:57:25 -0400 Date: Sat, 1 Aug 2015 12:57:18 +0200 From: Oleg Nesterov To: Peter Zijlstra Cc: Ingo Molnar , Rik van Riel , Tejun Heo , linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 6/6] stop_machine: kill stop_cpus_lock and lg_double_lock/unlock() Message-ID: <20150801105718.GA13901@redhat.com> References: <20150721192219.GA31150@redhat.com> <20150721192247.GA31191@redhat.com> <20150730215527.GQ25159@twins.programming.kicks-ass.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150730215527.GQ25159@twins.programming.kicks-ass.net> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Peter, Thanks for looking. I'll try to reply on Monday, just one note... On 07/30, Peter Zijlstra wrote: > > On Tue, Jul 21, 2015 at 09:22:47PM +0200, Oleg Nesterov wrote: > > > +static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1, > > + int cpu2, struct cpu_stop_work *work2) > > +{ > > + struct cpu_stopper *stopper1 = per_cpu_ptr(&cpu_stopper, cpu1); > > + struct cpu_stopper *stopper2 = per_cpu_ptr(&cpu_stopper, cpu2); > > + int err; > > +retry: > > + spin_lock_irq(&stopper1->lock); > > + spin_lock_nested(&stopper2->lock, SINGLE_DEPTH_NESTING); > > + /* > > + * If we observe both CPUs active we know _cpu_down() cannot yet have > > + * queued its stop_machine works and therefore ours will get executed > > + * first. Or its not either one of our CPUs that's getting unplugged, > > + * in which case we don't care. > > + */ > > + err = -ENOENT; > > + if (!cpu_active(cpu1) || !cpu_active(cpu2)) > > + goto unlock; > > + > > + WARN_ON(!stopper1->enabled || !stopper2->enabled); > > + /* > > + * Ensure that if we race with stop_cpus() the stoppers won't > > + * get queued up in reverse order, leading to system deadlock. > > + */ > > + err = -EDEADLK; > > + if (stop_work_pending(stopper1) != stop_work_pending(stopper2)) > > + goto unlock; > > You could DoS/false positive this by running stop_one_cpu() in a loop, > and thereby 'always' having work pending on one but not the other. IIRC no. I am pretty sure stop_one_cpu() doesn't use stopper->stop_work, only stop_machine() does. Oleg.