Merge tag 'i2c-for-6.4-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-block.git] / kernel / workqueue.c
index 209917792fa45f09a239fc36cf9f0f4946c5b76d..4666a1a92a31b22a402de2ba86d1687d21999b19 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/moduleparam.h>
 #include <linux/uaccess.h>
 #include <linux/sched/isolation.h>
+#include <linux/sched/debug.h>
 #include <linux/nmi.h>
 #include <linux/kvm_para.h>
 
@@ -141,6 +142,8 @@ enum {
  * WR: wq->mutex protected for writes.  RCU protected for reads.
  *
  * MD: wq_mayday_lock protected.
+ *
+ * WD: Used internally by the watchdog.
  */
 
 /* struct worker is defined in workqueue_internal.h */
@@ -153,6 +156,7 @@ struct worker_pool {
        unsigned int            flags;          /* X: flags */
 
        unsigned long           watchdog_ts;    /* L: watchdog timestamp */
+       bool                    cpu_stall;      /* WD: stalled cpu bound pool */
 
        /*
         * The counter is incremented in a process context on the associated CPU
@@ -1392,15 +1396,13 @@ static bool is_chained_work(struct workqueue_struct *wq)
  */
 static int wq_select_unbound_cpu(int cpu)
 {
-       static bool printed_dbg_warning;
        int new_cpu;
 
        if (likely(!wq_debug_force_rr_cpu)) {
                if (cpumask_test_cpu(cpu, wq_unbound_cpumask))
                        return cpu;
-       } else if (!printed_dbg_warning) {
-               pr_warn("workqueue: round-robin CPU selection forced, expect performance impact\n");
-               printed_dbg_warning = true;
+       } else {
+               pr_warn_once("workqueue: round-robin CPU selection forced, expect performance impact\n");
        }
 
        if (cpumask_empty(wq_unbound_cpumask))
@@ -1938,12 +1940,17 @@ static struct worker *create_worker(struct worker_pool *pool)
 
        /* ID is needed to determine kthread name */
        id = ida_alloc(&pool->worker_ida, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               pr_err_once("workqueue: Failed to allocate a worker ID: %pe\n",
+                           ERR_PTR(id));
                return NULL;
+       }
 
        worker = alloc_worker(pool->node);
-       if (!worker)
+       if (!worker) {
+               pr_err_once("workqueue: Failed to allocate a worker\n");
                goto fail;
+       }
 
        worker->id = id;
 
@@ -1955,8 +1962,16 @@ static struct worker *create_worker(struct worker_pool *pool)
 
        worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
                                              "kworker/%s", id_buf);
-       if (IS_ERR(worker->task))
+       if (IS_ERR(worker->task)) {
+               if (PTR_ERR(worker->task) == -EINTR) {
+                       pr_err("workqueue: Interrupted when creating a worker thread \"kworker/%s\"\n",
+                              id_buf);
+               } else {
+                       pr_err_once("workqueue: Failed to create a worker thread: %pe",
+                                   worker->task);
+               }
                goto fail;
+       }
 
        set_user_nice(worker->task, pool->attrs->nice);
        kthread_bind_mask(worker->task, pool->attrs->cpumask);
@@ -4380,13 +4395,18 @@ static int init_rescuer(struct workqueue_struct *wq)
                return 0;
 
        rescuer = alloc_worker(NUMA_NO_NODE);
-       if (!rescuer)
+       if (!rescuer) {
+               pr_err("workqueue: Failed to allocate a rescuer for wq \"%s\"\n",
+                      wq->name);
                return -ENOMEM;
+       }
 
        rescuer->rescue_wq = wq;
        rescuer->task = kthread_create(rescuer_thread, rescuer, "%s", wq->name);
        if (IS_ERR(rescuer->task)) {
                ret = PTR_ERR(rescuer->task);
+               pr_err("workqueue: Failed to create a rescuer kthread for wq \"%s\": %pe",
+                      wq->name, ERR_PTR(ret));
                kfree(rescuer);
                return ret;
        }
@@ -5002,10 +5022,16 @@ static void show_one_worker_pool(struct worker_pool *pool)
        struct worker *worker;
        bool first = true;
        unsigned long flags;
+       unsigned long hung = 0;
 
        raw_spin_lock_irqsave(&pool->lock, flags);
        if (pool->nr_workers == pool->nr_idle)
                goto next_pool;
+
+       /* How long the first pending work is waiting for a worker. */
+       if (!list_empty(&pool->worklist))
+               hung = jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000;
+
        /*
         * Defer printing to avoid deadlocks in console drivers that
         * queue work while holding locks also taken in their write
@@ -5014,9 +5040,7 @@ static void show_one_worker_pool(struct worker_pool *pool)
        printk_deferred_enter();
        pr_info("pool %d:", pool->id);
        pr_cont_pool_info(pool);
-       pr_cont(" hung=%us workers=%d",
-               jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
-               pool->nr_workers);
+       pr_cont(" hung=%lus workers=%d", hung, pool->nr_workers);
        if (pool->manager)
                pr_cont(" manager: %d",
                        task_pid_nr(pool->manager->task));
@@ -5041,8 +5065,7 @@ next_pool:
 /**
  * show_all_workqueues - dump workqueue state
  *
- * Called from a sysrq handler or try_to_freeze_tasks() and prints out
- * all busy workqueues and pools.
+ * Called from a sysrq handler and prints out all busy workqueues and pools.
  */
 void show_all_workqueues(void)
 {
@@ -5063,6 +5086,29 @@ void show_all_workqueues(void)
        rcu_read_unlock();
 }
 
+/**
+ * show_freezable_workqueues - dump freezable workqueue state
+ *
+ * Called from try_to_freeze_tasks() and prints out all freezable workqueues
+ * still busy.
+ */
+void show_freezable_workqueues(void)
+{
+       struct workqueue_struct *wq;
+
+       rcu_read_lock();
+
+       pr_info("Showing freezable workqueues that are still busy:\n");
+
+       list_for_each_entry_rcu(wq, &workqueues, list) {
+               if (!(wq->flags & WQ_FREEZABLE))
+                       continue;
+               show_one_workqueue(wq);
+       }
+
+       rcu_read_unlock();
+}
+
 /* used to show worker information through /proc/PID/{comm,stat,status} */
 void wq_worker_comm(char *buf, size_t size, struct task_struct *task)
 {
@@ -5962,6 +6008,57 @@ static struct timer_list wq_watchdog_timer;
 static unsigned long wq_watchdog_touched = INITIAL_JIFFIES;
 static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES;
 
+/*
+ * Show workers that might prevent the processing of pending work items.
+ * The only candidates are CPU-bound workers in the running state.
+ * Pending work items should be handled by another idle worker
+ * in all other situations.
+ */
+static void show_cpu_pool_hog(struct worker_pool *pool)
+{
+       struct worker *worker;
+       unsigned long flags;
+       int bkt;
+
+       raw_spin_lock_irqsave(&pool->lock, flags);
+
+       hash_for_each(pool->busy_hash, bkt, worker, hentry) {
+               if (task_is_running(worker->task)) {
+                       /*
+                        * Defer printing to avoid deadlocks in console
+                        * drivers that queue work while holding locks
+                        * also taken in their write paths.
+                        */
+                       printk_deferred_enter();
+
+                       pr_info("pool %d:\n", pool->id);
+                       sched_show_task(worker->task);
+
+                       printk_deferred_exit();
+               }
+       }
+
+       raw_spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void show_cpu_pools_hogs(void)
+{
+       struct worker_pool *pool;
+       int pi;
+
+       pr_info("Showing backtraces of running workers in stalled CPU-bound worker pools:\n");
+
+       rcu_read_lock();
+
+       for_each_pool(pool, pi) {
+               if (pool->cpu_stall)
+                       show_cpu_pool_hog(pool);
+
+       }
+
+       rcu_read_unlock();
+}
+
 static void wq_watchdog_reset_touched(void)
 {
        int cpu;
@@ -5975,6 +6072,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
 {
        unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
        bool lockup_detected = false;
+       bool cpu_pool_stall = false;
        unsigned long now = jiffies;
        struct worker_pool *pool;
        int pi;
@@ -5987,6 +6085,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
        for_each_pool(pool, pi) {
                unsigned long pool_ts, touched, ts;
 
+               pool->cpu_stall = false;
                if (list_empty(&pool->worklist))
                        continue;
 
@@ -6011,11 +6110,17 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
                /* did we stall? */
                if (time_after(now, ts + thresh)) {
                        lockup_detected = true;
+                       if (pool->cpu >= 0) {
+                               pool->cpu_stall = true;
+                               cpu_pool_stall = true;
+                       }
                        pr_emerg("BUG: workqueue lockup - pool");
                        pr_cont_pool_info(pool);
                        pr_cont(" stuck for %us!\n",
                                jiffies_to_msecs(now - pool_ts) / 1000);
                }
+
+
        }
 
        rcu_read_unlock();
@@ -6023,6 +6128,9 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
        if (lockup_detected)
                show_all_workqueues();
 
+       if (cpu_pool_stall)
+               show_cpu_pools_hogs();
+
        wq_watchdog_reset_touched();
        mod_timer(&wq_watchdog_timer, jiffies + thresh);
 }