From: "Zou, Nanhai" 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 Signed-off-by: Andrew Morton --- 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 2005-01-23 14:47:04.488514808 -0800 +++ 25-akpm/arch/ia64/kernel/domain.c 2005-01-23 14:47:04.495513744 -0800 @@ -359,6 +359,7 @@ next_sg: #endif cpu_attach_domain(sd, i); } + init_sched_domain_sysctl(); } void __devinit arch_destroy_sched_domains(void) @@ -379,5 +380,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 2005-01-23 14:47:04.490514504 -0800 +++ 25-akpm/include/linux/sched.h 2005-01-23 14:47:04.496513592 -0800 @@ -1235,4 +1235,6 @@ static inline int try_to_freeze(unsigned #endif /* CONFIG_PM */ #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 2005-01-23 14:47:04.492514200 -0800 +++ 25-akpm/kernel/sched.c 2005-01-23 14:47:04.501512832 -0800 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -5036,12 +5037,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 @@ -5190,6 +5192,143 @@ 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 + #ifdef CONFIG_MAGIC_SYSRQ void normalize_rt_tasks(void) { _