aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChunwei Chen <[email protected]>2016-12-01 10:06:27 -0800
committerBrian Behlendorf <[email protected]>2016-12-01 11:06:27 -0700
commit493492559e32aa77ff8a5b32572afab5b848a53b (patch)
tree6625b9ad7cb203ae0a479ca801ba2a467096d1bf
parentcbba7146676dd145f373bcbe4f4f435d9100ddbb (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.515
-rw-r--r--module/spl/spl-proc.c19
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);