aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/array.c7
-rw-r--r--include/linux/workqueue.h1
-rw-r--r--kernel/workqueue.c39
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);
494extern __printf(1, 2) void set_worker_desc(const char *fmt, ...); 494extern __printf(1, 2) void set_worker_desc(const char *fmt, ...);
495extern void print_worker_info(const char *log_lvl, struct task_struct *task); 495extern void print_worker_info(const char *log_lvl, struct task_struct *task);
496extern void show_workqueue_state(void); 496extern void show_workqueue_state(void);
497extern 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} */
4581void 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 *