diff options
| author | Sven Eckelmann <sven@narfation.org> | 2011-05-03 07:10:06 -0400 |
|---|---|---|
| committer | Sven Eckelmann <sven@narfation.org> | 2011-05-08 10:10:42 -0400 |
| commit | 3a4375a9f0080e6ae40af63e2e2c1e70a6dcb775 (patch) | |
| tree | a3448104babf921c217a1e94c2e46d5bd7613a2d | |
| parent | c3caf5196c47a5d1c325308d8eb7f6b020ba12df (diff) | |
batman-adv: Avoid deadlock between rtnl_lock and s_active
The hard_if_event is called by the notifier with rtnl_lock and tries to
remove sysfs entries when a NETDEV_UNREGISTER event is received. This
will automatically take the s_active lock.
The s_active lock is also used when a new interface is added to a meshif
through sysfs. In that situation we cannot wait for the rntl_lock before
creating the actual batman-adv interface to prevent a deadlock. It is
still possible to try to get the rtnl_lock and immediately abort the
current operation when the trylock call failed.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
| -rw-r--r-- | net/batman-adv/bat_sysfs.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index 85ba20d98a66..497a0700cc3c 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
| @@ -488,24 +488,24 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, | |||
| 488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) | 488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) |
| 489 | goto out; | 489 | goto out; |
| 490 | 490 | ||
| 491 | if (!rtnl_trylock()) { | ||
| 492 | ret = -ERESTARTSYS; | ||
| 493 | goto out; | ||
| 494 | } | ||
| 495 | |||
| 491 | if (status_tmp == IF_NOT_IN_USE) { | 496 | if (status_tmp == IF_NOT_IN_USE) { |
| 492 | rtnl_lock(); | ||
| 493 | hardif_disable_interface(hard_iface); | 497 | hardif_disable_interface(hard_iface); |
| 494 | rtnl_unlock(); | 498 | goto unlock; |
| 495 | goto out; | ||
| 496 | } | 499 | } |
| 497 | 500 | ||
| 498 | /* if the interface already is in use */ | 501 | /* if the interface already is in use */ |
| 499 | if (hard_iface->if_status != IF_NOT_IN_USE) { | 502 | if (hard_iface->if_status != IF_NOT_IN_USE) |
| 500 | rtnl_lock(); | ||
| 501 | hardif_disable_interface(hard_iface); | 503 | hardif_disable_interface(hard_iface); |
| 502 | rtnl_unlock(); | ||
| 503 | } | ||
| 504 | 504 | ||
| 505 | rtnl_lock(); | ||
| 506 | ret = hardif_enable_interface(hard_iface, buff); | 505 | ret = hardif_enable_interface(hard_iface, buff); |
| 507 | rtnl_unlock(); | ||
| 508 | 506 | ||
| 507 | unlock: | ||
| 508 | rtnl_unlock(); | ||
| 509 | out: | 509 | out: |
| 510 | hardif_free_ref(hard_iface); | 510 | hardif_free_ref(hard_iface); |
| 511 | return ret; | 511 | return ret; |
