diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7ff5dc7..9824d4f 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4012,7 +4012,7 @@ void destroy_workqueue(struct workqueue_struct *wq) /* drain it before proceeding with destruction */ drain_workqueue(wq); - /* sanity checks */ + /* nothing should be in flight */ mutex_lock(&wq->mutex); for_each_pwq(pwq, wq) { int i; @@ -4024,8 +4024,7 @@ void destroy_workqueue(struct workqueue_struct *wq) } } - if (WARN_ON((pwq != wq->dfl_pwq) && (pwq->refcnt > 1)) || - WARN_ON(pwq->nr_active) || + if (WARN_ON(pwq->nr_active) || WARN_ON(!list_empty(&pwq->delayed_works))) { mutex_unlock(&wq->mutex); return; @@ -4046,6 +4045,13 @@ void destroy_workqueue(struct workqueue_struct *wq) if (wq->rescuer) kthread_stop(wq->rescuer->task); + /* rescuer is gone, everything should be quiescent now */ + WARN_ON(!list_empty(&wq->maydays)); + mutex_lock(&wq->mutex); + for_each_pwq(pwq, wq) + WARN_ON((pwq != wq->dfl_pwq) && (pwq->refcnt > 1)); + mutex_unlock(&wq->mutex); + if (!(wq->flags & WQ_UNBOUND)) { /* * The base ref is never dropped on per-cpu pwqs. Directly