aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2009-05-13 17:02:50 +0000
committerDavid S. Miller <davem@davemloft.net>2009-05-18 22:16:00 -0700
commit496a60cdcd5d0d884dddf6c3b4ea912923a70f13 (patch)
treedd7c3e4e61d4c4bead3c7bd3db17401431e6d87e
parent26574401fef6766f6c3ca25b5c13febe662d2a32 (diff)
net: FIX bonding sysfs rtnl_lock deadlock
Sysfs files for a network device can not unconditionally take the rtnl_lock as the bonding sysfs files do. If someone accesses those sysfs files while the network device is being unregistered with the rtnl_lock held we will deadlock. So use trylock and restart_syscall to avoid this problem. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_sysfs.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index d2873153522..3a1b7b04eb7 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -251,7 +251,8 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Note: We can't hold bond->lock here, as bond_create grabs it. */
- rtnl_lock();
+ if (!rtnl_trylock())
+ return restart_syscall();
down_write(&(bonding_rwsem));
sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
@@ -1171,7 +1172,8 @@ static ssize_t bonding_store_primary(struct device *d,
struct slave *slave;
struct bonding *bond = to_bond(d);
- rtnl_lock();
+ if (!rtnl_trylock())
+ return restart_syscall();
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
@@ -1288,7 +1290,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
struct slave *new_active = NULL;
struct bonding *bond = to_bond(d);
- rtnl_lock();
+ if (!rtnl_trylock())
+ return restart_syscall();
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);