Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Mar 2010 22:43:01 +0000 (14:43 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Mar 2010 22:43:01 +0000 (14:43 -0800)
* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  locking: Make sparse work with inline spinlocks and rwlocks
  x86/mce: Fix RCU lockdep splats
  rcu: Increase RCU CPU stall timeouts if PROVE_RCU
  ftrace: Replace read_barrier_depends() with rcu_dereference_raw()
  rcu: Suppress RCU lockdep warnings during early boot
  rcu, ftrace: Fix RCU lockdep splat in ftrace_perf_buf_prepare()
  rcu: Suppress __mpol_dup() false positive from RCU lockdep
  rcu: Make rcu_read_lock_sched_held() handle !PREEMPT
  rcu: Add control variables to lockdep_rcu_dereference() diagnostics
  rcu, cgroup: Relax the check in task_subsys_state() as early boot is now handled by lockdep-RCU
  rcu: Use wrapper function instead of exporting tasklist_lock
  sched, rcu: Fix rcu_dereference() for RCU-lockdep
  rcu: Make task_subsys_state() RCU-lockdep checks handle boot-time use
  rcu: Fix holdoff for accelerated GPs for last non-dynticked CPU
  x86/gart: Unexport gart_iommu_aperture

Fix trivial conflicts in kernel/trace/ftrace.c

18 files changed:
arch/x86/kernel/aperture_64.c
arch/x86/kernel/cpu/mcheck/mce.c
include/linux/cred.h
include/linux/rcupdate.h
include/linux/rwlock.h
include/linux/sched.h
include/linux/spinlock.h
include/trace/ftrace.h
kernel/exit.c
kernel/fork.c
kernel/lockdep.c
kernel/pid.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/sched_fair.c
kernel/trace/ftrace.c
kernel/trace/trace_event_profile.c
mm/mempolicy.c

index f147a95fd84a17646892072e0e929a0fcb1b28f1..3704997e8b2573bda630720f4c47bd4a7ec3b8c5 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/x86_init.h>
 
 int gart_iommu_aperture;
-EXPORT_SYMBOL_GPL(gart_iommu_aperture);
 int gart_iommu_aperture_disabled __initdata;
 int gart_iommu_aperture_allowed __initdata;
 
index 28cba46bf32c5221afcfb2115237750d4da56dec..bd58de4d7a29e451616df150ba59256e9619bee7 100644 (file)
 
 #include "mce-internal.h"
 
+#define rcu_dereference_check_mce(p) \
+       rcu_dereference_check((p), \
+                             rcu_read_lock_sched_held() || \
+                             lockdep_is_held(&mce_read_mutex))
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
 
@@ -158,7 +163,7 @@ void mce_log(struct mce *mce)
        mce->finished = 0;
        wmb();
        for (;;) {
-               entry = rcu_dereference(mcelog.next);
+               entry = rcu_dereference_check_mce(mcelog.next);
                for (;;) {
                        /*
                         * When the buffer fills up discard new entries.
@@ -1500,7 +1505,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
                return -ENOMEM;
 
        mutex_lock(&mce_read_mutex);
-       next = rcu_dereference(mcelog.next);
+       next = rcu_dereference_check_mce(mcelog.next);
 
        /* Only supports full reads right now */
        if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
@@ -1565,7 +1570,7 @@ timeout:
 static unsigned int mce_poll(struct file *file, poll_table *wait)
 {
        poll_wait(file, &mce_wait, wait);
-       if (rcu_dereference(mcelog.next))
+       if (rcu_dereference_check_mce(mcelog.next))
                return POLLIN | POLLRDNORM;
        return 0;
 }
index 4db09f89b637539e3d3e76bdc8565d51c0f11a7b..52507c3e1387581b0e33b6435b26642bdb722d08 100644 (file)
@@ -280,7 +280,7 @@ static inline void put_cred(const struct cred *_cred)
  * task or by holding tasklist_lock to prevent it from being unlinked.
  */
 #define __task_cred(task) \
-       ((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_is_held(&tasklist_lock))))
+       ((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_tasklist_lock_is_held())))
 
 /**
  * get_task_cred - Get another task's objective credentials
index a005cac5e3024aa61eca92a76aa7d1473d7c7df7..3024050c82a12610222a1b5e7d1c40d44e339b5a 100644 (file)
@@ -101,6 +101,11 @@ extern struct lockdep_map rcu_sched_lock_map;
 # define rcu_read_release_sched() \
                lock_release(&rcu_sched_lock_map, 1, _THIS_IP_)
 
+static inline int debug_lockdep_rcu_enabled(void)
+{
+       return likely(rcu_scheduler_active && debug_locks);
+}
+
 /**
  * rcu_read_lock_held - might we be in RCU read-side critical section?
  *
@@ -108,12 +113,14 @@ extern struct lockdep_map rcu_sched_lock_map;
  * an RCU read-side critical section.  In absence of CONFIG_PROVE_LOCKING,
  * this assumes we are in an RCU read-side critical section unless it can
  * prove otherwise.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
 static inline int rcu_read_lock_held(void)
 {
-       if (debug_locks)
-               return lock_is_held(&rcu_lock_map);
-       return 1;
+       if (!debug_lockdep_rcu_enabled())
+               return 1;
+       return lock_is_held(&rcu_lock_map);
 }
 
 /**
@@ -123,12 +130,14 @@ static inline int rcu_read_lock_held(void)
  * an RCU-bh read-side critical section.  In absence of CONFIG_PROVE_LOCKING,
  * this assumes we are in an RCU-bh read-side critical section unless it can
  * prove otherwise.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
 static inline int rcu_read_lock_bh_held(void)
 {
-       if (debug_locks)
-               return lock_is_held(&rcu_bh_lock_map);
-       return 1;
+       if (!debug_lockdep_rcu_enabled())
+               return 1;
+       return lock_is_held(&rcu_bh_lock_map);
 }
 
 /**
@@ -139,15 +148,26 @@ static inline int rcu_read_lock_bh_held(void)
  * this assumes we are in an RCU-sched read-side critical section unless it
  * can prove otherwise.  Note that disabling of preemption (including
  * disabling irqs) counts as an RCU-sched read-side critical section.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
+#ifdef CONFIG_PREEMPT
 static inline int rcu_read_lock_sched_held(void)
 {
        int lockdep_opinion = 0;
 
+       if (!debug_lockdep_rcu_enabled())
+               return 1;
        if (debug_locks)
                lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
-       return lockdep_opinion || preempt_count() != 0 || !rcu_scheduler_active;
+       return lockdep_opinion || preempt_count() != 0;
+}
+#else /* #ifdef CONFIG_PREEMPT */
+static inline int rcu_read_lock_sched_held(void)
+{
+       return 1;
 }
+#endif /* #else #ifdef CONFIG_PREEMPT */
 
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
@@ -168,10 +188,17 @@ static inline int rcu_read_lock_bh_held(void)
        return 1;
 }
 
+#ifdef CONFIG_PREEMPT
 static inline int rcu_read_lock_sched_held(void)
 {
-       return preempt_count() != 0 || !rcu_scheduler_active;
+       return !rcu_scheduler_active || preempt_count() != 0;
+}
+#else /* #ifdef CONFIG_PREEMPT */
+static inline int rcu_read_lock_sched_held(void)
+{
+       return 1;
 }
+#endif /* #else #ifdef CONFIG_PREEMPT */
 
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
@@ -188,7 +215,7 @@ static inline int rcu_read_lock_sched_held(void)
  */
 #define rcu_dereference_check(p, c) \
        ({ \
-               if (debug_locks && !(c)) \
+               if (debug_lockdep_rcu_enabled() && !(c)) \
                        lockdep_rcu_dereference(__FILE__, __LINE__); \
                rcu_dereference_raw(p); \
        })
index 71e0b00b6f2c827bbb4a712e3cbd7a83331963b1..bc2994ed66e1c0e915ab7b9dbae61a470b282e50 100644 (file)
@@ -29,25 +29,25 @@ do {                                                                \
 #endif
 
 #ifdef CONFIG_DEBUG_SPINLOCK
- extern void do_raw_read_lock(rwlock_t *lock);
+ extern void do_raw_read_lock(rwlock_t *lock) __acquires(lock);
 #define do_raw_read_lock_flags(lock, flags) do_raw_read_lock(lock)
  extern int do_raw_read_trylock(rwlock_t *lock);
- extern void do_raw_read_unlock(rwlock_t *lock);
- extern void do_raw_write_lock(rwlock_t *lock);
+ extern void do_raw_read_unlock(rwlock_t *lock) __releases(lock);
+ extern void do_raw_write_lock(rwlock_t *lock) __acquires(lock);
 #define do_raw_write_lock_flags(lock, flags) do_raw_write_lock(lock)
  extern int do_raw_write_trylock(rwlock_t *lock);
- extern void do_raw_write_unlock(rwlock_t *lock);
+ extern void do_raw_write_unlock(rwlock_t *lock) __releases(lock);
 #else
-# define do_raw_read_lock(rwlock)      arch_read_lock(&(rwlock)->raw_lock)
+# define do_raw_read_lock(rwlock)      do {__acquire(lock); arch_read_lock(&(rwlock)->raw_lock); } while (0)
 # define do_raw_read_lock_flags(lock, flags) \
-               arch_read_lock_flags(&(lock)->raw_lock, *(flags))
+               do {__acquire(lock); arch_read_lock_flags(&(lock)->raw_lock, *(flags)); } while (0)
 # define do_raw_read_trylock(rwlock)   arch_read_trylock(&(rwlock)->raw_lock)
-# define do_raw_read_unlock(rwlock)    arch_read_unlock(&(rwlock)->raw_lock)
-# define do_raw_write_lock(rwlock)     arch_write_lock(&(rwlock)->raw_lock)
+# define do_raw_read_unlock(rwlock)    do {arch_read_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
+# define do_raw_write_lock(rwlock)     do {__acquire(lock); arch_write_lock(&(rwlock)->raw_lock); } while (0)
 # define do_raw_write_lock_flags(lock, flags) \
-               arch_write_lock_flags(&(lock)->raw_lock, *(flags))
+               do {__acquire(lock); arch_write_lock_flags(&(lock)->raw_lock, *(flags)); } while (0)
 # define do_raw_write_trylock(rwlock)  arch_write_trylock(&(rwlock)->raw_lock)
-# define do_raw_write_unlock(rwlock)   arch_write_unlock(&(rwlock)->raw_lock)
+# define do_raw_write_unlock(rwlock)   do {arch_write_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
 #endif
 
 #define read_can_lock(rwlock)          arch_read_can_lock(&(rwlock)->raw_lock)
index 8d70ff802da28ac9084eb2ea23c794019cce28b2..dad7f668ebf70041f3897102a0ff13a1a456edad 100644 (file)
@@ -258,6 +258,10 @@ extern spinlock_t mmlist_lock;
 
 struct task_struct;
 
+#ifdef CONFIG_PROVE_RCU
+extern int lockdep_tasklist_lock_is_held(void);
+#endif /* #ifdef CONFIG_PROVE_RCU */
+
 extern void sched_init(void);
 extern void sched_init_smp(void);
 extern asmlinkage void schedule_tail(struct task_struct *prev);
index 86088213334a48d3a0617d59af49af1610ecb2db..89fac6a3f78b5feb7a832816fc7665cb639ce83d 100644 (file)
@@ -128,19 +128,21 @@ static inline void smp_mb__after_lock(void) { smp_mb(); }
 #define raw_spin_unlock_wait(lock)     arch_spin_unlock_wait(&(lock)->raw_lock)
 
 #ifdef CONFIG_DEBUG_SPINLOCK
- extern void do_raw_spin_lock(raw_spinlock_t *lock);
+ extern void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock);
 #define do_raw_spin_lock_flags(lock, flags) do_raw_spin_lock(lock)
  extern int do_raw_spin_trylock(raw_spinlock_t *lock);
- extern void do_raw_spin_unlock(raw_spinlock_t *lock);
+ extern void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock);
 #else
-static inline void do_raw_spin_lock(raw_spinlock_t *lock)
+static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)
 {
+       __acquire(lock);
        arch_spin_lock(&lock->raw_lock);
 }
 
 static inline void
-do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags)
+do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags) __acquires(lock)
 {
+       __acquire(lock);
        arch_spin_lock_flags(&lock->raw_lock, *flags);
 }
 
@@ -149,9 +151,10 @@ static inline int do_raw_spin_trylock(raw_spinlock_t *lock)
        return arch_spin_trylock(&(lock)->raw_lock);
 }
 
-static inline void do_raw_spin_unlock(raw_spinlock_t *lock)
+static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
 {
        arch_spin_unlock(&lock->raw_lock);
+       __release(lock);
 }
 #endif
 
index 0804cd5948035d9dd8d59084e946c1d32cad330c..601ad7744247582feeec95555464ce4b8a2bdc0d 100644 (file)
@@ -699,9 +699,9 @@ __attribute__((section("_ftrace_events"))) event_##call = {         \
  *     __cpu = smp_processor_id();
  *
  *     if (in_nmi())
- *             trace_buf = rcu_dereference(perf_trace_buf_nmi);
+ *             trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
  *     else
- *             trace_buf = rcu_dereference(perf_trace_buf);
+ *             trace_buf = rcu_dereference_sched(perf_trace_buf);
  *
  *     if (!trace_buf)
  *             goto end;
index ce1e48c2d93d3dbae4769ecc518066df383f0310..cce59cb5ee6aececf1b663d39a1de3fb15b4b426 100644 (file)
@@ -87,7 +87,7 @@ static void __exit_signal(struct task_struct *tsk)
 
        sighand = rcu_dereference_check(tsk->sighand,
                                        rcu_read_lock_held() ||
-                                       lockdep_is_held(&tasklist_lock));
+                                       lockdep_tasklist_lock_is_held());
        spin_lock(&sighand->siglock);
 
        posix_cpu_timers_exit(tsk);
index 1beb6c303c416051e357e7e22637e29bffffcacc..4799c5f0e6d089a6287b7c7742a34f37146932c1 100644 (file)
@@ -86,7 +86,14 @@ int max_threads;             /* tunable limit on nr_threads */
 DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
 __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
-EXPORT_SYMBOL_GPL(tasklist_lock);
+
+#ifdef CONFIG_PROVE_RCU
+int lockdep_tasklist_lock_is_held(void)
+{
+       return lockdep_is_held(&tasklist_lock);
+}
+EXPORT_SYMBOL_GPL(lockdep_tasklist_lock_is_held);
+#endif /* #ifdef CONFIG_PROVE_RCU */
 
 int nr_processes(void)
 {
index 0c30d0455de12e02bad459a1da7cd0641ef4d76e..681bc2e1e1871209f36cd54baf7e80b29117d479 100644 (file)
@@ -3822,6 +3822,7 @@ void lockdep_rcu_dereference(const char *file, const int line)
        printk("%s:%d invoked rcu_dereference_check() without protection!\n",
                        file, line);
        printk("\nother info that might help us debug this:\n\n");
+       printk("\nrcu_scheduler_active = %d, debug_locks = %d\n", rcu_scheduler_active, debug_locks);
        lockdep_print_held_locks(curr);
        printk("\nstack backtrace:\n");
        dump_stack();
index 86b296943e5f274c2b4965a73275661a4c6c727e..aebb30d9c233df40876afa35ef21cc5c306590a1 100644 (file)
@@ -367,7 +367,9 @@ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
        struct task_struct *result = NULL;
        if (pid) {
                struct hlist_node *first;
-               first = rcu_dereference_check(pid->tasks[type].first, rcu_read_lock_held() || lockdep_is_held(&tasklist_lock));
+               first = rcu_dereference_check(pid->tasks[type].first,
+                                             rcu_read_lock_held() ||
+                                             lockdep_tasklist_lock_is_held());
                if (first)
                        result = hlist_entry(first, struct task_struct, pids[(type)].node);
        }
index 1439eb504c22475b59e17bc4da21831bb9f7b8ca..4a525a30e08e9e08f2cb7827b1d68412901d09a5 100644 (file)
@@ -246,12 +246,21 @@ struct rcu_data {
 
 #define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ)  /* for rsp->jiffies_stall */
-#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ)  /* for rsp->jiffies_stall */
-#define RCU_STALL_RAT_DELAY            2         /* Allow other CPUs time */
-                                                 /*  to take at least one */
-                                                 /*  scheduling clock irq */
-                                                 /*  before ratting on them. */
+
+#ifdef CONFIG_PROVE_RCU
+#define RCU_STALL_DELAY_DELTA         (5 * HZ)
+#else
+#define RCU_STALL_DELAY_DELTA         0
+#endif
+
+#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ + RCU_STALL_DELAY_DELTA)
+                                               /* for rsp->jiffies_stall */
+#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ + RCU_STALL_DELAY_DELTA)
+                                               /* for rsp->jiffies_stall */
+#define RCU_STALL_RAT_DELAY            2       /* Allow other CPUs time */
+                                               /*  to take at least one */
+                                               /*  scheduling clock irq */
+                                               /*  before ratting on them. */
 
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
index 464ad2cdee00a22bfbfe258853770f3bb60e3f5d..79b53bda894326838c200575c7f87e0b5f70b678 100644 (file)
@@ -1010,6 +1010,10 @@ int rcu_needs_cpu(int cpu)
        int c = 0;
        int thatcpu;
 
+       /* Check for being in the holdoff period. */
+       if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies)
+               return rcu_needs_cpu_quick_check(cpu);
+
        /* Don't bother unless we are the last non-dyntick-idle CPU. */
        for_each_cpu_not(thatcpu, nohz_cpu_mask)
                if (thatcpu != cpu) {
@@ -1041,10 +1045,8 @@ int rcu_needs_cpu(int cpu)
        }
 
        /* If RCU callbacks are still pending, RCU still needs this CPU. */
-       if (c) {
+       if (c)
                raise_softirq(RCU_SOFTIRQ);
-               per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
-       }
        return c;
 }
 
index 3e1fd96c6cf9cef8de27f7ba41dad905986f1959..5a5ea2cd924fa8494abfa21f8203f919f40ff1ca 100644 (file)
@@ -3476,7 +3476,7 @@ static void run_rebalance_domains(struct softirq_action *h)
 
 static inline int on_null_domain(int cpu)
 {
-       return !rcu_dereference(cpu_rq(cpu)->sd);
+       return !rcu_dereference_sched(cpu_rq(cpu)->sd);
 }
 
 /*
index bb53edbb5c8c7fc7a8f4a4f2db423aa1512b2a43..d9062f5cc0c01e598670d651fba80b87ccb68a57 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/ctype.h>
 #include <linux/list.h>
 #include <linux/hash.h>
+#include <linux/rcupdate.h>
 
 #include <trace/events/sched.h>
 
@@ -84,18 +85,22 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
 
+/*
+ * Traverse the ftrace_list, invoking all entries.  The reason that we
+ * can use rcu_dereference_raw() is that elements removed from this list
+ * are simply leaked, so there is no need to interact with a grace-period
+ * mechanism.  The rcu_dereference_raw() calls are needed to handle
+ * concurrent insertions into the ftrace_list.
+ *
+ * Silly Alpha and silly pointer-speculation compiler optimizations!
+ */
 static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
 {
-       struct ftrace_ops *op = ftrace_list;
-
-       /* in case someone actually ports this to alpha! */
-       read_barrier_depends();
+       struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/
 
        while (op != &ftrace_list_end) {
-               /* silly alpha */
-               read_barrier_depends();
                op->func(ip, parent_ip);
-               op = op->next;
+               op = rcu_dereference_raw(op->next); /*see above*/
        };
 }
 
@@ -150,8 +155,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
         * the ops->next pointer is valid before another CPU sees
         * the ops pointer included into the ftrace_list.
         */
-       smp_wmb();
-       ftrace_list = ops;
+       rcu_assign_pointer(ftrace_list, ops);
 
        if (ftrace_enabled) {
                ftrace_func_t func;
index f0d693005075c938a7163e38f67171587814f0cc..c1cc3ab633de6cab14b87463d4f70669feb8904b 100644 (file)
@@ -138,9 +138,9 @@ __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type,
        cpu = smp_processor_id();
 
        if (in_nmi())
-               trace_buf = rcu_dereference(perf_trace_buf_nmi);
+               trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
        else
-               trace_buf = rcu_dereference(perf_trace_buf);
+               trace_buf = rcu_dereference_sched(perf_trace_buf);
 
        if (!trace_buf)
                goto err;
index bda230e52acd94b0475640c4fd6b97895c6d3b9a..643f66e101878015cbea8b3dc9ac1eb948d2d702 100644 (file)
@@ -1756,10 +1756,12 @@ struct mempolicy *__mpol_dup(struct mempolicy *old)
 
        if (!new)
                return ERR_PTR(-ENOMEM);
+       rcu_read_lock();
        if (current_cpuset_is_being_rebound()) {
                nodemask_t mems = cpuset_mems_allowed(current);
                mpol_rebind_policy(old, &mems);
        }
+       rcu_read_unlock();
        *new = *old;
        atomic_set(&new->refcnt, 1);
        return new;