diff options
author | Jan Kara <jack@suse.cz> | 2014-06-04 19:11:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:54:16 -0400 |
commit | bd8d7cf5b8410fe98eba06a9aaa90efe88815d8a (patch) | |
tree | c00e0af9d7fbed0b5e6d89d7b2b8348513103328 /kernel/printk | |
parent | 608873cacb9d0d2811586fcc79a38b64eabd6d32 (diff) |
printk: fix lockdep instrumentation of console_sem
Printk calls mutex_acquire() / mutex_release() by hand to instrument
lockdep about console_sem. However in some corner cases the
instrumentation is missing. Fix the problem by creating helper functions
for locking / unlocking console_sem which take care of lockdep
instrumentation as well.
Signed-off-by: Jan Kara <jack@suse.cz>
Reported-by: Fabio Estevam <festevam@gmail.com>
Reported-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: Fabio Estevam <fabio.estevam@freescale.com>
Tested-By: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/printk')
-rw-r--r-- | kernel/printk/printk.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 6e1b21a8a497..5ba37f813723 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -91,6 +91,29 @@ static struct lockdep_map console_lock_dep_map = { | |||
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Helper macros to handle lockdep when locking/unlocking console_sem. We use | ||
95 | * macros instead of functions so that _RET_IP_ contains useful information. | ||
96 | */ | ||
97 | #define down_console_sem() do { \ | ||
98 | down(&console_sem);\ | ||
99 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);\ | ||
100 | } while (0) | ||
101 | |||
102 | static int __down_trylock_console_sem(unsigned long ip) | ||
103 | { | ||
104 | if (down_trylock(&console_sem)) | ||
105 | return 1; | ||
106 | mutex_acquire(&console_lock_dep_map, 0, 1, ip); | ||
107 | return 0; | ||
108 | } | ||
109 | #define down_trylock_console_sem() __down_trylock_console_sem(_RET_IP_) | ||
110 | |||
111 | #define up_console_sem() do { \ | ||
112 | mutex_release(&console_lock_dep_map, 1, _RET_IP_);\ | ||
113 | up(&console_sem);\ | ||
114 | } while (0) | ||
115 | |||
116 | /* | ||
94 | * This is used for debugging the mess that is the VT code by | 117 | * This is used for debugging the mess that is the VT code by |
95 | * keeping track if we have the console semaphore held. It's | 118 | * keeping track if we have the console semaphore held. It's |
96 | * definitely not the perfect debug tool (we don't know if _WE_ | 119 | * definitely not the perfect debug tool (we don't know if _WE_ |
@@ -1422,7 +1445,7 @@ static int console_trylock_for_printk(unsigned int cpu) | |||
1422 | */ | 1445 | */ |
1423 | if (!can_use_console(cpu)) { | 1446 | if (!can_use_console(cpu)) { |
1424 | console_locked = 0; | 1447 | console_locked = 0; |
1425 | up(&console_sem); | 1448 | up_console_sem(); |
1426 | return 0; | 1449 | return 0; |
1427 | } | 1450 | } |
1428 | return 1; | 1451 | return 1; |
@@ -1951,16 +1974,14 @@ void suspend_console(void) | |||
1951 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); | 1974 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); |
1952 | console_lock(); | 1975 | console_lock(); |
1953 | console_suspended = 1; | 1976 | console_suspended = 1; |
1954 | up(&console_sem); | 1977 | up_console_sem(); |
1955 | mutex_release(&console_lock_dep_map, 1, _RET_IP_); | ||
1956 | } | 1978 | } |
1957 | 1979 | ||
1958 | void resume_console(void) | 1980 | void resume_console(void) |
1959 | { | 1981 | { |
1960 | if (!console_suspend_enabled) | 1982 | if (!console_suspend_enabled) |
1961 | return; | 1983 | return; |
1962 | down(&console_sem); | 1984 | down_console_sem(); |
1963 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); | ||
1964 | console_suspended = 0; | 1985 | console_suspended = 0; |
1965 | console_unlock(); | 1986 | console_unlock(); |
1966 | } | 1987 | } |
@@ -2002,12 +2023,11 @@ void console_lock(void) | |||
2002 | { | 2023 | { |
2003 | might_sleep(); | 2024 | might_sleep(); |
2004 | 2025 | ||
2005 | down(&console_sem); | 2026 | down_console_sem(); |
2006 | if (console_suspended) | 2027 | if (console_suspended) |
2007 | return; | 2028 | return; |
2008 | console_locked = 1; | 2029 | console_locked = 1; |
2009 | console_may_schedule = 1; | 2030 | console_may_schedule = 1; |
2010 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); | ||
2011 | } | 2031 | } |
2012 | EXPORT_SYMBOL(console_lock); | 2032 | EXPORT_SYMBOL(console_lock); |
2013 | 2033 | ||
@@ -2021,15 +2041,14 @@ EXPORT_SYMBOL(console_lock); | |||
2021 | */ | 2041 | */ |
2022 | int console_trylock(void) | 2042 | int console_trylock(void) |
2023 | { | 2043 | { |
2024 | if (down_trylock(&console_sem)) | 2044 | if (down_trylock_console_sem()) |
2025 | return 0; | 2045 | return 0; |
2026 | if (console_suspended) { | 2046 | if (console_suspended) { |
2027 | up(&console_sem); | 2047 | up_console_sem(); |
2028 | return 0; | 2048 | return 0; |
2029 | } | 2049 | } |
2030 | console_locked = 1; | 2050 | console_locked = 1; |
2031 | console_may_schedule = 0; | 2051 | console_may_schedule = 0; |
2032 | mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_); | ||
2033 | return 1; | 2052 | return 1; |
2034 | } | 2053 | } |
2035 | EXPORT_SYMBOL(console_trylock); | 2054 | EXPORT_SYMBOL(console_trylock); |
@@ -2091,7 +2110,7 @@ void console_unlock(void) | |||
2091 | bool retry; | 2110 | bool retry; |
2092 | 2111 | ||
2093 | if (console_suspended) { | 2112 | if (console_suspended) { |
2094 | up(&console_sem); | 2113 | up_console_sem(); |
2095 | return; | 2114 | return; |
2096 | } | 2115 | } |
2097 | 2116 | ||
@@ -2153,7 +2172,6 @@ skip: | |||
2153 | local_irq_restore(flags); | 2172 | local_irq_restore(flags); |
2154 | } | 2173 | } |
2155 | console_locked = 0; | 2174 | console_locked = 0; |
2156 | mutex_release(&console_lock_dep_map, 1, _RET_IP_); | ||
2157 | 2175 | ||
2158 | /* Release the exclusive_console once it is used */ | 2176 | /* Release the exclusive_console once it is used */ |
2159 | if (unlikely(exclusive_console)) | 2177 | if (unlikely(exclusive_console)) |
@@ -2161,7 +2179,7 @@ skip: | |||
2161 | 2179 | ||
2162 | raw_spin_unlock(&logbuf_lock); | 2180 | raw_spin_unlock(&logbuf_lock); |
2163 | 2181 | ||
2164 | up(&console_sem); | 2182 | up_console_sem(); |
2165 | 2183 | ||
2166 | /* | 2184 | /* |
2167 | * Someone could have filled up the buffer again, so re-check if there's | 2185 | * Someone could have filled up the buffer again, so re-check if there's |
@@ -2206,7 +2224,7 @@ void console_unblank(void) | |||
2206 | * oops_in_progress is set to 1.. | 2224 | * oops_in_progress is set to 1.. |
2207 | */ | 2225 | */ |
2208 | if (oops_in_progress) { | 2226 | if (oops_in_progress) { |
2209 | if (down_trylock(&console_sem) != 0) | 2227 | if (down_trylock_console_sem() != 0) |
2210 | return; | 2228 | return; |
2211 | } else | 2229 | } else |
2212 | console_lock(); | 2230 | console_lock(); |