Skip to content

Commit 6b59808

Browse files
committed
workqueue: Show the latest workqueue name in /proc/PID/{comm,stat,status}
There can be a lot of workqueue workers and they all show up with the cryptic kworker/* names making it difficult to understand which is doing what and how they came to be. # ps -ef | grep kworker root 4 2 0 Feb25 ? 00:00:00 [kworker/0:0H] root 6 2 0 Feb25 ? 00:00:00 [kworker/u112:0] root 19 2 0 Feb25 ? 00:00:00 [kworker/1:0H] root 25 2 0 Feb25 ? 00:00:00 [kworker/2:0H] root 31 2 0 Feb25 ? 00:00:00 [kworker/3:0H] ... This patch makes workqueue workers report the latest workqueue it was executing for through /proc/PID/{comm,stat,status}. The extra information is appended to the kthread name with intervening '+' if currently executing, otherwise '-'. # cat /proc/25/comm kworker/2:0-events_power_efficient # cat /proc/25/stat 25 (kworker/2:0-events_power_efficient) I 2 0 0 0 -1 69238880 0 0... # grep Name /proc/25/status Name: kworker/2:0-events_power_efficient Unfortunately, ps(1) truncates comm to 15 characters, # ps 25 PID TTY STAT TIME COMMAND 25 ? I 0:00 [kworker/2:0-eve] making it a lot less useful; however, this should be an easy fix from ps(1) side. Signed-off-by: Tejun Heo <[email protected]> Suggested-by: Linus Torvalds <[email protected]> Cc: Craig Small <[email protected]>
1 parent 88b72b3 commit 6b59808

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

fs/proc/array.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
9999
{
100100
char *buf;
101101
size_t size;
102-
char tcomm[sizeof(p->comm)];
102+
char tcomm[64];
103103
int ret;
104104

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);
106109

107110
size = seq_get_buf(m, &buf);
108111
if (escape) {

include/linux/workqueue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ extern unsigned int work_busy(struct work_struct *work);
494494
extern __printf(1, 2) void set_worker_desc(const char *fmt, ...);
495495
extern void print_worker_info(const char *log_lvl, struct task_struct *task);
496496
extern void show_workqueue_state(void);
497+
extern void wq_worker_comm(char *buf, size_t size, struct task_struct *task);
497498

498499
/**
499500
* queue_work - queue work on a workqueue

kernel/workqueue.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4577,6 +4577,45 @@ void show_workqueue_state(void)
45774577
rcu_read_unlock_sched();
45784578
}
45794579

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+
45804619
/*
45814620
* CPU hotplug.
45824621
*

0 commit comments

Comments
 (0)