diff options
-rw-r--r-- | kernel/lockdep.c | 170 |
1 files changed, 105 insertions, 65 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 07a3d74a84be..01e750559034 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -43,13 +43,49 @@ | |||
43 | #include "lockdep_internals.h" | 43 | #include "lockdep_internals.h" |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * hash_lock: protects the lockdep hashes and class/list/hash allocators. | 46 | * lockdep_lock: protects the lockdep graph, the hashes and the |
47 | * class/list/hash allocators. | ||
47 | * | 48 | * |
48 | * This is one of the rare exceptions where it's justified | 49 | * This is one of the rare exceptions where it's justified |
49 | * to use a raw spinlock - we really dont want the spinlock | 50 | * to use a raw spinlock - we really dont want the spinlock |
50 | * code to recurse back into the lockdep code. | 51 | * code to recurse back into the lockdep code... |
51 | */ | 52 | */ |
52 | static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 53 | static raw_spinlock_t lockdep_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
54 | |||
55 | static int graph_lock(void) | ||
56 | { | ||
57 | __raw_spin_lock(&lockdep_lock); | ||
58 | /* | ||
59 | * Make sure that if another CPU detected a bug while | ||
60 | * walking the graph we dont change it (while the other | ||
61 | * CPU is busy printing out stuff with the graph lock | ||
62 | * dropped already) | ||
63 | */ | ||
64 | if (!debug_locks) { | ||
65 | __raw_spin_unlock(&lockdep_lock); | ||
66 | return 0; | ||
67 | } | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | static inline int graph_unlock(void) | ||
72 | { | ||
73 | __raw_spin_unlock(&lockdep_lock); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Turn lock debugging off and return with 0 if it was off already, | ||
79 | * and also release the graph lock: | ||
80 | */ | ||
81 | static inline int debug_locks_off_graph_unlock(void) | ||
82 | { | ||
83 | int ret = debug_locks_off(); | ||
84 | |||
85 | __raw_spin_unlock(&lockdep_lock); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
53 | 89 | ||
54 | static int lockdep_initialized; | 90 | static int lockdep_initialized; |
55 | 91 | ||
@@ -57,14 +93,15 @@ unsigned long nr_list_entries; | |||
57 | static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; | 93 | static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; |
58 | 94 | ||
59 | /* | 95 | /* |
60 | * Allocate a lockdep entry. (assumes hash_lock held, returns | 96 | * Allocate a lockdep entry. (assumes the graph_lock held, returns |
61 | * with NULL on failure) | 97 | * with NULL on failure) |
62 | */ | 98 | */ |
63 | static struct lock_list *alloc_list_entry(void) | 99 | static struct lock_list *alloc_list_entry(void) |
64 | { | 100 | { |
65 | if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) { | 101 | if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) { |
66 | __raw_spin_unlock(&hash_lock); | 102 | if (!debug_locks_off_graph_unlock()) |
67 | debug_locks_off(); | 103 | return NULL; |
104 | |||
68 | printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n"); | 105 | printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n"); |
69 | printk("turning off the locking correctness validator.\n"); | 106 | printk("turning off the locking correctness validator.\n"); |
70 | return NULL; | 107 | return NULL; |
@@ -205,7 +242,7 @@ static int softirq_verbose(struct lock_class *class) | |||
205 | 242 | ||
206 | /* | 243 | /* |
207 | * Stack-trace: tightly packed array of stack backtrace | 244 | * Stack-trace: tightly packed array of stack backtrace |
208 | * addresses. Protected by the hash_lock. | 245 | * addresses. Protected by the graph_lock. |
209 | */ | 246 | */ |
210 | unsigned long nr_stack_trace_entries; | 247 | unsigned long nr_stack_trace_entries; |
211 | static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; | 248 | static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; |
@@ -224,18 +261,15 @@ static int save_trace(struct stack_trace *trace) | |||
224 | trace->max_entries = trace->nr_entries; | 261 | trace->max_entries = trace->nr_entries; |
225 | 262 | ||
226 | nr_stack_trace_entries += trace->nr_entries; | 263 | nr_stack_trace_entries += trace->nr_entries; |
227 | if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) { | ||
228 | __raw_spin_unlock(&hash_lock); | ||
229 | return 0; | ||
230 | } | ||
231 | 264 | ||
232 | if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { | 265 | if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { |
233 | __raw_spin_unlock(&hash_lock); | 266 | if (!debug_locks_off_graph_unlock()) |
234 | if (debug_locks_off()) { | 267 | return 0; |
235 | printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n"); | 268 | |
236 | printk("turning off the locking correctness validator.\n"); | 269 | printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n"); |
237 | dump_stack(); | 270 | printk("turning off the locking correctness validator.\n"); |
238 | } | 271 | dump_stack(); |
272 | |||
239 | return 0; | 273 | return 0; |
240 | } | 274 | } |
241 | 275 | ||
@@ -524,9 +558,7 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth) | |||
524 | { | 558 | { |
525 | struct task_struct *curr = current; | 559 | struct task_struct *curr = current; |
526 | 560 | ||
527 | __raw_spin_unlock(&hash_lock); | 561 | if (!debug_locks_off_graph_unlock() || debug_locks_silent) |
528 | debug_locks_off(); | ||
529 | if (debug_locks_silent) | ||
530 | return 0; | 562 | return 0; |
531 | 563 | ||
532 | printk("\n=======================================================\n"); | 564 | printk("\n=======================================================\n"); |
@@ -554,12 +586,10 @@ static noinline int print_circular_bug_tail(void) | |||
554 | if (debug_locks_silent) | 586 | if (debug_locks_silent) |
555 | return 0; | 587 | return 0; |
556 | 588 | ||
557 | /* hash_lock unlocked by the header */ | ||
558 | __raw_spin_lock(&hash_lock); | ||
559 | this.class = check_source->class; | 589 | this.class = check_source->class; |
560 | if (!save_trace(&this.trace)) | 590 | if (!save_trace(&this.trace)) |
561 | return 0; | 591 | return 0; |
562 | __raw_spin_unlock(&hash_lock); | 592 | |
563 | print_circular_bug_entry(&this, 0); | 593 | print_circular_bug_entry(&this, 0); |
564 | 594 | ||
565 | printk("\nother info that might help us debug this:\n\n"); | 595 | printk("\nother info that might help us debug this:\n\n"); |
@@ -575,8 +605,10 @@ static noinline int print_circular_bug_tail(void) | |||
575 | 605 | ||
576 | static int noinline print_infinite_recursion_bug(void) | 606 | static int noinline print_infinite_recursion_bug(void) |
577 | { | 607 | { |
578 | __raw_spin_unlock(&hash_lock); | 608 | if (!debug_locks_off_graph_unlock()) |
579 | DEBUG_LOCKS_WARN_ON(1); | 609 | return 0; |
610 | |||
611 | WARN_ON(1); | ||
580 | 612 | ||
581 | return 0; | 613 | return 0; |
582 | } | 614 | } |
@@ -711,9 +743,7 @@ print_bad_irq_dependency(struct task_struct *curr, | |||
711 | enum lock_usage_bit bit2, | 743 | enum lock_usage_bit bit2, |
712 | const char *irqclass) | 744 | const char *irqclass) |
713 | { | 745 | { |
714 | __raw_spin_unlock(&hash_lock); | 746 | if (!debug_locks_off_graph_unlock() || debug_locks_silent) |
715 | debug_locks_off(); | ||
716 | if (debug_locks_silent) | ||
717 | return 0; | 747 | return 0; |
718 | 748 | ||
719 | printk("\n======================================================\n"); | 749 | printk("\n======================================================\n"); |
@@ -794,9 +824,7 @@ static int | |||
794 | print_deadlock_bug(struct task_struct *curr, struct held_lock *prev, | 824 | print_deadlock_bug(struct task_struct *curr, struct held_lock *prev, |
795 | struct held_lock *next) | 825 | struct held_lock *next) |
796 | { | 826 | { |
797 | debug_locks_off(); | 827 | if (!debug_locks_off_graph_unlock() || debug_locks_silent) |
798 | __raw_spin_unlock(&hash_lock); | ||
799 | if (debug_locks_silent) | ||
800 | return 0; | 828 | return 0; |
801 | 829 | ||
802 | printk("\n=============================================\n"); | 830 | printk("\n=============================================\n"); |
@@ -972,14 +1000,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, | |||
972 | * Debugging printouts: | 1000 | * Debugging printouts: |
973 | */ | 1001 | */ |
974 | if (verbose(prev->class) || verbose(next->class)) { | 1002 | if (verbose(prev->class) || verbose(next->class)) { |
975 | __raw_spin_unlock(&hash_lock); | 1003 | graph_unlock(); |
976 | printk("\n new dependency: "); | 1004 | printk("\n new dependency: "); |
977 | print_lock_name(prev->class); | 1005 | print_lock_name(prev->class); |
978 | printk(" => "); | 1006 | printk(" => "); |
979 | print_lock_name(next->class); | 1007 | print_lock_name(next->class); |
980 | printk("\n"); | 1008 | printk("\n"); |
981 | dump_stack(); | 1009 | dump_stack(); |
982 | __raw_spin_lock(&hash_lock); | 1010 | return graph_lock(); |
983 | } | 1011 | } |
984 | return 1; | 1012 | return 1; |
985 | } | 1013 | } |
@@ -1044,8 +1072,10 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) | |||
1044 | } | 1072 | } |
1045 | return 1; | 1073 | return 1; |
1046 | out_bug: | 1074 | out_bug: |
1047 | __raw_spin_unlock(&hash_lock); | 1075 | if (!debug_locks_off_graph_unlock()) |
1048 | DEBUG_LOCKS_WARN_ON(1); | 1076 | return 0; |
1077 | |||
1078 | WARN_ON(1); | ||
1049 | 1079 | ||
1050 | return 0; | 1080 | return 0; |
1051 | } | 1081 | } |
@@ -1199,7 +1229,10 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1199 | hash_head = classhashentry(key); | 1229 | hash_head = classhashentry(key); |
1200 | 1230 | ||
1201 | raw_local_irq_save(flags); | 1231 | raw_local_irq_save(flags); |
1202 | __raw_spin_lock(&hash_lock); | 1232 | if (!graph_lock()) { |
1233 | raw_local_irq_restore(flags); | ||
1234 | return NULL; | ||
1235 | } | ||
1203 | /* | 1236 | /* |
1204 | * We have to do the hash-walk again, to avoid races | 1237 | * We have to do the hash-walk again, to avoid races |
1205 | * with another CPU: | 1238 | * with another CPU: |
@@ -1212,9 +1245,12 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1212 | * the hash: | 1245 | * the hash: |
1213 | */ | 1246 | */ |
1214 | if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { | 1247 | if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { |
1215 | __raw_spin_unlock(&hash_lock); | 1248 | if (!debug_locks_off_graph_unlock()) { |
1249 | raw_local_irq_restore(flags); | ||
1250 | return NULL; | ||
1251 | } | ||
1216 | raw_local_irq_restore(flags); | 1252 | raw_local_irq_restore(flags); |
1217 | debug_locks_off(); | 1253 | |
1218 | printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); | 1254 | printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); |
1219 | printk("turning off the locking correctness validator.\n"); | 1255 | printk("turning off the locking correctness validator.\n"); |
1220 | return NULL; | 1256 | return NULL; |
@@ -1235,18 +1271,23 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1235 | list_add_tail_rcu(&class->hash_entry, hash_head); | 1271 | list_add_tail_rcu(&class->hash_entry, hash_head); |
1236 | 1272 | ||
1237 | if (verbose(class)) { | 1273 | if (verbose(class)) { |
1238 | __raw_spin_unlock(&hash_lock); | 1274 | graph_unlock(); |
1239 | raw_local_irq_restore(flags); | 1275 | raw_local_irq_restore(flags); |
1276 | |||
1240 | printk("\nnew class %p: %s", class->key, class->name); | 1277 | printk("\nnew class %p: %s", class->key, class->name); |
1241 | if (class->name_version > 1) | 1278 | if (class->name_version > 1) |
1242 | printk("#%d", class->name_version); | 1279 | printk("#%d", class->name_version); |
1243 | printk("\n"); | 1280 | printk("\n"); |
1244 | dump_stack(); | 1281 | dump_stack(); |
1282 | |||
1245 | raw_local_irq_save(flags); | 1283 | raw_local_irq_save(flags); |
1246 | __raw_spin_lock(&hash_lock); | 1284 | if (!graph_lock()) { |
1285 | raw_local_irq_restore(flags); | ||
1286 | return NULL; | ||
1287 | } | ||
1247 | } | 1288 | } |
1248 | out_unlock_set: | 1289 | out_unlock_set: |
1249 | __raw_spin_unlock(&hash_lock); | 1290 | graph_unlock(); |
1250 | raw_local_irq_restore(flags); | 1291 | raw_local_irq_restore(flags); |
1251 | 1292 | ||
1252 | if (!subclass || force) | 1293 | if (!subclass || force) |
@@ -1287,19 +1328,21 @@ cache_hit: | |||
1287 | * Allocate a new chain entry from the static array, and add | 1328 | * Allocate a new chain entry from the static array, and add |
1288 | * it to the hash: | 1329 | * it to the hash: |
1289 | */ | 1330 | */ |
1290 | __raw_spin_lock(&hash_lock); | 1331 | if (!graph_lock()) |
1332 | return 0; | ||
1291 | /* | 1333 | /* |
1292 | * We have to walk the chain again locked - to avoid duplicates: | 1334 | * We have to walk the chain again locked - to avoid duplicates: |
1293 | */ | 1335 | */ |
1294 | list_for_each_entry(chain, hash_head, entry) { | 1336 | list_for_each_entry(chain, hash_head, entry) { |
1295 | if (chain->chain_key == chain_key) { | 1337 | if (chain->chain_key == chain_key) { |
1296 | __raw_spin_unlock(&hash_lock); | 1338 | graph_unlock(); |
1297 | goto cache_hit; | 1339 | goto cache_hit; |
1298 | } | 1340 | } |
1299 | } | 1341 | } |
1300 | if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) { | 1342 | if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) { |
1301 | __raw_spin_unlock(&hash_lock); | 1343 | if (!debug_locks_off_graph_unlock()) |
1302 | debug_locks_off(); | 1344 | return 0; |
1345 | |||
1303 | printk("BUG: MAX_LOCKDEP_CHAINS too low!\n"); | 1346 | printk("BUG: MAX_LOCKDEP_CHAINS too low!\n"); |
1304 | printk("turning off the locking correctness validator.\n"); | 1347 | printk("turning off the locking correctness validator.\n"); |
1305 | return 0; | 1348 | return 0; |
@@ -1375,9 +1418,7 @@ print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other, | |||
1375 | struct held_lock *this, int forwards, | 1418 | struct held_lock *this, int forwards, |
1376 | const char *irqclass) | 1419 | const char *irqclass) |
1377 | { | 1420 | { |
1378 | __raw_spin_unlock(&hash_lock); | 1421 | if (!debug_locks_off_graph_unlock() || debug_locks_silent) |
1379 | debug_locks_off(); | ||
1380 | if (debug_locks_silent) | ||
1381 | return 0; | 1422 | return 0; |
1382 | 1423 | ||
1383 | printk("\n=========================================================\n"); | 1424 | printk("\n=========================================================\n"); |
@@ -1466,9 +1507,7 @@ static int | |||
1466 | print_usage_bug(struct task_struct *curr, struct held_lock *this, | 1507 | print_usage_bug(struct task_struct *curr, struct held_lock *this, |
1467 | enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit) | 1508 | enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit) |
1468 | { | 1509 | { |
1469 | __raw_spin_unlock(&hash_lock); | 1510 | if (!debug_locks_off_graph_unlock() || debug_locks_silent) |
1470 | debug_locks_off(); | ||
1471 | if (debug_locks_silent) | ||
1472 | return 0; | 1511 | return 0; |
1473 | 1512 | ||
1474 | printk("\n=================================\n"); | 1513 | printk("\n=================================\n"); |
@@ -1529,12 +1568,13 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, | |||
1529 | if (likely(this->class->usage_mask & new_mask)) | 1568 | if (likely(this->class->usage_mask & new_mask)) |
1530 | return 1; | 1569 | return 1; |
1531 | 1570 | ||
1532 | __raw_spin_lock(&hash_lock); | 1571 | if (!graph_lock()) |
1572 | return 0; | ||
1533 | /* | 1573 | /* |
1534 | * Make sure we didnt race: | 1574 | * Make sure we didnt race: |
1535 | */ | 1575 | */ |
1536 | if (unlikely(this->class->usage_mask & new_mask)) { | 1576 | if (unlikely(this->class->usage_mask & new_mask)) { |
1537 | __raw_spin_unlock(&hash_lock); | 1577 | graph_unlock(); |
1538 | return 1; | 1578 | return 1; |
1539 | } | 1579 | } |
1540 | 1580 | ||
@@ -1720,16 +1760,16 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, | |||
1720 | debug_atomic_dec(&nr_unused_locks); | 1760 | debug_atomic_dec(&nr_unused_locks); |
1721 | break; | 1761 | break; |
1722 | default: | 1762 | default: |
1723 | __raw_spin_unlock(&hash_lock); | 1763 | if (!debug_locks_off_graph_unlock()) |
1724 | debug_locks_off(); | 1764 | return 0; |
1725 | WARN_ON(1); | 1765 | WARN_ON(1); |
1726 | return 0; | 1766 | return 0; |
1727 | } | 1767 | } |
1728 | 1768 | ||
1729 | __raw_spin_unlock(&hash_lock); | 1769 | graph_unlock(); |
1730 | 1770 | ||
1731 | /* | 1771 | /* |
1732 | * We must printk outside of the hash_lock: | 1772 | * We must printk outside of the graph_lock: |
1733 | */ | 1773 | */ |
1734 | if (ret == 2) { | 1774 | if (ret == 2) { |
1735 | printk("\nmarked lock as {%s}:\n", usage_str[new_bit]); | 1775 | printk("\nmarked lock as {%s}:\n", usage_str[new_bit]); |
@@ -2127,7 +2167,7 @@ out_calc_hash: | |||
2127 | * We look up the chain_key and do the O(N^2) check and update of | 2167 | * We look up the chain_key and do the O(N^2) check and update of |
2128 | * the dependencies only if this is a new dependency chain. | 2168 | * the dependencies only if this is a new dependency chain. |
2129 | * (If lookup_chain_cache() returns with 1 it acquires | 2169 | * (If lookup_chain_cache() returns with 1 it acquires |
2130 | * hash_lock for us) | 2170 | * graph_lock for us) |
2131 | */ | 2171 | */ |
2132 | if (!trylock && (check == 2) && lookup_chain_cache(chain_key, class)) { | 2172 | if (!trylock && (check == 2) && lookup_chain_cache(chain_key, class)) { |
2133 | /* | 2173 | /* |
@@ -2160,7 +2200,7 @@ out_calc_hash: | |||
2160 | if (!chain_head && ret != 2) | 2200 | if (!chain_head && ret != 2) |
2161 | if (!check_prevs_add(curr, hlock)) | 2201 | if (!check_prevs_add(curr, hlock)) |
2162 | return 0; | 2202 | return 0; |
2163 | __raw_spin_unlock(&hash_lock); | 2203 | graph_unlock(); |
2164 | } | 2204 | } |
2165 | curr->lockdep_depth++; | 2205 | curr->lockdep_depth++; |
2166 | check_chain_key(curr); | 2206 | check_chain_key(curr); |
@@ -2472,7 +2512,7 @@ void lockdep_free_key_range(void *start, unsigned long size) | |||
2472 | int i; | 2512 | int i; |
2473 | 2513 | ||
2474 | raw_local_irq_save(flags); | 2514 | raw_local_irq_save(flags); |
2475 | __raw_spin_lock(&hash_lock); | 2515 | graph_lock(); |
2476 | 2516 | ||
2477 | /* | 2517 | /* |
2478 | * Unhash all classes that were created by this module: | 2518 | * Unhash all classes that were created by this module: |
@@ -2486,7 +2526,7 @@ void lockdep_free_key_range(void *start, unsigned long size) | |||
2486 | zap_class(class); | 2526 | zap_class(class); |
2487 | } | 2527 | } |
2488 | 2528 | ||
2489 | __raw_spin_unlock(&hash_lock); | 2529 | graph_unlock(); |
2490 | raw_local_irq_restore(flags); | 2530 | raw_local_irq_restore(flags); |
2491 | } | 2531 | } |
2492 | 2532 | ||
@@ -2514,20 +2554,20 @@ void lockdep_reset_lock(struct lockdep_map *lock) | |||
2514 | * Debug check: in the end all mapped classes should | 2554 | * Debug check: in the end all mapped classes should |
2515 | * be gone. | 2555 | * be gone. |
2516 | */ | 2556 | */ |
2517 | __raw_spin_lock(&hash_lock); | 2557 | graph_lock(); |
2518 | for (i = 0; i < CLASSHASH_SIZE; i++) { | 2558 | for (i = 0; i < CLASSHASH_SIZE; i++) { |
2519 | head = classhash_table + i; | 2559 | head = classhash_table + i; |
2520 | if (list_empty(head)) | 2560 | if (list_empty(head)) |
2521 | continue; | 2561 | continue; |
2522 | list_for_each_entry_safe(class, next, head, hash_entry) { | 2562 | list_for_each_entry_safe(class, next, head, hash_entry) { |
2523 | if (unlikely(class == lock->class_cache)) { | 2563 | if (unlikely(class == lock->class_cache)) { |
2524 | __raw_spin_unlock(&hash_lock); | 2564 | if (debug_locks_off_graph_unlock()) |
2525 | DEBUG_LOCKS_WARN_ON(1); | 2565 | WARN_ON(1); |
2526 | goto out_restore; | 2566 | goto out_restore; |
2527 | } | 2567 | } |
2528 | } | 2568 | } |
2529 | } | 2569 | } |
2530 | __raw_spin_unlock(&hash_lock); | 2570 | graph_unlock(); |
2531 | 2571 | ||
2532 | out_restore: | 2572 | out_restore: |
2533 | raw_local_irq_restore(flags); | 2573 | raw_local_irq_restore(flags); |