Skip to contentSkip to conversation

core/printk changes for v3.1

GIT PULL Ingo Molnar 6 participants 10 messages Jul 22, 2011 – Aug 4, 2011

lore
Share & tools
lore
#0 lore raw

Linus,

Please pull the latest core-printk-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git core-printk-for-linus

( These are just the tested-safe commits - the ones that were causing
problems are not included. )

Thanks,

Ingo

------------------>
Peter Zijlstra (3):
printk: Release console_sem after logbuf_lock
printk: Fix console_sem vs logbuf_lock unlock race
lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion

 kernel/lockdep.c |   30 ++++++++++++++++++++----------
 kernel/printk.c  |   24 +++++++++++++++++++++---
 2 files changed, 41 insertions(+), 13 deletions(-)
kernel/lockdep.c +20 -10
index 63437d0..81968a0 100644
@@ -2478,15 +2478,10 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
 /*
  * Hardirqs will be enabled:
  */
-void trace_hardirqs_on_caller(unsigned long ip)
+static void __trace_hardirqs_on_caller(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	time_hardirqs_on(CALLER_ADDR0, ip);
-
-	if (unlikely(!debug_locks || current->lockdep_recursion))
-		return;
-
 	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
 		return;
 
@@ -2502,8 +2497,6 @@ void trace_hardirqs_on_caller(unsigned long ip)
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
-		return;
 	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
 		return;
 	/*
@@ -2525,6 +2518,21 @@ void trace_hardirqs_on_caller(unsigned long ip)
 	curr->hardirq_enable_event = ++curr->irq_events;
 	debug_atomic_inc(hardirqs_on_events);
 }
+
+void trace_hardirqs_on_caller(unsigned long ip)
+{
+	time_hardirqs_on(CALLER_ADDR0, ip);
+
+	if (unlikely(!debug_locks || current->lockdep_recursion))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+		return;
+
+	current->lockdep_recursion = 1;
+	__trace_hardirqs_on_caller(ip);
+	current->lockdep_recursion = 0;
+}
 EXPORT_SYMBOL(trace_hardirqs_on_caller);
 
 void trace_hardirqs_on(void)
@@ -2574,7 +2582,7 @@ void trace_softirqs_on(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	if (unlikely(!debug_locks))
+	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
@@ -2585,6 +2593,7 @@ void trace_softirqs_on(unsigned long ip)
 		return;
 	}
 
+	current->lockdep_recursion = 1;
 	/*
 	 * We'll do an OFF -> ON transition:
 	 */
@@ -2599,6 +2608,7 @@ void trace_softirqs_on(unsigned long ip)
 	 */
 	if (curr->hardirqs_enabled)
 		mark_held_locks(curr, SOFTIRQ);
+	current->lockdep_recursion = 0;
 }
 
 /*
@@ -2608,7 +2618,7 @@ void trace_softirqs_off(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	if (unlikely(!debug_locks))
+	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
kernel/printk.c +21 -3
index 3518539..37dff34 100644
@@ -782,7 +782,7 @@ static inline int can_use_console(unsigned int cpu)
 static int console_trylock_for_printk(unsigned int cpu)
 	__releases(&logbuf_lock)
 {
-	int retval = 0;
+	int retval = 0, wake = 0;
 
 	if (console_trylock()) {
 		retval = 1;
@@ -795,12 +795,14 @@ static int console_trylock_for_printk(unsigned int cpu)
 		 */
 		if (!can_use_console(cpu)) {
 			console_locked = 0;
-			up(&console_sem);
+			wake = 1;
 			retval = 0;
 		}
 	}
 	printk_cpu = UINT_MAX;
 	spin_unlock(&logbuf_lock);
+	if (wake)
+		up(&console_sem);
 	return retval;
 }
 static const char recursion_bug_msg [] =
@@ -1242,7 +1244,7 @@ void console_unlock(void)
 {
 	unsigned long flags;
 	unsigned _con_start, _log_end;
-	unsigned wake_klogd = 0;
+	unsigned wake_klogd = 0, retry = 0;
 
 	if (console_suspended) {
 		up(&console_sem);
@@ -1251,6 +1253,7 @@ void console_unlock(void)
 
 	console_may_schedule = 0;
 
+again:
 	for ( ; ; ) {
 		spin_lock_irqsave(&logbuf_lock, flags);
 		wake_klogd |= log_start - log_end;
@@ -1271,8 +1274,23 @@ void console_unlock(void)
 	if (unlikely(exclusive_console))
 		exclusive_console = NULL;
 
+	spin_unlock(&logbuf_lock);
+
 	up(&console_sem);
+
+	/*
+	 * Someone could have filled up the buffer again, so re-check if there's
+	 * something to flush. In case we cannot trylock the console_sem again,
+	 * there's a new owner and the console_unlock() from them will do the
+	 * flush, no worries.
+	 */
+	spin_lock(&logbuf_lock);
+	if (con_start != log_end)
+		retry = 1;
 	spin_unlock_irqrestore(&logbuf_lock, flags);
+	if (retry && console_trylock())
+		goto again;
+
 	if (wake_klogd)
 		wake_up_klogd();
 }
#1 lore raw

Hi,

Quoted 9 lines · Ingo Molnar

Linus,

Please pull the latest core-printk-for-linus git tree from:

  git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git core-printk-for-linus

( These are just the tested-safe commits - the ones that were causing problems are not included. )

Quoted 9 lines

 Thanks,

       Ingo

------------------>
Peter Zijlstra (3):

     [...]

     lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion

This commit is triggering:

WARNING: at /src/linux/linux/kernel/lockdep.c:2529
trace_hardirqs_on_caller+0x52/0x79()
Hardware name: Bochs
Modules linked in:
Pid: 0, comm: swapper Not tainted 3.0.0-rc2+ #12
Call Trace:
 [<c101be35>] warn_slowpath_common+0x65/0x7a
 [<c103d976>] ? trace_hardirqs_on_caller+0x52/0x79
 [<c11fdfc4>] ? restore_all+0xf/0xf
 [<c1003254>] ? math_state_restore+0x40/0x40
 [<c101be59>] warn_slowpath_null+0xf/0x13
 [<c103d976>] trace_hardirqs_on_caller+0x52/0x79
 [<c10df760>] trace_hardirqs_on_thunk+0xc/0x10
 [<c11fdfc4>] ? restore_all+0xf/0xf
 [<c1003254>] ? math_state_restore+0x40/0x40
 [<c146a774>] ? check_bugs+0x54/0xdd
 [<c14750ab>] ? proc_root_init+0x8d/0x8f
 [<c1465680>] ? start_kernel+0x27f/0x28e
 [<c14650b0>] ? i386_start_kernel+0xb0/0xb7

in qemu.

- Arnaud

#2 lore raw
Quoted 7 lines · Arnaud Lacombe
Quoted 4 lines

Peter Zijlstra (3):
[...]
lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion

This commit is triggering:

WARNING: at /src/linux/linux/kernel/lockdep.c:2529

Not actually having reproduced the problem, does the below cure things?

---
Subject: lockdep: Fix trace_hardirqs_on_caller()
From: Peter Zijlstra <[email protected]>
Date: Tue Jul 26 13:13:44 CEST 2011

Commit dd4e5d3ac4a ("lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion") made a bit of a mess of the various checks and error conditions.

In particular it moved the check for !irqs_disabled() before the spurious enable test, resulting in some warnings.

---
 kernel/lockdep.c |   30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)
kernel/lockdep.c +16 -14
Index: linux-2.6/kernel/lockdep.c
===================================================================
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(u
 {
 	struct task_struct *curr = current;
 
-	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-		return;
-
-	if (unlikely(curr->hardirqs_enabled)) {
-		/*
-		 * Neither irq nor preemption are disabled here
-		 * so this is racy by nature but losing one hit
-		 * in a stat is not a big deal.
-		 */
-		__debug_atomic_inc(redundant_hardirqs_on);
-		return;
-	}
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-		return;
 	/*
 	 * We are going to turn hardirqs on, so set the
 	 * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned l
 	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
+	if (unlikely(current->hardirqs_enabled)) {
+		/*
+		 * Neither irq nor preemption are disabled here
+		 * so this is racy by nature but losing one hit
+		 * in a stat is not a big deal.
+		 */
+		__debug_atomic_inc(redundant_hardirqs_on);
+		return;
+	}
+
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
 		return;
 
+	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+		return;
+
 	current->lockdep_recursion = 1;
 	__trace_hardirqs_on_caller(ip);
 	current->lockdep_recursion = 0;
#3 lore raw
Quoted 10 lines · Peter Zijlstra
Quoted 7 lines
Quoted 4 lines

Peter Zijlstra (3):
[...]
lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion

This commit is triggering:

WARNING: at /src/linux/linux/kernel/lockdep.c:2529

Not actually having reproduced the problem, does the below cure things?

Hello,
Well, it's not that it happens often on my system. I'll test for several hours.

Sergey

Quoted 74 lines

---
Subject: lockdep: Fix trace_hardirqs_on_caller()
From: Peter Zijlstra <[email protected]>
Date: Tue Jul 26 13:13:44 CEST 2011

Commit dd4e5d3ac4a ("lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion") made a bit of a mess of the various checks and error conditions.

In particular it moved the check for !irqs_disabled() before the spurious enable test, resulting in some warnings.

---
 kernel/lockdep.c |   30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

Index: linux-2.6/kernel/lockdep.c
===================================================================

kernel/lockdep.c +16 -14
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(u
 {
 	struct task_struct *curr = current;
 
-	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-		return;
-
-	if (unlikely(curr->hardirqs_enabled)) {
-		/*
-		 * Neither irq nor preemption are disabled here
-		 * so this is racy by nature but losing one hit
-		 * in a stat is not a big deal.
-		 */
-		__debug_atomic_inc(redundant_hardirqs_on);
-		return;
-	}
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-		return;
 	/*
 	 * We are going to turn hardirqs on, so set the
 	 * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned l
 	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
+	if (unlikely(current->hardirqs_enabled)) {
+		/*
+		 * Neither irq nor preemption are disabled here
+		 * so this is racy by nature but losing one hit
+		 * in a stat is not a big deal.
+		 */
+		__debug_atomic_inc(redundant_hardirqs_on);
+		return;
+	}
+
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
 		return;
 
+	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+		return;
+
 	current->lockdep_recursion = 1;
 	__trace_hardirqs_on_caller(ip);
 	current->lockdep_recursion = 0;
#4 lore raw
In reply to Peter Zijlstra
Quoted 4 lines · Peter Zijlstra
Quoted 1 line
WARNING: at /src/linux/linux/kernel/lockdep.c:2529

Not actually having reproduced the problem, does the below cure things?

Able to reproduce bad_area()-cases (http://lkml.org/lkml/2011/7/25/144).
Previously:
kernel: [ 3634.499710] Call Trace:
kernel: [ 3634.499718] [<ffffffff8103e630>] warn_slowpath_common+0x7e/0x96
kernel: [ 3634.499726] [<ffffffff81474f38>] ? __bad_area_nosemaphore+0x35/0x1b9
kernel: [ 3634.499730] [<ffffffff8103e65d>] warn_slowpath_null+0x15/0x17
kernel: [ 3634.499735] [<ffffffff81072200>] trace_hardirqs_on_caller+0x6d/0x166
kernel: [ 3634.499741] [<ffffffff81072306>] trace_hardirqs_on+0xd/0xf
kernel: [ 3634.499746] [<ffffffff81474f38>] __bad_area_nosemaphore+0x35/0x1b9
kernel: [ 3634.499751] [<ffffffff81475111>] bad_area+0x45/0x4c
kernel: [ 3634.499759] [<ffffffff81482fb9>] do_page_fault+0x2da/0x48a
kernel: [ 3634.499766] [<ffffffff810ebd41>] ? do_brk+0x24e/0x2a2
kernel: [ 3634.499774] [<ffffffff812450bd>] ? trace_hardirqs_off_thunk+0x3a/0x3c
kernel: [ 3634.499780] [<ffffffff81480835>] page_fault+0x25/0x30
kernel: [ 3634.499784] ---[ end trace 642edd2b5d1b3694 ]---
kernel: [ 3634.499791] conftest[21907]: segfault at 0 ip 00007f591a6e7144 sp 00007fff03423550 error 4 in libc-2.14.so[7f591a62a000+157000]

which is not true for the patched kernel. That said, that at least bad_area() is cured for now.

Here is mine:

Best,
Sergey

Quoted 74 lines

---
Subject: lockdep: Fix trace_hardirqs_on_caller()
From: Peter Zijlstra <[email protected]>
Date: Tue Jul 26 13:13:44 CEST 2011

Commit dd4e5d3ac4a ("lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion") made a bit of a mess of the various checks and error conditions.

In particular it moved the check for !irqs_disabled() before the spurious enable test, resulting in some warnings.

---
 kernel/lockdep.c |   30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

Index: linux-2.6/kernel/lockdep.c
===================================================================

kernel/lockdep.c +16 -14
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(u
 {
 	struct task_struct *curr = current;
 
-	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-		return;
-
-	if (unlikely(curr->hardirqs_enabled)) {
-		/*
-		 * Neither irq nor preemption are disabled here
-		 * so this is racy by nature but losing one hit
-		 * in a stat is not a big deal.
-		 */
-		__debug_atomic_inc(redundant_hardirqs_on);
-		return;
-	}
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-		return;
 	/*
 	 * We are going to turn hardirqs on, so set the
 	 * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned l
 	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
+	if (unlikely(current->hardirqs_enabled)) {
+		/*
+		 * Neither irq nor preemption are disabled here
+		 * so this is racy by nature but losing one hit
+		 * in a stat is not a big deal.
+		 */
+		__debug_atomic_inc(redundant_hardirqs_on);
+		return;
+	}
+
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
 		return;
 
+	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+		return;
+
 	current->lockdep_recursion = 1;
 	__trace_hardirqs_on_caller(ip);
 	current->lockdep_recursion = 0;
Tested-by
#5 lore raw
In reply to Peter Zijlstra

Hi,

Quoted 21 lines · Peter Zijlstra
Quoted 7 lines · Arnaud Lacombe
Quoted 4 lines

Peter Zijlstra (3):
     [...]
     lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion

This commit is triggering:

WARNING: at /src/linux/linux/kernel/lockdep.c:2529

Not actually having reproduced the problem, does the below cure things?

---
Subject: lockdep: Fix trace_hardirqs_on_caller()
From: Peter Zijlstra <[email protected]>
Date: Tue Jul 26 13:13:44 CEST 2011

Commit dd4e5d3ac4a ("lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion") made a bit of a mess of the various checks and error conditions.

Quoted 7 lines

In particular it moved the check for !irqs_disabled() before the spurious enable test, resulting in some warnings.

The patch has been a bit difficult to apply[0], but the warning no longer happen once done, thanks.

- Arnaud
[0]: I still have to find an easy way to transfer patch between gmail and my tree... For now, I ruled out mutt as it mangle the patch...

Quoted 59 lines

---
 kernel/lockdep.c |   30 ++++++++++++++++--------------

 1 file changed, 16 insertions(+), 14 deletions(-)

Index: linux-2.6/kernel/lockdep.c
===================================================================

kernel/lockdep.c +16 -14
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(u
  {
        struct task_struct *curr = current;
 
-       if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-               return;
-
-       if (unlikely(curr->hardirqs_enabled)) {
-               /*
-                * Neither irq nor preemption are disabled here
-                * so this is racy by nature but losing one hit
-                * in a stat is not a big deal.
-                */
-               __debug_atomic_inc(redundant_hardirqs_on);
-               return;
-       }
        /* we'll do an OFF -> ON transition: */
        curr->hardirqs_enabled = 1;
 
-       if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-               return;
        /*
         * We are going to turn hardirqs on, so set the
         * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned l
        if (unlikely(!debug_locks || current->lockdep_recursion))
                return;
 
+       if (unlikely(current->hardirqs_enabled)) {
+               /*
+                * Neither irq nor preemption are disabled here
+                * so this is racy by nature but losing one hit
+                * in a stat is not a big deal.
+                */
+               __debug_atomic_inc(redundant_hardirqs_on);
+               return;
+       }
+
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return;
 
+       if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+               return;
+
        current->lockdep_recursion = 1;
        __trace_hardirqs_on_caller(ip);
        current->lockdep_recursion = 0;
#6 lore raw
Quoted 3 lines · Arnaud Lacombe

[0]: I still have to find an easy way to transfer patch between gmail and my tree... For now, I ruled out mutt as it mangle the patch...

The gmail web interface on the *receiving* end is easy enough, and I do it all the time: just go to the per-email menu in the upper right corner of the email, and choose "Show original". Then you just save that, and you're done.

Sadly, the gmail web interface cannot *send* patches without whitespace-mangling them. You have to send them as attachements, and there is no way to say "do this attachement inline".

Sad, sad, sad. gmail gets so many other things right, but sending patches is a big pain in the *ss for no good reason.

The gmail web client also does threading the wrong way (by subject line rather than by following references), but that's apparently what Windows people want and are used to because of how Exchange works. Or so I've been told - I've never touched that pile of crap. It's sad how it has then resulted in crud in gmail. It's not like proper threading is some kind of unheard-of feature..

Linus

#7 lore raw

Hi,

Quoted 10 lines · Linus Torvalds
Quoted 3 lines · Arnaud Lacombe

[0]: I still have to find an easy way to transfer patch between gmail and my tree... For now, I ruled out mutt as it mangle the patch...

The gmail web interface on the *receiving* end is easy enough, and I do it all the time: just go to the per-email menu in the upper right corner of the email, and choose "Show original". Then you just save that, and you're done.

yes and no. This works locally, but my desktop machine, and my dev machine are not the same, so I have to do an extra-copy. Moreover, this gets complicated when working remotely.

I guess the solution I'll ends-up doing is a mix between tagging the mail in gmail, and retrieving the mbox/maildir through IMAP, but I'd need a way to tag a single message, not a conversation...

Quoted 7 lines

Sadly, the gmail web interface cannot *send* patches without whitespace-mangling them. You have to send them as attachements, and there is no way to say "do this attachement inline".

Sad, sad, sad. gmail gets so many other things right, but sending patches is a big pain in the *ss for no good reason.

Quoted 7 lines

The gmail web client also does threading the wrong way (by subject line rather than by following references), but that's apparently what Windows people want and are used to because of how Exchange works. Or so I've been told - I've never touched that pile of crap. It's sad how it has then resulted in crud in gmail. It's not like proper threading is some kind of unheard-of feature..

agree on most of that :)

It would have been nice if there was a Labs feature to provide threading the traditional way and to provide a way for inline attachment. If some people at Google read this message... who knows!

- Arnaud

#8 lore raw

Re: [06.5] Re: [GIT PULL] core/printk changes for v3.1

In reply to Linus Torvalds
Quoted 3 lines · On Tue, 26 Jul 2011 13:30:06 -0700 Linus Torvalds…

Sadly, the gmail web interface cannot *send* patches without whitespace-mangling them. You have to send them as attachements, and there is no way to say "do this attachement inline".

I have updated my sendpatchset utility. It works well with gmail's SMTP server. It could be used by those with a gmail account instead of trying to send patches via their web interface. Place one's gmail account information in the $HOME/.sendpatchset.ini file, as documented within the sendpatchset utility.

It requires Python.

You can find the latest sendpatchset at:

http://pauljackson.us/sendpatchset.py
http://pauljackson.us/COPYING

It's released under GPL license, and is an update of the same sendpatchset that I published a few times back in 2004 - 2007, while I worked at Silicon Graphics. I am the same Paul Jackson who worked on cpusets for a while, formerly known as pj AT sgi.com.

Signature · 1 line
Paul Jackson <[email protected]>
#9 lore raw

[tip:core/urgent] lockdep: Fix trace_hardirqs_on_caller()

In reply to Peter Zijlstra
Commit-ID:  7d36b26be0f3c6b86e3ab7e1539e42f3a3bc79ca
Gitweb:     http://git.kernel.org/tip/7d36b26be0f3c6b86e3ab7e1539e42f3a3bc79ca
Author:     Peter Zijlstra <[email protected]>
AuthorDate: Tue, 26 Jul 2011 13:13:44 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Thu, 4 Aug 2011 10:17:36 +0200

lockdep: Fix trace_hardirqs_on_caller()

Commit dd4e5d3ac4a ("lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion") made a bit of a mess of the various checks and error conditions.

In particular it moved the check for !irqs_disabled() before the spurious enable test, resulting in some warnings.

---
 kernel/lockdep.c |   30 ++++++++++++++++--------------
 1 files changed, 16 insertions(+), 14 deletions(-)
kernel/lockdep.c +16 -14
index 3956f51..74ca247 100644
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
-		return;
-
-	if (unlikely(curr->hardirqs_enabled)) {
-		/*
-		 * Neither irq nor preemption are disabled here
-		 * so this is racy by nature but losing one hit
-		 * in a stat is not a big deal.
-		 */
-		__debug_atomic_inc(redundant_hardirqs_on);
-		return;
-	}
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
-		return;
 	/*
 	 * We are going to turn hardirqs on, so set the
 	 * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned long ip)
 	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
+	if (unlikely(current->hardirqs_enabled)) {
+		/*
+		 * Neither irq nor preemption are disabled here
+		 * so this is racy by nature but losing one hit
+		 * in a stat is not a big deal.
+		 */
+		__debug_atomic_inc(redundant_hardirqs_on);
+		return;
+	}
+
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
 		return;
 
+	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+		return;
+
 	current->lockdep_recursion = 1;
 	__trace_hardirqs_on_caller(ip);
 	current->lockdep_recursion = 0;