From 26ff6ad9786abf6f40a6d3cbb89753b4fa50cb00 Mon Sep 17 00:00:00 2001 From: Srivatsa Vaddagiri Date: Fri, 16 Sep 2005 19:27:40 -0700 Subject: [PATCH] CPU hotplug breaks wake_up_new_task Fix a problem wherein a new-born task is added to a dead CPU. Signed-off-by: Srivatsa Vaddagiri Acked-by: Nick Piggin Acked-by: Shaohua Li Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/fork.c b/kernel/fork.c index 8149f360288..533ce27f4b2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1062,7 +1062,8 @@ static task_t *copy_process(unsigned long clone_flags, * parent's CPU). This avoids alot of nasty races. */ p->cpus_allowed = current->cpus_allowed; - if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed))) + if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || + !cpu_online(task_cpu(p)))) set_task_cpu(p, smp_processor_id()); /* -- cgit v1.2.3 From 2030c0fd3db3332378f95f479c286181e3920644 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Fri, 16 Sep 2005 19:28:02 -0700 Subject: [PATCH] PR_GET_DUMPABLE returns incorrect info 2.6.13 incorporated Alan Cox's patch for /proc/sys/fs/suid_dumpable (one version of this patch can be found here http://marc.theaimsgroup.com/?l=linux-kernel&m=109647550421014&w=2 ). This patch also made corresponding changes in kernel/sys.c to change the prctl() PR_SET_DUMPABLE operation so that the permitted range of 'arg2' was modified from 0..1 to 0..2. However, a corresponding change was not made for PR_GET_DUMPABLE: if the dumpable flag is non-zero, then PR_GET_DUMPABLE always returns 1, so that the caller can't determine the true setting of this flag. Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sys.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/sys.c b/kernel/sys.c index c80412be230..f723522e698 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, error = put_user(current->pdeath_signal, (int __user *)arg2); break; case PR_GET_DUMPABLE: - if (current->mm->dumpable) - error = 1; + error = current->mm->dumpable; break; case PR_SET_DUMPABLE: if (arg2 < 0 || arg2 > 2) { -- cgit v1.2.3 From 4fb3a53860cee2aaaf81186c451b7da0b95b45c1 Mon Sep 17 00:00:00 2001 From: Dipankar Sarma Date: Fri, 16 Sep 2005 19:28:13 -0700 Subject: [PATCH] files: fix preemption issues With the new fdtable locking rules, you have to protect fdtable with either ->file_lock or rcu_read_lock/unlock(). There are some places where we aren't doing either. This patch fixes those places. Signed-off-by: Dipankar Sarma Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/osf_sys.c | 7 ++++++- arch/ia64/kernel/perfmon.c | 3 ++- fs/locks.c | 3 +++ fs/proc/array.c | 3 +++ kernel/exit.c | 6 ++++++ 5 files changed, 20 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0636116210d..01fe990d3e5 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, long timeout; int ret = -EINVAL; struct fdtable *fdt; + int max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, } } + rcu_read_lock(); fdt = files_fdtable(current->files); - if (n < 0 || n > fdt->max_fdset) + max_fdset = fdt->max_fdset; + rcu_read_unlock(); + if (n < 0 || n > max_fdset) goto out_nofds; /* diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index af42cda6be8..d71731ee5b6 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2218,12 +2218,13 @@ static void pfm_free_fd(int fd, struct file *file) { struct files_struct *files = current->files; - struct fdtable *fdt = files_fdtable(files); + struct fdtable *fdt; /* * there ie no fd_uninstall(), so we do it here */ spin_lock(&files->file_lock); + fdt = files_fdtable(files); rcu_assign_pointer(fdt->fd[fd], NULL); spin_unlock(&files->file_lock); diff --git a/fs/locks.c b/fs/locks.c index c2c09b4798d..f7daa5f4894 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -124,6 +124,7 @@ #include #include #include +#include #include #include @@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from) lock_kernel(); j = 0; + rcu_read_lock(); fdt = files_fdtable(files); for (;;) { unsigned long set; @@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from) set >>= 1; } } + rcu_read_unlock(); unlock_kernel(); } EXPORT_SYMBOL(steal_locks); diff --git a/fs/proc/array.c b/fs/proc/array.c index d88d518d30f..d84eecacbea 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer) p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); task_lock(p); + rcu_read_lock(); if (p->files) fdt = files_fdtable(p->files); buffer += sprintf(buffer, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); + rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); diff --git a/kernel/exit.c b/kernel/exit.c index 6d2089a1bce..ee6d8b8abef 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files) struct fdtable *fdt; j = 0; + + /* + * It is safe to dereference the fd table without RCU or + * ->file_lock because this is the last reference to the + * files structure. + */ fdt = files_fdtable(files); for (;;) { unsigned long set; -- cgit v1.2.3 From 31f6d9d628739c097964b8dbae939ea997da94a3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 21 Sep 2005 09:55:30 -0700 Subject: [PATCH] Add printk_clock() ia64's sched_clock() accesses per-cpu data which isn't set up at boot time. Hence ia64 cannot use printk timestamping, because printk() will crash in sched_clock(). So make printk() use printk_clock(), defaulting to sched_clock(), overrideable by the architecture via attribute(weak). Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/printk.c b/kernel/printk.c index a967605bc2e..4b8f0f9230a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -488,6 +488,11 @@ static int __init printk_time_setup(char *str) __setup("time", printk_time_setup); +__attribute__((weak)) unsigned long long printk_clock(void) +{ + return sched_clock(); +} + /* * This is printk. It can be called from any context. We want it to work. * @@ -565,7 +570,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) loglev_char = default_message_loglevel + '0'; } - t = sched_clock(); + t = printk_clock(); nanosec_rem = do_div(t, 1000000000); tlen = sprintf(tbuf, "<%c>[%5lu.%06lu] ", -- cgit v1.2.3