Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ethtool: take rss_lock for all rxfh changes

Always take the rss_lock in ethtool_set_rxfh(). We will want to
make a similar change in ethtool_set_rxfh_fields() and some
drivers lock that callback regardless of rss context ID being set.
Having some callbacks locked unconditionally and some only if
context ID is set would be very confusing.

ethtool handling is under rtnl_lock, so rss_lock is very unlikely
to ever be congested.

Link: https://patch.msgid.link/20250626202848.104457-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+21 -21
+21 -21
net/ethtool/ioctl.c
··· 1334 1334 } 1335 1335 1336 1336 rxfh_dev.hfunc = ETH_RSS_HASH_NO_CHANGE; 1337 + 1338 + mutex_lock(&dev->ethtool->rss_lock); 1337 1339 ret = ops->set_rxfh(dev, &rxfh_dev, extack); 1338 1340 if (ret) 1339 - goto out; 1341 + goto out_unlock; 1340 1342 1341 1343 /* indicate whether rxfh was set to default */ 1342 1344 if (user_size == 0) ··· 1346 1344 else 1347 1345 dev->priv_flags |= IFF_RXFH_CONFIGURED; 1348 1346 1347 + out_unlock: 1348 + mutex_unlock(&dev->ethtool->rss_lock); 1349 1349 out: 1350 1350 kfree(rxfh_dev.indir); 1351 1351 return ret; ··· 1504 1500 struct netlink_ext_ack *extack = NULL; 1505 1501 struct ethtool_rxnfc rx_rings; 1506 1502 struct ethtool_rxfh rxfh; 1507 - bool locked = false; /* dev->ethtool->rss_lock taken */ 1508 1503 bool create = false; 1509 1504 bool mod = false; 1510 1505 u8 *rss_config; ··· 1573 1570 rx_rings.cmd = ETHTOOL_GRXRINGS; 1574 1571 ret = ops->get_rxnfc(dev, &rx_rings, NULL); 1575 1572 if (ret) 1576 - goto out; 1573 + goto out_free; 1577 1574 1578 1575 /* rxfh.indir_size == 0 means reset the indir table to default (master 1579 1576 * context) or delete the context (other RSS contexts). ··· 1589 1586 &rx_rings, 1590 1587 rxfh.indir_size); 1591 1588 if (ret) 1592 - goto out; 1589 + goto out_free; 1593 1590 } else if (rxfh.indir_size == 0) { 1594 1591 if (rxfh.rss_context == 0) { 1595 1592 u32 *indir; ··· 1611 1608 useraddr + rss_cfg_offset + user_indir_len, 1612 1609 rxfh.key_size)) { 1613 1610 ret = -EFAULT; 1614 - goto out; 1611 + goto out_free; 1615 1612 } 1616 1613 } 1617 1614 1618 - if (rxfh.rss_context) { 1619 - mutex_lock(&dev->ethtool->rss_lock); 1620 - locked = true; 1621 - } 1615 + mutex_lock(&dev->ethtool->rss_lock); 1622 1616 1623 1617 if (rxfh.rss_context && rxfh_dev.rss_delete) { 1624 1618 ret = ethtool_check_rss_ctx_busy(dev, rxfh.rss_context); 1625 1619 if (ret) 1626 - goto out; 1620 + goto out_unlock; 1627 1621 } 1628 1622 1629 1623 if (create) { 1630 1624 if (rxfh_dev.rss_delete) { 1631 1625 ret = -EINVAL; 1632 - goto out; 1626 + goto out_unlock; 1633 1627 } 1634 1628 ctx = ethtool_rxfh_ctx_alloc(ops, dev_indir_size, dev_key_size); 1635 1629 if (!ctx) { 1636 1630 ret = -ENOMEM; 1637 - goto out; 1631 + goto out_unlock; 1638 1632 } 1639 1633 1640 1634 if (ops->create_rxfh_context) { ··· 1644 1644 GFP_KERNEL_ACCOUNT); 1645 1645 if (ret < 0) { 1646 1646 kfree(ctx); 1647 - goto out; 1647 + goto out_unlock; 1648 1648 } 1649 1649 WARN_ON(!ctx_id); /* can't happen */ 1650 1650 rxfh.rss_context = ctx_id; ··· 1653 1653 ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context); 1654 1654 if (!ctx) { 1655 1655 ret = -ENOENT; 1656 - goto out; 1656 + goto out_unlock; 1657 1657 } 1658 1658 } 1659 1659 rxfh_dev.hfunc = rxfh.hfunc; ··· 1687 1687 xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context); 1688 1688 kfree(ctx); 1689 1689 } 1690 - goto out; 1690 + goto out_unlock; 1691 1691 } 1692 1692 mod = !create && !rxfh_dev.rss_delete; 1693 1693 ··· 1708 1708 if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh_dev.rss_context))) { 1709 1709 /* context ID reused, our tracking is screwed */ 1710 1710 kfree(ctx); 1711 - goto out; 1711 + goto out_unlock; 1712 1712 } 1713 1713 /* Allocate the exact ID the driver gave us */ 1714 1714 if (xa_is_err(xa_store(&dev->ethtool->rss_ctx, rxfh_dev.rss_context, 1715 1715 ctx, GFP_KERNEL))) { 1716 1716 kfree(ctx); 1717 - goto out; 1717 + goto out_unlock; 1718 1718 } 1719 1719 1720 1720 /* Fetch the defaults for the old API, in the new API drivers ··· 1730 1730 if (WARN_ON(ret)) { 1731 1731 xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context); 1732 1732 kfree(ctx); 1733 - goto out; 1733 + goto out_unlock; 1734 1734 } 1735 1735 } 1736 1736 if (rxfh_dev.rss_delete) { ··· 1755 1755 ctx->input_xfrm = rxfh_dev.input_xfrm; 1756 1756 } 1757 1757 1758 - out: 1759 - if (locked) 1760 - mutex_unlock(&dev->ethtool->rss_lock); 1758 + out_unlock: 1759 + mutex_unlock(&dev->ethtool->rss_lock); 1760 + out_free: 1761 1761 kfree(rss_config); 1762 1762 if (mod) 1763 1763 ethtool_rss_notify(dev, rxfh.rss_context);