Commit 50599e4c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'wq-for-7.1-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq

Pull workqueue fixes from Tejun Heo:

 - Plug a wq->cpu_pwq leak on the WQ_UNBOUND allocation failure path

 - Fix a cancel_delayed_work_sync() livelock against drain_workqueue()
   caused by the drain/destroy reject path leaving WORK_STRUCT_PENDING
   set with no owner

* tag 'wq-for-7.1-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
  workqueue: Fix wq->cpu_pwq leak in alloc_and_link_pwqs() WQ_UNBOUND path
  workqueue: Release PENDING in __queue_work() drain/destroy reject path
parents e1914add 0143033d
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -2296,6 +2296,18 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
	if (unlikely(wq->flags & (__WQ_DESTROYING | __WQ_DRAINING) &&
		     WARN_ONCE(!is_chained_work(wq), "workqueue: cannot queue %ps on wq %s\n",
			       work->func, wq->name))) {
		struct work_offq_data offqd;

		/*
		 * State on entry: PENDING is set, work is off-queue (no
		 * insert_work() has run).
		 *
		 * Returning without clearing PENDING would leave the work
		 * in a weird state (PENDING=1, PWQ=0, entry empty)
		 */
		work_offqd_unpack(&offqd, *work_data_bits(work));
		set_work_pool_and_clear_pending(work, offqd.pool_id,
						work_offqd_pack_flags(&offqd));
		return;
	}
	rcu_read_lock();
@@ -5642,7 +5654,9 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
		ret = apply_workqueue_attrs_locked(wq, unbound_std_wq_attrs[highpri]);
	}

	return ret;
	if (ret)
		goto enomem;
	return 0;

enomem:
	if (wq->cpu_pwq) {