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 /net/batman-adv/bat_sysfs.c | |
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>
Diffstat (limited to 'net/batman-adv/bat_sysfs.c')
-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; |