On 10/16/20 6:40 AM, Stefan Metzmacher wrote: > Am 16.10.20 um 14:28 schrieb Stefan Metzmacher via samba-technical: >>> I just found that proc_task_name() handles PF_WQ_WORKER special >>> and cat /proc/$pid/comm can expose something like: >>> kworker/u17:2-btrfs-worker-high >>> >>> ps and top still truncate, but that can be fixed. >> >> I commented on https://gitlab.com/procps-ng/procps/-/issues/51 > > Ok, it's already fixed in newer versions: > https://gitlab.com/procps-ng/procps/-/commit/2cfdbbe897f0d4e41460c7c2b92acfc5804652c8 > > So it would be great to let proc_task_name() expose more verbose > for io-wq tasks in order to avoid the limit of set_task_comm(). Here's a first cut, format is explained in the last hunk in io-wq. We can't easily get the fd in there, so for sequence, it's just an incrementing long. It shows up in fdinfo as well, so you can match them up. diff --git a/fs/io-wq.c b/fs/io-wq.c index 0c852b75384d..3e2cab10e6f3 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -41,6 +41,8 @@ enum { IO_WQE_FLAG_STALLED = 1, /* stalled on hash */ }; +static atomic_long_t seq; + /* * One for each thread in a wqe pool */ @@ -117,6 +119,8 @@ struct io_wq { free_work_fn *free_work; io_wq_work_fn *do_work; + long seq; + struct task_struct *manager; struct user_struct *user; refcount_t refs; @@ -671,7 +675,7 @@ static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index) spin_lock_init(&worker->lock); worker->task = kthread_create_on_node(io_wqe_worker, worker, wqe->node, - "io_wqe_worker-%d/%d", index, wqe->node); + "io_wq"); if (IS_ERR(worker->task)) { kfree(worker); return false; @@ -1084,6 +1088,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) wq->free_work = data->free_work; wq->do_work = data->do_work; + wq->seq = atomic_long_inc_return(&seq); /* caller must already hold a reference to this */ wq->user = data->user; @@ -1177,3 +1182,39 @@ struct task_struct *io_wq_get_task(struct io_wq *wq) { return wq->manager; } + +long io_wq_get_seq(struct io_wq *wq) +{ + return wq ? wq->seq : 0; +} + +void io_wq_comm(char *buf, size_t size, struct task_struct *task) +{ + struct io_worker *worker = kthread_data(task); + struct io_wqe *wqe; + int off; + + off = strscpy(buf, task->comm, size); + if (off < 0) + return; + + rcu_read_lock(); + if (!io_worker_get(worker)) { + rcu_read_unlock(); + return; + } + rcu_read_unlock(); + + spin_lock_irq(&worker->lock); + wqe = worker->wqe; + + /* + * Format: -seq-node-U/B for bound or unbound. Seq can be found in + * the ring fd fdinfo as well. + */ + scnprintf(buf + off, size - off, "-%ld-%d%c%c", wqe->wq->seq, wqe->node, + worker->flags & IO_WORKER_F_RUNNING ? '+' : '-', + worker->flags & IO_WORKER_F_BOUND ? 'B' : 'U'); + spin_unlock_irq(&worker->lock); + io_worker_release(worker); +} diff --git a/fs/io-wq.h b/fs/io-wq.h index be21c500c925..bede7ab5ac95 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -136,6 +136,7 @@ enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel, void *data, bool cancel_all); struct task_struct *io_wq_get_task(struct io_wq *wq); +long io_wq_get_seq(struct io_wq *wq); #if defined(CONFIG_IO_WQ) extern void io_wq_worker_sleeping(struct task_struct *); diff --git a/fs/io_uring.c b/fs/io_uring.c index 39c38e48dc11..83df6a326903 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8980,6 +8980,7 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) seq_printf(m, "SqThread:\t%d\n", sq ? task_pid_nr(sq->thread) : -1); seq_printf(m, "SqThreadCpu:\t%d\n", sq ? task_cpu(sq->thread) : -1); + seq_printf(m, "WqSeq:\t%ld\n", io_wq_get_seq(ctx->io_wq)); seq_printf(m, "UserFiles:\t%u\n", ctx->nr_user_files); for (i = 0; has_lock && i < ctx->nr_user_files; i++) { struct fixed_file_table *table; diff --git a/fs/proc/array.c b/fs/proc/array.c index 65ec2029fa80..d8f8fbbe9639 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -91,6 +91,7 @@ #include <linux/string_helpers.h> #include <linux/user_namespace.h> #include <linux/fs_struct.h> +#include <linux/io_uring.h> #include <asm/processor.h> #include "internal.h" @@ -104,6 +105,8 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape) if (p->flags & PF_WQ_WORKER) wq_worker_comm(tcomm, sizeof(tcomm), p); + else if (p->flags & PF_IO_WORKER) + io_wq_comm(tcomm, sizeof(tcomm), p); else __get_task_comm(tcomm, sizeof(tcomm), p); diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h index 28939820b6b0..507077f3dac9 100644 --- a/include/linux/io_uring.h +++ b/include/linux/io_uring.h @@ -34,6 +34,7 @@ struct sock *io_uring_get_socket(struct file *file); void __io_uring_task_cancel(void); void __io_uring_files_cancel(struct files_struct *files); void __io_uring_free(struct task_struct *tsk); +void io_wq_comm(char *buf, size_t size, struct task_struct *task); static inline void io_uring_task_cancel(void) { @@ -64,6 +65,9 @@ static inline void io_uring_files_cancel(struct files_struct *files) static inline void io_uring_free(struct task_struct *tsk) { } +static inline void io_wq_comm(char *buf, size_t size, struct task_struct *task) +{ +} #endif #endif -- Jens Axboe