diff options
| -rw-r--r-- | fs/proc/array.c | 7 | ||||
| -rw-r--r-- | include/linux/workqueue.h | 1 | ||||
| -rw-r--r-- | kernel/workqueue.c | 39 |
3 files changed, 45 insertions, 2 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index f29221e95792..bb1d3619ca12 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
| @@ -99,10 +99,13 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape) | |||
| 99 | { | 99 | { |
| 100 | char *buf; | 100 | char *buf; |
| 101 | size_t size; | 101 | size_t size; |
| 102 | char tcomm[sizeof(p->comm)]; | 102 | char tcomm[64]; |
| 103 | int ret; | 103 | int ret; |
| 104 | 104 | ||
| 105 | get_task_comm(tcomm, p); | 105 | if (p->flags & PF_WQ_WORKER) |
| 106 | wq_worker_comm(tcomm, sizeof(tcomm), p); | ||
| 107 | else | ||
| 108 | __get_task_comm(tcomm, sizeof(tcomm), p); | ||
| 106 | 109 | ||
| 107 | size = seq_get_buf(m, &buf); | 110 | size = seq_get_buf(m, &buf); |
| 108 | if (escape) { | 111 | if (escape) { |
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 39a0e215022a..60d673e15632 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
| @@ -494,6 +494,7 @@ extern unsigned int work_busy(struct work_struct *work); | |||
| 494 | extern __printf(1, 2) void set_worker_desc(const char *fmt, ...); | 494 | extern __printf(1, 2) void set_worker_desc(const char *fmt, ...); |
| 495 | extern void print_worker_info(const char *log_lvl, struct task_struct *task); | 495 | extern void print_worker_info(const char *log_lvl, struct task_struct *task); |
| 496 | extern void show_workqueue_state(void); | 496 | extern void show_workqueue_state(void); |
| 497 | extern void wq_worker_comm(char *buf, size_t size, struct task_struct *task); | ||
| 497 | 498 | ||
| 498 | /** | 499 | /** |
| 499 | * queue_work - queue work on a workqueue | 500 | * queue_work - queue work on a workqueue |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3fbe0076492c..b4a39a15c931 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -4577,6 +4577,45 @@ void show_workqueue_state(void) | |||
| 4577 | rcu_read_unlock_sched(); | 4577 | rcu_read_unlock_sched(); |
| 4578 | } | 4578 | } |
| 4579 | 4579 | ||
| 4580 | /* used to show worker information through /proc/PID/{comm,stat,status} */ | ||
| 4581 | void wq_worker_comm(char *buf, size_t size, struct task_struct *task) | ||
| 4582 | { | ||
| 4583 | struct worker *worker; | ||
| 4584 | struct worker_pool *pool; | ||
| 4585 | int off; | ||
| 4586 | |||
| 4587 | /* always show the actual comm */ | ||
| 4588 | off = strscpy(buf, task->comm, size); | ||
| 4589 | if (off < 0) | ||
| 4590 | return; | ||
| 4591 | |||
| 4592 | /* stabilize worker pool association */ | ||
| 4593 | mutex_lock(&wq_pool_attach_mutex); | ||
| 4594 | |||
| 4595 | worker = kthread_data(task); | ||
| 4596 | pool = worker->pool; | ||
| 4597 | |||
| 4598 | if (pool) { | ||
| 4599 | spin_lock_irq(&pool->lock); | ||
| 4600 | /* | ||
| 4601 | * ->desc tracks information (wq name or set_worker_desc()) | ||
| 4602 | * for the latest execution. If current, prepend '+', | ||
| 4603 | * otherwise '-'. | ||
| 4604 | */ | ||
| 4605 | if (worker->desc[0] != '\0') { | ||
| 4606 | if (worker->current_work) | ||
| 4607 | scnprintf(buf + off, size - off, "+%s", | ||
| 4608 | worker->desc); | ||
| 4609 | else | ||
| 4610 | scnprintf(buf + off, size - off, "-%s", | ||
| 4611 | worker->desc); | ||
| 4612 | } | ||
| 4613 | spin_unlock_irq(&pool->lock); | ||
| 4614 | } | ||
| 4615 | |||
| 4616 | mutex_unlock(&wq_pool_attach_mutex); | ||
| 4617 | } | ||
| 4618 | |||
| 4580 | /* | 4619 | /* |
| 4581 | * CPU hotplug. | 4620 | * CPU hotplug. |
| 4582 | * | 4621 | * |
