Files
scst/scst/kernel/nolockdep-3.5.patch
Vladislav Bolkhovitin 6c95c681ac scst: avoid false lockdep complaints about recursive locking
In some cases SCST needs to take multiple locks recursivly, e.g. to lock
all tgt_devs in a session. For this case SCST takes those locks in their
current sort order, e.g. by LUN for tgt_devs, then releases in the
opposite order. Unfortunately, lockdep complains on such actions as
recursive locking, then disables itself. The disabling itself action is
the most unpleasant one leading to lockdep being useless after this point.

Unfortunately, nested locking annotations can't help, because after
free, then alloc again, or after LUN change (in case of tgt_devs) order
of locks can change.

So, this patch implements a way to annotate some lock and unlock actions
as "no lockdep", so lockdep will not track them. It contains related
kernel patches for some kernels.

This is a debug aid only useful only with lockdep enabled kernels.



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7065 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2016-12-20 05:47:15 +00:00

117 lines
3.3 KiB
Diff

=== modified file 'include/linux/lockdep.h'
--- old/include/linux/lockdep.h 2012-08-08 02:57:29 +0000
+++ new/include/linux/lockdep.h 2012-08-28 21:26:26 +0000
@@ -355,7 +355,7 @@ extern void lockdep_set_current_reclaim_
extern void lockdep_clear_current_reclaim_state(void);
extern void lockdep_trace_alloc(gfp_t mask);
-# define INIT_LOCKDEP .lockdep_recursion = 0, .lockdep_reclaim_gfp = 0,
+# define INIT_LOCKDEP .lockdep_recursion = 0, .lockdep_reclaim_gfp = 0, .nolockdep_call = 0,
#define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0)
=== modified file 'include/linux/sched.h'
--- old/include/linux/sched.h 2012-08-08 02:57:29 +0000
+++ new/include/linux/sched.h 2012-08-28 22:49:36 +0000
@@ -1454,6 +1454,9 @@ struct task_struct {
# define MAX_LOCK_DEPTH 48UL
u64 curr_chain_key;
int lockdep_depth;
+# define NOLOCKDEP_SUPPORTED 1
+ unsigned int nolockdep_call:1;
+ unsigned int nolockdep_call_irq_saved:1;
unsigned int lockdep_recursion;
struct held_lock held_locks[MAX_LOCK_DEPTH];
gfp_t lockdep_reclaim_gfp;
=== modified file 'kernel/lockdep.c'
--- old/kernel/lockdep.c 2012-08-08 02:57:29 +0000
+++ new/kernel/lockdep.c 2012-08-28 23:02:47 +0000
@@ -3547,9 +3547,11 @@ void lock_acquire(struct lockdep_map *lo
if (unlikely(current->lockdep_recursion))
return;
+ if (unlikely(current->nolockdep_call))
+ return;
+
raw_local_irq_save(flags);
check_flags(flags);
-
current->lockdep_recursion = 1;
trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip);
__lock_acquire(lock, subclass, trylock, read, check,
@@ -3567,6 +3569,9 @@ void lock_release(struct lockdep_map *lo
if (unlikely(current->lockdep_recursion))
return;
+ if (unlikely(current->nolockdep_call))
+ return;
+
raw_local_irq_save(flags);
check_flags(flags);
current->lockdep_recursion = 1;
@@ -3760,6 +3765,9 @@ void lock_contended(struct lockdep_map *
if (unlikely(current->lockdep_recursion))
return;
+ if (unlikely(current->nolockdep_call))
+ return;
+
raw_local_irq_save(flags);
check_flags(flags);
current->lockdep_recursion = 1;
@@ -3780,6 +3788,9 @@ void lock_acquired(struct lockdep_map *l
if (unlikely(current->lockdep_recursion))
return;
+ if (unlikely(current->nolockdep_call))
+ return;
+
raw_local_irq_save(flags);
check_flags(flags);
current->lockdep_recursion = 1;
=== modified file 'kernel/softirq.c'
--- old/kernel/softirq.c 2012-08-08 02:57:29 +0000
+++ new/kernel/softirq.c 2012-08-28 23:23:07 +0000
@@ -296,6 +296,18 @@ void irq_enter(void)
{
int cpu = smp_processor_id();
+#ifdef CONFIG_LOCKDEP
+ if (unlikely(current->nolockdep_call)) {
+ unsigned long flags;
+ local_irq_save(flags);
+ if (current->nolockdep_call) {
+ current->nolockdep_call_irq_saved = 1;
+ current->nolockdep_call = 0;
+ }
+ local_irq_restore(flags);
+ }
+#endif
+
rcu_irq_enter();
if (is_idle_task(current) && !in_interrupt()) {
/*
@@ -344,6 +356,18 @@ void irq_exit(void)
#endif
rcu_irq_exit();
sched_preempt_enable_no_resched();
+
+#ifdef CONFIG_LOCKDEP
+ if (unlikely(current->nolockdep_call_irq_saved)) {
+ unsigned long flags;
+ local_irq_save(flags);
+ if (current->nolockdep_call_irq_saved) {
+ current->nolockdep_call_irq_saved = 0;
+ current->nolockdep_call = 1;
+ }
+ local_irq_restore(flags);
+ }
+#endif
}
/*