]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
rcu: Provide better diagnostics for blocking in RCU callback functions
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 28 Oct 2013 16:22:24 +0000 (09:22 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 9 Dec 2013 23:12:39 +0000 (15:12 -0800)
Currently blocking in an RCU callback function will result in
"scheduling while atomic", which could be triggered for any number
of reasons.  To aid debugging, this patch introduces a rcu_callback_map
that is used to tie the inappropriate voluntary context switch back
to the fact that the function is being invoked from within a callback.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
include/linux/rcupdate.h
kernel/rcu/rcu.h
kernel/rcu/update.c

index 39cbb889e20da020c8936aae8124601b718e05a5..a94a5805d378bae7163e42259ab20e5414f62830 100644 (file)
@@ -325,6 +325,7 @@ static inline void rcu_lock_release(struct lockdep_map *map)
 extern struct lockdep_map rcu_lock_map;
 extern struct lockdep_map rcu_bh_lock_map;
 extern struct lockdep_map rcu_sched_lock_map;
+extern struct lockdep_map rcu_callback_map;
 extern int debug_lockdep_rcu_enabled(void);
 
 /**
index 7859a0a3951eae09e50a11df267213af0f6bace4..a8f981a2d1109309c5e06fb79fcd5a047f11ed86 100644 (file)
@@ -102,13 +102,16 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
 {
        unsigned long offset = (unsigned long)head->func;
 
+       rcu_lock_acquire(&rcu_callback_map);
        if (__is_kfree_rcu_offset(offset)) {
                RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset));
                kfree((void *)head - offset);
+               rcu_lock_release(&rcu_callback_map);
                return 1;
        } else {
                RCU_TRACE(trace_rcu_invoke_callback(rn, head));
                head->func(head);
+               rcu_lock_release(&rcu_callback_map);
                return 0;
        }
 }
index 6cb3dff89e2b73d214c9fd67d70a2abd43b64f17..802365ccd591826a60e08009a3927c9bed8c69bf 100644 (file)
@@ -128,6 +128,11 @@ struct lockdep_map rcu_sched_lock_map =
        STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
 EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
 
+static struct lock_class_key rcu_callback_key;
+struct lockdep_map rcu_callback_map =
+       STATIC_LOCKDEP_MAP_INIT("rcu_callback", &rcu_callback_key);
+EXPORT_SYMBOL_GPL(rcu_callback_map);
+
 int notrace debug_lockdep_rcu_enabled(void)
 {
        return rcu_scheduler_active && debug_locks &&