From e761b7725234276a802322549cee5255305a0930 Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Tue, 15 Jul 2008 04:43:49 -0700 Subject: cpu hotplug, sched: Introduce cpu_active_map and redo sched domain managment (take 2) This is based on Linus' idea of creating cpu_active_map that prevents scheduler load balancer from migrating tasks to the cpu that is going down. It allows us to simplify domain management code and avoid unecessary domain rebuilds during cpu hotplug event handling. Please ignore the cpusets part for now. It needs some more work in order to avoid crazy lock nesting. Although I did simplfy and unify domain reinitialization logic. We now simply call partition_sched_domains() in all the cases. This means that we're using exact same code paths as in cpusets case and hence the test below cover cpusets too. Cpuset changes to make rebuild_sched_domains() callable from various contexts are in the separate patch (right next after this one). This not only boots but also easily handles while true; do make clean; make -j 8; done and while true; do on-off-cpu 1; done at the same time. (on-off-cpu 1 simple does echo 0/1 > /sys/.../cpu1/online thing). Suprisingly the box (dual-core Core2) is quite usable. In fact I'm typing this on right now in gnome-terminal and things are moving just fine. Also this is running with most of the debug features enabled (lockdep, mutex, etc) no BUG_ONs or lockdep complaints so far. I believe I addressed all of the Dmitry's comments for original Linus' version. I changed both fair and rt balancer to mask out non-active cpus. And replaced cpu_is_offline() with !cpu_active() in the main scheduler code where it made sense (to me). Signed-off-by: Max Krasnyanskiy Acked-by: Linus Torvalds Acked-by: Peter Zijlstra Acked-by: Gregory Haskins Cc: dmitry.adamushko@gmail.com Cc: pj@sgi.com Signed-off-by: Ingo Molnar --- init/main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index edeace036fd..dd25259530e 100644 --- a/init/main.c +++ b/init/main.c @@ -415,6 +415,13 @@ static void __init smp_init(void) { unsigned int cpu; + /* + * Set up the current CPU as possible to migrate to. + * The other ones will be done by cpu_up/cpu_down() + */ + cpu = smp_processor_id(); + cpu_set(cpu, cpu_active_map); + /* FIXME: This should be done in userspace --RR */ for_each_present_cpu(cpu) { if (num_online_cpus() >= setup_max_cpus) -- cgit v1.2.3-70-g09d2 From 3ae4eed34be0177a8e003411a84e4ee212adbced Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 25 Jul 2008 01:48:34 -0700 Subject: proper pid{hash,map}_init() prototypes This patch adds proper prototypes for pid{hash,map}_init() in include/linux/pid_namespace.h Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pid_namespace.h | 3 +++ init/main.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'init/main.c') diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index caff5283d15..1a49ab5ec7b 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -85,4 +85,7 @@ static inline struct task_struct *task_child_reaper(struct task_struct *tsk) return tsk->nsproxy->pid_ns->child_reaper; } +void pidhash_init(void); +void pidmap_init(void); + #endif /* _LINUX_PID_NS_H */ diff --git a/init/main.c b/init/main.c index 2769dc031c6..0604cbcaf1e 100644 --- a/init/main.c +++ b/init/main.c @@ -87,8 +87,6 @@ extern void init_IRQ(void); extern void fork_init(unsigned long); extern void mca_init(void); extern void sbus_init(void); -extern void pidhash_init(void); -extern void pidmap_init(void); extern void prio_tree_init(void); extern void radix_tree_init(void); extern void free_initmem(void); -- cgit v1.2.3-70-g09d2 From c2147a5092cfe13dbf3210e54e8a622015edeecc Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Fri, 25 Jul 2008 19:45:11 -0700 Subject: Better interface for hooking early initcalls Added early initcall (pre-SMP) support, using an identical interface to that of regular initcalls. Functions called from do_pre_smp_initcalls() could be converted to use this cleaner interface. This is required by CPU hotplug, because early users have to register notifiers before going SMP. One such CPU hotplug user is the relay interface with buffer-only channels, which needs to register such a notifier, to be usable in early code. This in turn is used by kmemtrace. Signed-off-by: Eduard - Gabriel Munteanu Cc: Tom Zanussi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/vmlinux.lds.h | 2 ++ include/linux/init.h | 7 +++++++ init/main.c | 13 +++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'init/main.c') diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 729f6b0a60e..9cd44b162ba 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -359,6 +359,8 @@ } #define INITCALLS \ + *(.initcallearly.init) \ + __early_initcall_end = .; \ *(.initcall0.init) \ *(.initcall0s.init) \ *(.initcall1.init) \ diff --git a/include/linux/init.h b/include/linux/init.h index 42ae95411a9..11b84e10605 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -169,6 +169,13 @@ extern void (*late_time_init)(void); static initcall_t __initcall_##fn##id __used \ __attribute__((__section__(".initcall" level ".init"))) = fn +/* + * Early initcalls run before initializing SMP. + * + * Only for built-in code, not modules. + */ +#define early_initcall(fn) __define_initcall("early",fn,early) + /* * A "pure" initcall has no dependencies on anything else, and purely * initializes variables that couldn't be statically initialized. diff --git a/init/main.c b/init/main.c index 0604cbcaf1e..b6fec08dbbe 100644 --- a/init/main.c +++ b/init/main.c @@ -743,13 +743,13 @@ static void __init do_one_initcall(initcall_t fn) } -extern initcall_t __initcall_start[], __initcall_end[]; +extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; static void __init do_initcalls(void) { initcall_t *call; - for (call = __initcall_start; call < __initcall_end; call++) + for (call = __early_initcall_end; call < __initcall_end; call++) do_one_initcall(*call); /* Make sure there is no pending stuff from the initcall sequence */ @@ -783,6 +783,14 @@ static int __init nosoftlockup_setup(char *str) } __setup("nosoftlockup", nosoftlockup_setup); +static void __init __do_pre_smp_initcalls(void) +{ + initcall_t *call; + + for (call = __initcall_start; call < __early_initcall_end; call++) + do_one_initcall(*call); +} + static void __init do_pre_smp_initcalls(void) { extern int spawn_ksoftirqd(void); @@ -865,6 +873,7 @@ static int __init kernel_init(void * unused) smp_prepare_cpus(setup_max_cpus); + __do_pre_smp_initcalls(); do_pre_smp_initcalls(); smp_init(); -- cgit v1.2.3-70-g09d2 From 7babe8db99d305340cf4828ce1f5a1481d5622ef Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Fri, 25 Jul 2008 19:45:11 -0700 Subject: Full conversion to early_initcall() interface, remove old interface A previous patch added the early_initcall(), to allow a cleaner hooking of pre-SMP initcalls. Now we remove the older interface, converting all existing users to the new one. [akpm@linux-foundation.org: cleanups] [akpm@linux-foundation.org: build fix] [kosaki.motohiro@jp.fujitsu.com: warning fix] [kosaki.motohiro@jp.fujitsu.com: warning fix] Signed-off-by: Eduard - Gabriel Munteanu Cc: Tom Zanussi Signed-off-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 9 --------- include/linux/smp.h | 5 ----- init/main.c | 23 +---------------------- kernel/sched.c | 5 ++++- kernel/smp.c | 4 +++- kernel/softirq.c | 3 ++- kernel/softlockup.c | 25 ++++++++++++++++++++++--- 7 files changed, 32 insertions(+), 42 deletions(-) (limited to 'init/main.c') diff --git a/include/linux/sched.h b/include/linux/sched.h index 3260a5c42b9..adb8077dc46 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -292,7 +292,6 @@ extern void sched_show_task(struct task_struct *p); #ifdef CONFIG_DETECT_SOFTLOCKUP extern void softlockup_tick(void); -extern void spawn_softlockup_task(void); extern void touch_softlockup_watchdog(void); extern void touch_all_softlockup_watchdogs(void); extern unsigned int softlockup_panic; @@ -2222,14 +2221,6 @@ static inline void inc_syscw(struct task_struct *tsk) } #endif -#ifdef CONFIG_SMP -void migration_init(void); -#else -static inline void migration_init(void) -{ -} -#endif - #ifndef TASK_SIZE_OF #define TASK_SIZE_OF(tsk) TASK_SIZE #endif diff --git a/include/linux/smp.h b/include/linux/smp.h index 48262f86c96..66484d4a845 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -74,15 +74,10 @@ void __smp_call_function_single(int cpuid, struct call_single_data *data); #ifdef CONFIG_USE_GENERIC_SMP_HELPERS void generic_smp_call_function_single_interrupt(void); void generic_smp_call_function_interrupt(void); -void init_call_single_data(void); void ipi_call_lock(void); void ipi_call_unlock(void); void ipi_call_lock_irq(void); void ipi_call_unlock_irq(void); -#else -static inline void init_call_single_data(void) -{ -} #endif /* diff --git a/init/main.c b/init/main.c index b6fec08dbbe..20fdc9884b7 100644 --- a/init/main.c +++ b/init/main.c @@ -774,16 +774,7 @@ static void __init do_basic_setup(void) do_initcalls(); } -static int __initdata nosoftlockup; - -static int __init nosoftlockup_setup(char *str) -{ - nosoftlockup = 1; - return 1; -} -__setup("nosoftlockup", nosoftlockup_setup); - -static void __init __do_pre_smp_initcalls(void) +static void __init do_pre_smp_initcalls(void) { initcall_t *call; @@ -791,17 +782,6 @@ static void __init __do_pre_smp_initcalls(void) do_one_initcall(*call); } -static void __init do_pre_smp_initcalls(void) -{ - extern int spawn_ksoftirqd(void); - - init_call_single_data(); - migration_init(); - spawn_ksoftirqd(); - if (!nosoftlockup) - spawn_softlockup_task(); -} - static void run_init_process(char *init_filename) { argv_init[0] = init_filename; @@ -873,7 +853,6 @@ static int __init kernel_init(void * unused) smp_prepare_cpus(setup_max_cpus); - __do_pre_smp_initcalls(); do_pre_smp_initcalls(); smp_init(); diff --git a/kernel/sched.c b/kernel/sched.c index 0047bd9b96a..fde1a102635 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6389,7 +6389,7 @@ static struct notifier_block __cpuinitdata migration_notifier = { .priority = 10 }; -void __init migration_init(void) +static int __init migration_init(void) { void *cpu = (void *)(long)smp_processor_id(); int err; @@ -6399,7 +6399,10 @@ void __init migration_init(void) BUG_ON(err == NOTIFY_BAD); migration_call(&migration_notifier, CPU_ONLINE, cpu); register_cpu_notifier(&migration_notifier); + + return err; } +early_initcall(migration_init); #endif #ifdef CONFIG_SMP diff --git a/kernel/smp.c b/kernel/smp.c index 462c785ca1e..96fc7c0edc5 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -33,7 +33,7 @@ struct call_single_queue { spinlock_t lock; }; -void __cpuinit init_call_single_data(void) +static int __cpuinit init_call_single_data(void) { int i; @@ -43,7 +43,9 @@ void __cpuinit init_call_single_data(void) spin_lock_init(&q->lock); INIT_LIST_HEAD(&q->list); } + return 0; } +early_initcall(init_call_single_data); static void csd_flag_wait(struct call_single_data *data) { diff --git a/kernel/softirq.c b/kernel/softirq.c index f6b03d56c2b..c506f266a6b 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -630,7 +630,7 @@ static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; -__init int spawn_ksoftirqd(void) +static __init int spawn_ksoftirqd(void) { void *cpu = (void *)(long)smp_processor_id(); int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); @@ -640,6 +640,7 @@ __init int spawn_ksoftirqd(void) register_cpu_notifier(&cpu_nfb); return 0; } +early_initcall(spawn_ksoftirqd); #ifdef CONFIG_SMP /* diff --git a/kernel/softlockup.c b/kernel/softlockup.c index 7bd8d1aadd5..b75b492fbfc 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -338,14 +338,33 @@ static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; -__init void spawn_softlockup_task(void) +static int __initdata nosoftlockup; + +static int __init nosoftlockup_setup(char *str) +{ + nosoftlockup = 1; + return 1; +} +__setup("nosoftlockup", nosoftlockup_setup); + +static int __init spawn_softlockup_task(void) { void *cpu = (void *)(long)smp_processor_id(); - int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); + int err; - BUG_ON(err == NOTIFY_BAD); + if (nosoftlockup) + return 0; + + err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); + if (err == NOTIFY_BAD) { + BUG(); + return 1; + } cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); register_cpu_notifier(&cpu_nfb); atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + + return 0; } +early_initcall(spawn_softlockup_task); -- cgit v1.2.3-70-g09d2 From bd673c7c3b1681dbfabab0062e67398dadf806af Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Jul 2008 22:33:36 -0700 Subject: initrd: cast `initrd_start' to `void *' commit fb6624ebd912e3d6907ca6490248e73368223da9 (initrd: Fix virtual/physical mix-up in overwrite test) introduced the compiler warning below on mips, as its virt_to_page() doesn't cast the passed address to unsigned long internally, unlike on most other architectures: init/main.c: In function `start_kernel': init/main.c:633: warning: passing argument 1 of `virt_to_phys' makes pointer from integer without a cast init/main.c:636: warning: passing argument 1 of `virt_to_phys' makes pointer from integer without a cast For now, kill the warning by explicitly casting initrd_start to `void *', as that's the type it should really be. Reported-by: Atsushi Nemoto Signed-off-by: Geert Uytterhoeven Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index 20fdc9884b7..9c3b68b86ca 100644 --- a/init/main.c +++ b/init/main.c @@ -635,10 +635,11 @@ asmlinkage void __init start_kernel(void) #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && - page_to_pfn(virt_to_page(initrd_start)) < min_low_pfn) { + page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " "disabling it.\n", - page_to_pfn(virt_to_page(initrd_start)), min_low_pfn); + page_to_pfn(virt_to_page((void *)initrd_start)), + min_low_pfn); initrd_start = 0; } #endif -- cgit v1.2.3-70-g09d2 From b5b9309d3415480b3e66314a1d6c89db58bff9de Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 5 Aug 2008 18:16:58 +0200 Subject: remove unnecessary includes Following files don't need at all: - arch/mips/jazz/setup.c - arch/sh/boards/mach-systemh/irq.c - drivers/macintosh/mediabay.c - drivers/scsi/hptiop.c - drivers/usb/storage/freecom.c - arch/powerpc/include/asm/ide.h - init/main.c Cc: Christoph Hellwig Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/mips/jazz/setup.c | 1 - arch/powerpc/include/asm/ide.h | 1 - arch/sh/boards/mach-systemh/irq.c | 1 - drivers/macintosh/mediabay.c | 1 - drivers/scsi/hptiop.c | 1 - drivers/usb/storage/freecom.c | 2 -- init/main.c | 1 - 7 files changed, 8 deletions(-) (limited to 'init/main.c') diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index f60524e8bc4..d3a531ad4ea 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -10,7 +10,6 @@ * Copyright (C) 2007 by Thomas Bogendoerfer */ #include -#include #include #include #include diff --git a/arch/powerpc/include/asm/ide.h b/arch/powerpc/include/asm/ide.h index 1aaf27be874..048480e340f 100644 --- a/arch/powerpc/include/asm/ide.h +++ b/arch/powerpc/include/asm/ide.h @@ -20,7 +20,6 @@ #define __ide_mm_outsl(p, a, c) writesl((void __iomem *)(p), (a), (c)) #ifndef __powerpc64__ -#include #include /* FIXME: use ide_platform host driver */ diff --git a/arch/sh/boards/mach-systemh/irq.c b/arch/sh/boards/mach-systemh/irq.c index 0ba2fe674c4..82101cc66dc 100644 --- a/arch/sh/boards/mach-systemh/irq.c +++ b/arch/sh/boards/mach-systemh/irq.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index b1e5b470525..d7e46d345d9 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 74d12b58a26..a48e4990fe1 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 7a4d4567722..73ac7262239 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -26,8 +26,6 @@ * (http://www.freecom.de/) */ -#include - #include #include diff --git a/init/main.c b/init/main.c index 9c3b68b86ca..0bc7e167bf4 100644 --- a/init/main.c +++ b/init/main.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-70-g09d2 From 59f9415ffb9759e950d775f4c400f747b332cc02 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 30 Jul 2008 12:49:02 -0700 Subject: modules: extend initcall_debug functionality to the module loader The kernel has this really nice facility where if you put "initcall_debug" on the kernel commandline, it'll print which function it's going to execute just before calling an initcall, and then after the call completes it will 1) print if it had an error code 2) checks for a few simple bugs (like leaving irqs off) and 3) print how long the init call took in milliseconds. While trying to optimize the boot speed of my laptop, I have been loving number 3 to figure out what to optimize... ... and then I wished that the same thing was done for module loading. This patch makes the module loader use this exact same functionality; it's a logical extension in my view (since modules are just sort of late binding initcalls anyway) and so far I've found it quite useful in finding where things are too slow in my boot. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Rusty Russell --- include/linux/init.h | 1 + init/main.c | 6 ++++-- kernel/module.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'init/main.c') diff --git a/include/linux/init.h b/include/linux/init.h index 11b84e10605..93538b696e3 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -139,6 +139,7 @@ extern initcall_t __con_initcall_start[], __con_initcall_end[]; extern initcall_t __security_initcall_start[], __security_initcall_end[]; /* Defined in init/main.c */ +extern int do_one_initcall(initcall_t fn); extern char __initdata boot_command_line[]; extern char *saved_command_line; extern unsigned int reset_devices; diff --git a/init/main.c b/init/main.c index 0bc7e167bf4..f6f7042331d 100644 --- a/init/main.c +++ b/init/main.c @@ -691,7 +691,7 @@ asmlinkage void __init start_kernel(void) rest_init(); } -static int __initdata initcall_debug; +static int initcall_debug; static int __init initcall_debug_setup(char *str) { @@ -700,7 +700,7 @@ static int __init initcall_debug_setup(char *str) } __setup("initcall_debug", initcall_debug_setup); -static void __init do_one_initcall(initcall_t fn) +int do_one_initcall(initcall_t fn) { int count = preempt_count(); ktime_t t0, t1, delta; @@ -740,6 +740,8 @@ static void __init do_one_initcall(initcall_t fn) print_fn_descriptor_symbol(KERN_WARNING "initcall %s", fn); printk(" returned with %s\n", msgbuf); } + + return result; } diff --git a/kernel/module.c b/kernel/module.c index 61d212120df..08864d257eb 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2288,7 +2288,7 @@ sys_init_module(void __user *umod, /* Start the module */ if (mod->init != NULL) - ret = mod->init(); + ret = do_one_initcall(mod->init); if (ret < 0) { /* Init routine failed: abort. Try to protect us from buggy refcounters. */ -- cgit v1.2.3-70-g09d2