aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2009-01-21 02:12:39 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-14 17:27:49 -0500
commitcf40bd16fdad42c053040bcd3988f5fdedbb6c57 (patch)
treed97ab25726981712be806d77650b7f65167cfc88 /kernel
parent6f2b9b9a9d750a9175dc79c74bfed5add840983c (diff)
lockdep: annotate reclaim context (__GFP_NOFS)
Here is another version, with the incremental patch rolled up, and added reclaim context annotation to kswapd, and allocation tracing to slab allocators (which may only ever reach the page allocator in rare cases, so it is good to put annotations here too). Haven't tested this version as such, but it should be getting closer to merge worthy ;) -- After noticing some code in mm/filemap.c accidentally perform a __GFP_FS allocation when it should not have been, I thought it might be a good idea to try to catch this kind of thing with lockdep. I coded up a little idea that seems to work. Unfortunately the system has to actually be in __GFP_FS page reclaim, then take the lock, before it will mark it. But at least that might still be some orders of magnitude more common (and more debuggable) than an actual deadlock condition, so we have some improvement I hope (the concept is no less complete than discovery of a lock's interrupt contexts). I guess we could even do the same thing with __GFP_IO (normal reclaim), and even GFP_NOIO locks too... but filesystems will have the most locks and fiddly code paths, so let's start there and see how it goes. It *seems* to work. I did a quick test. ================================= [ INFO: inconsistent lock state ] 2.6.28-rc6-00007-ged31348-dirty #26 --------------------------------- inconsistent {in-reclaim-W} -> {ov-reclaim-W} usage. modprobe/8526 [HC0[0]:SC0[0]:HE1:SE1] takes: (testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd] {in-reclaim-W} state was registered at: [<ffffffff80267bdb>] __lock_acquire+0x75b/0x1a60 [<ffffffff80268f71>] lock_acquire+0x91/0xc0 [<ffffffff8070f0e1>] mutex_lock_nested+0xb1/0x310 [<ffffffffa002002b>] brd_init+0x2b/0x216 [brd] [<ffffffff8020903b>] _stext+0x3b/0x170 [<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0 [<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b [<ffffffffffffffff>] 0xffffffffffffffff irq event stamp: 3929 hardirqs last enabled at (3929): [<ffffffff8070f2b5>] mutex_lock_nested+0x285/0x310 hardirqs last disabled at (3928): [<ffffffff8070f089>] mutex_lock_nested+0x59/0x310 softirqs last enabled at (3732): [<ffffffff8061f623>] sk_filter+0x83/0xe0 softirqs last disabled at (3730): [<ffffffff8061f5b6>] sk_filter+0x16/0xe0 other info that might help us debug this: 1 lock held by modprobe/8526: #0: (testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd] stack backtrace: Pid: 8526, comm: modprobe Not tainted 2.6.28-rc6-00007-ged31348-dirty #26 Call Trace: [<ffffffff80265483>] print_usage_bug+0x193/0x1d0 [<ffffffff80266530>] mark_lock+0xaf0/0xca0 [<ffffffff80266735>] mark_held_locks+0x55/0xc0 [<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd] [<ffffffff802667ca>] trace_reclaim_fs+0x2a/0x60 [<ffffffff80285005>] __alloc_pages_internal+0x475/0x580 [<ffffffff8070f29e>] ? mutex_lock_nested+0x26e/0x310 [<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd] [<ffffffffa002006a>] brd_init+0x6a/0x216 [brd] [<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd] [<ffffffff8020903b>] _stext+0x3b/0x170 [<ffffffff8070f8b9>] ? mutex_unlock+0x9/0x10 [<ffffffff8070f83d>] ? __mutex_unlock_slowpath+0x10d/0x180 [<ffffffff802669ec>] ? trace_hardirqs_on_caller+0x12c/0x190 [<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0 [<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/lockdep.c229
-rw-r--r--kernel/lockdep_internals.h3
-rw-r--r--kernel/lockdep_proc.c6
3 files changed, 222 insertions, 16 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 06b0c3568f0b..977f940fd562 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -310,12 +310,14 @@ EXPORT_SYMBOL(lockdep_on);
310#if VERBOSE 310#if VERBOSE
311# define HARDIRQ_VERBOSE 1 311# define HARDIRQ_VERBOSE 1
312# define SOFTIRQ_VERBOSE 1 312# define SOFTIRQ_VERBOSE 1
313# define RECLAIM_VERBOSE 1
313#else 314#else
314# define HARDIRQ_VERBOSE 0 315# define HARDIRQ_VERBOSE 0
315# define SOFTIRQ_VERBOSE 0 316# define SOFTIRQ_VERBOSE 0
317# define RECLAIM_VERBOSE 0
316#endif 318#endif
317 319
318#if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE 320#if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE || RECLAIM_VERBOSE
319/* 321/*
320 * Quick filtering for interesting events: 322 * Quick filtering for interesting events:
321 */ 323 */
@@ -454,6 +456,10 @@ static const char *usage_str[] =
454 [LOCK_USED_IN_SOFTIRQ_READ] = "in-softirq-R", 456 [LOCK_USED_IN_SOFTIRQ_READ] = "in-softirq-R",
455 [LOCK_ENABLED_SOFTIRQS_READ] = "softirq-on-R", 457 [LOCK_ENABLED_SOFTIRQS_READ] = "softirq-on-R",
456 [LOCK_ENABLED_HARDIRQS_READ] = "hardirq-on-R", 458 [LOCK_ENABLED_HARDIRQS_READ] = "hardirq-on-R",
459 [LOCK_USED_IN_RECLAIM_FS] = "in-reclaim-W",
460 [LOCK_USED_IN_RECLAIM_FS_READ] = "in-reclaim-R",
461 [LOCK_HELD_OVER_RECLAIM_FS] = "ov-reclaim-W",
462 [LOCK_HELD_OVER_RECLAIM_FS_READ] = "ov-reclaim-R",
457}; 463};
458 464
459const char * __get_key_name(struct lockdep_subclass_key *key, char *str) 465const char * __get_key_name(struct lockdep_subclass_key *key, char *str)
@@ -462,9 +468,10 @@ const char * __get_key_name(struct lockdep_subclass_key *key, char *str)
462} 468}
463 469
464void 470void
465get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4) 471get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3,
472 char *c4, char *c5, char *c6)
466{ 473{
467 *c1 = '.', *c2 = '.', *c3 = '.', *c4 = '.'; 474 *c1 = '.', *c2 = '.', *c3 = '.', *c4 = '.', *c5 = '.', *c6 = '.';
468 475
469 if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) 476 if (class->usage_mask & LOCKF_USED_IN_HARDIRQ)
470 *c1 = '+'; 477 *c1 = '+';
@@ -493,14 +500,29 @@ get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4
493 if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) 500 if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ)
494 *c4 = '?'; 501 *c4 = '?';
495 } 502 }
503
504 if (class->usage_mask & LOCKF_USED_IN_RECLAIM_FS)
505 *c5 = '+';
506 else
507 if (class->usage_mask & LOCKF_HELD_OVER_RECLAIM_FS)
508 *c5 = '-';
509
510 if (class->usage_mask & LOCKF_HELD_OVER_RECLAIM_FS_READ)
511 *c6 = '-';
512 if (class->usage_mask & LOCKF_USED_IN_RECLAIM_FS_READ) {
513 *c6 = '+';
514 if (class->usage_mask & LOCKF_HELD_OVER_RECLAIM_FS_READ)
515 *c6 = '?';
516 }
517
496} 518}
497 519
498static void print_lock_name(struct lock_class *class) 520static void print_lock_name(struct lock_class *class)
499{ 521{
500 char str[KSYM_NAME_LEN], c1, c2, c3, c4; 522 char str[KSYM_NAME_LEN], c1, c2, c3, c4, c5, c6;
501 const char *name; 523 const char *name;
502 524
503 get_usage_chars(class, &c1, &c2, &c3, &c4); 525 get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6);
504 526
505 name = class->name; 527 name = class->name;
506 if (!name) { 528 if (!name) {
@@ -513,7 +535,7 @@ static void print_lock_name(struct lock_class *class)
513 if (class->subclass) 535 if (class->subclass)
514 printk("/%d", class->subclass); 536 printk("/%d", class->subclass);
515 } 537 }
516 printk("){%c%c%c%c}", c1, c2, c3, c4); 538 printk("){%c%c%c%c%c%c}", c1, c2, c3, c4, c5, c6);
517} 539}
518 540
519static void print_lockdep_cache(struct lockdep_map *lock) 541static void print_lockdep_cache(struct lockdep_map *lock)
@@ -1306,6 +1328,26 @@ check_prev_add_irq(struct task_struct *curr, struct held_lock *prev,
1306 LOCK_ENABLED_SOFTIRQS, "soft")) 1328 LOCK_ENABLED_SOFTIRQS, "soft"))
1307 return 0; 1329 return 0;
1308 1330
1331 /*
1332 * Prove that the new dependency does not connect a reclaim-fs-safe
1333 * lock with a reclaim-fs-unsafe lock - to achieve this we search
1334 * the backwards-subgraph starting at <prev>, and the
1335 * forwards-subgraph starting at <next>:
1336 */
1337 if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS,
1338 LOCK_HELD_OVER_RECLAIM_FS, "reclaim-fs"))
1339 return 0;
1340
1341 /*
1342 * Prove that the new dependency does not connect a reclaim-fs-safe-read
1343 * lock with a reclaim-fs-unsafe lock - to achieve this we search
1344 * the backwards-subgraph starting at <prev>, and the
1345 * forwards-subgraph starting at <next>:
1346 */
1347 if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS_READ,
1348 LOCK_HELD_OVER_RECLAIM_FS, "reclaim-fs-read"))
1349 return 0;
1350
1309 return 1; 1351 return 1;
1310} 1352}
1311 1353
@@ -1949,6 +1991,14 @@ static int softirq_verbose(struct lock_class *class)
1949 return 0; 1991 return 0;
1950} 1992}
1951 1993
1994static int reclaim_verbose(struct lock_class *class)
1995{
1996#if RECLAIM_VERBOSE
1997 return class_filter(class);
1998#endif
1999 return 0;
2000}
2001
1952#define STRICT_READ_CHECKS 1 2002#define STRICT_READ_CHECKS 1
1953 2003
1954static int mark_lock_irq(struct task_struct *curr, struct held_lock *this, 2004static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
@@ -2007,6 +2057,31 @@ static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
2007 if (softirq_verbose(hlock_class(this))) 2057 if (softirq_verbose(hlock_class(this)))
2008 ret = 2; 2058 ret = 2;
2009 break; 2059 break;
2060 case LOCK_USED_IN_RECLAIM_FS:
2061 if (!valid_state(curr, this, new_bit, LOCK_HELD_OVER_RECLAIM_FS))
2062 return 0;
2063 if (!valid_state(curr, this, new_bit,
2064 LOCK_HELD_OVER_RECLAIM_FS_READ))
2065 return 0;
2066 /*
2067 * just marked it reclaim-fs-safe, check that this lock
2068 * took no reclaim-fs-unsafe lock in the past:
2069 */
2070 if (!check_usage_forwards(curr, this,
2071 LOCK_HELD_OVER_RECLAIM_FS, "reclaim-fs"))
2072 return 0;
2073#if STRICT_READ_CHECKS
2074 /*
2075 * just marked it reclaim-fs-safe, check that this lock
2076 * took no reclaim-fs-unsafe-read lock in the past:
2077 */
2078 if (!check_usage_forwards(curr, this,
2079 LOCK_HELD_OVER_RECLAIM_FS_READ, "reclaim-fs-read"))
2080 return 0;
2081#endif
2082 if (reclaim_verbose(hlock_class(this)))
2083 ret = 2;
2084 break;
2010 case LOCK_USED_IN_HARDIRQ_READ: 2085 case LOCK_USED_IN_HARDIRQ_READ:
2011 if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS)) 2086 if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS))
2012 return 0; 2087 return 0;
@@ -2033,6 +2108,19 @@ static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
2033 if (softirq_verbose(hlock_class(this))) 2108 if (softirq_verbose(hlock_class(this)))
2034 ret = 2; 2109 ret = 2;
2035 break; 2110 break;
2111 case LOCK_USED_IN_RECLAIM_FS_READ:
2112 if (!valid_state(curr, this, new_bit, LOCK_HELD_OVER_RECLAIM_FS))
2113 return 0;
2114 /*
2115 * just marked it reclaim-fs-read-safe, check that this lock
2116 * took no reclaim-fs-unsafe lock in the past:
2117 */
2118 if (!check_usage_forwards(curr, this,
2119 LOCK_HELD_OVER_RECLAIM_FS, "reclaim-fs"))
2120 return 0;
2121 if (reclaim_verbose(hlock_class(this)))
2122 ret = 2;
2123 break;
2036 case LOCK_ENABLED_HARDIRQS: 2124 case LOCK_ENABLED_HARDIRQS:
2037 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ)) 2125 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
2038 return 0; 2126 return 0;
@@ -2085,6 +2173,32 @@ static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
2085 if (softirq_verbose(hlock_class(this))) 2173 if (softirq_verbose(hlock_class(this)))
2086 ret = 2; 2174 ret = 2;
2087 break; 2175 break;
2176 case LOCK_HELD_OVER_RECLAIM_FS:
2177 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_RECLAIM_FS))
2178 return 0;
2179 if (!valid_state(curr, this, new_bit,
2180 LOCK_USED_IN_RECLAIM_FS_READ))
2181 return 0;
2182 /*
2183 * just marked it reclaim-fs-unsafe, check that no reclaim-fs-safe
2184 * lock in the system ever took it in the past:
2185 */
2186 if (!check_usage_backwards(curr, this,
2187 LOCK_USED_IN_RECLAIM_FS, "reclaim-fs"))
2188 return 0;
2189#if STRICT_READ_CHECKS
2190 /*
2191 * just marked it softirq-unsafe, check that no
2192 * softirq-safe-read lock in the system ever took
2193 * it in the past:
2194 */
2195 if (!check_usage_backwards(curr, this,
2196 LOCK_USED_IN_RECLAIM_FS_READ, "reclaim-fs-read"))
2197 return 0;
2198#endif
2199 if (reclaim_verbose(hlock_class(this)))
2200 ret = 2;
2201 break;
2088 case LOCK_ENABLED_HARDIRQS_READ: 2202 case LOCK_ENABLED_HARDIRQS_READ:
2089 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ)) 2203 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
2090 return 0; 2204 return 0;
@@ -2115,6 +2229,21 @@ static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
2115 if (softirq_verbose(hlock_class(this))) 2229 if (softirq_verbose(hlock_class(this)))
2116 ret = 2; 2230 ret = 2;
2117 break; 2231 break;
2232 case LOCK_HELD_OVER_RECLAIM_FS_READ:
2233 if (!valid_state(curr, this, new_bit, LOCK_USED_IN_RECLAIM_FS))
2234 return 0;
2235#if STRICT_READ_CHECKS
2236 /*
2237 * just marked it reclaim-fs-read-unsafe, check that no
2238 * reclaim-fs-safe lock in the system ever took it in the past:
2239 */
2240 if (!check_usage_backwards(curr, this,
2241 LOCK_USED_IN_RECLAIM_FS, "reclaim-fs"))
2242 return 0;
2243#endif
2244 if (reclaim_verbose(hlock_class(this)))
2245 ret = 2;
2246 break;
2118 default: 2247 default:
2119 WARN_ON(1); 2248 WARN_ON(1);
2120 break; 2249 break;
@@ -2123,11 +2252,17 @@ static int mark_lock_irq(struct task_struct *curr, struct held_lock *this,
2123 return ret; 2252 return ret;
2124} 2253}
2125 2254
2255enum mark_type {
2256 HARDIRQ,
2257 SOFTIRQ,
2258 RECLAIM_FS,
2259};
2260
2126/* 2261/*
2127 * Mark all held locks with a usage bit: 2262 * Mark all held locks with a usage bit:
2128 */ 2263 */
2129static int 2264static int
2130mark_held_locks(struct task_struct *curr, int hardirq) 2265mark_held_locks(struct task_struct *curr, enum mark_type mark)
2131{ 2266{
2132 enum lock_usage_bit usage_bit; 2267 enum lock_usage_bit usage_bit;
2133 struct held_lock *hlock; 2268 struct held_lock *hlock;
@@ -2136,17 +2271,32 @@ mark_held_locks(struct task_struct *curr, int hardirq)
2136 for (i = 0; i < curr->lockdep_depth; i++) { 2271 for (i = 0; i < curr->lockdep_depth; i++) {
2137 hlock = curr->held_locks + i; 2272 hlock = curr->held_locks + i;
2138 2273
2139 if (hardirq) { 2274 switch (mark) {
2275 case HARDIRQ:
2140 if (hlock->read) 2276 if (hlock->read)
2141 usage_bit = LOCK_ENABLED_HARDIRQS_READ; 2277 usage_bit = LOCK_ENABLED_HARDIRQS_READ;
2142 else 2278 else
2143 usage_bit = LOCK_ENABLED_HARDIRQS; 2279 usage_bit = LOCK_ENABLED_HARDIRQS;
2144 } else { 2280 break;
2281
2282 case SOFTIRQ:
2145 if (hlock->read) 2283 if (hlock->read)
2146 usage_bit = LOCK_ENABLED_SOFTIRQS_READ; 2284 usage_bit = LOCK_ENABLED_SOFTIRQS_READ;
2147 else 2285 else
2148 usage_bit = LOCK_ENABLED_SOFTIRQS; 2286 usage_bit = LOCK_ENABLED_SOFTIRQS;
2287 break;
2288
2289 case RECLAIM_FS:
2290 if (hlock->read)
2291 usage_bit = LOCK_HELD_OVER_RECLAIM_FS_READ;
2292 else
2293 usage_bit = LOCK_HELD_OVER_RECLAIM_FS;
2294 break;
2295
2296 default:
2297 BUG();
2149 } 2298 }
2299
2150 if (!mark_lock(curr, hlock, usage_bit)) 2300 if (!mark_lock(curr, hlock, usage_bit))
2151 return 0; 2301 return 0;
2152 } 2302 }
@@ -2200,7 +2350,7 @@ void trace_hardirqs_on_caller(unsigned long ip)
2200 * We are going to turn hardirqs on, so set the 2350 * We are going to turn hardirqs on, so set the
2201 * usage bit for all held locks: 2351 * usage bit for all held locks:
2202 */ 2352 */
2203 if (!mark_held_locks(curr, 1)) 2353 if (!mark_held_locks(curr, HARDIRQ))
2204 return; 2354 return;
2205 /* 2355 /*
2206 * If we have softirqs enabled, then set the usage 2356 * If we have softirqs enabled, then set the usage
@@ -2208,7 +2358,7 @@ void trace_hardirqs_on_caller(unsigned long ip)
2208 * this bit from being set before) 2358 * this bit from being set before)
2209 */ 2359 */
2210 if (curr->softirqs_enabled) 2360 if (curr->softirqs_enabled)
2211 if (!mark_held_locks(curr, 0)) 2361 if (!mark_held_locks(curr, SOFTIRQ))
2212 return; 2362 return;
2213 2363
2214 curr->hardirq_enable_ip = ip; 2364 curr->hardirq_enable_ip = ip;
@@ -2288,7 +2438,7 @@ void trace_softirqs_on(unsigned long ip)
2288 * enabled too: 2438 * enabled too:
2289 */ 2439 */
2290 if (curr->hardirqs_enabled) 2440 if (curr->hardirqs_enabled)
2291 mark_held_locks(curr, 0); 2441 mark_held_locks(curr, SOFTIRQ);
2292} 2442}
2293 2443
2294/* 2444/*
@@ -2317,6 +2467,31 @@ void trace_softirqs_off(unsigned long ip)
2317 debug_atomic_inc(&redundant_softirqs_off); 2467 debug_atomic_inc(&redundant_softirqs_off);
2318} 2468}
2319 2469
2470void lockdep_trace_alloc(gfp_t gfp_mask)
2471{
2472 struct task_struct *curr = current;
2473
2474 if (unlikely(!debug_locks))
2475 return;
2476
2477 /* no reclaim without waiting on it */
2478 if (!(gfp_mask & __GFP_WAIT))
2479 return;
2480
2481 /* this guy won't enter reclaim */
2482 if ((curr->flags & PF_MEMALLOC) && !(gfp_mask & __GFP_NOMEMALLOC))
2483 return;
2484
2485 /* We're only interested __GFP_FS allocations for now */
2486 if (!(gfp_mask & __GFP_FS))
2487 return;
2488
2489 if (DEBUG_LOCKS_WARN_ON(irqs_disabled()))
2490 return;
2491
2492 mark_held_locks(curr, RECLAIM_FS);
2493}
2494
2320static int mark_irqflags(struct task_struct *curr, struct held_lock *hlock) 2495static int mark_irqflags(struct task_struct *curr, struct held_lock *hlock)
2321{ 2496{
2322 /* 2497 /*
@@ -2362,6 +2537,22 @@ static int mark_irqflags(struct task_struct *curr, struct held_lock *hlock)
2362 } 2537 }
2363 } 2538 }
2364 2539
2540 /*
2541 * We reuse the irq context infrastructure more broadly as a general
2542 * context checking code. This tests GFP_FS recursion (a lock taken
2543 * during reclaim for a GFP_FS allocation is held over a GFP_FS
2544 * allocation).
2545 */
2546 if (!hlock->trylock && (curr->lockdep_reclaim_gfp & __GFP_FS)) {
2547 if (hlock->read) {
2548 if (!mark_lock(curr, hlock, LOCK_USED_IN_RECLAIM_FS_READ))
2549 return 0;
2550 } else {
2551 if (!mark_lock(curr, hlock, LOCK_USED_IN_RECLAIM_FS))
2552 return 0;
2553 }
2554 }
2555
2365 return 1; 2556 return 1;
2366} 2557}
2367 2558
@@ -2453,6 +2644,10 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
2453 case LOCK_ENABLED_SOFTIRQS: 2644 case LOCK_ENABLED_SOFTIRQS:
2454 case LOCK_ENABLED_HARDIRQS_READ: 2645 case LOCK_ENABLED_HARDIRQS_READ:
2455 case LOCK_ENABLED_SOFTIRQS_READ: 2646 case LOCK_ENABLED_SOFTIRQS_READ:
2647 case LOCK_USED_IN_RECLAIM_FS:
2648 case LOCK_USED_IN_RECLAIM_FS_READ:
2649 case LOCK_HELD_OVER_RECLAIM_FS:
2650 case LOCK_HELD_OVER_RECLAIM_FS_READ:
2456 ret = mark_lock_irq(curr, this, new_bit); 2651 ret = mark_lock_irq(curr, this, new_bit);
2457 if (!ret) 2652 if (!ret)
2458 return 0; 2653 return 0;
@@ -2966,6 +3161,16 @@ void lock_release(struct lockdep_map *lock, int nested,
2966} 3161}
2967EXPORT_SYMBOL_GPL(lock_release); 3162EXPORT_SYMBOL_GPL(lock_release);
2968 3163
3164void lockdep_set_current_reclaim_state(gfp_t gfp_mask)
3165{
3166 current->lockdep_reclaim_gfp = gfp_mask;
3167}
3168
3169void lockdep_clear_current_reclaim_state(void)
3170{
3171 current->lockdep_reclaim_gfp = 0;
3172}
3173
2969#ifdef CONFIG_LOCK_STAT 3174#ifdef CONFIG_LOCK_STAT
2970static int 3175static int
2971print_lock_contention_bug(struct task_struct *curr, struct lockdep_map *lock, 3176print_lock_contention_bug(struct task_struct *curr, struct lockdep_map *lock,
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index 56b196932c08..e887b783244f 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -32,7 +32,8 @@ extern struct list_head all_lock_classes;
32extern struct lock_chain lock_chains[]; 32extern struct lock_chain lock_chains[];
33 33
34extern void 34extern void
35get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4); 35get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3,
36 char *c4, char *c5, char *c6);
36 37
37extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); 38extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str);
38 39
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index 13716b813896..b84a1dfa9077 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -84,7 +84,7 @@ static int l_show(struct seq_file *m, void *v)
84{ 84{
85 struct lock_class *class = v; 85 struct lock_class *class = v;
86 struct lock_list *entry; 86 struct lock_list *entry;
87 char c1, c2, c3, c4; 87 char c1, c2, c3, c4, c5, c6;
88 88
89 if (v == SEQ_START_TOKEN) { 89 if (v == SEQ_START_TOKEN) {
90 seq_printf(m, "all lock classes:\n"); 90 seq_printf(m, "all lock classes:\n");
@@ -100,8 +100,8 @@ static int l_show(struct seq_file *m, void *v)
100 seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class)); 100 seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class));
101#endif 101#endif
102 102
103 get_usage_chars(class, &c1, &c2, &c3, &c4); 103 get_usage_chars(class, &c1, &c2, &c3, &c4, &c5, &c6);
104 seq_printf(m, " %c%c%c%c", c1, c2, c3, c4); 104 seq_printf(m, " %c%c%c%c%c%c", c1, c2, c3, c4, c5, c6);
105 105
106 seq_printf(m, ": "); 106 seq_printf(m, ": ");
107 print_name(m, class); 107 print_name(m, class);