All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: Re: workqueue destruction BUG_ON
Date: Tue, 24 Aug 2010 14:35:34 +0200	[thread overview]
Message-ID: <4C73BC96.6000003@kernel.org> (raw)
In-Reply-To: <1282646268.3695.9.camel@jlt3.sipsolutions.net>

Hello,

On 08/24/2010 12:37 PM, Johannes Berg wrote:
> I think in my iwlwifi case it's actually destroying the iwlwifi
> workqueue (not sure why it even exists though).

Yeah, I'm planning on auditing each workqueue and remove unnecessary
ones.

>> I'll prep a debug patch to print out some details.
> 
> That'd be helpful, thanks!

Can you please apply the following patch and report the result?

Thanks.

>From 492a242b75b0abae3b1c17b4a654ab9ef67e612d Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj@kernel.org>
Date: Tue, 24 Aug 2010 14:22:47 +0200
Subject: [PATCH] workqueue: improve destroy_workqueue() debuggability

Now that the worklist is global, having works pending after wq
destruction can easily lead to oops and destroy_workqueue() have
several BUG_ON()s to catch these cases.  Unfortunately, BUG_ON()
doesn't tell much about how the work became pending after the final
flush_workqueue().

This patch adds WQ_DYING which is set before the final flush begins
and WARN_ON_ONCE() is triggered if a work is requested to be queued on
a dying workqueue and the request is ignored.  This clearly indicates
which caller is trying to queue a work on a dying workqueue and keeps
the system working in most cases.

Locking rule comment is updated such that the 'I' rule includes
modifying the field from destruction path.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 include/linux/workqueue.h |    2 ++
 kernel/workqueue.c        |    7 ++++++-
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 4f9d277..c959666 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -241,6 +241,8 @@ enum {
 	WQ_HIGHPRI		= 1 << 4, /* high priority */
 	WQ_CPU_INTENSIVE	= 1 << 5, /* cpu instensive workqueue */

+	WQ_DYING		= 1 << 6, /* internal: workqueue is dying */
+
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
 	WQ_MAX_UNBOUND_PER_CPU	= 4,	  /* 4 * #cpus for unbound wq */
 	WQ_DFL_ACTIVE		= WQ_MAX_ACTIVE / 2,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index cc3456f..362b50d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -87,7 +87,8 @@ enum {
 /*
  * Structure fields follow one of the following exclusion rules.
  *
- * I: Set during initialization and read-only afterwards.
+ * I: Modifiable by initialization/destruction paths and read-only for
+ *    everyone else.
  *
  * P: Preemption protected.  Disabling preemption is enough and should
  *    only be modified and accessed from the local cpu.
@@ -944,6 +945,9 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,

 	debug_work_activate(work);

+	if (WARN_ON_ONCE(wq->flags & WQ_DYING))
+		return;
+
 	/* determine gcwq to use */
 	if (!(wq->flags & WQ_UNBOUND)) {
 		struct global_cwq *last_gcwq;
@@ -2828,6 +2832,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
 {
 	unsigned int cpu;

+	wq->flags |= WQ_DYING;
 	flush_workqueue(wq);

 	/*
-- 
1.7.1

  reply	other threads:[~2010-08-24 12:40 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-24  8:55 workqueue destruction BUG_ON Johannes Berg
2010-08-24 10:24 ` Tejun Heo
2010-08-24 10:37   ` Johannes Berg
2010-08-24 12:35     ` Tejun Heo [this message]
2010-08-24 13:04       ` Johannes Berg
2010-08-24 13:10       ` Johannes Berg
2010-08-24 13:07         ` Tejun Heo
2010-08-24 13:17           ` Johannes Berg
2010-08-24 13:15             ` Tejun Heo
2010-08-24 13:23               ` Johannes Berg
2010-08-24 14:56                 ` Tejun Heo
2010-08-24 15:52                   ` Johannes Berg
2010-08-24 15:47                     ` Tejun Heo
2010-08-24 15:56                       ` Johannes Berg
2010-08-24 13:19           ` Johannes Berg

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=4C73BC96.6000003@kernel.org \
    --to=tj@kernel.org \
    --cc=johannes@sipsolutions.net \
    --cc=linux-kernel@vger.kernel.org \
    /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.