diff options
author | David Decotigny <decot@googlers.com> | 2013-01-11 17:31:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-11 17:54:54 -0500 |
commit | 896f97ea95c1d29c0520ee0766b66b7f64cb967c (patch) | |
tree | 9898ba669c2348294452fcfd5b7b81fe04cb072f /include | |
parent | 254adaa465c40151df11fc1f88f93e6e86eb61d4 (diff) |
lib: cpu_rmap: avoid flushing all workqueues
In some cases, free_irq_cpu_rmap() is called while holding a lock (eg
rtnl). This can lead to deadlocks, because it invokes
flush_scheduled_work() which ends up waiting for whole system workqueue
to flush, but some pending works might try to acquire the lock we are
already holding.
This commit uses reference-counting to replace
irq_run_affinity_notifiers(). It also removes
irq_run_affinity_notifiers() altogether.
[akpm@linux-foundation.org: eliminate free_cpu_rmap, rename cpu_rmap_reclaim() to cpu_rmap_release(), propagate kref_put() retval from cpu_rmap_put()]
Signed-off-by: David Decotigny <decot@googlers.com>
Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Acked-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/cpu_rmap.h | 13 | ||||
-rw-r--r-- | include/linux/interrupt.h | 5 |
2 files changed, 4 insertions, 14 deletions
diff --git a/include/linux/cpu_rmap.h b/include/linux/cpu_rmap.h index ac3bbb5b9502..1739510d8994 100644 --- a/include/linux/cpu_rmap.h +++ b/include/linux/cpu_rmap.h | |||
@@ -13,9 +13,11 @@ | |||
13 | #include <linux/cpumask.h> | 13 | #include <linux/cpumask.h> |
14 | #include <linux/gfp.h> | 14 | #include <linux/gfp.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/kref.h> | ||
16 | 17 | ||
17 | /** | 18 | /** |
18 | * struct cpu_rmap - CPU affinity reverse-map | 19 | * struct cpu_rmap - CPU affinity reverse-map |
20 | * @refcount: kref for object | ||
19 | * @size: Number of objects to be reverse-mapped | 21 | * @size: Number of objects to be reverse-mapped |
20 | * @used: Number of objects added | 22 | * @used: Number of objects added |
21 | * @obj: Pointer to array of object pointers | 23 | * @obj: Pointer to array of object pointers |
@@ -23,6 +25,7 @@ | |||
23 | * based on affinity masks | 25 | * based on affinity masks |
24 | */ | 26 | */ |
25 | struct cpu_rmap { | 27 | struct cpu_rmap { |
28 | struct kref refcount; | ||
26 | u16 size, used; | 29 | u16 size, used; |
27 | void **obj; | 30 | void **obj; |
28 | struct { | 31 | struct { |
@@ -33,15 +36,7 @@ struct cpu_rmap { | |||
33 | #define CPU_RMAP_DIST_INF 0xffff | 36 | #define CPU_RMAP_DIST_INF 0xffff |
34 | 37 | ||
35 | extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags); | 38 | extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags); |
36 | 39 | extern int cpu_rmap_put(struct cpu_rmap *rmap); | |
37 | /** | ||
38 | * free_cpu_rmap - free CPU affinity reverse-map | ||
39 | * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL | ||
40 | */ | ||
41 | static inline void free_cpu_rmap(struct cpu_rmap *rmap) | ||
42 | { | ||
43 | kfree(rmap); | ||
44 | } | ||
45 | 40 | ||
46 | extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj); | 41 | extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj); |
47 | extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index, | 42 | extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index, |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5e4e6170f43a..5fa5afeeb759 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -268,11 +268,6 @@ struct irq_affinity_notify { | |||
268 | extern int | 268 | extern int |
269 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); | 269 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); |
270 | 270 | ||
271 | static inline void irq_run_affinity_notifiers(void) | ||
272 | { | ||
273 | flush_scheduled_work(); | ||
274 | } | ||
275 | |||
276 | #else /* CONFIG_SMP */ | 271 | #else /* CONFIG_SMP */ |
277 | 272 | ||
278 | static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) | 273 | static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) |