From: "Zou, Nanhai" <nanhai.zou@intel.com>

I think add sysctl interface to sched_domain parameters is helpful to debug
and tuning those parameters at run time.

Signed-off-by: Zou Nan hai <nanhai.zou@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ia64/kernel/domain.c |    2 
 25-akpm/include/linux/sched.h     |    2 
 25-akpm/kernel/sched.c            |  141 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 144 insertions(+), 1 deletion(-)

diff -puN arch/ia64/kernel/domain.c~add-sysctl-interface-to-sched_domain-parameters arch/ia64/kernel/domain.c
--- 25/arch/ia64/kernel/domain.c~add-sysctl-interface-to-sched_domain-parameters	2004-11-03 20:25:44.879927296 -0800
+++ 25-akpm/arch/ia64/kernel/domain.c	2004-11-03 20:25:44.885926384 -0800
@@ -357,6 +357,7 @@ next_sg:
 #endif
 		cpu_attach_domain(sd, i);
 	}
+	init_sched_domain_sysctl();
 }
 
 void __devinit arch_destroy_sched_domains(void)
@@ -377,5 +378,6 @@ next_sg:
 		sched_group_nodes[i] = NULL;
 	}
 #endif
+	destroy_sched_domain_sysctl();
 }
 
diff -puN include/linux/sched.h~add-sysctl-interface-to-sched_domain-parameters include/linux/sched.h
--- 25/include/linux/sched.h~add-sysctl-interface-to-sched_domain-parameters	2004-11-03 20:25:44.880927144 -0800
+++ 25-akpm/include/linux/sched.h	2004-11-03 20:25:44.886926232 -0800
@@ -1110,4 +1110,6 @@ extern long sched_getaffinity(pid_t pid,
 
 #endif /* __KERNEL__ */
 
+extern void init_sched_domain_sysctl(void);
+extern void destroy_sched_domain_sysctl(void);
 #endif
diff -puN kernel/sched.c~add-sysctl-interface-to-sched_domain-parameters kernel/sched.c
--- 25/kernel/sched.c~add-sysctl-interface-to-sched_domain-parameters	2004-11-03 20:25:44.882926840 -0800
+++ 25-akpm/kernel/sched.c	2004-11-03 20:25:44.891925472 -0800
@@ -43,6 +43,7 @@
 #include <linux/perfctr.h>
 #include <linux/kthread.h>
 #include <linux/seq_file.h>
+#include <linux/sysctl.h>
 #include <linux/syscalls.h>
 #include <linux/times.h>
 #include <asm/tlb.h>
@@ -4378,12 +4379,13 @@ static void __devinit arch_init_sched_do
 #endif
 		cpu_attach_domain(sd, i);
 	}
+	init_sched_domain_sysctl();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 static void __devinit arch_destroy_sched_domains(void)
 {
-	/* Do nothing: everything is statically allocated. */
+	destroy_sched_domain_sysctl();
 }
 #endif
 
@@ -4620,3 +4622,140 @@ void __might_sleep(char *file, int line)
 }
 EXPORT_SYMBOL(__might_sleep);
 #endif
+
+#if defined(CONFIG_DEBUG_KERNEL)&&defined(CONFIG_SYSCTL)&&defined(CONFIG_SMP)
+static struct ctl_table sd_ctl_dir[] = {
+	{1, "sched_domain", NULL, 0, 0755, NULL, },
+	{0,},
+};
+
+static struct ctl_table sd_ctl_root[] = {
+	{1, "kernel", NULL, 0, 0755, sd_ctl_dir, },
+	{0,},
+};
+static char *sched_strdup(char *str)
+{
+	int n = strlen(str)+1;
+	char *s = kmalloc(n, GFP_KERNEL);
+	if (!s)
+		return NULL;
+	return strcpy(s, str);
+}
+static struct ctl_table *sd_alloc_ctl_entry(int n)
+{
+	struct ctl_table *entry =
+		kmalloc(n * sizeof(struct ctl_table), GFP_KERNEL);
+	BUG_ON(!entry);
+	memset(entry, 0, n * sizeof(struct ctl_table));
+	return entry;
+}
+
+static void
+set_table_entry(struct ctl_table *entry, int ctl_name, const char *procname,
+		void *data, int maxlen, mode_t mode,
+		proc_handler *proc_handler)
+{
+	entry->ctl_name = ctl_name;
+	entry->procname = procname;
+	entry->data = data;
+	entry->maxlen = maxlen;
+	entry->mode = mode;
+	entry->proc_handler = proc_handler;
+}
+
+static struct ctl_table *
+sd_alloc_ctl_domain_table(struct sched_domain *sd)
+{
+	struct ctl_table *table;
+	table = sd_alloc_ctl_entry(9);
+
+	set_table_entry(&table[0], 1, "min_interval", &sd->min_interval,
+			sizeof(long), 0644, proc_doulongvec_minmax);
+	set_table_entry(&table[1], 2, "max_interval", &sd->max_interval,
+			sizeof(long), 0644, proc_doulongvec_minmax);
+	set_table_entry(&table[2], 3, "busy_factor", &sd->busy_factor,
+			sizeof(int), 0644, proc_dointvec_minmax);
+	set_table_entry(&table[3], 4, "imbalance_pct", &sd->imbalance_pct,
+			sizeof(int), 0644, proc_dointvec_minmax);
+	set_table_entry(&table[4], 5, "cache_hot_time", &sd->cache_hot_time,
+			sizeof(long long), 0644, proc_doulonglongvec_minmax);
+	set_table_entry(&table[5], 6, "cache_nice_tries", &sd->cache_nice_tries,
+			sizeof(int), 0644, proc_dointvec_minmax);
+	set_table_entry(&table[6], 7, "per_cpu_gain", &sd->per_cpu_gain,
+			sizeof(int), 0644, proc_dointvec_minmax);
+	set_table_entry(&table[7], 8, "flags", &sd->flags,
+			sizeof(int), 0644, proc_dointvec_minmax);
+	return table;
+}
+
+static ctl_table *sd_alloc_ctl_cpu_table(int cpu)
+{
+	struct sched_domain *sd;
+	int domain_num = 0, i;
+	struct ctl_table *entry, *table;
+	char buf[32];
+	for_each_domain(cpu, sd)
+		domain_num++;
+	entry = table = sd_alloc_ctl_entry(domain_num + 1);
+
+	i = 0;
+	for_each_domain(cpu, sd) {
+		sprintf(buf, "domain-%d", i);
+		entry->ctl_name = i + 1;
+		entry->procname = sched_strdup(buf);
+		entry->mode = 0755;
+		entry->child = sd_alloc_ctl_domain_table(sd);
+		entry++;
+		i++;
+	}
+	return table;
+}
+
+static struct ctl_table_header *sd_sysctl_header;
+void init_sched_domain_sysctl()
+{
+	int i, cpu_num = num_online_cpus();
+	char buf[32];
+	struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
+
+	sd_ctl_dir[0].child = entry;
+
+	for (i = 0; i < cpu_num; i++, entry++) {
+		sprintf(buf, "cpu%d", i);
+		entry->ctl_name = i + 1;
+		entry->procname = sched_strdup(buf);
+		entry->mode = 0755;
+		entry->child = sd_alloc_ctl_cpu_table(i);
+	}
+	sd_sysctl_header = register_sysctl_table(sd_ctl_root, 0);
+}
+
+void destroy_sched_domain_sysctl()
+{
+	int cpu, cpu_num = num_online_cpus();
+	struct sched_domain *sd;
+	struct ctl_table *root = sd_ctl_dir[0].child;
+	struct ctl_table *entry, *table;
+
+	unregister_sysctl_table(sd_sysctl_header);
+	entry = root;
+	for (cpu = 0; cpu < cpu_num; cpu++, entry++) {
+		kfree(entry->procname);
+		table = entry->child;
+		for_each_domain(cpu, sd) {
+			kfree(table->procname);
+			kfree(table->child);
+			table++;
+		}
+		kfree(entry->child);
+	}
+	kfree(root);
+}
+#else
+void init_sched_domain_sysctl()
+{
+}
+void destroy_sched_domain_sysctl()
+{
+}
+#endif
_