diff options
author | Jakub Kicinski <kuba@kernel.org> | 2024-04-09 17:31:47 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2024-04-09 17:31:48 -0700 |
commit | 91f2210ce3f92f8f1a8ba899f0b85a4ebf162abe (patch) | |
tree | c46b6b66eb2ed9ecf7307bbbf6b7ef45eb12bf56 | |
parent | d034d02de882d0ac600806724f9ffeb52de11e2e (diff) | |
parent | 662e451d9a6224ff7fbec8e94c2da75b93258df3 (diff) | |
download | net-next-91f2210ce3f92f8f1a8ba899f0b85a4ebf162abe.tar.gz |
Merge branch 'bonding-remove-rtnl-from-three-sysfs-files'
Eric Dumazet says:
====================
bonding: remove RTNL from three sysfs files
First patch might fix a potential deadlock.
sysfs handlers should use rtnl_trylock() instead of rtnl_lock().
Following files can be read without acquiring RTNL :
- /sys/class/net/bonding_masters
- /sys/class/net/<name>/bonding/slaves
- /sys/class/net/<name>/bonding/queue_id
====================
Link: https://lore.kernel.org/r/20240408190437.2214473-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | drivers/net/bonding/bond_main.c | 6 | ||||
-rw-r--r-- | drivers/net/bonding/bond_netlink.c | 3 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.c | 2 | ||||
-rw-r--r-- | drivers/net/bonding/bond_procfs.c | 2 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 25 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs_slave.c | 2 |
6 files changed, 20 insertions, 20 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c9f0415f780ab0..b3a7d60c3a5ca6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5245,7 +5245,7 @@ static inline int bond_slave_override(struct bonding *bond, /* Find out if any slaves have the same mapping as this skb. */ bond_for_each_slave_rcu(bond, slave, iter) { - if (slave->queue_id == skb_get_queue_mapping(skb)) { + if (READ_ONCE(slave->queue_id) == skb_get_queue_mapping(skb)) { if (bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) { bond_dev_queue_xmit(bond, skb, slave->dev); @@ -5933,7 +5933,7 @@ static void bond_uninit(struct net_device *bond_dev) bond_set_slave_arr(bond, NULL, NULL); - list_del(&bond->bond_list); + list_del_rcu(&bond->bond_list); bond_debug_unregister(bond); } @@ -6347,7 +6347,7 @@ static int bond_init(struct net_device *bond_dev) spin_lock_init(&bond->stats_lock); netdev_lockdep_set_classes(bond_dev); - list_add_tail(&bond->bond_list, &bn->dev_list); + list_add_tail_rcu(&bond->bond_list, &bn->dev_list); bond_prepare_sysfs_group(bond); diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 29b4c3d1b9b6ff..2a6a424806aa60 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -51,7 +51,8 @@ static int bond_fill_slave_info(struct sk_buff *skb, slave_dev->addr_len, slave->perm_hwaddr)) goto nla_put_failure; - if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id)) + if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, + READ_ONCE(slave->queue_id))) goto nla_put_failure; if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio)) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 4cdbc7e084f4b4..0cacd7027e352d 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1589,7 +1589,7 @@ static int bond_option_queue_id_set(struct bonding *bond, goto err_no_cmd; /* Actually set the qids for the slave */ - update_slave->queue_id = qid; + WRITE_ONCE(update_slave->queue_id, qid); out: return ret; diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index 43be458422b3f9..7edf72ec816abd 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c @@ -209,7 +209,7 @@ static void bond_info_show_slave(struct seq_file *seq, seq_printf(seq, "Permanent HW addr: %*phC\n", slave->dev->addr_len, slave->perm_hwaddr); - seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id); + seq_printf(seq, "Slave queue ID: %d\n", READ_ONCE(slave->queue_id)); if (BOND_MODE(bond) == BOND_MODE_8023AD) { const struct port *port = &SLAVE_AD_INFO(slave)->port; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 2805135a7205ba..1e13bb17051567 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -37,12 +37,12 @@ static ssize_t bonding_show_bonds(const struct class *cls, { const struct bond_net *bn = container_of_const(attr, struct bond_net, class_attr_bonding_masters); - int res = 0; struct bonding *bond; + int res = 0; - rtnl_lock(); + rcu_read_lock(); - list_for_each_entry(bond, &bn->dev_list, bond_list) { + list_for_each_entry_rcu(bond, &bn->dev_list, bond_list) { if (res > (PAGE_SIZE - IFNAMSIZ)) { /* not enough space for another interface name */ if ((PAGE_SIZE - res) > 10) @@ -55,7 +55,7 @@ static ssize_t bonding_show_bonds(const struct class *cls, if (res) buf[res-1] = '\n'; /* eat the leftover space */ - rtnl_unlock(); + rcu_read_unlock(); return res; } @@ -170,10 +170,9 @@ static ssize_t bonding_show_slaves(struct device *d, struct slave *slave; int res = 0; - if (!rtnl_trylock()) - return restart_syscall(); + rcu_read_lock(); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { if (res > (PAGE_SIZE - IFNAMSIZ)) { /* not enough space for another interface name */ if ((PAGE_SIZE - res) > 10) @@ -184,7 +183,7 @@ static ssize_t bonding_show_slaves(struct device *d, res += sysfs_emit_at(buf, res, "%s ", slave->dev->name); } - rtnl_unlock(); + rcu_read_unlock(); if (res) buf[res-1] = '\n'; /* eat the leftover space */ @@ -626,10 +625,9 @@ static ssize_t bonding_show_queue_id(struct device *d, struct slave *slave; int res = 0; - if (!rtnl_trylock()) - return restart_syscall(); + rcu_read_lock(); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { if (res > (PAGE_SIZE - IFNAMSIZ - 6)) { /* not enough space for another interface_name:queue_id pair */ if ((PAGE_SIZE - res) > 10) @@ -638,12 +636,13 @@ static ssize_t bonding_show_queue_id(struct device *d, break; } res += sysfs_emit_at(buf, res, "%s:%d ", - slave->dev->name, slave->queue_id); + slave->dev->name, + READ_ONCE(slave->queue_id)); } if (res) buf[res-1] = '\n'; /* eat the leftover space */ - rtnl_unlock(); + rcu_read_unlock(); return res; } diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c index 313866f2c0e49a..36d0e8440b5b94 100644 --- a/drivers/net/bonding/bond_sysfs_slave.c +++ b/drivers/net/bonding/bond_sysfs_slave.c @@ -53,7 +53,7 @@ static SLAVE_ATTR_RO(perm_hwaddr); static ssize_t queue_id_show(struct slave *slave, char *buf) { - return sysfs_emit(buf, "%d\n", slave->queue_id); + return sysfs_emit(buf, "%d\n", READ_ONCE(slave->queue_id)); } static SLAVE_ATTR_RO(queue_id); |