lkml.org 
[lkml]   [2019]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 202/267] workqueue: Fix pwq ref leak in rescuer_thread()
    Date
    From: Tejun Heo <tj@kernel.org>

    commit e66b39af00f426b3356b96433d620cb3367ba1ff upstream.

    008847f66c3 ("workqueue: allow rescuer thread to do more work.") made
    the rescuer worker requeue the pwq immediately if there may be more
    work items which need rescuing instead of waiting for the next mayday
    timer expiration. Unfortunately, it doesn't check whether the pwq is
    already on the mayday list and unconditionally gets the ref and moves
    it onto the list. This doesn't corrupt the list but creates an
    additional reference to the pwq. It got queued twice but will only be
    removed once.

    This leak later can trigger pwq refcnt warning on workqueue
    destruction and prevent freeing of the workqueue.

    Signed-off-by: Tejun Heo <tj@kernel.org>
    Cc: "Williams, Gerald S" <gerald.s.williams@intel.com>
    Cc: NeilBrown <neilb@suse.de>
    Cc: stable@vger.kernel.org # v3.19+
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/workqueue.c | 13 ++++++++++---
    1 file changed, 10 insertions(+), 3 deletions(-)

    --- a/kernel/workqueue.c
    +++ b/kernel/workqueue.c
    @@ -2366,8 +2366,14 @@ repeat:
    */
    if (need_to_create_worker(pool)) {
    spin_lock(&wq_mayday_lock);
    - get_pwq(pwq);
    - list_move_tail(&pwq->mayday_node, &wq->maydays);
    + /*
    + * Queue iff we aren't racing destruction
    + * and somebody else hasn't queued it already.
    + */
    + if (wq->rescuer && list_empty(&pwq->mayday_node)) {
    + get_pwq(pwq);
    + list_add_tail(&pwq->mayday_node, &wq->maydays);
    + }
    spin_unlock(&wq_mayday_lock);
    }
    }
    @@ -4413,7 +4419,8 @@ static void show_pwq(struct pool_workque
    pr_info(" pwq %d:", pool->id);
    pr_cont_pool_info(pool);

    - pr_cont(" active=%d/%d%s\n", pwq->nr_active, pwq->max_active,
    + pr_cont(" active=%d/%d refcnt=%d%s\n",
    + pwq->nr_active, pwq->max_active, pwq->refcnt,
    !list_empty(&pwq->mayday_node) ? " MAYDAY" : "");

    hash_for_each(pool->busy_hash, bkt, worker, hentry) {

    \
     
     \ /
      Last update: 2019-12-16 19:44    [W:4.070 / U:0.112 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site