diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/lockdep.c | 154 |
1 files changed, 61 insertions, 93 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 22ced8d4912f..42dfc28d12cc 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -1268,68 +1268,84 @@ check_usage(struct task_struct *curr, struct held_lock *prev, | |||
1268 | bit_backwards, bit_forwards, irqclass); | 1268 | bit_backwards, bit_forwards, irqclass); |
1269 | } | 1269 | } |
1270 | 1270 | ||
1271 | static int | 1271 | static const char *state_names[] = { |
1272 | check_prev_add_irq(struct task_struct *curr, struct held_lock *prev, | 1272 | #define LOCKDEP_STATE(__STATE) \ |
1273 | struct held_lock *next) | 1273 | STR(__STATE), |
1274 | #include "lockdep_states.h" | ||
1275 | #undef LOCKDEP_STATE | ||
1276 | }; | ||
1277 | |||
1278 | static const char *state_rnames[] = { | ||
1279 | #define LOCKDEP_STATE(__STATE) \ | ||
1280 | STR(__STATE)"-READ", | ||
1281 | #include "lockdep_states.h" | ||
1282 | #undef LOCKDEP_STATE | ||
1283 | }; | ||
1284 | |||
1285 | static inline const char *state_name(enum lock_usage_bit bit) | ||
1274 | { | 1286 | { |
1275 | /* | 1287 | return (bit & 1) ? state_rnames[bit >> 2] : state_names[bit >> 2]; |
1276 | * Prove that the new dependency does not connect a hardirq-safe | 1288 | } |
1277 | * lock with a hardirq-unsafe lock - to achieve this we search | ||
1278 | * the backwards-subgraph starting at <prev>, and the | ||
1279 | * forwards-subgraph starting at <next>: | ||
1280 | */ | ||
1281 | if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ, | ||
1282 | LOCK_ENABLED_HARDIRQ, "hard")) | ||
1283 | return 0; | ||
1284 | 1289 | ||
1290 | static int exclusive_bit(int new_bit) | ||
1291 | { | ||
1285 | /* | 1292 | /* |
1286 | * Prove that the new dependency does not connect a hardirq-safe-read | 1293 | * USED_IN |
1287 | * lock with a hardirq-unsafe lock - to achieve this we search | 1294 | * USED_IN_READ |
1288 | * the backwards-subgraph starting at <prev>, and the | 1295 | * ENABLED |
1289 | * forwards-subgraph starting at <next>: | 1296 | * ENABLED_READ |
1297 | * | ||
1298 | * bit 0 - write/read | ||
1299 | * bit 1 - used_in/enabled | ||
1300 | * bit 2+ state | ||
1290 | */ | 1301 | */ |
1291 | if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ_READ, | 1302 | |
1292 | LOCK_ENABLED_HARDIRQ, "hard-read")) | 1303 | int state = new_bit & ~3; |
1293 | return 0; | 1304 | int dir = new_bit & 2; |
1294 | 1305 | ||
1295 | /* | 1306 | /* |
1296 | * Prove that the new dependency does not connect a softirq-safe | 1307 | * keep state, bit flip the direction and strip read. |
1297 | * lock with a softirq-unsafe lock - to achieve this we search | ||
1298 | * the backwards-subgraph starting at <prev>, and the | ||
1299 | * forwards-subgraph starting at <next>: | ||
1300 | */ | 1308 | */ |
1301 | if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ, | 1309 | return state | (dir ^ 2); |
1302 | LOCK_ENABLED_SOFTIRQ, "soft")) | 1310 | } |
1303 | return 0; | 1311 | |
1312 | static int check_irq_usage(struct task_struct *curr, struct held_lock *prev, | ||
1313 | struct held_lock *next, enum lock_usage_bit bit) | ||
1314 | { | ||
1304 | /* | 1315 | /* |
1305 | * Prove that the new dependency does not connect a softirq-safe-read | 1316 | * Prove that the new dependency does not connect a hardirq-safe |
1306 | * lock with a softirq-unsafe lock - to achieve this we search | 1317 | * lock with a hardirq-unsafe lock - to achieve this we search |
1307 | * the backwards-subgraph starting at <prev>, and the | 1318 | * the backwards-subgraph starting at <prev>, and the |
1308 | * forwards-subgraph starting at <next>: | 1319 | * forwards-subgraph starting at <next>: |
1309 | */ | 1320 | */ |
1310 | if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ_READ, | 1321 | if (!check_usage(curr, prev, next, bit, |
1311 | LOCK_ENABLED_SOFTIRQ, "soft")) | 1322 | exclusive_bit(bit), state_name(bit))) |
1312 | return 0; | 1323 | return 0; |
1313 | 1324 | ||
1325 | bit++; /* _READ */ | ||
1326 | |||
1314 | /* | 1327 | /* |
1315 | * Prove that the new dependency does not connect a reclaim-fs-safe | 1328 | * Prove that the new dependency does not connect a hardirq-safe-read |
1316 | * lock with a reclaim-fs-unsafe lock - to achieve this we search | 1329 | * lock with a hardirq-unsafe lock - to achieve this we search |
1317 | * the backwards-subgraph starting at <prev>, and the | 1330 | * the backwards-subgraph starting at <prev>, and the |
1318 | * forwards-subgraph starting at <next>: | 1331 | * forwards-subgraph starting at <next>: |
1319 | */ | 1332 | */ |
1320 | if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS, | 1333 | if (!check_usage(curr, prev, next, bit, |
1321 | LOCK_ENABLED_RECLAIM_FS, "reclaim-fs")) | 1334 | exclusive_bit(bit), state_name(bit))) |
1322 | return 0; | 1335 | return 0; |
1323 | 1336 | ||
1324 | /* | 1337 | return 1; |
1325 | * Prove that the new dependency does not connect a reclaim-fs-safe-read | 1338 | } |
1326 | * lock with a reclaim-fs-unsafe lock - to achieve this we search | 1339 | |
1327 | * the backwards-subgraph starting at <prev>, and the | 1340 | static int |
1328 | * forwards-subgraph starting at <next>: | 1341 | check_prev_add_irq(struct task_struct *curr, struct held_lock *prev, |
1329 | */ | 1342 | struct held_lock *next) |
1330 | if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS_READ, | 1343 | { |
1331 | LOCK_ENABLED_RECLAIM_FS, "reclaim-fs-read")) | 1344 | #define LOCKDEP_STATE(__STATE) \ |
1345 | if (!check_irq_usage(curr, prev, next, LOCK_USED_IN_##__STATE)) \ | ||
1332 | return 0; | 1346 | return 0; |
1347 | #include "lockdep_states.h" | ||
1348 | #undef LOCKDEP_STATE | ||
1333 | 1349 | ||
1334 | return 1; | 1350 | return 1; |
1335 | } | 1351 | } |
@@ -1984,30 +2000,6 @@ static int RECLAIM_FS_verbose(struct lock_class *class) | |||
1984 | 2000 | ||
1985 | #define STRICT_READ_CHECKS 1 | 2001 | #define STRICT_READ_CHECKS 1 |
1986 | 2002 | ||
1987 | static const char *state_names[] = { | ||
1988 | #define LOCKDEP_STATE(__STATE) \ | ||
1989 | STR(__STATE), | ||
1990 | #include "lockdep_states.h" | ||
1991 | #undef LOCKDEP_STATE | ||
1992 | }; | ||
1993 | |||
1994 | static inline const char *state_name(enum lock_usage_bit bit) | ||
1995 | { | ||
1996 | return state_names[bit >> 2]; | ||
1997 | } | ||
1998 | |||
1999 | static const char *state_rnames[] = { | ||
2000 | #define LOCKDEP_STATE(__STATE) \ | ||
2001 | STR(__STATE)"-READ", | ||
2002 | #include "lockdep_states.h" | ||
2003 | #undef LOCKDEP_STATE | ||
2004 | }; | ||
2005 | |||
2006 | static inline const char *state_rname(enum lock_usage_bit bit) | ||
2007 | { | ||
2008 | return state_rnames[bit >> 2]; | ||
2009 | } | ||
2010 | |||
2011 | static int (*state_verbose_f[])(struct lock_class *class) = { | 2003 | static int (*state_verbose_f[])(struct lock_class *class) = { |
2012 | #define LOCKDEP_STATE(__STATE) \ | 2004 | #define LOCKDEP_STATE(__STATE) \ |
2013 | __STATE##_verbose, | 2005 | __STATE##_verbose, |
@@ -2021,37 +2013,12 @@ static inline int state_verbose(enum lock_usage_bit bit, | |||
2021 | return state_verbose_f[bit >> 2](class); | 2013 | return state_verbose_f[bit >> 2](class); |
2022 | } | 2014 | } |
2023 | 2015 | ||
2024 | static int exclusive_bit(int new_bit) | ||
2025 | { | ||
2026 | /* | ||
2027 | * USED_IN | ||
2028 | * USED_IN_READ | ||
2029 | * ENABLED | ||
2030 | * ENABLED_READ | ||
2031 | * | ||
2032 | * bit 0 - write/read | ||
2033 | * bit 1 - used_in/enabled | ||
2034 | * bit 2+ state | ||
2035 | */ | ||
2036 | |||
2037 | int state = new_bit & ~3; | ||
2038 | int dir = new_bit & 2; | ||
2039 | |||
2040 | /* | ||
2041 | * keep state, bit flip the direction and strip read. | ||
2042 | */ | ||
2043 | return state | (dir ^ 2); | ||
2044 | } | ||
2045 | |||
2046 | typedef int (*check_usage_f)(struct task_struct *, struct held_lock *, | 2016 | typedef int (*check_usage_f)(struct task_struct *, struct held_lock *, |
2047 | enum lock_usage_bit bit, const char *name); | 2017 | enum lock_usage_bit bit, const char *name); |
2048 | 2018 | ||
2049 | static int | 2019 | static int |
2050 | mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit) | 2020 | mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit) |
2051 | { | 2021 | { |
2052 | const char *name = state_name(new_bit); | ||
2053 | const char *rname = state_rname(new_bit); | ||
2054 | |||
2055 | int excl_bit = exclusive_bit(new_bit); | 2022 | int excl_bit = exclusive_bit(new_bit); |
2056 | int read = new_bit & 1; | 2023 | int read = new_bit & 1; |
2057 | int dir = new_bit & 2; | 2024 | int dir = new_bit & 2; |
@@ -2078,7 +2045,7 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit) | |||
2078 | * states. | 2045 | * states. |
2079 | */ | 2046 | */ |
2080 | if ((!read || !dir || STRICT_READ_CHECKS) && | 2047 | if ((!read || !dir || STRICT_READ_CHECKS) && |
2081 | !usage(curr, this, excl_bit, name)) | 2048 | !usage(curr, this, excl_bit, state_name(new_bit))) |
2082 | return 0; | 2049 | return 0; |
2083 | 2050 | ||
2084 | /* | 2051 | /* |
@@ -2089,7 +2056,8 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit) | |||
2089 | return 0; | 2056 | return 0; |
2090 | 2057 | ||
2091 | if (STRICT_READ_CHECKS && | 2058 | if (STRICT_READ_CHECKS && |
2092 | !usage(curr, this, excl_bit + 1, rname)) | 2059 | !usage(curr, this, excl_bit + 1, |
2060 | state_name(new_bit + 1))) | ||
2093 | return 0; | 2061 | return 0; |
2094 | } | 2062 | } |
2095 | 2063 | ||