All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@tv-sign.ru>
To: Andrew Morton <akpm@osdl.org>
Cc: vatsa@in.ibm.com, David Howells <dhowells@redhat.com>,
	Christoph Hellwig <hch@infradead.org>,
	Ingo Molnar <mingo@elte.hu>, Linus Torvalds <torvalds@osdl.org>,
	linux-kernel@vger.kernel.org, Gautham shenoy <ego@in.ibm.com>
Subject: Re: [PATCH] fix-flush_workqueue-vs-cpu_dead-race-update
Date: Mon, 8 Jan 2007 00:51:03 +0300	[thread overview]
Message-ID: <20070107215103.GA7960@tv-sign.ru> (raw)
In-Reply-To: <20070107115957.6080aa08.akpm@osdl.org>

On 01/07, Andrew Morton wrote:
>
> Plus flush_workqueue() is on the way out.  We're slowly edging towards a
> working cancel_work() which will only block if the work which you're trying
> to cancel is presently running.  With that, pretty much all the
> flush_workqueue() calls go away, and all these accidental rarely-occurring
> deadlocks go away too.

So. If we can forget about the race we have - fine. Otherwise, how about the
patch below? It is untested and needs a review. I can't suggest any simpler
now.

Change flush_workqueue() to use for_each_possible_cpu(). This means that
flush_cpu_workqueue() may hit CPU which is already dead. However in that
case

	if (!list_empty(&cwq->worklist) || cwq->current_work != NULL)

means that CPU_DEAD in progress, it will do kthread_stop() + take_over_work()
so we can proceed and insert a barrier. We hold cwq->lock, so we are safe.

This patch replaces fix-flush_workqueue-vs-cpu_dead-race.patch which was
broken by switching to preempt_disable (now we don't need locking at all).
Note that migrate_sequence (was hotplug_sequence) is incremented under
cwq->lock. Since flush_workqueue does lock/unlock of cwq->lock on all CPUs,
it must see the new value if take_over_work() happened before we checked
this cwq, and this is the case we should worry about: otherwise we added
a barrier.

Srivatsa?

--- mm-6.20-rc3/kernel/workqueue.c~2_race	2007-01-08 00:07:07.000000000 +0300
+++ mm-6.20-rc3/kernel/workqueue.c	2007-01-08 00:28:55.000000000 +0300
@@ -65,6 +65,7 @@ struct workqueue_struct {
 
 /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove
    threads to each one as cpus come/go. */
+static long migrate_sequence __read_mostly;
 static DEFINE_MUTEX(workqueue_mutex);
 static LIST_HEAD(workqueues);
 
@@ -422,13 +423,7 @@ static void flush_cpu_workqueue(struct c
 		 * Probably keventd trying to flush its own queue. So simply run
 		 * it by hand rather than deadlocking.
 		 */
-		preempt_enable();
-		/*
-		 * We can still touch *cwq here because we are keventd, and
-		 * hot-unplug will be waiting us to exit.
-		 */
 		run_workqueue(cwq);
-		preempt_disable();
 	} else {
 		struct wq_barrier barr;
 		int active = 0;
@@ -441,9 +436,7 @@ static void flush_cpu_workqueue(struct c
 		spin_unlock_irq(&cwq->lock);
 
 		if (active) {
-			preempt_enable();
 			wait_for_completion(&barr.done);
-			preempt_disable();
 		}
 	}
 }
@@ -463,17 +456,21 @@ static void flush_cpu_workqueue(struct c
  */
 void fastcall flush_workqueue(struct workqueue_struct *wq)
 {
-	preempt_disable();		/* CPU hotplug */
 	if (is_single_threaded(wq)) {
 		/* Always use first cpu's area. */
 		flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
 	} else {
+		long sequence;
 		int cpu;
+again:
+		sequence = migrate_sequence;
 
-		for_each_online_cpu(cpu)
+		for_each_possible_cpu(cpu)
 			flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
+
+		if (unlikely(sequence != migrate_sequence))
+			goto again;
 	}
-	preempt_enable();
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
@@ -545,18 +542,22 @@ out:
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
-static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
-						   int cpu, int freezeable)
+static void init_cpu_workqueue(struct workqueue_struct *wq,
+			struct cpu_workqueue_struct *cwq, int freezeable)
 {
-	struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-	struct task_struct *p;
-
 	spin_lock_init(&cwq->lock);
 	cwq->wq = wq;
 	cwq->thread = NULL;
 	cwq->freezeable = freezeable;
 	INIT_LIST_HEAD(&cwq->worklist);
 	init_waitqueue_head(&cwq->more_work);
+}
+
+static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
+						   int cpu)
+{
+	struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
+	struct task_struct *p;
 
 	if (is_single_threaded(wq))
 		p = kthread_create(worker_thread, cwq, "%s", wq->name);
@@ -589,15 +590,20 @@ struct workqueue_struct *__create_workqu
 	mutex_lock(&workqueue_mutex);
 	if (singlethread) {
 		INIT_LIST_HEAD(&wq->list);
-		p = create_workqueue_thread(wq, singlethread_cpu, freezeable);
+		init_cpu_workqueue(wq, per_cpu_ptr(wq->cpu_wq, singlethread_cpu),
+					freezeable);
+		p = create_workqueue_thread(wq, singlethread_cpu);
 		if (!p)
 			destroy = 1;
 		else
 			wake_up_process(p);
 	} else {
 		list_add(&wq->list, &workqueues);
+		for_each_possible_cpu(cpu)
+			init_cpu_workqueue(wq, per_cpu_ptr(wq->cpu_wq, cpu),
+						freezeable);
 		for_each_online_cpu(cpu) {
-			p = create_workqueue_thread(wq, cpu, freezeable);
+			p = create_workqueue_thread(wq, cpu);
 			if (p) {
 				kthread_bind(p, cpu);
 				wake_up_process(p);
@@ -833,6 +839,7 @@ static void take_over_work(struct workqu
 
 	spin_lock_irq(&cwq->lock);
 	list_replace_init(&cwq->worklist, &list);
+	migrate_sequence++;
 
 	while (!list_empty(&list)) {
 		printk("Taking work for %s\n", wq->name);
@@ -859,7 +866,7 @@ static int __devinit workqueue_cpu_callb
 	case CPU_UP_PREPARE:
 		/* Create a new workqueue thread for it. */
 		list_for_each_entry(wq, &workqueues, list) {
-			if (!create_workqueue_thread(wq, hotcpu, 0)) {
+			if (!create_workqueue_thread(wq, hotcpu)) {
 				printk("workqueue for %i failed\n", hotcpu);
 				return NOTIFY_BAD;
 			}


  parent reply	other threads:[~2007-01-07 21:51 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-17 22:34 [PATCH, RFC] reimplement flush_workqueue() Oleg Nesterov
2006-12-18  3:09 ` Linus Torvalds
2006-12-19  0:27 ` Andrew Morton
2006-12-19  0:43   ` Oleg Nesterov
2006-12-19  1:00     ` Andrew Morton
2007-01-04 11:32     ` Srivatsa Vaddagiri
2007-01-04 14:29       ` Oleg Nesterov
2007-01-04 15:56         ` Srivatsa Vaddagiri
2007-01-04 16:31           ` Oleg Nesterov
2007-01-04 16:57             ` Srivatsa Vaddagiri
2007-01-04 17:18         ` Andrew Morton
2007-01-04 18:09           ` Oleg Nesterov
2007-01-04 18:31             ` Andrew Morton
2007-01-05  9:03               ` Srivatsa Vaddagiri
2007-01-05 14:07                 ` Oleg Nesterov
2007-01-06 15:24                   ` Srivatsa Vaddagiri
2007-01-05  8:56           ` Srivatsa Vaddagiri
2007-01-05 12:42             ` Oleg Nesterov
2007-01-06 15:11               ` Srivatsa Vaddagiri
2007-01-06 15:10           ` [PATCH] fix-flush_workqueue-vs-cpu_dead-race-update Oleg Nesterov
2007-01-06 15:45             ` Srivatsa Vaddagiri
2007-01-06 16:30               ` Oleg Nesterov
2007-01-06 16:38                 ` Srivatsa Vaddagiri
2007-01-06 17:34                   ` Oleg Nesterov
2007-01-07 10:43                     ` Srivatsa Vaddagiri
2007-01-07 12:56                       ` Oleg Nesterov
2007-01-07 14:22                         ` Oleg Nesterov
2007-01-07 14:42                           ` Oleg Nesterov
2007-01-07 16:43                           ` Srivatsa Vaddagiri
2007-01-07 17:01                             ` Srivatsa Vaddagiri
2007-01-07 17:33                               ` Oleg Nesterov
2007-01-07 17:18                             ` Oleg Nesterov
2007-01-07 16:21                         ` Srivatsa Vaddagiri
2007-01-07 17:09                           ` Oleg Nesterov
2007-01-06 19:11                   ` Andrew Morton
2007-01-06 19:13                     ` Ingo Molnar
2007-01-07 11:00                     ` Srivatsa Vaddagiri
2007-01-07 19:59                       ` Andrew Morton
2007-01-07 21:01                         ` [PATCH] flush_cpu_workqueue: don't flush an empty ->worklist Oleg Nesterov
2007-01-08 23:54                           ` Andrew Morton
2007-01-09  5:04                             ` Srivatsa Vaddagiri
2007-01-09  5:26                               ` Andrew Morton
2007-01-09  6:56                                 ` Ingo Molnar
2007-01-09  9:33                                 ` Srivatsa Vaddagiri
2007-01-09  9:44                                   ` Ingo Molnar
2007-01-09  9:51                                   ` Andrew Morton
2007-01-09 10:09                                     ` Srivatsa Vaddagiri
2007-01-09 10:15                                       ` Andrew Morton
2007-01-09 15:07                                 ` Oleg Nesterov
2007-01-09 15:59                                   ` Srivatsa Vaddagiri
2007-01-09 16:38                                     ` Oleg Nesterov
2007-01-09 16:46                                       ` Srivatsa Vaddagiri
2007-01-09 16:56                                         ` Oleg Nesterov
2007-01-14 23:54                                           ` Oleg Nesterov
2007-01-15  4:33                                             ` Srivatsa Vaddagiri
2007-01-15 12:54                                               ` Oleg Nesterov
2007-01-15 13:08                                                 ` Oleg Nesterov
2007-01-15 16:18                                                 ` Srivatsa Vaddagiri
2007-01-15 16:55                                                   ` Oleg Nesterov
2007-01-16  5:26                                                     ` Srivatsa Vaddagiri
2007-01-16 13:27                                                       ` Oleg Nesterov
2007-01-17  6:17                                                         ` Srivatsa Vaddagiri
2007-01-17 15:47                                                           ` Oleg Nesterov
2007-01-17 16:12                                                             ` Srivatsa Vaddagiri
2007-01-17 17:01                                                               ` Oleg Nesterov
2007-01-17 16:25                                                             ` Srivatsa Vaddagiri
2007-01-07 21:51                         ` Oleg Nesterov [this message]
2007-01-08 15:22                           ` [PATCH] fix-flush_workqueue-vs-cpu_dead-race-update Srivatsa Vaddagiri
2007-01-08 15:56                             ` Oleg Nesterov
2007-01-08 16:31                               ` Srivatsa Vaddagiri
2007-01-08 17:06                                 ` Oleg Nesterov
2007-01-08 18:37                                   ` Pallipadi, Venkatesh
2007-01-09  1:11                                     ` Srivatsa Vaddagiri
2007-01-09  4:39                                   ` Srivatsa Vaddagiri
2007-01-09 14:38                                     ` Oleg Nesterov
2007-01-08 15:37                         ` Srivatsa Vaddagiri
2007-01-04 12:02 ` [PATCH, RFC] reimplement flush_workqueue() Srivatsa Vaddagiri
2007-01-04 14:38   ` Oleg Nesterov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070107215103.GA7960@tv-sign.ru \
    --to=oleg@tv-sign.ru \
    --cc=akpm@osdl.org \
    --cc=dhowells@redhat.com \
    --cc=ego@in.ibm.com \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=torvalds@osdl.org \
    --cc=vatsa@in.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.