]> granicus.if.org Git - spl/commitdiff
Limit number of tasks shown in taskq proc
authorChunwei Chen <tuxoko@gmail.com>
Thu, 1 Dec 2016 18:06:27 +0000 (10:06 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 1 Dec 2016 18:06:27 +0000 (11:06 -0700)
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 <tim@chase2k.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Closes #586

man/man5/spl-module-parameters.5
module/spl/spl-proc.c

index 1b760243e2bcbf17ffced5f9c6824a8725d9cb7d..97241fd53780e858a7bf408e8457efb90e6d9a63 100644 (file)
@@ -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
index db546ea618406cee38689c74f5bd549da2e1079c..345d0d5c7a444e4ea08fe8028c22f113f1aaf07d 100644 (file)
@@ -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);