Signed-off-by: Stefan Metzmacher <metze@xxxxxxxxx> --- fs/io-wq.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/io-wq.h | 4 +++ 2 files changed, 81 insertions(+) diff --git a/fs/io-wq.c b/fs/io-wq.c index 5c7d2a8c112e..1267171f6388 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -559,6 +559,83 @@ void io_wq_worker_sleeping(struct task_struct *tsk) raw_spin_unlock_irq(&worker->wqe->lock); } +/* used to show worker information through /proc/PID/{comm,stat,status} */ +void io_wq_worker_comm(char *buf, size_t size, struct task_struct *tsk) +{ + struct io_worker *worker = tsk->pf_io_worker; + bool working = false; + unsigned flags = 0; + unsigned int cpu; + int node; + int wqe_node = NUMA_NO_NODE; + int off; + + BUG_ON(!(tsk->flags & PF_IO_WORKER)); + + /* prepend iothread/ to the actual comm */ + off = scnprintf(buf, size, "iothread/%s", tsk->comm); + if (off < 0) + return; + + cpu = task_cpu(tsk); + node = cpu_to_node(cpu); + + if (worker && io_worker_get(worker)) { + spin_lock_irq(&worker->lock); + flags = worker->flags; + working = worker->cur_work != NULL; + wqe_node = worker->wqe->node; + spin_unlock_irq(&worker->lock); + io_worker_release(worker); + } + + /* + * It may or may not run on the desired node + */ + if (node == wqe_node) + off += scnprintf(buf + off, size - off, "/+numa%u", node); + else + off += scnprintf(buf + off, size - off, "/-numa%u", node); + if (off < 0) + return; + + /* + * It maybe created via create_io_thread(), but not + * via the create_io_worker() wrapper. + */ + if (worker == NULL) + return; + + if (!(flags & IO_WORKER_F_UP)) + off += scnprintf(buf + off, size - off, "-down"); + else if (flags & IO_WORKER_F_FREE) + off += scnprintf(buf + off, size - off, "-free"); + else if (flags & IO_WORKER_F_RUNNING) { + if (working) + off += scnprintf(buf + off, size - off, "+working"); + else + off += scnprintf(buf + off, size - off, "+running"); + if (off < 0) + return; + } + if (off < 0) + return; + + if (flags & IO_WORKER_F_BOUND) + off += scnprintf(buf + off, size - off, "+bound"); + else + off += scnprintf(buf + off, size - off, "-unbound"); + if (off < 0) + return; + + if (flags & IO_WORKER_F_FIXED) + off += scnprintf(buf + off, size - off, "+fixed"); + if (off < 0) + return; + + return; +} + static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index) { struct io_wqe_acct *acct = &wqe->acct[index]; diff --git a/fs/io-wq.h b/fs/io-wq.h index 80d590564ff9..470f854256d1 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -140,6 +140,7 @@ enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel, #if defined(CONFIG_IO_WQ) extern void io_wq_worker_sleeping(struct task_struct *); extern void io_wq_worker_running(struct task_struct *); +extern void io_wq_worker_comm(char *buf, size_t size, struct task_struct *tsk); #else static inline void io_wq_worker_sleeping(struct task_struct *tsk) { @@ -147,6 +148,9 @@ static inline void io_wq_worker_sleeping(struct task_struct *tsk) static inline void io_wq_worker_running(struct task_struct *tsk) { } +static inline void io_wq_worker_comm(char *buf, size_t size, struct task_struct *tsk) +{ +} #endif static inline bool io_wq_current_is_worker(void) -- 2.25.1