workqueue: Set worker->desc to workqueue name by default

Work functions can use set_worker_desc() to improve the visibility of
what the worker task is doing.  Currently, the desc field is unset at
the beginning of each execution and there is a separate field to track
the field is set during the current execution.

Instead of leaving empty till desc is set, worker->desc can be used to
remember the last workqueue the worker worked on by default and users
that use set_worker_desc() can override it to something more
informative as necessary.

This simplifies desc handling and helps tracking the last workqueue
that the worker exected on to improve visibility.

Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Tejun Heo 2018-05-18 08:47:13 -07:00
parent a2d812a27a
commit 8bf895931e
2 changed files with 10 additions and 12 deletions

View File

@ -2088,6 +2088,12 @@ __acquires(&pool->lock)
worker->current_pwq = pwq; worker->current_pwq = pwq;
work_color = get_work_color(work); work_color = get_work_color(work);
/*
* Record wq name for cmdline and debug reporting, may get
* overridden through set_worker_desc().
*/
strscpy(worker->desc, pwq->wq->name, WORKER_DESC_LEN);
list_del_init(&work->entry); list_del_init(&work->entry);
/* /*
@ -2183,7 +2189,6 @@ __acquires(&pool->lock)
worker->current_work = NULL; worker->current_work = NULL;
worker->current_func = NULL; worker->current_func = NULL;
worker->current_pwq = NULL; worker->current_pwq = NULL;
worker->desc_valid = false;
pwq_dec_nr_in_flight(pwq, work_color); pwq_dec_nr_in_flight(pwq, work_color);
} }
@ -4346,7 +4351,6 @@ void set_worker_desc(const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vsnprintf(worker->desc, sizeof(worker->desc), fmt, args); vsnprintf(worker->desc, sizeof(worker->desc), fmt, args);
va_end(args); va_end(args);
worker->desc_valid = true;
} }
} }
@ -4370,7 +4374,6 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
char desc[WORKER_DESC_LEN] = { }; char desc[WORKER_DESC_LEN] = { };
struct pool_workqueue *pwq = NULL; struct pool_workqueue *pwq = NULL;
struct workqueue_struct *wq = NULL; struct workqueue_struct *wq = NULL;
bool desc_valid = false;
struct worker *worker; struct worker *worker;
if (!(task->flags & PF_WQ_WORKER)) if (!(task->flags & PF_WQ_WORKER))
@ -4383,22 +4386,18 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
worker = kthread_probe_data(task); worker = kthread_probe_data(task);
/* /*
* Carefully copy the associated workqueue's workfn and name. Keep * Carefully copy the associated workqueue's workfn, name and desc.
* the original last '\0' in case the original contains garbage. * Keep the original last '\0' in case the original is garbage.
*/ */
probe_kernel_read(&fn, &worker->current_func, sizeof(fn)); probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq)); probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
probe_kernel_read(&wq, &pwq->wq, sizeof(wq)); probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
probe_kernel_read(name, wq->name, sizeof(name) - 1); probe_kernel_read(name, wq->name, sizeof(name) - 1);
/* copy worker description */
probe_kernel_read(&desc_valid, &worker->desc_valid, sizeof(desc_valid));
if (desc_valid)
probe_kernel_read(desc, worker->desc, sizeof(desc) - 1); probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
if (fn || name[0] || desc[0]) { if (fn || name[0] || desc[0]) {
printk("%sWorkqueue: %s %pf", log_lvl, name, fn); printk("%sWorkqueue: %s %pf", log_lvl, name, fn);
if (desc[0]) if (strcmp(name, desc))
pr_cont(" (%s)", desc); pr_cont(" (%s)", desc);
pr_cont("\n"); pr_cont("\n");
} }

View File

@ -31,7 +31,6 @@ struct worker {
struct work_struct *current_work; /* L: work being processed */ struct work_struct *current_work; /* L: work being processed */
work_func_t current_func; /* L: current_work's fn */ work_func_t current_func; /* L: current_work's fn */
struct pool_workqueue *current_pwq; /* L: current_work's pwq */ struct pool_workqueue *current_pwq; /* L: current_work's pwq */
bool desc_valid; /* ->desc is valid */
struct list_head scheduled; /* L: scheduled works */ struct list_head scheduled; /* L: scheduled works */
/* 64 bytes boundary on 64bit, 32 on 32bit */ /* 64 bytes boundary on 64bit, 32 on 32bit */