Re: [PATCH 2/3] workqueue: expose per-workqueue stats in debugfs

From: Tejun Heo

Date: Thu Oct 22 2026 - 20:19:13 EST


Hello, Wilson.

On Thu, Oct 22, 2026 at 10:46:19PM +0000, Wilson Felipe Pereira wrote:
> Why not drgn? For continuous monitoring, running drgn on every machine,
> with vmlinux debuginfo, and memory footprint from Python/drgn, while
> having CONFIG_PROC_KCORE available, it adds up. Having a simple file
> interface, it can be read from an existing monitoring collector.
>
> Why debugfs? If sysfs is picked, not all queues are in
> /sys/bus/workqueue/devices/. Using debugfs, a single file can include
> all queues. If you have a suggestion, I'm open to change this series.

I'm usually really skeptical when people suggest debugfs as a solution.
If you need continuous monitoring and drgn is too heavy, this is trivial
to do with BPF. The following bpftrace script prints the per-workqueue
stats and needs only BTF, no DWARF debuginfo, /proc/kcore or Python:

BEGIN
{
printf("%-24s %10s %10s %12s %6s %6s %6s\n", "workqueue", "started",
"completed", "cpu_time_us", "active", "cmw", "mayday");

$whead = (uint64)kaddr("workqueues");
$wpos = (uint64)((struct list_head *)$whead)->next;
for ($i : 0..4096) {
if ($wpos == $whead) {
break;
}
$wq = (struct workqueue_struct *)($wpos - offsetof(struct workqueue_struct, list));
$started = (uint64)0; $completed = (uint64)0; $cpu = (uint64)0;
$cmw = (uint64)0; $mayday = (uint64)0; $active = 0;

$phead = (uint64)$wq + offsetof(struct workqueue_struct, pwqs);
$ppos = (uint64)((struct list_head *)$phead)->next;
for ($j : 0..8192) {
if ($ppos == $phead) {
break;
}
$pwq = (struct pool_workqueue *)($ppos - offsetof(struct pool_workqueue, pwqs_node));
$started += $pwq->stats[PWQ_STAT_STARTED];
$completed += $pwq->stats[PWQ_STAT_COMPLETED];
$cpu += $pwq->stats[PWQ_STAT_CPU_TIME];
$cmw += $pwq->stats[PWQ_STAT_CM_WAKEUP];
$mayday += $pwq->stats[PWQ_STAT_MAYDAY];
$active += $pwq->nr_active;
$ppos = (uint64)((struct list_head *)$ppos)->next;
}

printf("%-24s %10lu %10lu %12lu %6d %6lu %6lu\n", $wq->name, $started,
$completed, $cpu, $active, $cmw, $mayday);
$wpos = (uint64)((struct list_head *)$wpos)->next;
}
exit();
}

It took an AI agent about a minute to write and test.

Thanks.

--
tejun