diff options
author | Chunwei Chen <[email protected]> | 2016-12-01 10:06:27 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-12-01 11:06:27 -0700 |
commit | 493492559e32aa77ff8a5b32572afab5b848a53b (patch) | |
tree | 6625b9ad7cb203ae0a479ca801ba2a467096d1bf | |
parent | cbba7146676dd145f373bcbe4f4f435d9100ddbb (diff) |
Limit number of tasks shown in taskq proc
To prevent holding tq_lock for too long.
Before zfsonlinux/zfs@8e71ab9, hogging delay tasks and cat /proc/spl/taskq
would easily cause a lockup. While that bug has been fixed. It's probably
still a good idea to do this just in case task lists grow too large.
Reviewed-by: Tim Chase <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Chunwei Chen <[email protected]>
Closes #586
-rw-r--r-- | man/man5/spl-module-parameters.5 | 15 | ||||
-rw-r--r-- | module/spl/spl-proc.c | 19 |
2 files changed, 28 insertions, 6 deletions
diff --git a/man/man5/spl-module-parameters.5 b/man/man5/spl-module-parameters.5 index 1b760243e..97241fd53 100644 --- a/man/man5/spl-module-parameters.5 +++ b/man/man5/spl-module-parameters.5 @@ -326,3 +326,18 @@ configurations. .sp Default value: \fB4\fR .RE + +.sp +.ne 2 +.na +\fBspl_max_show_tasks\fR (uint) +.ad +.RS 12n +The maximum number of tasks per pending list in each taskq shown in +/proc/spl/{taskq,taskq-all}. Write 0 to turn off the limit. The proc file will +walk the lists with lock held, reading it could cause a lock up if the list +grow too large without limiting the output. "(truncated)" will be shown if the +list is larger than the limit. +.sp +Default value: \fB512\fR +.RE diff --git a/module/spl/spl-proc.c b/module/spl/spl-proc.c index db546ea61..345d0d5c7 100644 --- a/module/spl/spl-proc.c +++ b/module/spl/spl-proc.c @@ -234,6 +234,10 @@ taskq_seq_show_headers(struct seq_file *f) #define LHEAD_ACTIVE 4 #define LHEAD_SIZE 5 +static unsigned int spl_max_show_tasks = 512; +module_param(spl_max_show_tasks, uint, 0644); +MODULE_PARM_DESC(spl_max_show_tasks, "Max number of tasks shown in taskq proc"); + static int taskq_seq_show_impl(struct seq_file *f, void *p, boolean_t allflag) { @@ -308,16 +312,20 @@ taskq_seq_show_impl(struct seq_file *f, void *p, boolean_t allflag) if (lheads[i]) { j = 0; list_for_each(lh, lheads[i]) { + if (spl_max_show_tasks != 0 && + j >= spl_max_show_tasks) { + seq_printf(f, "\n\t(truncated)"); + break; + } /* show the wait waitq list */ if (i == LHEAD_WAIT) { wq = list_entry(lh, wait_queue_t, task_list); if (j == 0) seq_printf(f, "\t%s:", list_names[i]); - else if (j == 12) { + else if (j % 8 == 0) seq_printf(f, "\n\t "); - j = 0; - } + tsk = wq->private; seq_printf(f, " %d", tsk->pid); /* pend, prio and delay lists */ @@ -327,10 +335,9 @@ taskq_seq_show_impl(struct seq_file *f, void *p, boolean_t allflag) if (j == 0) seq_printf(f, "\t%s:", list_names[i]); - else if (j == 2) { + else if (j % 2 == 0) seq_printf(f, "\n\t "); - j = 0; - } + seq_printf(f, " %pf(%ps)", tqe->tqent_func, tqe->tqent_arg); |