diff options
author | Ursula Braun <braunu@de.ibm.com> | 2007-07-14 22:03:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-07-14 22:03:41 -0400 |
commit | 13fdc9a74df0fec70f421c6891e184ed8c3b9088 (patch) | |
tree | efd81d0f35e2300ee86e538fa8c136654c7c0dae | |
parent | da7de31cc50796a53593785d4508b7b7ffa9a9b2 (diff) |
[AF_IUCV]: Avoid deadlock between iucv_path_connect and tasklet.
An iucv deadlock may occur, where one CPU is spinning on the
iucv_table_lock for iucv_tasklet_fn(), while another CPU is holding
the iucv_table_lock for an iucv_path_connect() and is waiting for
the first CPU in an smp_call_function.
Solution: replace spin_lock in iucv_tasklet_fn by spin_trylock and
reschedule tasklet in case of non-granted lock.
Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Acked-by: Frank Pavlic <fpavlic@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/iucv/iucv.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index b7333061016d..ad5150b8dfa9 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -1494,7 +1494,10 @@ static void iucv_tasklet_fn(unsigned long ignored) | |||
1494 | struct iucv_irq_list *p, *n; | 1494 | struct iucv_irq_list *p, *n; |
1495 | 1495 | ||
1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ | 1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ |
1497 | spin_lock(&iucv_table_lock); | 1497 | if (!spin_trylock(&iucv_table_lock)) { |
1498 | tasklet_schedule(&iucv_tasklet); | ||
1499 | return; | ||
1500 | } | ||
1498 | iucv_active_cpu = smp_processor_id(); | 1501 | iucv_active_cpu = smp_processor_id(); |
1499 | 1502 | ||
1500 | spin_lock_irq(&iucv_queue_lock); | 1503 | spin_lock_irq(&iucv_queue_lock); |