diff options
author | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2019-01-14 12:25:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-01-14 14:31:18 -0500 |
commit | 3719876809e745b9db5293d418600c194bbf5c23 (patch) | |
tree | 395e8ab29d48c025bae872b23830ad0c0fa47c03 /lib/sbitmap.c | |
parent | c962cb323ec260652cff9331e7bf3d606292db88 (diff) |
sbitmap: Protect swap_lock from softirqs
The swap_lock used by sbitmap has a chain with locks taken from softirq,
but the swap_lock is not protected from being preempted by softirqs.
A chain exists of:
sbq->ws[i].wait -> dispatch_wait_lock -> swap_lock
Where the sbq->ws[i].wait lock can be taken from softirq context, which
means all locks below it in the chain must also be protected from
softirqs.
Reported-by: Clark Williams <williams@redhat.com>
Fixes: 58ab5e32e6fd ("sbitmap: silence bogus lockdep IRQ warning")
Fixes: ea86ea2cdced ("sbitmap: amortize cost of clearing bits")
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/sbitmap.c')
-rw-r--r-- | lib/sbitmap.c | 12 |
1 files changed, 2 insertions, 10 deletions
diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 65c2d06250a6..864354000e04 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c | |||
@@ -26,14 +26,9 @@ | |||
26 | static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) | 26 | static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) |
27 | { | 27 | { |
28 | unsigned long mask, val; | 28 | unsigned long mask, val; |
29 | unsigned long __maybe_unused flags; | ||
30 | bool ret = false; | 29 | bool ret = false; |
31 | 30 | ||
32 | /* Silence bogus lockdep warning */ | 31 | spin_lock_bh(&sb->map[index].swap_lock); |
33 | #if defined(CONFIG_LOCKDEP) | ||
34 | local_irq_save(flags); | ||
35 | #endif | ||
36 | spin_lock(&sb->map[index].swap_lock); | ||
37 | 32 | ||
38 | if (!sb->map[index].cleared) | 33 | if (!sb->map[index].cleared) |
39 | goto out_unlock; | 34 | goto out_unlock; |
@@ -54,10 +49,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) | |||
54 | 49 | ||
55 | ret = true; | 50 | ret = true; |
56 | out_unlock: | 51 | out_unlock: |
57 | spin_unlock(&sb->map[index].swap_lock); | 52 | spin_unlock_bh(&sb->map[index].swap_lock); |
58 | #if defined(CONFIG_LOCKDEP) | ||
59 | local_irq_restore(flags); | ||
60 | #endif | ||
61 | return ret; | 53 | return ret; |
62 | } | 54 | } |
63 | 55 | ||