From: Lai Jiangshan <laijs@cn.fujitsu.com>
To: Tejun Heo <tj@kernel.org>, Eric Sandeen <sandeen@sandeen.net>
Cc: Eric Sandeen <sandeen@redhat.com>,
linux-kernel@vger.kernel.org, xfs-oss <xfs@oss.sgi.com>
Subject: Re: [PATCH workqueue wq/for-3.19-fixes] workqueue: fix subtle pool management issue which can stall whole worker_pool
Date: Mon, 19 Jan 2015 10:15:41 +0800 [thread overview]
Message-ID: <54BC68CD.7020809@cn.fujitsu.com> (raw)
In-Reply-To: <20150116193239.GA3715@htj.dyndns.org>
On 01/17/2015 03:32 AM, Tejun Heo wrote:
>>From 29187a9eeaf362d8422e62e17a22a6e115277a49 Mon Sep 17 00:00:00 2001
> From: Tejun Heo <tj@kernel.org>
> Date: Fri, 16 Jan 2015 14:21:16 -0500
>
> A worker_pool's forward progress is guaranteed by the fact that the
> last idle worker assumes the manager role to create more workers and
> summon the rescuers if creating workers doesn't succeed in timely
> manner before proceeding to execute work items.
>
> This manager role is implemented in manage_workers(), which indicates
> whether the worker may proceed to work item execution with its return
> value. This is necessary because multiple workers may contend for the
> manager role, and, if there already is a manager, others should
> proceed to work item execution.
>
> Unfortunately, the function also indicates that the worker may proceed
> to work item execution if need_to_create_worker() is false at the head
> of the function. need_to_create_worker() tests the following
> conditions.
>
> pending work items && !nr_running && !nr_idle
>
> The first and third conditions are protected by pool->lock and thus
> won't change while holding pool->lock; however, nr_running can change
> asynchronously as other workers block and resume and while it's likely
> to be zero, as someone woke this worker up in the first place, some
> other workers could have become runnable inbetween making it non-zero.
I had sent a patch similar:
https://lkml.org/lkml/2014/7/10/446
It was shame for me that I did not think deep enough that time.
>
> If this happens, manage_worker() could return false even with zero
> nr_idle making the worker, the last idle one, proceed to execute work
> items. If then all workers of the pool end up blocking on a resource
> which can only be released by a work item which is pending on that
> pool, the whole pool can deadlock as there's no one to create more
> workers or summon the rescuers.
How nr_running is decreased to zero in this case?
( The decreasing of nr_running is also protected by "X" )
( I just checked the cpu-hotplug code again ... find no suspect)
> -static bool maybe_create_worker(struct worker_pool *pool)
> +static void maybe_create_worker(struct worker_pool *pool)
> __releases(&pool->lock)
> __acquires(&pool->lock)
> {
> - if (!need_to_create_worker(pool))
> - return false;
It only returns false here, if there ware bug, the bug would be here.
But it still holds the pool->lock and no releasing form the beginning to here)
My doubt might be wrong, but at least it is a good cleanup
Acked-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Thanks
Lai
> restart:
> spin_unlock_irq(&pool->lock);
>
> @@ -1877,7 +1871,6 @@ restart:
> */
> if (need_to_create_worker(pool))
> goto restart;
> - return true;
> }
>
> /**
> @@ -1897,16 +1890,14 @@ restart:
> * multiple times. Does GFP_KERNEL allocations.
> *
> * Return:
> - * %false if the pool don't need management and the caller can safely start
> - * processing works, %true indicates that the function released pool->lock
> - * and reacquired it to perform some management function and that the
> - * conditions that the caller verified while holding the lock before
> - * calling the function might no longer be true.
> + * %false if the pool doesn't need management and the caller can safely
> + * start processing works, %true if management function was performed and
> + * the conditions that the caller verified before calling the function may
> + * no longer be true.
> */
> static bool manage_workers(struct worker *worker)
> {
> struct worker_pool *pool = worker->pool;
> - bool ret = false;
>
> /*
> * Anyone who successfully grabs manager_arb wins the arbitration
> @@ -1919,12 +1910,12 @@ static bool manage_workers(struct worker *worker)
> * actual management, the pool may stall indefinitely.
> */
> if (!mutex_trylock(&pool->manager_arb))
> - return ret;
> + return false;
>
> - ret |= maybe_create_worker(pool);
> + maybe_create_worker(pool);
>
> mutex_unlock(&pool->manager_arb);
> - return ret;
> + return true;
> }
>
> /**
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
WARNING: multiple messages have this Message-ID (diff)
From: Lai Jiangshan <laijs@cn.fujitsu.com>
To: Tejun Heo <tj@kernel.org>, Eric Sandeen <sandeen@sandeen.net>
Cc: Eric Sandeen <sandeen@redhat.com>, xfs-oss <xfs@oss.sgi.com>,
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH workqueue wq/for-3.19-fixes] workqueue: fix subtle pool management issue which can stall whole worker_pool
Date: Mon, 19 Jan 2015 10:15:41 +0800 [thread overview]
Message-ID: <54BC68CD.7020809@cn.fujitsu.com> (raw)
In-Reply-To: <20150116193239.GA3715@htj.dyndns.org>
On 01/17/2015 03:32 AM, Tejun Heo wrote:
>>From 29187a9eeaf362d8422e62e17a22a6e115277a49 Mon Sep 17 00:00:00 2001
> From: Tejun Heo <tj@kernel.org>
> Date: Fri, 16 Jan 2015 14:21:16 -0500
>
> A worker_pool's forward progress is guaranteed by the fact that the
> last idle worker assumes the manager role to create more workers and
> summon the rescuers if creating workers doesn't succeed in timely
> manner before proceeding to execute work items.
>
> This manager role is implemented in manage_workers(), which indicates
> whether the worker may proceed to work item execution with its return
> value. This is necessary because multiple workers may contend for the
> manager role, and, if there already is a manager, others should
> proceed to work item execution.
>
> Unfortunately, the function also indicates that the worker may proceed
> to work item execution if need_to_create_worker() is false at the head
> of the function. need_to_create_worker() tests the following
> conditions.
>
> pending work items && !nr_running && !nr_idle
>
> The first and third conditions are protected by pool->lock and thus
> won't change while holding pool->lock; however, nr_running can change
> asynchronously as other workers block and resume and while it's likely
> to be zero, as someone woke this worker up in the first place, some
> other workers could have become runnable inbetween making it non-zero.
I had sent a patch similar:
https://lkml.org/lkml/2014/7/10/446
It was shame for me that I did not think deep enough that time.
>
> If this happens, manage_worker() could return false even with zero
> nr_idle making the worker, the last idle one, proceed to execute work
> items. If then all workers of the pool end up blocking on a resource
> which can only be released by a work item which is pending on that
> pool, the whole pool can deadlock as there's no one to create more
> workers or summon the rescuers.
How nr_running is decreased to zero in this case?
( The decreasing of nr_running is also protected by "X" )
( I just checked the cpu-hotplug code again ... find no suspect)
> -static bool maybe_create_worker(struct worker_pool *pool)
> +static void maybe_create_worker(struct worker_pool *pool)
> __releases(&pool->lock)
> __acquires(&pool->lock)
> {
> - if (!need_to_create_worker(pool))
> - return false;
It only returns false here, if there ware bug, the bug would be here.
But it still holds the pool->lock and no releasing form the beginning to here)
My doubt might be wrong, but at least it is a good cleanup
Acked-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Thanks
Lai
> restart:
> spin_unlock_irq(&pool->lock);
>
> @@ -1877,7 +1871,6 @@ restart:
> */
> if (need_to_create_worker(pool))
> goto restart;
> - return true;
> }
>
> /**
> @@ -1897,16 +1890,14 @@ restart:
> * multiple times. Does GFP_KERNEL allocations.
> *
> * Return:
> - * %false if the pool don't need management and the caller can safely start
> - * processing works, %true indicates that the function released pool->lock
> - * and reacquired it to perform some management function and that the
> - * conditions that the caller verified while holding the lock before
> - * calling the function might no longer be true.
> + * %false if the pool doesn't need management and the caller can safely
> + * start processing works, %true if management function was performed and
> + * the conditions that the caller verified before calling the function may
> + * no longer be true.
> */
> static bool manage_workers(struct worker *worker)
> {
> struct worker_pool *pool = worker->pool;
> - bool ret = false;
>
> /*
> * Anyone who successfully grabs manager_arb wins the arbitration
> @@ -1919,12 +1910,12 @@ static bool manage_workers(struct worker *worker)
> * actual management, the pool may stall indefinitely.
> */
> if (!mutex_trylock(&pool->manager_arb))
> - return ret;
> + return false;
>
> - ret |= maybe_create_worker(pool);
> + maybe_create_worker(pool);
>
> mutex_unlock(&pool->manager_arb);
> - return ret;
> + return true;
> }
>
> /**
>
next prev parent reply other threads:[~2015-01-19 2:30 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-09 18:08 [PATCH 0/2] xfs: make xfs allocation workqueue per-mount, and high priority Eric Sandeen
2015-01-09 18:10 ` [PATCH 1/2] xfs: make global xfsalloc workqueue per-mount Eric Sandeen
2015-01-12 15:35 ` Brian Foster
2015-01-09 18:12 ` [PATCH 2/2] xfs: mark the xfs-alloc workqueue as high priority Eric Sandeen
2015-01-09 18:23 ` Tejun Heo
2015-01-09 20:36 ` Eric Sandeen
2015-01-10 19:28 ` Tejun Heo
2015-01-11 0:04 ` Eric Sandeen
2015-01-11 6:33 ` Tejun Heo
2015-01-12 20:09 ` Eric Sandeen
2015-01-12 22:53 ` Tejun Heo
2015-01-12 23:12 ` Eric Sandeen
2015-01-12 23:37 ` Tejun Heo
2015-01-13 19:08 ` Eric Sandeen
2015-01-13 20:19 ` Tejun Heo
2015-01-13 20:29 ` Eric Sandeen
2015-01-13 20:46 ` Tejun Heo
2015-01-13 22:58 ` Eric Sandeen
2015-01-13 23:35 ` [PATCH wq/for-3.19] workqueue: fix subtle pool management issue which can stall whole worker_pool Tejun Heo
2015-01-16 19:32 ` [PATCH workqueue wq/for-3.19-fixes] " Tejun Heo
2015-01-16 19:32 ` Tejun Heo
2015-01-19 2:15 ` Lai Jiangshan [this message]
2015-01-19 2:15 ` Lai Jiangshan
2015-01-09 23:28 ` [PATCH 2/2] xfs: mark the xfs-alloc workqueue as high priority Dave Chinner
2015-01-10 17:41 ` Tejun Heo
2015-01-12 3:30 ` Dave Chinner
2015-01-13 20:50 ` Tejun Heo
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=54BC68CD.7020809@cn.fujitsu.com \
--to=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=sandeen@redhat.com \
--cc=sandeen@sandeen.net \
--cc=tj@kernel.org \
--cc=xfs@oss.sgi.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.