sched/debug: Add debugfs knob for "sched_debug"
[linux] / kernel / sched / debug.c
index 4fa66de..b19d06e 100644 (file)
@@ -181,11 +181,16 @@ static const struct file_operations sched_feat_fops = {
        .release        = single_release,
 };
 
+__read_mostly bool sched_debug_enabled;
+
 static __init int sched_init_debug(void)
 {
        debugfs_create_file("sched_features", 0644, NULL, NULL,
                        &sched_feat_fops);
 
+       debugfs_create_bool("sched_debug", 0644, NULL,
+                       &sched_debug_enabled);
+
        return 0;
 }
 late_initcall(sched_init_debug);
@@ -327,38 +332,78 @@ static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu)
        return table;
 }
 
+static cpumask_var_t sd_sysctl_cpus;
 static struct ctl_table_header *sd_sysctl_header;
+
 void register_sched_domain_sysctl(void)
 {
-       int i, cpu_num = num_possible_cpus();
-       struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
+       static struct ctl_table *cpu_entries;
+       static struct ctl_table **cpu_idx;
        char buf[32];
+       int i;
 
-       WARN_ON(sd_ctl_dir[0].child);
-       sd_ctl_dir[0].child = entry;
+       if (!cpu_entries) {
+               cpu_entries = sd_alloc_ctl_entry(num_possible_cpus() + 1);
+               if (!cpu_entries)
+                       return;
 
-       if (entry == NULL)
-               return;
+               WARN_ON(sd_ctl_dir[0].child);
+               sd_ctl_dir[0].child = cpu_entries;
+       }
 
-       for_each_possible_cpu(i) {
-               snprintf(buf, 32, "cpu%d", i);
-               entry->procname = kstrdup(buf, GFP_KERNEL);
-               entry->mode = 0555;
-               entry->child = sd_alloc_ctl_cpu_table(i);
-               entry++;
+       if (!cpu_idx) {
+               struct ctl_table *e = cpu_entries;
+
+               cpu_idx = kcalloc(nr_cpu_ids, sizeof(struct ctl_table*), GFP_KERNEL);
+               if (!cpu_idx)
+                       return;
+
+               /* deal with sparse possible map */
+               for_each_possible_cpu(i) {
+                       cpu_idx[i] = e;
+                       e++;
+               }
+       }
+
+       if (!cpumask_available(sd_sysctl_cpus)) {
+               if (!alloc_cpumask_var(&sd_sysctl_cpus, GFP_KERNEL))
+                       return;
+
+               /* init to possible to not have holes in @cpu_entries */
+               cpumask_copy(sd_sysctl_cpus, cpu_possible_mask);
+       }
+
+       for_each_cpu(i, sd_sysctl_cpus) {
+               struct ctl_table *e = cpu_idx[i];
+
+               if (e->child)
+                       sd_free_ctl_entry(&e->child);
+
+               if (!e->procname) {
+                       snprintf(buf, 32, "cpu%d", i);
+                       e->procname = kstrdup(buf, GFP_KERNEL);
+               }
+               e->mode = 0555;
+               e->child = sd_alloc_ctl_cpu_table(i);
+
+               __cpumask_clear_cpu(i, sd_sysctl_cpus);
        }
 
        WARN_ON(sd_sysctl_header);
        sd_sysctl_header = register_sysctl_table(sd_ctl_root);
 }
 
+void dirty_sched_domain_sysctl(int cpu)
+{
+       if (cpumask_available(sd_sysctl_cpus))
+               __cpumask_set_cpu(cpu, sd_sysctl_cpus);
+}
+
 /* may be called multiple times per register */
 void unregister_sched_domain_sysctl(void)
 {
        unregister_sysctl_table(sd_sysctl_header);
        sd_sysctl_header = NULL;
-       if (sd_ctl_dir[0].child)
-               sd_free_ctl_entry(&sd_ctl_dir[0].child);
 }
 #endif /* CONFIG_SYSCTL */
 #endif /* CONFIG_SMP */
@@ -421,13 +466,15 @@ static char *task_group_path(struct task_group *tg)
 }
 #endif
 
+static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
+
 static void
 print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
 {
        if (rq->curr == p)
-               SEQ_printf(m, "R");
+               SEQ_printf(m, ">R");
        else
-               SEQ_printf(m, " ");
+               SEQ_printf(m, " %c", task_state_to_char(p));
 
        SEQ_printf(m, "%15s %5d %9Ld.%06ld %9Ld %5d ",
                p->comm, task_pid_nr(p),
@@ -456,9 +503,9 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
 
        SEQ_printf(m,
        "\nrunnable tasks:\n"
-       "            task   PID         tree-key  switches  prio"
+       " S           task   PID         tree-key  switches  prio"
        "     wait-time             sum-exec        sum-sleep\n"
-       "------------------------------------------------------"
+       "-------------------------------------------------------"
        "----------------------------------------------------\n");
 
        rcu_read_lock();
@@ -872,11 +919,12 @@ static void sched_show_numa(struct task_struct *p, struct seq_file *m)
 #endif
 }
 
-void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
+                                                 struct seq_file *m)
 {
        unsigned long nr_switches;
 
-       SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr(p),
+       SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns),
                                                get_nr_threads(p));
        SEQ_printf(m,
                "---------------------------------------------------------"