diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Kconfig.preempt | 3 | ||||
-rw-r--r-- | kernel/acct.c | 2 | ||||
-rw-r--r-- | kernel/auditsc.c | 6 | ||||
-rw-r--r-- | kernel/futex.c | 4 | ||||
-rw-r--r-- | kernel/hrtimer.c | 6 | ||||
-rw-r--r-- | kernel/irq/devres.c | 1 | ||||
-rw-r--r-- | kernel/kmod.c | 8 | ||||
-rw-r--r-- | kernel/kthread.c | 12 | ||||
-rw-r--r-- | kernel/lockdep_proc.c | 2 | ||||
-rw-r--r-- | kernel/params.c | 7 | ||||
-rw-r--r-- | kernel/power/Kconfig | 45 | ||||
-rw-r--r-- | kernel/power/Makefile | 5 | ||||
-rw-r--r-- | kernel/power/disk.c | 1 | ||||
-rw-r--r-- | kernel/power/main.c | 28 | ||||
-rw-r--r-- | kernel/power/power.h | 12 | ||||
-rw-r--r-- | kernel/relay.c | 3 | ||||
-rw-r--r-- | kernel/sched.c | 206 | ||||
-rw-r--r-- | kernel/sched_debug.c | 4 | ||||
-rw-r--r-- | kernel/sys.c | 5 | ||||
-rw-r--r-- | kernel/sysctl.c | 2 | ||||
-rw-r--r-- | kernel/time.c | 16 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 38 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 2 | ||||
-rw-r--r-- | kernel/time/timer_stats.c | 2 | ||||
-rw-r--r-- | kernel/tsacct.c | 2 |
25 files changed, 340 insertions, 82 deletions
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt index c64ce9c1420..6b066632e40 100644 --- a/kernel/Kconfig.preempt +++ b/kernel/Kconfig.preempt @@ -63,3 +63,6 @@ config PREEMPT_BKL Say Y here if you are building a kernel for a desktop system. Say N if you are unsure. +config PREEMPT_NOTIFIERS + bool + diff --git a/kernel/acct.c b/kernel/acct.c index 70d0d88e555..24f0f8b2ba7 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -468,7 +468,7 @@ static void do_acct_process(struct file *file) } #endif do_div(elapsed, AHZ); - ac.ac_btime = xtime.tv_sec - elapsed; + ac.ac_btime = get_seconds() - elapsed; /* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index bde1124d590..a777d376141 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -824,12 +824,14 @@ static void audit_log_execve_info(struct audit_buffer *ab, { int i; long len, ret; - const char __user *p = (const char __user *)axi->mm->arg_start; + const char __user *p; char *buf; if (axi->mm != current->mm) return; /* execve failed, no additional info */ + p = (const char __user *)axi->mm->arg_start; + for (i = 0; i < axi->argc; i++, p += len) { len = strnlen_user(p, MAX_ARG_STRLEN); /* @@ -855,7 +857,7 @@ static void audit_log_execve_info(struct audit_buffer *ab, * copied them here, and the mm hasn't been exposed to user- * space yet. */ - if (!ret) { + if (ret) { WARN_ON(1); send_sig(SIGKILL, current, 0); } diff --git a/kernel/futex.c b/kernel/futex.c index a12425051ee..3415e9ad139 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2060,8 +2060,10 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, } /* * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE. + * number of waiters to wake in 'utime' if cmd == FUTEX_WAKE_OP. */ - if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE || + cmd == FUTEX_WAKE_OP) val2 = (u32) (unsigned long) utime; return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index eb1ddebd2c0..c21ca6bfaa6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -141,11 +141,7 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) do { seq = read_seqbegin(&xtime_lock); -#ifdef CONFIG_NO_HZ - getnstimeofday(&xts); -#else - xts = xtime; -#endif + xts = current_kernel_time(); tom = wall_to_monotonic; } while (read_seqretry(&xtime_lock, seq)); diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c index d8ee241115f..6d9204f3a37 100644 --- a/kernel/irq/devres.c +++ b/kernel/irq/devres.c @@ -1,5 +1,6 @@ #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/device.h> /* * Device resource management aware IRQ request/free implementation. diff --git a/kernel/kmod.c b/kernel/kmod.c index beedbdc6460..9809cc1f33d 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -351,11 +351,11 @@ static inline void register_pm_notifier_callback(void) {} /** * call_usermodehelper_setup - prepare to call a usermode helper - * @path - path to usermode executable - * @argv - arg vector for process - * @envp - environment for process + * @path: path to usermode executable + * @argv: arg vector for process + * @envp: environment for process * - * Returns either NULL on allocation failure, or a subprocess_info + * Returns either %NULL on allocation failure, or a subprocess_info * structure. This should be passed to call_usermodehelper_exec to * exec the process and free the structure. */ diff --git a/kernel/kthread.c b/kernel/kthread.c index a404f7ee739..dcfe724300e 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -214,23 +214,15 @@ int kthread_stop(struct task_struct *k) } EXPORT_SYMBOL(kthread_stop); - -static noinline __init_refok void kthreadd_setup(void) +int kthreadd(void *unused) { struct task_struct *tsk = current; + /* Setup a clean context for our children to inherit. */ set_task_comm(tsk, "kthreadd"); - ignore_signals(tsk); - set_user_nice(tsk, -5); set_cpus_allowed(tsk, CPU_MASK_ALL); -} - -int kthreadd(void *unused) -{ - /* Setup a clean context for our children to inherit. */ - kthreadd_setup(); current->flags |= PF_NOFREEZE; diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index 9f17af4a249..c851b2dcc68 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c @@ -346,7 +346,7 @@ static const struct file_operations proc_lockdep_stats_operations = { .open = lockdep_stats_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; #ifdef CONFIG_LOCK_STAT diff --git a/kernel/params.c b/kernel/params.c index effbaaedd7f..4e57732fcfb 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -567,7 +567,12 @@ static void __init kernel_param_sysfs_setup(const char *name, kobject_set_name(&mk->kobj, name); kobject_init(&mk->kobj); ret = kobject_add(&mk->kobj); - BUG_ON(ret < 0); + if (ret) { + printk(KERN_ERR "Module '%s' failed to be added to sysfs, " + "error number %d\n", name, ret); + printk(KERN_ERR "The system will be unstable now.\n"); + return; + } param_sysfs_setup(mk, kparam, num_params, name_skip); kobject_uevent(&mk->kobj, KOBJ_ADD); } diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index c1a106d87d9..412859f8d94 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -46,7 +46,7 @@ config PM_VERBOSE config DISABLE_CONSOLE_SUSPEND bool "Keep console(s) enabled during suspend/resume (DANGEROUS)" - depends on PM_DEBUG + depends on PM_DEBUG && PM_SLEEP default n ---help--- This option turns off the console suspend mechanism that prevents @@ -57,7 +57,7 @@ config DISABLE_CONSOLE_SUSPEND config PM_TRACE bool "Suspend/resume event tracing" - depends on PM_DEBUG && X86 && EXPERIMENTAL + depends on PM_DEBUG && X86 && PM_SLEEP && EXPERIMENTAL default n ---help--- This enables some cheesy code to save the last PM event point in the @@ -72,9 +72,37 @@ config PM_TRACE CAUTION: this option will cause your machine's real-time clock to be set to an invalid time after a resume. -config SOFTWARE_SUSPEND - bool "Software Suspend (Hibernation)" - depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) +config SUSPEND_SMP_POSSIBLE + bool + depends on (X86 && !X86_VOYAGER) || (PPC64 && (PPC_PSERIES || PPC_PMAC)) + depends on SMP + default y + +config SUSPEND_SMP + bool + depends on SUSPEND_SMP_POSSIBLE && PM_SLEEP + select HOTPLUG_CPU + default y + +config PM_SLEEP + bool + depends on SUSPEND || HIBERNATION + default y + +config SUSPEND + bool "Suspend to RAM and standby" + depends on PM + depends on !SMP || SUSPEND_SMP_POSSIBLE + default y + ---help--- + Allow the system to enter sleep states in which main memory is + powered and thus its contents are preserved, such as the + suspend-to-RAM state (i.e. the ACPI S3 state). + +config HIBERNATION + bool "Hibernation (aka 'suspend to disk')" + depends on PM && SWAP + depends on ((X86 || PPC64_SWSUSP || FRV || PPC32) && !SMP) || SUSPEND_SMP_POSSIBLE ---help--- Enable the suspend to disk (STD) functionality, which is usually called "hibernation" in user interfaces. STD checkpoints the @@ -112,7 +140,7 @@ config SOFTWARE_SUSPEND config PM_STD_PARTITION string "Default resume partition" - depends on SOFTWARE_SUSPEND + depends on HIBERNATION default "" ---help--- The default resume partition is the partition that the suspend- @@ -132,11 +160,6 @@ config PM_STD_PARTITION suspended image to. It will simply pick the first available swap device. -config SUSPEND_SMP - bool - depends on HOTPLUG_CPU && (X86 || PPC64) && PM - default y - config APM_EMULATION tristate "Advanced Power Management Emulation" depends on PM && SYS_SUPPORTS_APM_EMULATION diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 38725f526af..f7dfff28ecd 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -3,8 +3,9 @@ ifeq ($(CONFIG_PM_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif -obj-y := main.o process.o console.o +obj-y := main.o obj-$(CONFIG_PM_LEGACY) += pm.o -obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o +obj-$(CONFIG_PM_SLEEP) += process.o console.o +obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 324ac0188ce..eb72255b5c8 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -216,6 +216,7 @@ int hibernation_platform_enter(void) * sleep state after all */ error = hibernation_ops->prepare(); + sysdev_shutdown(); if (!error) error = hibernation_ops->enter(); } else { diff --git a/kernel/power/main.c b/kernel/power/main.c index 32147b57c3b..350b485b3b6 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -25,11 +25,13 @@ BLOCKING_NOTIFIER_HEAD(pm_chain_head); -/*This is just an arbitrary number */ -#define FREE_PAGE_NUMBER (100) - DEFINE_MUTEX(pm_mutex); +#ifdef CONFIG_SUSPEND + +/* This is just an arbitrary number */ +#define FREE_PAGE_NUMBER (100) + struct pm_ops *pm_ops; /** @@ -269,6 +271,8 @@ int pm_suspend(suspend_state_t state) EXPORT_SYMBOL(pm_suspend); +#endif /* CONFIG_SUSPEND */ + decl_subsys(power,NULL,NULL); @@ -285,14 +289,16 @@ decl_subsys(power,NULL,NULL); static ssize_t state_show(struct kset *kset, char *buf) { + char *s = buf; +#ifdef CONFIG_SUSPEND int i; - char * s = buf; for (i = 0; i < PM_SUSPEND_MAX; i++) { if (pm_states[i] && valid_state(i)) s += sprintf(s,"%s ", pm_states[i]); } -#ifdef CONFIG_SOFTWARE_SUSPEND +#endif +#ifdef CONFIG_HIBERNATION s += sprintf(s, "%s\n", "disk"); #else if (s != buf) @@ -304,11 +310,13 @@ static ssize_t state_show(struct kset *kset, char *buf) static ssize_t state_store(struct kset *kset, const char *buf, size_t n) { +#ifdef CONFIG_SUSPEND suspend_state_t state = PM_SUSPEND_STANDBY; const char * const *s; +#endif char *p; - int error; int len; + int error = -EINVAL; p = memchr(buf, '\n', n); len = p ? p - buf : n; @@ -316,17 +324,19 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) /* First, check if we are requested to hibernate */ if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); - return error ? error : n; + goto Exit; } +#ifdef CONFIG_SUSPEND for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } if (state < PM_SUSPEND_MAX && *s) error = enter_state(state); - else - error = -EINVAL; +#endif + + Exit: return error ? error : n; } diff --git a/kernel/power/power.h b/kernel/power/power.h index 5f24c786f8e..95fbf2dd3fe 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -13,7 +13,7 @@ struct swsusp_info { -#ifdef CONFIG_SOFTWARE_SUSPEND +#ifdef CONFIG_HIBERNATION /* * Keep some memory free so that I/O operations can succeed without paging * [Might this be more than 4 MB?] @@ -176,9 +176,17 @@ struct timeval; extern void swsusp_show_speed(struct timeval *, struct timeval *, unsigned int, char *); +#ifdef CONFIG_SUSPEND /* kernel/power/main.c */ -extern int suspend_enter(suspend_state_t state); extern int suspend_devices_and_enter(suspend_state_t state); +#else /* !CONFIG_SUSPEND */ +static inline int suspend_devices_and_enter(suspend_state_t state) +{ + return -ENOSYS; +} +#endif /* !CONFIG_SUSPEND */ + +/* kernel/power/common.c */ extern struct blocking_notifier_head pm_chain_head; static inline int pm_notifier_call_chain(unsigned long val) diff --git a/kernel/relay.c b/kernel/relay.c index 510fbbd7b50..ad855017bc5 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -1,7 +1,7 @@ /* * Public API and common code for kernel->userspace relay file support. * - * See Documentation/filesystems/relayfs.txt for an overview of relayfs. + * See Documentation/filesystems/relay.txt for an overview. * * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) @@ -426,6 +426,7 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu) free_buf: relay_destroy_buf(buf); + buf = NULL; free_name: kfree(tmpname); end: diff --git a/kernel/sched.c b/kernel/sched.c index 93cf241cfbe..238a76957e8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -53,6 +53,7 @@ #include <linux/percpu.h> #include <linux/kthread.h> #include <linux/seq_file.h> +#include <linux/sysctl.h> #include <linux/syscalls.h> #include <linux/times.h> #include <linux/tsacct_kern.h> @@ -263,8 +264,6 @@ struct rq { unsigned int clock_warps, clock_overflows; unsigned int clock_unstable_events; - struct sched_class *load_balance_class; - atomic_t nr_iowait; #ifdef CONFIG_SMP @@ -385,13 +384,12 @@ static inline unsigned long long rq_clock(struct rq *rq) */ unsigned long long cpu_clock(int cpu) { - struct rq *rq = cpu_rq(cpu); unsigned long long now; unsigned long flags; - spin_lock_irqsave(&rq->lock, flags); - now = rq_clock(rq); - spin_unlock_irqrestore(&rq->lock, flags); + local_irq_save(flags); + now = rq_clock(cpu_rq(cpu)); + local_irq_restore(flags); return now; } @@ -1592,6 +1590,10 @@ static void __sched_fork(struct task_struct *p) INIT_LIST_HEAD(&p->run_list); p->se.on_rq = 0; +#ifdef CONFIG_PREEMPT_NOTIFIERS + INIT_HLIST_HEAD(&p->preempt_notifiers); +#endif + /* * We mark the process as running here, but have not actually * inserted it onto the runqueue yet. This guarantees that @@ -1673,9 +1675,68 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags) task_rq_unlock(rq, &flags); } +#ifdef CONFIG_PREEMPT_NOTIFIERS + +/** + * preempt_notifier_register - tell me when current is being being preempted & rescheduled + * @notifier: notifier struct to register + */ +void preempt_notifier_register(struct preempt_notifier *notifier) +{ + hlist_add_head(¬ifier->link, ¤t->preempt_notifiers); +} +EXPORT_SYMBOL_GPL(preempt_notifier_register); + +/** + * preempt_notifier_unregister - no longer interested in preemption notifications + * @notifier: notifier struct to unregister + * + * This is safe to call from within a preemption notifier. + */ +void preempt_notifier_unregister(struct preempt_notifier *notifier) +{ + hlist_del(¬ifier->link); +} +EXPORT_SYMBOL_GPL(preempt_notifier_unregister); + +static void fire_sched_in_preempt_notifiers(struct task_struct *curr) +{ + struct preempt_notifier *notifier; + struct hlist_node *node; + + hlist_for_each_entry(notifier, node, &curr->preempt_notifiers, link) + notifier->ops->sched_in(notifier, raw_smp_processor_id()); +} + +static void +fire_sched_out_preempt_notifiers(struct task_struct *curr, + struct task_struct *next) +{ + struct preempt_notifier *notifier; + struct hlist_node *node; + + hlist_for_each_entry(notifier, node, &curr->preempt_notifiers, link) + notifier->ops->sched_out(notifier, next); +} + +#else + +static void fire_sched_in_preempt_notifiers(struct task_struct *curr) +{ +} + +static void +fire_sched_out_preempt_notifiers(struct task_struct *curr, + struct task_struct *next) +{ +} + +#endif + /** * prepare_task_switch - prepare to switch tasks * @rq: the runqueue preparing to switch + * @prev: the current task that is being switched out * @next: the task we are going to switch to. * * This is called with the rq lock held and interrupts off. It must @@ -1685,8 +1746,11 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags) * prepare_task_switch sets up locking and calls architecture specific * hooks. */ -static inline void prepare_task_switch(struct rq *rq, struct task_struct *next) +static inline void +prepare_task_switch(struct rq *rq, struct task_struct *prev, + struct task_struct *next) { + fire_sched_out_preempt_notifiers(prev, next); prepare_lock_switch(rq, next); prepare_arch_switch(next); } @@ -1728,6 +1792,7 @@ static inline void finish_task_switch(struct rq *rq, struct task_struct *prev) prev_state = prev->state; finish_arch_switch(prev); finish_lock_switch(rq, prev); + fire_sched_in_preempt_notifiers(current); if (mm) mmdrop(mm); if (unlikely(prev_state == TASK_DEAD)) { @@ -1768,7 +1833,7 @@ context_switch(struct rq *rq, struct task_struct *prev, { struct mm_struct *mm, *oldmm; - prepare_task_switch(rq, next); + prepare_task_switch(rq, prev, next); mm = next->mm; oldmm = prev->active_mm; /* @@ -5140,10 +5205,129 @@ static void migrate_dead_tasks(unsigned int dead_cpu) if (!next) break; migrate_dead(dead_cpu, next); + } } #endif /* CONFIG_HOTPLUG_CPU */ +#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) + +static struct ctl_table sd_ctl_dir[] = { + {CTL_UNNUMBERED, "sched_domain", NULL, 0, 0755, NULL, }, + {0,}, +}; + +static struct ctl_table sd_ctl_root[] = { + {CTL_UNNUMBERED, "kernel", NULL, 0, 0755, sd_ctl_dir, }, + {0,}, +}; + +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 = sd_alloc_ctl_entry(14); + + 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_idx", &sd->busy_idx, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[3], 4, "idle_idx", &sd->idle_idx, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[4], 5, "newidle_idx", &sd->newidle_idx, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[5], 6, "wake_idx", &sd->wake_idx, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[6], 7, "forkexec_idx", &sd->forkexec_idx, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[7], 8, "busy_factor", &sd->busy_factor, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[8], 9, "imbalance_pct", &sd->imbalance_pct, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[9], 10, "cache_hot_time", &sd->cache_hot_time, + sizeof(long long), 0644, proc_doulongvec_minmax); + set_table_entry(&table[10], 11, "cache_nice_tries", + &sd->cache_nice_tries, + sizeof(int), 0644, proc_dointvec_minmax); + set_table_entry(&table[12], 13, "flags", &sd->flags, + sizeof(int), 0644, proc_dointvec_minmax); + + return table; +} + +static ctl_table *sd_alloc_ctl_cpu_table(int cpu) +{ + struct ctl_table *entry, *table; + struct sched_domain *sd; + int domain_num = 0, i; + 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) { + snprintf(buf, 32, "domain%d", i); + entry->ctl_name = i + 1; + entry->procname = kstrdup(buf, GFP_KERNEL); + entry->mode = 0755; + entry->child = sd_alloc_ctl_domain_table(sd); + entry++; + i++; + } + return table; +} + +static struct ctl_table_header *sd_sysctl_header; +static void init_sched_domain_sysctl(void) +{ + int i, cpu_num = num_online_cpus(); + struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); + char buf[32]; + + sd_ctl_dir[0].child = entry; + + for (i = 0; i < cpu_num; i++, entry++) { + snprintf(buf, 32, "cpu%d", i); + entry->ctl_name = i + 1; + entry->procname = kstrdup(buf, GFP_KERNEL); + entry->mode = 0755; + entry->child = sd_alloc_ctl_cpu_table(i); + } + sd_sysctl_header = register_sysctl_table(sd_ctl_root); +} +#else +static void init_sched_domain_sysctl(void) +{ +} +#endif + /* * migration_call - callback that gets triggered when a CPU is added. * Here we can start up the necessary migration thread for the new CPU. @@ -6249,6 +6433,8 @@ void __init sched_init_smp(void) /* XXX: Theoretical race here - CPU may be hotplugged now */ hotcpu_notifier(update_sched_domains, 0); + init_sched_domain_sysctl(); + /* Move init over to a non-isolated CPU */ if (set_cpus_allowed(current, non_isolated_cpus) < 0) BUG(); @@ -6335,6 +6521,10 @@ void __init sched_init(void) set_load_weight(&init_task); +#ifdef CONFIG_PREEMPT_NOTIFIERS + INIT_HLIST_HEAD(&init_task.preempt_notifiers); +#endif + #ifdef CONFIG_SMP nr_cpu_ids = highest_cpu + 1; open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL); diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 29f2c21e7da..0eca442b779 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -186,7 +186,7 @@ static int sched_debug_show(struct seq_file *m, void *v) return 0; } -void sysrq_sched_debug_show(void) +static void sysrq_sched_debug_show(void) { sched_debug_show(NULL, NULL); } @@ -200,7 +200,7 @@ static struct file_operations sched_debug_fops = { .open = sched_debug_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; static int __init init_sched_debug_procfs(void) diff --git a/kernel/sys.c b/kernel/sys.c index 08562f41976..449b81b98b3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -804,6 +804,7 @@ static void kernel_restart_prepare(char *cmd) blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; device_shutdown(); + sysdev_shutdown(); } /** @@ -860,6 +861,7 @@ void kernel_shutdown_prepare(enum system_states state) void kernel_halt(void) { kernel_shutdown_prepare(SYSTEM_HALT); + sysdev_shutdown(); printk(KERN_EMERG "System halted.\n"); machine_halt(); } @@ -876,6 +878,7 @@ void kernel_power_off(void) kernel_shutdown_prepare(SYSTEM_POWER_OFF); if (pm_power_off_prepare) pm_power_off_prepare(); + sysdev_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); } @@ -951,7 +954,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user unlock_kernel(); return -EINVAL; -#ifdef CONFIG_SOFTWARE_SUSPEND +#ifdef CONFIG_HIBERNATION case LINUX_REBOOT_CMD_SW_SUSPEND: { int ret = hibernate(); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ddebf3f2aff..79c891e6266 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -689,7 +689,7 @@ static ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif -#ifdef CONFIG_ACPI_SLEEP +#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) { .ctl_name = KERN_ACPI_VIDEO_FLAGS, .procname = "acpi_video_flags", diff --git a/kernel/time.c b/kernel/time.c index 5b81da08bbd..2289a8d6831 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -215,22 +215,6 @@ asmlinkage long sys_adjtimex(struct timex __user *txc_p) return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret; } -inline struct timespec current_kernel_time(void) -{ - struct timespec now; - unsigned long seq; - - do { - seq = read_seqbegin(&xtime_lock); - - now = xtime; - } while (read_seqretry(&xtime_lock, seq)); - - return now; -} - -EXPORT_SYMBOL(current_kernel_time); - /** * current_fs_time - Return FS time * @sb: Superblock. diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 88c81026e00..acc417b5a9b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -47,10 +47,22 @@ EXPORT_SYMBOL(xtime_lock); struct timespec xtime __attribute__ ((aligned (16))); struct timespec wall_to_monotonic __attribute__ ((aligned (16))); static unsigned long total_sleep_time; /* seconds */ - EXPORT_SYMBOL(xtime); +#ifdef CONFIG_NO_HZ +static struct timespec xtime_cache __attribute__ ((aligned (16))); +static inline void update_xtime_cache(u64 nsec) +{ + xtime_cache = xtime; + timespec_add_ns(&xtime_cache, nsec); +} +#else +#define xtime_cache xtime +/* We do *not* want to evaluate the argument for this case */ +#define update_xtime_cache(n) do { } while (0) +#endif + static struct clocksource *clock; /* pointer to current clocksource */ @@ -478,6 +490,8 @@ void update_wall_time(void) xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift; clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift; + update_xtime_cache(cyc2ns(clock, offset)); + /* check to see if there is a new clocksource to use */ change_clocksource(); update_vsyscall(&xtime, clock); @@ -509,3 +523,25 @@ void monotonic_to_bootbased(struct timespec *ts) { ts->tv_sec += total_sleep_time; } + +unsigned long get_seconds(void) +{ + return xtime_cache.tv_sec; +} +EXPORT_SYMBOL(get_seconds); + + +struct timespec current_kernel_time(void) +{ + struct timespec now; + unsigned long seq; + + do { + seq = read_seqbegin(&xtime_lock); + + now = xtime_cache; + } while (read_seqretry(&xtime_lock, seq)); + + return now; +} +EXPORT_SYMBOL(current_kernel_time); diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index e5edc3a22a0..fdb2e03d4fe 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -267,7 +267,7 @@ static struct file_operations timer_list_fops = { .open = timer_list_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; static int __init init_timer_list_procfs(void) diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index 8ed62fda16c..3c38fb5eae1 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -399,7 +399,7 @@ static struct file_operations tstats_fops = { .read = seq_read, .write = tstats_write, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; void __init init_timer_stats(void) diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 658f638c402..c122131a122 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -39,7 +39,7 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) ac_etime = timespec_to_ns(&ts); do_div(ac_etime, NSEC_PER_USEC); stats->ac_etime = ac_etime; - stats->ac_btime = xtime.tv_sec - ts.tv_sec; + stats->ac_btime = get_seconds() - ts.tv_sec; if (thread_group_leader(tsk)) { stats->ac_exitcode = tsk->exit_code; if (tsk->flags & PF_FORKNOEXEC) |