]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
move 6.8 review away
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Apr 2024 17:50:22 +0000 (19:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Apr 2024 17:50:22 +0000 (19:50 +0200)
12 files changed:
review-6.8/revert-workqueue-don-t-call-cpumask_test_cpu-with-1-cpu-in-wq_update_node_max_active.patch [deleted file]
review-6.8/revert-workqueue-factor-out-pwq_is_empty.patch [deleted file]
review-6.8/revert-workqueue-implement-system-wide-nr_active-enforcement-for-unbound-workqueues.patch [deleted file]
review-6.8/revert-workqueue-introduce-struct-wq_node_nr_active.patch [deleted file]
review-6.8/revert-workqueue-make-wq_adjust_max_active-round-robin-pwqs-while-activating.patch [deleted file]
review-6.8/revert-workqueue-move-nr_active-handling-into-helpers.patch [deleted file]
review-6.8/revert-workqueue-move-pwq-max_active-to-wq-max_active.patch [deleted file]
review-6.8/revert-workqueue-rcu-protect-wq-dfl_pwq-and-implement-accessors-for-it.patch [deleted file]
review-6.8/revert-workqueue-replace-pwq_activate_inactive_work-with-pwq_activate_work.patch [deleted file]
review-6.8/revert-workqueue-shorten-events_freezable_power_efficient-name.patch [deleted file]
review-6.8/revert-workqueue.c-increase-workqueue-name-length.patch [deleted file]
review-6.8/series [deleted file]

diff --git a/review-6.8/revert-workqueue-don-t-call-cpumask_test_cpu-with-1-cpu-in-wq_update_node_max_active.patch b/review-6.8/revert-workqueue-don-t-call-cpumask_test_cpu-with-1-cpu-in-wq_update_node_max_active.patch
deleted file mode 100644 (file)
index 26d22c2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 517cd3032fa424c6b79e26858b0457cb5bfae7dd Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:12 +0200
-Subject: Revert "workqueue: Don't call cpumask_test_cpu() with -1 CPU in wq_update_node_max_active()"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 9fc557d489f8163c1aabcb89114b8eba960f4097 which is commit
-15930da42f8981dc42c19038042947b475b19f47 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -1506,7 +1506,7 @@ static void wq_update_node_max_active(st
-       lockdep_assert_held(&wq->mutex);
--      if (off_cpu >= 0 && !cpumask_test_cpu(off_cpu, effective))
-+      if (!cpumask_test_cpu(off_cpu, effective))
-               off_cpu = -1;
-       total_cpus = cpumask_weight_and(effective, cpu_online_mask);
diff --git a/review-6.8/revert-workqueue-factor-out-pwq_is_empty.patch b/review-6.8/revert-workqueue-factor-out-pwq_is_empty.patch
deleted file mode 100644 (file)
index 2187b2c..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From 71a2e79b9a53efb703033e61a264003b3ea85840 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:23 +0200
-Subject: Revert "workqueue: Factor out pwq_is_empty()"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 70abdc2f6c906ffea699f6e0e08fcbd9437e6bcc which is commit
-afa87ce85379e2d93863fce595afdb5771a84004 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |   13 ++++---------
- 1 file changed, 4 insertions(+), 9 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -1456,11 +1456,6 @@ static void put_pwq_unlocked(struct pool
-       }
- }
--static bool pwq_is_empty(struct pool_workqueue *pwq)
--{
--      return !pwq->nr_active && list_empty(&pwq->inactive_works);
--}
--
- static void pwq_activate_inactive_work(struct work_struct *work)
- {
-       struct pool_workqueue *pwq = get_work_pwq(work);
-@@ -3330,7 +3325,7 @@ reflush:
-               bool drained;
-               raw_spin_lock_irq(&pwq->pool->lock);
--              drained = pwq_is_empty(pwq);
-+              drained = !pwq->nr_active && list_empty(&pwq->inactive_works);
-               raw_spin_unlock_irq(&pwq->pool->lock);
-               if (drained)
-@@ -4777,7 +4772,7 @@ static bool pwq_busy(struct pool_workque
-       if ((pwq != pwq->wq->dfl_pwq) && (pwq->refcnt > 1))
-               return true;
--      if (!pwq_is_empty(pwq))
-+      if (pwq->nr_active || !list_empty(&pwq->inactive_works))
-               return true;
-       return false;
-@@ -5215,7 +5210,7 @@ void show_one_workqueue(struct workqueue
-       unsigned long flags;
-       for_each_pwq(pwq, wq) {
--              if (!pwq_is_empty(pwq)) {
-+              if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
-                       idle = false;
-                       break;
-               }
-@@ -5227,7 +5222,7 @@ void show_one_workqueue(struct workqueue
-       for_each_pwq(pwq, wq) {
-               raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--              if (!pwq_is_empty(pwq)) {
-+              if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
-                       /*
-                        * Defer printing to avoid deadlocks in console
-                        * drivers that queue work while holding locks
diff --git a/review-6.8/revert-workqueue-implement-system-wide-nr_active-enforcement-for-unbound-workqueues.patch b/review-6.8/revert-workqueue-implement-system-wide-nr_active-enforcement-for-unbound-workqueues.patch
deleted file mode 100644 (file)
index 3978338..0000000
+++ /dev/null
@@ -1,645 +0,0 @@
-From 258a95622e9ad94cf68aa8dc56f31532a65545bc Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:14 +0200
-Subject: Revert "workqueue: Implement system-wide nr_active enforcement for unbound workqueues"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 843288afd3cc6f3342659c6cf81fc47684d25563 which is commit
-5797b1c18919cd9c289ded7954383e499f729ce0 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- include/linux/workqueue.h |   35 ----
- kernel/workqueue.c        |  341 ++++------------------------------------------
- 2 files changed, 35 insertions(+), 341 deletions(-)
-
---- a/include/linux/workqueue.h
-+++ b/include/linux/workqueue.h
-@@ -391,13 +391,6 @@ enum {
-       WQ_MAX_ACTIVE           = 512,    /* I like 512, better ideas? */
-       WQ_UNBOUND_MAX_ACTIVE   = WQ_MAX_ACTIVE,
-       WQ_DFL_ACTIVE           = WQ_MAX_ACTIVE / 2,
--
--      /*
--       * Per-node default cap on min_active. Unless explicitly set, min_active
--       * is set to min(max_active, WQ_DFL_MIN_ACTIVE). For more details, see
--       * workqueue_struct->min_active definition.
--       */
--      WQ_DFL_MIN_ACTIVE       = 8,
- };
- /*
-@@ -440,33 +433,11 @@ extern struct workqueue_struct *system_f
-  * alloc_workqueue - allocate a workqueue
-  * @fmt: printf format for the name of the workqueue
-  * @flags: WQ_* flags
-- * @max_active: max in-flight work items, 0 for default
-+ * @max_active: max in-flight work items per CPU, 0 for default
-  * remaining args: args for @fmt
-  *
-- * For a per-cpu workqueue, @max_active limits the number of in-flight work
-- * items for each CPU. e.g. @max_active of 1 indicates that each CPU can be
-- * executing at most one work item for the workqueue.
-- *
-- * For unbound workqueues, @max_active limits the number of in-flight work items
-- * for the whole system. e.g. @max_active of 16 indicates that that there can be
-- * at most 16 work items executing for the workqueue in the whole system.
-- *
-- * As sharing the same active counter for an unbound workqueue across multiple
-- * NUMA nodes can be expensive, @max_active is distributed to each NUMA node
-- * according to the proportion of the number of online CPUs and enforced
-- * independently.
-- *
-- * Depending on online CPU distribution, a node may end up with per-node
-- * max_active which is significantly lower than @max_active, which can lead to
-- * deadlocks if the per-node concurrency limit is lower than the maximum number
-- * of interdependent work items for the workqueue.
-- *
-- * To guarantee forward progress regardless of online CPU distribution, the
-- * concurrency limit on every node is guaranteed to be equal to or greater than
-- * min_active which is set to min(@max_active, %WQ_DFL_MIN_ACTIVE). This means
-- * that the sum of per-node max_active's may be larger than @max_active.
-- *
-- * For detailed information on %WQ_* flags, please refer to
-+ * Allocate a workqueue with the specified parameters.  For detailed
-+ * information on WQ_* flags, please refer to
-  * Documentation/core-api/workqueue.rst.
-  *
-  * RETURNS:
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -122,9 +122,6 @@ enum {
-  *
-  * L: pool->lock protected.  Access with pool->lock held.
-  *
-- * LN: pool->lock and wq_node_nr_active->lock protected for writes. Either for
-- *     reads.
-- *
-  * K: Only modified by worker while holding pool->lock. Can be safely read by
-  *    self, while holding pool->lock or from IRQ context if %current is the
-  *    kworker.
-@@ -246,18 +243,17 @@ struct pool_workqueue {
-        * pwq->inactive_works instead of pool->worklist and marked with
-        * WORK_STRUCT_INACTIVE.
-        *
--       * All work items marked with WORK_STRUCT_INACTIVE do not participate in
--       * nr_active and all work items in pwq->inactive_works are marked with
--       * WORK_STRUCT_INACTIVE. But not all WORK_STRUCT_INACTIVE work items are
--       * in pwq->inactive_works. Some of them are ready to run in
--       * pool->worklist or worker->scheduled. Those work itmes are only struct
--       * wq_barrier which is used for flush_work() and should not participate
--       * in nr_active. For non-barrier work item, it is marked with
--       * WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
-+       * All work items marked with WORK_STRUCT_INACTIVE do not participate
-+       * in pwq->nr_active and all work items in pwq->inactive_works are
-+       * marked with WORK_STRUCT_INACTIVE.  But not all WORK_STRUCT_INACTIVE
-+       * work items are in pwq->inactive_works.  Some of them are ready to
-+       * run in pool->worklist or worker->scheduled.  Those work itmes are
-+       * only struct wq_barrier which is used for flush_work() and should
-+       * not participate in pwq->nr_active.  For non-barrier work item, it
-+       * is marked with WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
-        */
-       int                     nr_active;      /* L: nr of active works */
-       struct list_head        inactive_works; /* L: inactive works */
--      struct list_head        pending_node;   /* LN: node on wq_node_nr_active->pending_pwqs */
-       struct list_head        pwqs_node;      /* WR: node on wq->pwqs */
-       struct list_head        mayday_node;    /* MD: node on wq->maydays */
-@@ -289,19 +285,9 @@ struct wq_device;
-  * on each CPU, in an unbound workqueue, max_active applies to the whole system.
-  * As sharing a single nr_active across multiple sockets can be very expensive,
-  * the counting and enforcement is per NUMA node.
-- *
-- * The following struct is used to enforce per-node max_active. When a pwq wants
-- * to start executing a work item, it should increment ->nr using
-- * tryinc_node_nr_active(). If acquisition fails due to ->nr already being over
-- * ->max, the pwq is queued on ->pending_pwqs. As in-flight work items finish
-- * and decrement ->nr, node_activate_pending_pwq() activates the pending pwqs in
-- * round-robin order.
-  */
- struct wq_node_nr_active {
--      int                     max;            /* per-node max_active */
--      atomic_t                nr;             /* per-node nr_active */
--      raw_spinlock_t          lock;           /* nests inside pool locks */
--      struct list_head        pending_pwqs;   /* LN: pwqs with inactive works */
-+      atomic_t                nr;             /* per-node nr_active count */
- };
- /*
-@@ -324,12 +310,8 @@ struct workqueue_struct {
-       struct worker           *rescuer;       /* MD: rescue worker */
-       int                     nr_drainers;    /* WQ: drain in progress */
--
--      /* See alloc_workqueue() function comment for info on min/max_active */
-       int                     max_active;     /* WO: max active works */
--      int                     min_active;     /* WO: min active works */
-       int                     saved_max_active; /* WQ: saved max_active */
--      int                     saved_min_active; /* WQ: saved min_active */
-       struct workqueue_attrs  *unbound_attrs; /* PW: only for unbound wqs */
-       struct pool_workqueue __rcu *dfl_pwq;   /* PW: only for unbound wqs */
-@@ -681,19 +663,6 @@ static struct pool_workqueue *unbound_pw
-                                    lockdep_is_held(&wq->mutex));
- }
--/**
-- * unbound_effective_cpumask - effective cpumask of an unbound workqueue
-- * @wq: workqueue of interest
-- *
-- * @wq->unbound_attrs->cpumask contains the cpumask requested by the user which
-- * is masked with wq_unbound_cpumask to determine the effective cpumask. The
-- * default pwq is always mapped to the pool with the current effective cpumask.
-- */
--static struct cpumask *unbound_effective_cpumask(struct workqueue_struct *wq)
--{
--      return unbound_pwq(wq, -1)->pool->attrs->__pod_cpumask;
--}
--
- static unsigned int work_color_to_flags(int color)
- {
-       return color << WORK_STRUCT_COLOR_SHIFT;
-@@ -1489,46 +1458,6 @@ static struct wq_node_nr_active *wq_node
- }
- /**
-- * wq_update_node_max_active - Update per-node max_actives to use
-- * @wq: workqueue to update
-- * @off_cpu: CPU that's going down, -1 if a CPU is not going down
-- *
-- * Update @wq->node_nr_active[]->max. @wq must be unbound. max_active is
-- * distributed among nodes according to the proportions of numbers of online
-- * cpus. The result is always between @wq->min_active and max_active.
-- */
--static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
--{
--      struct cpumask *effective = unbound_effective_cpumask(wq);
--      int min_active = READ_ONCE(wq->min_active);
--      int max_active = READ_ONCE(wq->max_active);
--      int total_cpus, node;
--
--      lockdep_assert_held(&wq->mutex);
--
--      if (!cpumask_test_cpu(off_cpu, effective))
--              off_cpu = -1;
--
--      total_cpus = cpumask_weight_and(effective, cpu_online_mask);
--      if (off_cpu >= 0)
--              total_cpus--;
--
--      for_each_node(node) {
--              int node_cpus;
--
--              node_cpus = cpumask_weight_and(effective, cpumask_of_node(node));
--              if (off_cpu >= 0 && cpu_to_node(off_cpu) == node)
--                      node_cpus--;
--
--              wq_node_nr_active(wq, node)->max =
--                      clamp(DIV_ROUND_UP(max_active * node_cpus, total_cpus),
--                            min_active, max_active);
--      }
--
--      wq_node_nr_active(wq, NUMA_NO_NODE)->max = min_active;
--}
--
--/**
-  * get_pwq - get an extra reference on the specified pool_workqueue
-  * @pwq: pool_workqueue to get
-  *
-@@ -1625,98 +1554,35 @@ static bool pwq_activate_work(struct poo
-       return true;
- }
--static bool tryinc_node_nr_active(struct wq_node_nr_active *nna)
--{
--      int max = READ_ONCE(nna->max);
--
--      while (true) {
--              int old, tmp;
--
--              old = atomic_read(&nna->nr);
--              if (old >= max)
--                      return false;
--              tmp = atomic_cmpxchg_relaxed(&nna->nr, old, old + 1);
--              if (tmp == old)
--                      return true;
--      }
--}
--
- /**
-  * pwq_tryinc_nr_active - Try to increment nr_active for a pwq
-  * @pwq: pool_workqueue of interest
-- * @fill: max_active may have increased, try to increase concurrency level
-  *
-  * Try to increment nr_active for @pwq. Returns %true if an nr_active count is
-  * successfully obtained. %false otherwise.
-  */
--static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq, bool fill)
-+static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq)
- {
-       struct workqueue_struct *wq = pwq->wq;
-       struct worker_pool *pool = pwq->pool;
-       struct wq_node_nr_active *nna = wq_node_nr_active(wq, pool->node);
--      bool obtained = false;
-+      bool obtained;
-       lockdep_assert_held(&pool->lock);
--      if (!nna) {
--              /* per-cpu workqueue, pwq->nr_active is sufficient */
--              obtained = pwq->nr_active < READ_ONCE(wq->max_active);
--              goto out;
--      }
--
--      /*
--       * Unbound workqueue uses per-node shared nr_active $nna. If @pwq is
--       * already waiting on $nna, pwq_dec_nr_active() will maintain the
--       * concurrency level. Don't jump the line.
--       *
--       * We need to ignore the pending test after max_active has increased as
--       * pwq_dec_nr_active() can only maintain the concurrency level but not
--       * increase it. This is indicated by @fill.
--       */
--      if (!list_empty(&pwq->pending_node) && likely(!fill))
--              goto out;
--
--      obtained = tryinc_node_nr_active(nna);
--      if (obtained)
--              goto out;
--
--      /*
--       * Lockless acquisition failed. Lock, add ourself to $nna->pending_pwqs
--       * and try again. The smp_mb() is paired with the implied memory barrier
--       * of atomic_dec_return() in pwq_dec_nr_active() to ensure that either
--       * we see the decremented $nna->nr or they see non-empty
--       * $nna->pending_pwqs.
--       */
--      raw_spin_lock(&nna->lock);
--
--      if (list_empty(&pwq->pending_node))
--              list_add_tail(&pwq->pending_node, &nna->pending_pwqs);
--      else if (likely(!fill))
--              goto out_unlock;
--
--      smp_mb();
--
--      obtained = tryinc_node_nr_active(nna);
--
--      /*
--       * If @fill, @pwq might have already been pending. Being spuriously
--       * pending in cold paths doesn't affect anything. Let's leave it be.
--       */
--      if (obtained && likely(!fill))
--              list_del_init(&pwq->pending_node);
-+      obtained = pwq->nr_active < READ_ONCE(wq->max_active);
--out_unlock:
--      raw_spin_unlock(&nna->lock);
--out:
--      if (obtained)
-+      if (obtained) {
-               pwq->nr_active++;
-+              if (nna)
-+                      atomic_inc(&nna->nr);
-+      }
-       return obtained;
- }
- /**
-  * pwq_activate_first_inactive - Activate the first inactive work item on a pwq
-  * @pwq: pool_workqueue of interest
-- * @fill: max_active may have increased, try to increase concurrency level
-  *
-  * Activate the first inactive work item of @pwq if available and allowed by
-  * max_active limit.
-@@ -1724,13 +1590,13 @@ out:
-  * Returns %true if an inactive work item has been activated. %false if no
-  * inactive work item is found or max_active limit is reached.
-  */
--static bool pwq_activate_first_inactive(struct pool_workqueue *pwq, bool fill)
-+static bool pwq_activate_first_inactive(struct pool_workqueue *pwq)
- {
-       struct work_struct *work =
-               list_first_entry_or_null(&pwq->inactive_works,
-                                        struct work_struct, entry);
--      if (work && pwq_tryinc_nr_active(pwq, fill)) {
-+      if (work && pwq_tryinc_nr_active(pwq)) {
-               __pwq_activate_work(pwq, work);
-               return true;
-       } else {
-@@ -1739,92 +1605,10 @@ static bool pwq_activate_first_inactive(
- }
- /**
-- * node_activate_pending_pwq - Activate a pending pwq on a wq_node_nr_active
-- * @nna: wq_node_nr_active to activate a pending pwq for
-- * @caller_pool: worker_pool the caller is locking
-- *
-- * Activate a pwq in @nna->pending_pwqs. Called with @caller_pool locked.
-- * @caller_pool may be unlocked and relocked to lock other worker_pools.
-- */
--static void node_activate_pending_pwq(struct wq_node_nr_active *nna,
--                                    struct worker_pool *caller_pool)
--{
--      struct worker_pool *locked_pool = caller_pool;
--      struct pool_workqueue *pwq;
--      struct work_struct *work;
--
--      lockdep_assert_held(&caller_pool->lock);
--
--      raw_spin_lock(&nna->lock);
--retry:
--      pwq = list_first_entry_or_null(&nna->pending_pwqs,
--                                     struct pool_workqueue, pending_node);
--      if (!pwq)
--              goto out_unlock;
--
--      /*
--       * If @pwq is for a different pool than @locked_pool, we need to lock
--       * @pwq->pool->lock. Let's trylock first. If unsuccessful, do the unlock
--       * / lock dance. For that, we also need to release @nna->lock as it's
--       * nested inside pool locks.
--       */
--      if (pwq->pool != locked_pool) {
--              raw_spin_unlock(&locked_pool->lock);
--              locked_pool = pwq->pool;
--              if (!raw_spin_trylock(&locked_pool->lock)) {
--                      raw_spin_unlock(&nna->lock);
--                      raw_spin_lock(&locked_pool->lock);
--                      raw_spin_lock(&nna->lock);
--                      goto retry;
--              }
--      }
--
--      /*
--       * $pwq may not have any inactive work items due to e.g. cancellations.
--       * Drop it from pending_pwqs and see if there's another one.
--       */
--      work = list_first_entry_or_null(&pwq->inactive_works,
--                                      struct work_struct, entry);
--      if (!work) {
--              list_del_init(&pwq->pending_node);
--              goto retry;
--      }
--
--      /*
--       * Acquire an nr_active count and activate the inactive work item. If
--       * $pwq still has inactive work items, rotate it to the end of the
--       * pending_pwqs so that we round-robin through them. This means that
--       * inactive work items are not activated in queueing order which is fine
--       * given that there has never been any ordering across different pwqs.
--       */
--      if (likely(tryinc_node_nr_active(nna))) {
--              pwq->nr_active++;
--              __pwq_activate_work(pwq, work);
--
--              if (list_empty(&pwq->inactive_works))
--                      list_del_init(&pwq->pending_node);
--              else
--                      list_move_tail(&pwq->pending_node, &nna->pending_pwqs);
--
--              /* if activating a foreign pool, make sure it's running */
--              if (pwq->pool != caller_pool)
--                      kick_pool(pwq->pool);
--      }
--
--out_unlock:
--      raw_spin_unlock(&nna->lock);
--      if (locked_pool != caller_pool) {
--              raw_spin_unlock(&locked_pool->lock);
--              raw_spin_lock(&caller_pool->lock);
--      }
--}
--
--/**
-  * pwq_dec_nr_active - Retire an active count
-  * @pwq: pool_workqueue of interest
-  *
-  * Decrement @pwq's nr_active and try to activate the first inactive work item.
-- * For unbound workqueues, this function may temporarily drop @pwq->pool->lock.
-  */
- static void pwq_dec_nr_active(struct pool_workqueue *pwq)
- {
-@@ -1844,29 +1628,12 @@ static void pwq_dec_nr_active(struct poo
-        * inactive work item on @pwq itself.
-        */
-       if (!nna) {
--              pwq_activate_first_inactive(pwq, false);
-+              pwq_activate_first_inactive(pwq);
-               return;
-       }
--      /*
--       * If @pwq is for an unbound workqueue, it's more complicated because
--       * multiple pwqs and pools may be sharing the nr_active count. When a
--       * pwq needs to wait for an nr_active count, it puts itself on
--       * $nna->pending_pwqs. The following atomic_dec_return()'s implied
--       * memory barrier is paired with smp_mb() in pwq_tryinc_nr_active() to
--       * guarantee that either we see non-empty pending_pwqs or they see
--       * decremented $nna->nr.
--       *
--       * $nna->max may change as CPUs come online/offline and @pwq->wq's
--       * max_active gets updated. However, it is guaranteed to be equal to or
--       * larger than @pwq->wq->min_active which is above zero unless freezing.
--       * This maintains the forward progress guarantee.
--       */
--      if (atomic_dec_return(&nna->nr) >= READ_ONCE(nna->max))
--              return;
--
--      if (!list_empty(&nna->pending_pwqs))
--              node_activate_pending_pwq(nna, pool);
-+      atomic_dec(&nna->nr);
-+      pwq_activate_first_inactive(pwq);
- }
- /**
-@@ -2187,7 +1954,7 @@ retry:
-        * @work must also queue behind existing inactive work items to maintain
-        * ordering when max_active changes. See wq_adjust_max_active().
-        */
--      if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq, false)) {
-+      if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq)) {
-               if (list_empty(&pool->worklist))
-                       pool->watchdog_ts = jiffies;
-@@ -3420,7 +3187,7 @@ static void insert_wq_barrier(struct poo
-       barr->task = current;
--      /* The barrier work item does not participate in nr_active. */
-+      /* The barrier work item does not participate in pwq->nr_active. */
-       work_flags |= WORK_STRUCT_INACTIVE;
-       /*
-@@ -4336,8 +4103,6 @@ static void free_node_nr_active(struct w
- static void init_node_nr_active(struct wq_node_nr_active *nna)
- {
-       atomic_set(&nna->nr, 0);
--      raw_spin_lock_init(&nna->lock);
--      INIT_LIST_HEAD(&nna->pending_pwqs);
- }
- /*
-@@ -4577,15 +4342,6 @@ static void pwq_release_workfn(struct kt
-               mutex_unlock(&wq_pool_mutex);
-       }
--      if (!list_empty(&pwq->pending_node)) {
--              struct wq_node_nr_active *nna =
--                      wq_node_nr_active(pwq->wq, pwq->pool->node);
--
--              raw_spin_lock_irq(&nna->lock);
--              list_del_init(&pwq->pending_node);
--              raw_spin_unlock_irq(&nna->lock);
--      }
--
-       call_rcu(&pwq->rcu, rcu_free_pwq);
-       /*
-@@ -4611,7 +4367,6 @@ static void init_pwq(struct pool_workque
-       pwq->flush_color = -1;
-       pwq->refcnt = 1;
-       INIT_LIST_HEAD(&pwq->inactive_works);
--      INIT_LIST_HEAD(&pwq->pending_node);
-       INIT_LIST_HEAD(&pwq->pwqs_node);
-       INIT_LIST_HEAD(&pwq->mayday_node);
-       kthread_init_work(&pwq->release_work, pwq_release_workfn);
-@@ -4819,9 +4574,6 @@ static void apply_wqattrs_commit(struct
-                                                       ctx->pwq_tbl[cpu]);
-       ctx->dfl_pwq = install_unbound_pwq(ctx->wq, -1, ctx->dfl_pwq);
--      /* update node_nr_active->max */
--      wq_update_node_max_active(ctx->wq, -1);
--
-       mutex_unlock(&ctx->wq->mutex);
- }
-@@ -5082,35 +4834,24 @@ static int init_rescuer(struct workqueue
- static void wq_adjust_max_active(struct workqueue_struct *wq)
- {
-       bool activated;
--      int new_max, new_min;
-       lockdep_assert_held(&wq->mutex);
-       if ((wq->flags & WQ_FREEZABLE) && workqueue_freezing) {
--              new_max = 0;
--              new_min = 0;
--      } else {
--              new_max = wq->saved_max_active;
--              new_min = wq->saved_min_active;
-+              WRITE_ONCE(wq->max_active, 0);
-+              return;
-       }
--      if (wq->max_active == new_max && wq->min_active == new_min)
-+      if (wq->max_active == wq->saved_max_active)
-               return;
-       /*
--       * Update @wq->max/min_active and then kick inactive work items if more
-+       * Update @wq->max_active and then kick inactive work items if more
-        * active work items are allowed. This doesn't break work item ordering
-        * because new work items are always queued behind existing inactive
-        * work items if there are any.
-        */
--      WRITE_ONCE(wq->max_active, new_max);
--      WRITE_ONCE(wq->min_active, new_min);
--
--      if (wq->flags & WQ_UNBOUND)
--              wq_update_node_max_active(wq, -1);
--
--      if (new_max == 0)
--              return;
-+      WRITE_ONCE(wq->max_active, wq->saved_max_active);
-       /*
-        * Round-robin through pwq's activating the first inactive work item
-@@ -5125,7 +4866,7 @@ static void wq_adjust_max_active(struct
-                       /* can be called during early boot w/ irq disabled */
-                       raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--                      if (pwq_activate_first_inactive(pwq, true)) {
-+                      if (pwq_activate_first_inactive(pwq)) {
-                               activated = true;
-                               kick_pool(pwq->pool);
-                       }
-@@ -5187,9 +4928,7 @@ struct workqueue_struct *alloc_workqueue
-       /* init wq */
-       wq->flags = flags;
-       wq->max_active = max_active;
--      wq->min_active = min(max_active, WQ_DFL_MIN_ACTIVE);
--      wq->saved_max_active = wq->max_active;
--      wq->saved_min_active = wq->min_active;
-+      wq->saved_max_active = max_active;
-       mutex_init(&wq->mutex);
-       atomic_set(&wq->nr_pwqs_to_flush, 0);
-       INIT_LIST_HEAD(&wq->pwqs);
-@@ -5355,8 +5094,7 @@ EXPORT_SYMBOL_GPL(destroy_workqueue);
-  * @wq: target workqueue
-  * @max_active: new max_active value.
-  *
-- * Set max_active of @wq to @max_active. See the alloc_workqueue() function
-- * comment.
-+ * Set max_active of @wq to @max_active.
-  *
-  * CONTEXT:
-  * Don't call from IRQ context.
-@@ -5373,9 +5111,6 @@ void workqueue_set_max_active(struct wor
-       wq->flags &= ~__WQ_ORDERED;
-       wq->saved_max_active = max_active;
--      if (wq->flags & WQ_UNBOUND)
--              wq->saved_min_active = min(wq->saved_min_active, max_active);
--
-       wq_adjust_max_active(wq);
-       mutex_unlock(&wq->mutex);
-@@ -6057,10 +5792,6 @@ int workqueue_online_cpu(unsigned int cp
-                       for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
-                               wq_update_pod(wq, tcpu, cpu, true);
--
--                      mutex_lock(&wq->mutex);
--                      wq_update_node_max_active(wq, -1);
--                      mutex_unlock(&wq->mutex);
-               }
-       }
-@@ -6089,10 +5820,6 @@ int workqueue_offline_cpu(unsigned int c
-                       for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
-                               wq_update_pod(wq, tcpu, cpu, false);
--
--                      mutex_lock(&wq->mutex);
--                      wq_update_node_max_active(wq, cpu);
--                      mutex_unlock(&wq->mutex);
-               }
-       }
-       mutex_unlock(&wq_pool_mutex);
-@@ -7373,12 +7100,8 @@ void __init workqueue_init_topology(void
-        * combinations to apply per-pod sharing.
-        */
-       list_for_each_entry(wq, &workqueues, list) {
--              for_each_online_cpu(cpu)
-+              for_each_online_cpu(cpu) {
-                       wq_update_pod(wq, cpu, cpu, true);
--              if (wq->flags & WQ_UNBOUND) {
--                      mutex_lock(&wq->mutex);
--                      wq_update_node_max_active(wq, -1);
--                      mutex_unlock(&wq->mutex);
-               }
-       }
diff --git a/review-6.8/revert-workqueue-introduce-struct-wq_node_nr_active.patch b/review-6.8/revert-workqueue-introduce-struct-wq_node_nr_active.patch
deleted file mode 100644 (file)
index ab931be..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-From fb5e5e004c4c1e3c6f3a209a7d16909d2a9ffac2 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:16 +0200
-Subject: Revert "workqueue: Introduce struct wq_node_nr_active"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 7a5cd14a4900e0017142ad479ba8e34671822fc6 which is
-commit 91ccc6e7233bb10a9c176aa4cc70d6f432a441a5 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |  142 ++---------------------------------------------------
- 1 file changed, 7 insertions(+), 135 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -281,16 +281,6 @@ struct wq_flusher {
- struct wq_device;
- /*
-- * Unlike in a per-cpu workqueue where max_active limits its concurrency level
-- * on each CPU, in an unbound workqueue, max_active applies to the whole system.
-- * As sharing a single nr_active across multiple sockets can be very expensive,
-- * the counting and enforcement is per NUMA node.
-- */
--struct wq_node_nr_active {
--      atomic_t                nr;             /* per-node nr_active count */
--};
--
--/*
-  * The externally visible workqueue.  It relays the issued work items to
-  * the appropriate worker_pool through its pool_workqueues.
-  */
-@@ -336,7 +326,6 @@ struct workqueue_struct {
-       /* hot fields used during command issue, aligned to cacheline */
-       unsigned int            flags ____cacheline_aligned; /* WQ: WQ_* flags */
-       struct pool_workqueue __percpu __rcu **cpu_pwq; /* I: per-cpu pwqs */
--      struct wq_node_nr_active *node_nr_active[]; /* I: per-node nr_active */
- };
- static struct kmem_cache *pwq_cache;
-@@ -1433,31 +1422,6 @@ work_func_t wq_worker_last_func(struct t
- }
- /**
-- * wq_node_nr_active - Determine wq_node_nr_active to use
-- * @wq: workqueue of interest
-- * @node: NUMA node, can be %NUMA_NO_NODE
-- *
-- * Determine wq_node_nr_active to use for @wq on @node. Returns:
-- *
-- * - %NULL for per-cpu workqueues as they don't need to use shared nr_active.
-- *
-- * - node_nr_active[nr_node_ids] if @node is %NUMA_NO_NODE.
-- *
-- * - Otherwise, node_nr_active[@node].
-- */
--static struct wq_node_nr_active *wq_node_nr_active(struct workqueue_struct *wq,
--                                                 int node)
--{
--      if (!(wq->flags & WQ_UNBOUND))
--              return NULL;
--
--      if (node == NUMA_NO_NODE)
--              node = nr_node_ids;
--
--      return wq->node_nr_active[node];
--}
--
--/**
-  * get_pwq - get an extra reference on the specified pool_workqueue
-  * @pwq: pool_workqueue to get
-  *
-@@ -1538,17 +1502,12 @@ static bool pwq_activate_work(struct poo
-                             struct work_struct *work)
- {
-       struct worker_pool *pool = pwq->pool;
--      struct wq_node_nr_active *nna;
-       lockdep_assert_held(&pool->lock);
-       if (!(*work_data_bits(work) & WORK_STRUCT_INACTIVE))
-               return false;
--      nna = wq_node_nr_active(pwq->wq, pool->node);
--      if (nna)
--              atomic_inc(&nna->nr);
--
-       pwq->nr_active++;
-       __pwq_activate_work(pwq, work);
-       return true;
-@@ -1565,18 +1524,14 @@ static bool pwq_tryinc_nr_active(struct
- {
-       struct workqueue_struct *wq = pwq->wq;
-       struct worker_pool *pool = pwq->pool;
--      struct wq_node_nr_active *nna = wq_node_nr_active(wq, pool->node);
-       bool obtained;
-       lockdep_assert_held(&pool->lock);
-       obtained = pwq->nr_active < READ_ONCE(wq->max_active);
--      if (obtained) {
-+      if (obtained)
-               pwq->nr_active++;
--              if (nna)
--                      atomic_inc(&nna->nr);
--      }
-       return obtained;
- }
-@@ -1613,26 +1568,10 @@ static bool pwq_activate_first_inactive(
- static void pwq_dec_nr_active(struct pool_workqueue *pwq)
- {
-       struct worker_pool *pool = pwq->pool;
--      struct wq_node_nr_active *nna = wq_node_nr_active(pwq->wq, pool->node);
-       lockdep_assert_held(&pool->lock);
--      /*
--       * @pwq->nr_active should be decremented for both percpu and unbound
--       * workqueues.
--       */
-       pwq->nr_active--;
--
--      /*
--       * For a percpu workqueue, it's simple. Just need to kick the first
--       * inactive work item on @pwq itself.
--       */
--      if (!nna) {
--              pwq_activate_first_inactive(pwq);
--              return;
--      }
--
--      atomic_dec(&nna->nr);
-       pwq_activate_first_inactive(pwq);
- }
-@@ -4087,63 +4026,11 @@ static void wq_free_lockdep(struct workq
- }
- #endif
--static void free_node_nr_active(struct wq_node_nr_active **nna_ar)
--{
--      int node;
--
--      for_each_node(node) {
--              kfree(nna_ar[node]);
--              nna_ar[node] = NULL;
--      }
--
--      kfree(nna_ar[nr_node_ids]);
--      nna_ar[nr_node_ids] = NULL;
--}
--
--static void init_node_nr_active(struct wq_node_nr_active *nna)
--{
--      atomic_set(&nna->nr, 0);
--}
--
--/*
-- * Each node's nr_active counter will be accessed mostly from its own node and
-- * should be allocated in the node.
-- */
--static int alloc_node_nr_active(struct wq_node_nr_active **nna_ar)
--{
--      struct wq_node_nr_active *nna;
--      int node;
--
--      for_each_node(node) {
--              nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, node);
--              if (!nna)
--                      goto err_free;
--              init_node_nr_active(nna);
--              nna_ar[node] = nna;
--      }
--
--      /* [nr_node_ids] is used as the fallback */
--      nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, NUMA_NO_NODE);
--      if (!nna)
--              goto err_free;
--      init_node_nr_active(nna);
--      nna_ar[nr_node_ids] = nna;
--
--      return 0;
--
--err_free:
--      free_node_nr_active(nna_ar);
--      return -ENOMEM;
--}
--
- static void rcu_free_wq(struct rcu_head *rcu)
- {
-       struct workqueue_struct *wq =
-               container_of(rcu, struct workqueue_struct, rcu);
--      if (wq->flags & WQ_UNBOUND)
--              free_node_nr_active(wq->node_nr_active);
--
-       wq_free_lockdep(wq);
-       free_percpu(wq->cpu_pwq);
-       free_workqueue_attrs(wq->unbound_attrs);
-@@ -4882,8 +4769,7 @@ struct workqueue_struct *alloc_workqueue
- {
-       va_list args;
-       struct workqueue_struct *wq;
--      size_t wq_size;
--      int name_len;
-+      int len;
-       /*
-        * Unbound && max_active == 1 used to imply ordered, which is no longer
-@@ -4899,12 +4785,7 @@ struct workqueue_struct *alloc_workqueue
-               flags |= WQ_UNBOUND;
-       /* allocate wq and format name */
--      if (flags & WQ_UNBOUND)
--              wq_size = struct_size(wq, node_nr_active, nr_node_ids + 1);
--      else
--              wq_size = sizeof(*wq);
--
--      wq = kzalloc(wq_size, GFP_KERNEL);
-+      wq = kzalloc(sizeof(*wq), GFP_KERNEL);
-       if (!wq)
-               return NULL;
-@@ -4915,12 +4796,11 @@ struct workqueue_struct *alloc_workqueue
-       }
-       va_start(args, max_active);
--      name_len = vsnprintf(wq->name, sizeof(wq->name), fmt, args);
-+      len = vsnprintf(wq->name, sizeof(wq->name), fmt, args);
-       va_end(args);
--      if (name_len >= WQ_NAME_LEN)
--              pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n",
--                           wq->name);
-+      if (len >= WQ_NAME_LEN)
-+              pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n", wq->name);
-       max_active = max_active ?: WQ_DFL_ACTIVE;
-       max_active = wq_clamp_max_active(max_active, flags, wq->name);
-@@ -4939,13 +4819,8 @@ struct workqueue_struct *alloc_workqueue
-       wq_init_lockdep(wq);
-       INIT_LIST_HEAD(&wq->list);
--      if (flags & WQ_UNBOUND) {
--              if (alloc_node_nr_active(wq->node_nr_active) < 0)
--                      goto err_unreg_lockdep;
--      }
--
-       if (alloc_and_link_pwqs(wq) < 0)
--              goto err_free_node_nr_active;
-+              goto err_unreg_lockdep;
-       if (wq_online && init_rescuer(wq) < 0)
-               goto err_destroy;
-@@ -4970,9 +4845,6 @@ struct workqueue_struct *alloc_workqueue
-       return wq;
--err_free_node_nr_active:
--      if (wq->flags & WQ_UNBOUND)
--              free_node_nr_active(wq->node_nr_active);
- err_unreg_lockdep:
-       wq_unregister_lockdep(wq);
-       wq_free_lockdep(wq);
diff --git a/review-6.8/revert-workqueue-make-wq_adjust_max_active-round-robin-pwqs-while-activating.patch b/review-6.8/revert-workqueue-make-wq_adjust_max_active-round-robin-pwqs-while-activating.patch
deleted file mode 100644 (file)
index c71e12b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From c1160908b097134695a131c2d974c6d801058eff Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:19 +0200
-Subject: Revert "workqueue: Make wq_adjust_max_active() round-robin pwqs while activating"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit ddb232dc0f1339f9ed506730fd6bee6f5e3dcb37 which is
-commit c5404d4e6df6faba1007544b5f4e62c7c14416dd upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |   33 +++++++++++++--------------------
- 1 file changed, 13 insertions(+), 20 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -4703,7 +4703,7 @@ static int init_rescuer(struct workqueue
-  */
- static void wq_adjust_max_active(struct workqueue_struct *wq)
- {
--      bool activated;
-+      struct pool_workqueue *pwq;
-       lockdep_assert_held(&wq->mutex);
-@@ -4723,26 +4723,19 @@ static void wq_adjust_max_active(struct
-        */
-       WRITE_ONCE(wq->max_active, wq->saved_max_active);
--      /*
--       * Round-robin through pwq's activating the first inactive work item
--       * until max_active is filled.
--       */
--      do {
--              struct pool_workqueue *pwq;
-+      for_each_pwq(pwq, wq) {
-+              unsigned long flags;
-+
-+              /* this function can be called during early boot w/ irq disabled */
-+              raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--              activated = false;
--              for_each_pwq(pwq, wq) {
--                      unsigned long flags;
--
--                      /* can be called during early boot w/ irq disabled */
--                      raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--                      if (pwq_activate_first_inactive(pwq)) {
--                              activated = true;
--                              kick_pool(pwq->pool);
--                      }
--                      raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
--              }
--      } while (activated);
-+              while (pwq_activate_first_inactive(pwq))
-+                      ;
-+
-+              kick_pool(pwq->pool);
-+
-+              raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
-+      }
- }
- __printf(1, 4)
diff --git a/review-6.8/revert-workqueue-move-nr_active-handling-into-helpers.patch b/review-6.8/revert-workqueue-move-nr_active-handling-into-helpers.patch
deleted file mode 100644 (file)
index e893656..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-From c7cb60780ff4256313fc047682cfd498e2b5a3e7 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:20 +0200
-Subject: Revert "workqueue: Move nr_active handling into helpers"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 6584970ff38fc8f875c683dbb47bb38d4132a528 which is
-commit 1c270b79ce0b8290f146255ea9057243f6dd3c17 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |   86 +++++++++++------------------------------------------
- 1 file changed, 19 insertions(+), 67 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -1464,14 +1464,11 @@ static bool pwq_is_empty(struct pool_wor
- static void __pwq_activate_work(struct pool_workqueue *pwq,
-                               struct work_struct *work)
- {
--      unsigned long *wdb = work_data_bits(work);
--
--      WARN_ON_ONCE(!(*wdb & WORK_STRUCT_INACTIVE));
-       trace_workqueue_activate_work(work);
-       if (list_empty(&pwq->pool->worklist))
-               pwq->pool->watchdog_ts = jiffies;
-       move_linked_works(work, &pwq->pool->worklist, NULL);
--      __clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb);
-+      __clear_bit(WORK_STRUCT_INACTIVE_BIT, work_data_bits(work));
- }
- /**
-@@ -1496,66 +1493,12 @@ static bool pwq_activate_work(struct poo
-       return true;
- }
--/**
-- * pwq_tryinc_nr_active - Try to increment nr_active for a pwq
-- * @pwq: pool_workqueue of interest
-- *
-- * Try to increment nr_active for @pwq. Returns %true if an nr_active count is
-- * successfully obtained. %false otherwise.
-- */
--static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq)
--{
--      struct workqueue_struct *wq = pwq->wq;
--      struct worker_pool *pool = pwq->pool;
--      bool obtained;
--
--      lockdep_assert_held(&pool->lock);
--
--      obtained = pwq->nr_active < READ_ONCE(wq->max_active);
--
--      if (obtained)
--              pwq->nr_active++;
--      return obtained;
--}
--
--/**
-- * pwq_activate_first_inactive - Activate the first inactive work item on a pwq
-- * @pwq: pool_workqueue of interest
-- *
-- * Activate the first inactive work item of @pwq if available and allowed by
-- * max_active limit.
-- *
-- * Returns %true if an inactive work item has been activated. %false if no
-- * inactive work item is found or max_active limit is reached.
-- */
--static bool pwq_activate_first_inactive(struct pool_workqueue *pwq)
--{
--      struct work_struct *work =
--              list_first_entry_or_null(&pwq->inactive_works,
--                                       struct work_struct, entry);
--
--      if (work && pwq_tryinc_nr_active(pwq)) {
--              __pwq_activate_work(pwq, work);
--              return true;
--      } else {
--              return false;
--      }
--}
--
--/**
-- * pwq_dec_nr_active - Retire an active count
-- * @pwq: pool_workqueue of interest
-- *
-- * Decrement @pwq's nr_active and try to activate the first inactive work item.
-- */
--static void pwq_dec_nr_active(struct pool_workqueue *pwq)
-+static void pwq_activate_first_inactive(struct pool_workqueue *pwq)
- {
--      struct worker_pool *pool = pwq->pool;
-+      struct work_struct *work = list_first_entry(&pwq->inactive_works,
-+                                                  struct work_struct, entry);
--      lockdep_assert_held(&pool->lock);
--
--      pwq->nr_active--;
--      pwq_activate_first_inactive(pwq);
-+      pwq_activate_work(pwq, work);
- }
- /**
-@@ -1573,8 +1516,14 @@ static void pwq_dec_nr_in_flight(struct
- {
-       int color = get_work_color(work_data);
--      if (!(work_data & WORK_STRUCT_INACTIVE))
--              pwq_dec_nr_active(pwq);
-+      if (!(work_data & WORK_STRUCT_INACTIVE)) {
-+              pwq->nr_active--;
-+              if (!list_empty(&pwq->inactive_works)) {
-+                      /* one down, submit an inactive one */
-+                      if (pwq->nr_active < READ_ONCE(pwq->wq->max_active))
-+                              pwq_activate_first_inactive(pwq);
-+              }
-+      }
-       pwq->nr_in_flight[color]--;
-@@ -1876,11 +1825,13 @@ retry:
-        * @work must also queue behind existing inactive work items to maintain
-        * ordering when max_active changes. See wq_adjust_max_active().
-        */
--      if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq)) {
-+      if (list_empty(&pwq->inactive_works) &&
-+          pwq->nr_active < READ_ONCE(pwq->wq->max_active)) {
-               if (list_empty(&pool->worklist))
-                       pool->watchdog_ts = jiffies;
-               trace_workqueue_activate_work(work);
-+              pwq->nr_active++;
-               insert_work(pwq, work, &pool->worklist, work_flags);
-               kick_pool(pool);
-       } else {
-@@ -4729,8 +4680,9 @@ static void wq_adjust_max_active(struct
-               /* this function can be called during early boot w/ irq disabled */
-               raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--              while (pwq_activate_first_inactive(pwq))
--                      ;
-+              while (!list_empty(&pwq->inactive_works) &&
-+                     pwq->nr_active < wq->max_active)
-+                      pwq_activate_first_inactive(pwq);
-               kick_pool(pwq->pool);
diff --git a/review-6.8/revert-workqueue-move-pwq-max_active-to-wq-max_active.patch b/review-6.8/revert-workqueue-move-pwq-max_active-to-wq-max_active.patch
deleted file mode 100644 (file)
index 272fcf9..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-From 4dedc2c9ac17a5bcbe456f5a76018487ab1cdf68 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:25 +0200
-Subject: Revert "workqueue: Move pwq->max_active to wq->max_active"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 0c4ce23e6323e52d0590e78825cd3c63323d7a52 which is commit
-a045a272d887575da17ad86d6573e82871b50c27 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |  133 ++++++++++++++++++++++++++---------------------------
- 1 file changed, 67 insertions(+), 66 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -143,9 +143,6 @@ enum {
-  *
-  * WR: wq->mutex protected for writes.  RCU protected for reads.
-  *
-- * WO: wq->mutex protected for writes. Updated with WRITE_ONCE() and can be read
-- *     with READ_ONCE() without locking.
-- *
-  * MD: wq_mayday_lock protected.
-  *
-  * WD: Used internally by the watchdog.
-@@ -253,6 +250,7 @@ struct pool_workqueue {
-        * is marked with WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
-        */
-       int                     nr_active;      /* L: nr of active works */
-+      int                     max_active;     /* L: max active works */
-       struct list_head        inactive_works; /* L: inactive works */
-       struct list_head        pwqs_node;      /* WR: node on wq->pwqs */
-       struct list_head        mayday_node;    /* MD: node on wq->maydays */
-@@ -300,8 +298,7 @@ struct workqueue_struct {
-       struct worker           *rescuer;       /* MD: rescue worker */
-       int                     nr_drainers;    /* WQ: drain in progress */
--      int                     max_active;     /* WO: max active works */
--      int                     saved_max_active; /* WQ: saved max_active */
-+      int                     saved_max_active; /* WQ: saved pwq max_active */
-       struct workqueue_attrs  *unbound_attrs; /* PW: only for unbound wqs */
-       struct pool_workqueue   *dfl_pwq;       /* PW: only for unbound wqs */
-@@ -1495,7 +1492,7 @@ static void pwq_dec_nr_in_flight(struct
-               pwq->nr_active--;
-               if (!list_empty(&pwq->inactive_works)) {
-                       /* one down, submit an inactive one */
--                      if (pwq->nr_active < READ_ONCE(pwq->wq->max_active))
-+                      if (pwq->nr_active < pwq->max_active)
-                               pwq_activate_first_inactive(pwq);
-               }
-       }
-@@ -1796,13 +1793,7 @@ retry:
-       pwq->nr_in_flight[pwq->work_color]++;
-       work_flags = work_color_to_flags(pwq->work_color);
--      /*
--       * Limit the number of concurrently active work items to max_active.
--       * @work must also queue behind existing inactive work items to maintain
--       * ordering when max_active changes. See wq_adjust_max_active().
--       */
--      if (list_empty(&pwq->inactive_works) &&
--          pwq->nr_active < READ_ONCE(pwq->wq->max_active)) {
-+      if (likely(pwq->nr_active < pwq->max_active)) {
-               if (list_empty(&pool->worklist))
-                       pool->watchdog_ts = jiffies;
-@@ -4151,6 +4142,50 @@ static void pwq_release_workfn(struct kt
-       }
- }
-+/**
-+ * pwq_adjust_max_active - update a pwq's max_active to the current setting
-+ * @pwq: target pool_workqueue
-+ *
-+ * If @pwq isn't freezing, set @pwq->max_active to the associated
-+ * workqueue's saved_max_active and activate inactive work items
-+ * accordingly.  If @pwq is freezing, clear @pwq->max_active to zero.
-+ */
-+static void pwq_adjust_max_active(struct pool_workqueue *pwq)
-+{
-+      struct workqueue_struct *wq = pwq->wq;
-+      bool freezable = wq->flags & WQ_FREEZABLE;
-+      unsigned long flags;
-+
-+      /* for @wq->saved_max_active */
-+      lockdep_assert_held(&wq->mutex);
-+
-+      /* fast exit for non-freezable wqs */
-+      if (!freezable && pwq->max_active == wq->saved_max_active)
-+              return;
-+
-+      /* this function can be called during early boot w/ irq disabled */
-+      raw_spin_lock_irqsave(&pwq->pool->lock, flags);
-+
-+      /*
-+       * During [un]freezing, the caller is responsible for ensuring that
-+       * this function is called at least once after @workqueue_freezing
-+       * is updated and visible.
-+       */
-+      if (!freezable || !workqueue_freezing) {
-+              pwq->max_active = wq->saved_max_active;
-+
-+              while (!list_empty(&pwq->inactive_works) &&
-+                     pwq->nr_active < pwq->max_active)
-+                      pwq_activate_first_inactive(pwq);
-+
-+              kick_pool(pwq->pool);
-+      } else {
-+              pwq->max_active = 0;
-+      }
-+
-+      raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
-+}
-+
- /* initialize newly allocated @pwq which is associated with @wq and @pool */
- static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
-                    struct worker_pool *pool)
-@@ -4183,6 +4218,9 @@ static void link_pwq(struct pool_workque
-       /* set the matching work_color */
-       pwq->work_color = wq->work_color;
-+      /* sync max_active to the current setting */
-+      pwq_adjust_max_active(pwq);
-+
-       /* link in @pwq */
-       list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
- }
-@@ -4620,52 +4658,6 @@ static int init_rescuer(struct workqueue
-       return 0;
- }
--/**
-- * wq_adjust_max_active - update a wq's max_active to the current setting
-- * @wq: target workqueue
-- *
-- * If @wq isn't freezing, set @wq->max_active to the saved_max_active and
-- * activate inactive work items accordingly. If @wq is freezing, clear
-- * @wq->max_active to zero.
-- */
--static void wq_adjust_max_active(struct workqueue_struct *wq)
--{
--      struct pool_workqueue *pwq;
--
--      lockdep_assert_held(&wq->mutex);
--
--      if ((wq->flags & WQ_FREEZABLE) && workqueue_freezing) {
--              WRITE_ONCE(wq->max_active, 0);
--              return;
--      }
--
--      if (wq->max_active == wq->saved_max_active)
--              return;
--
--      /*
--       * Update @wq->max_active and then kick inactive work items if more
--       * active work items are allowed. This doesn't break work item ordering
--       * because new work items are always queued behind existing inactive
--       * work items if there are any.
--       */
--      WRITE_ONCE(wq->max_active, wq->saved_max_active);
--
--      for_each_pwq(pwq, wq) {
--              unsigned long flags;
--
--              /* this function can be called during early boot w/ irq disabled */
--              raw_spin_lock_irqsave(&pwq->pool->lock, flags);
--
--              while (!list_empty(&pwq->inactive_works) &&
--                     pwq->nr_active < wq->max_active)
--                      pwq_activate_first_inactive(pwq);
--
--              kick_pool(pwq->pool);
--
--              raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
--      }
--}
--
- __printf(1, 4)
- struct workqueue_struct *alloc_workqueue(const char *fmt,
-                                        unsigned int flags,
-@@ -4673,6 +4665,7 @@ struct workqueue_struct *alloc_workqueue
- {
-       va_list args;
-       struct workqueue_struct *wq;
-+      struct pool_workqueue *pwq;
-       int len;
-       /*
-@@ -4711,7 +4704,6 @@ struct workqueue_struct *alloc_workqueue
-       /* init wq */
-       wq->flags = flags;
--      wq->max_active = max_active;
-       wq->saved_max_active = max_active;
-       mutex_init(&wq->mutex);
-       atomic_set(&wq->nr_pwqs_to_flush, 0);
-@@ -4740,7 +4732,8 @@ struct workqueue_struct *alloc_workqueue
-       mutex_lock(&wq_pool_mutex);
-       mutex_lock(&wq->mutex);
--      wq_adjust_max_active(wq);
-+      for_each_pwq(pwq, wq)
-+              pwq_adjust_max_active(pwq);
-       mutex_unlock(&wq->mutex);
-       list_add_tail_rcu(&wq->list, &workqueues);
-@@ -4878,6 +4871,8 @@ EXPORT_SYMBOL_GPL(destroy_workqueue);
-  */
- void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
- {
-+      struct pool_workqueue *pwq;
-+
-       /* disallow meddling with max_active for ordered workqueues */
-       if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
-               return;
-@@ -4888,7 +4883,9 @@ void workqueue_set_max_active(struct wor
-       wq->flags &= ~__WQ_ORDERED;
-       wq->saved_max_active = max_active;
--      wq_adjust_max_active(wq);
-+
-+      for_each_pwq(pwq, wq)
-+              pwq_adjust_max_active(pwq);
-       mutex_unlock(&wq->mutex);
- }
-@@ -5135,8 +5132,8 @@ static void show_pwq(struct pool_workque
-       pr_info("  pwq %d:", pool->id);
-       pr_cont_pool_info(pool);
--      pr_cont(" active=%d refcnt=%d%s\n",
--              pwq->nr_active, pwq->refcnt,
-+      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) {
-@@ -5684,6 +5681,7 @@ EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
- void freeze_workqueues_begin(void)
- {
-       struct workqueue_struct *wq;
-+      struct pool_workqueue *pwq;
-       mutex_lock(&wq_pool_mutex);
-@@ -5692,7 +5690,8 @@ void freeze_workqueues_begin(void)
-       list_for_each_entry(wq, &workqueues, list) {
-               mutex_lock(&wq->mutex);
--              wq_adjust_max_active(wq);
-+              for_each_pwq(pwq, wq)
-+                      pwq_adjust_max_active(pwq);
-               mutex_unlock(&wq->mutex);
-       }
-@@ -5757,6 +5756,7 @@ out_unlock:
- void thaw_workqueues(void)
- {
-       struct workqueue_struct *wq;
-+      struct pool_workqueue *pwq;
-       mutex_lock(&wq_pool_mutex);
-@@ -5768,7 +5768,8 @@ void thaw_workqueues(void)
-       /* restore max_active and repopulate worklist */
-       list_for_each_entry(wq, &workqueues, list) {
-               mutex_lock(&wq->mutex);
--              wq_adjust_max_active(wq);
-+              for_each_pwq(pwq, wq)
-+                      pwq_adjust_max_active(pwq);
-               mutex_unlock(&wq->mutex);
-       }
diff --git a/review-6.8/revert-workqueue-rcu-protect-wq-dfl_pwq-and-implement-accessors-for-it.patch b/review-6.8/revert-workqueue-rcu-protect-wq-dfl_pwq-and-implement-accessors-for-it.patch
deleted file mode 100644 (file)
index e7f9077..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-From 18283fa5e3fdc933ca98239d4e46041de7f79b1f Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:17 +0200
-Subject: Revert "workqueue: RCU protect wq->dfl_pwq and implement accessors for it"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 3fb5dbc8bb3759ad0a82d6bf5ed32866c0410a79 which is commit
-9f66cff212bb3c1cd25996aaa0dfd0c9e9d8baab upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |   64 +++++++++++++++++++----------------------------------
- 1 file changed, 24 insertions(+), 40 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -304,7 +304,7 @@ struct workqueue_struct {
-       int                     saved_max_active; /* WQ: saved max_active */
-       struct workqueue_attrs  *unbound_attrs; /* PW: only for unbound wqs */
--      struct pool_workqueue __rcu *dfl_pwq;   /* PW: only for unbound wqs */
-+      struct pool_workqueue   *dfl_pwq;       /* PW: only for unbound wqs */
- #ifdef CONFIG_SYSFS
-       struct wq_device        *wq_dev;        /* I: for sysfs interface */
-@@ -635,23 +635,6 @@ static int worker_pool_assign_id(struct
-       return ret;
- }
--static struct pool_workqueue __rcu **
--unbound_pwq_slot(struct workqueue_struct *wq, int cpu)
--{
--       if (cpu >= 0)
--               return per_cpu_ptr(wq->cpu_pwq, cpu);
--       else
--               return &wq->dfl_pwq;
--}
--
--/* @cpu < 0 for dfl_pwq */
--static struct pool_workqueue *unbound_pwq(struct workqueue_struct *wq, int cpu)
--{
--      return rcu_dereference_check(*unbound_pwq_slot(wq, cpu),
--                                   lockdep_is_held(&wq_pool_mutex) ||
--                                   lockdep_is_held(&wq->mutex));
--}
--
- static unsigned int work_color_to_flags(int color)
- {
-       return color << WORK_STRUCT_COLOR_SHIFT;
-@@ -4341,11 +4324,10 @@ static void wq_calc_pod_cpumask(struct w
-                               "possible intersect\n");
- }
--/* install @pwq into @wq and return the old pwq, @cpu < 0 for dfl_pwq */
-+/* install @pwq into @wq's cpu_pwq and return the old pwq */
- static struct pool_workqueue *install_unbound_pwq(struct workqueue_struct *wq,
-                                       int cpu, struct pool_workqueue *pwq)
- {
--      struct pool_workqueue __rcu **slot = unbound_pwq_slot(wq, cpu);
-       struct pool_workqueue *old_pwq;
-       lockdep_assert_held(&wq_pool_mutex);
-@@ -4354,8 +4336,8 @@ static struct pool_workqueue *install_un
-       /* link_pwq() can handle duplicate calls */
-       link_pwq(pwq);
--      old_pwq = rcu_access_pointer(*slot);
--      rcu_assign_pointer(*slot, pwq);
-+      old_pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
-+      rcu_assign_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu), pwq);
-       return old_pwq;
- }
-@@ -4455,11 +4437,14 @@ static void apply_wqattrs_commit(struct
-       copy_workqueue_attrs(ctx->wq->unbound_attrs, ctx->attrs);
--      /* save the previous pwqs and install the new ones */
-+      /* save the previous pwq and install the new one */
-       for_each_possible_cpu(cpu)
-               ctx->pwq_tbl[cpu] = install_unbound_pwq(ctx->wq, cpu,
-                                                       ctx->pwq_tbl[cpu]);
--      ctx->dfl_pwq = install_unbound_pwq(ctx->wq, -1, ctx->dfl_pwq);
-+
-+      /* @dfl_pwq might not have been used, ensure it's linked */
-+      link_pwq(ctx->dfl_pwq);
-+      swap(ctx->wq->dfl_pwq, ctx->dfl_pwq);
-       mutex_unlock(&ctx->wq->mutex);
- }
-@@ -4569,7 +4554,9 @@ static void wq_update_pod(struct workque
-       /* nothing to do if the target cpumask matches the current pwq */
-       wq_calc_pod_cpumask(target_attrs, cpu, off_cpu);
--      if (wqattrs_equal(target_attrs, unbound_pwq(wq, cpu)->pool->attrs))
-+      pwq = rcu_dereference_protected(*per_cpu_ptr(wq->cpu_pwq, cpu),
-+                                      lockdep_is_held(&wq_pool_mutex));
-+      if (wqattrs_equal(target_attrs, pwq->pool->attrs))
-               return;
-       /* create a new pwq */
-@@ -4587,11 +4574,10 @@ static void wq_update_pod(struct workque
- use_dfl_pwq:
-       mutex_lock(&wq->mutex);
--      pwq = unbound_pwq(wq, -1);
--      raw_spin_lock_irq(&pwq->pool->lock);
--      get_pwq(pwq);
--      raw_spin_unlock_irq(&pwq->pool->lock);
--      old_pwq = install_unbound_pwq(wq, cpu, pwq);
-+      raw_spin_lock_irq(&wq->dfl_pwq->pool->lock);
-+      get_pwq(wq->dfl_pwq);
-+      raw_spin_unlock_irq(&wq->dfl_pwq->pool->lock);
-+      old_pwq = install_unbound_pwq(wq, cpu, wq->dfl_pwq);
- out_unlock:
-       mutex_unlock(&wq->mutex);
-       put_pwq_unlocked(old_pwq);
-@@ -4629,13 +4615,10 @@ static int alloc_and_link_pwqs(struct wo
-       cpus_read_lock();
-       if (wq->flags & __WQ_ORDERED) {
--              struct pool_workqueue *dfl_pwq;
--
-               ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
-               /* there should only be single pwq for ordering guarantee */
--              dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
--              WARN(!ret && (wq->pwqs.next != &dfl_pwq->pwqs_node ||
--                            wq->pwqs.prev != &dfl_pwq->pwqs_node),
-+              WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
-+                            wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
-                    "ordering guarantee broken for workqueue %s\n", wq->name);
-       } else {
-               ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
-@@ -4866,7 +4849,7 @@ static bool pwq_busy(struct pool_workque
-               if (pwq->nr_in_flight[i])
-                       return true;
--      if ((pwq != rcu_access_pointer(pwq->wq->dfl_pwq)) && (pwq->refcnt > 1))
-+      if ((pwq != pwq->wq->dfl_pwq) && (pwq->refcnt > 1))
-               return true;
-       if (!pwq_is_empty(pwq))
-               return true;
-@@ -4950,12 +4933,13 @@ void destroy_workqueue(struct workqueue_
-       rcu_read_lock();
-       for_each_possible_cpu(cpu) {
--              put_pwq_unlocked(unbound_pwq(wq, cpu));
--              RCU_INIT_POINTER(*unbound_pwq_slot(wq, cpu), NULL);
-+              pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
-+              RCU_INIT_POINTER(*per_cpu_ptr(wq->cpu_pwq, cpu), NULL);
-+              put_pwq_unlocked(pwq);
-       }
--      put_pwq_unlocked(unbound_pwq(wq, -1));
--      RCU_INIT_POINTER(*unbound_pwq_slot(wq, -1), NULL);
-+      put_pwq_unlocked(wq->dfl_pwq);
-+      wq->dfl_pwq = NULL;
-       rcu_read_unlock();
- }
diff --git a/review-6.8/revert-workqueue-replace-pwq_activate_inactive_work-with-pwq_activate_work.patch b/review-6.8/revert-workqueue-replace-pwq_activate_inactive_work-with-pwq_activate_work.patch
deleted file mode 100644 (file)
index 7a373a1..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-From 631ccfe01b65406b05e290709716177b62d4cded Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:22 +0200
-Subject: Revert "workqueue: Replace pwq_activate_inactive_work() with [__]pwq_activate_work()"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit f4505c2033ad25839f6fd9be6fc474b8306c44eb which is commit
-4c6380305d21e36581b451f7337a36c93b64e050 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |   31 ++++++-------------------------
- 1 file changed, 6 insertions(+), 25 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -1461,36 +1461,16 @@ static bool pwq_is_empty(struct pool_wor
-       return !pwq->nr_active && list_empty(&pwq->inactive_works);
- }
--static void __pwq_activate_work(struct pool_workqueue *pwq,
--                              struct work_struct *work)
-+static void pwq_activate_inactive_work(struct work_struct *work)
- {
-+      struct pool_workqueue *pwq = get_work_pwq(work);
-+
-       trace_workqueue_activate_work(work);
-       if (list_empty(&pwq->pool->worklist))
-               pwq->pool->watchdog_ts = jiffies;
-       move_linked_works(work, &pwq->pool->worklist, NULL);
-       __clear_bit(WORK_STRUCT_INACTIVE_BIT, work_data_bits(work));
--}
--
--/**
-- * pwq_activate_work - Activate a work item if inactive
-- * @pwq: pool_workqueue @work belongs to
-- * @work: work item to activate
-- *
-- * Returns %true if activated. %false if already active.
-- */
--static bool pwq_activate_work(struct pool_workqueue *pwq,
--                            struct work_struct *work)
--{
--      struct worker_pool *pool = pwq->pool;
--
--      lockdep_assert_held(&pool->lock);
--
--      if (!(*work_data_bits(work) & WORK_STRUCT_INACTIVE))
--              return false;
--
-       pwq->nr_active++;
--      __pwq_activate_work(pwq, work);
--      return true;
- }
- static void pwq_activate_first_inactive(struct pool_workqueue *pwq)
-@@ -1498,7 +1478,7 @@ static void pwq_activate_first_inactive(
-       struct work_struct *work = list_first_entry(&pwq->inactive_works,
-                                                   struct work_struct, entry);
--      pwq_activate_work(pwq, work);
-+      pwq_activate_inactive_work(work);
- }
- /**
-@@ -1636,7 +1616,8 @@ static int try_to_grab_pending(struct wo
-                * management later on and cause stall.  Make sure the work
-                * item is activated before grabbing.
-                */
--              pwq_activate_work(pwq, work);
-+              if (*work_data_bits(work) & WORK_STRUCT_INACTIVE)
-+                      pwq_activate_inactive_work(work);
-               list_del_init(&work->entry);
-               pwq_dec_nr_in_flight(pwq, *work_data_bits(work));
diff --git a/review-6.8/revert-workqueue-shorten-events_freezable_power_efficient-name.patch b/review-6.8/revert-workqueue-shorten-events_freezable_power_efficient-name.patch
deleted file mode 100644 (file)
index a8278e2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From c8a28e4d35da4f0a0209826199b0187ea4ec0a20 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:26:42 +0200
-Subject: Revert "workqueue: Shorten events_freezable_power_efficient name"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit fb89c8fa412f6caa34316c140e861bd3c4d7e83a which is
-commit 8318d6a6362f5903edb4c904a8dd447e59be4ad1 upstream
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Cc: Audra Mitchell <audra@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -7186,7 +7186,7 @@ void __init workqueue_init_early(void)
-                                             WQ_FREEZABLE, 0);
-       system_power_efficient_wq = alloc_workqueue("events_power_efficient",
-                                             WQ_POWER_EFFICIENT, 0);
--      system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_pwr_efficient",
-+      system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",
-                                             WQ_FREEZABLE | WQ_POWER_EFFICIENT,
-                                             0);
-       BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
diff --git a/review-6.8/revert-workqueue.c-increase-workqueue-name-length.patch b/review-6.8/revert-workqueue.c-increase-workqueue-name-length.patch
deleted file mode 100644 (file)
index 1af34bf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 6964db035e2d9e8fb121cc2ff8711cc57a6ad09d Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Wed, 3 Apr 2024 16:29:27 +0200
-Subject: Revert "workqueue.c: Increase workqueue name length"
-
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-This reverts commit 43f0cec175f92c7a01e43d5d6f276262670a97ed which is commit
-31c89007285d365aa36f71d8fb0701581c770a27 upstream.
-
-The workqueue patches backported to 6.8.y caused some reported
-regressions, so revert them for now.
-
-Reported-by: Thorsten Leemhuis <regressions@leemhuis.info>
-Cc: Tejun Heo <tj@kernel.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Nathan Chancellor <nathan@kernel.org>
-Cc: Sasha Levin <sashal@kernel.org>
-Cc: Audra Mitchell <audra@redhat.com>
-Link: https://lore.kernel.org/all/ce4c2f67-c298-48a0-87a3-f933d646c73b@leemhuis.info/
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- kernel/workqueue.c |    8 ++------
- 1 file changed, 2 insertions(+), 6 deletions(-)
-
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -108,7 +108,7 @@ enum {
-       RESCUER_NICE_LEVEL      = MIN_NICE,
-       HIGHPRI_NICE_LEVEL      = MIN_NICE,
--      WQ_NAME_LEN             = 32,
-+      WQ_NAME_LEN             = 24,
- };
- /*
-@@ -4666,7 +4666,6 @@ struct workqueue_struct *alloc_workqueue
-       va_list args;
-       struct workqueue_struct *wq;
-       struct pool_workqueue *pwq;
--      int len;
-       /*
-        * Unbound && max_active == 1 used to imply ordered, which is no longer
-@@ -4693,12 +4692,9 @@ struct workqueue_struct *alloc_workqueue
-       }
-       va_start(args, max_active);
--      len = vsnprintf(wq->name, sizeof(wq->name), fmt, args);
-+      vsnprintf(wq->name, sizeof(wq->name), fmt, args);
-       va_end(args);
--      if (len >= WQ_NAME_LEN)
--              pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n", wq->name);
--
-       max_active = max_active ?: WQ_DFL_ACTIVE;
-       max_active = wq_clamp_max_active(max_active, flags, wq->name);
diff --git a/review-6.8/series b/review-6.8/series
deleted file mode 100644 (file)
index 739caff..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-revert-workqueue-shorten-events_freezable_power_efficient-name.patch
-revert-workqueue-don-t-call-cpumask_test_cpu-with-1-cpu-in-wq_update_node_max_active.patch
-revert-workqueue-implement-system-wide-nr_active-enforcement-for-unbound-workqueues.patch
-revert-workqueue-introduce-struct-wq_node_nr_active.patch
-revert-workqueue-rcu-protect-wq-dfl_pwq-and-implement-accessors-for-it.patch
-revert-workqueue-make-wq_adjust_max_active-round-robin-pwqs-while-activating.patch
-revert-workqueue-move-nr_active-handling-into-helpers.patch
-revert-workqueue-replace-pwq_activate_inactive_work-with-pwq_activate_work.patch
-revert-workqueue-factor-out-pwq_is_empty.patch
-revert-workqueue-move-pwq-max_active-to-wq-max_active.patch
-revert-workqueue.c-increase-workqueue-name-length.patch