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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-remove-rtnl_lock-from-the-callers-of-queue-apis'

Stanislav Fomichev says:

====================
net: remove rtnl_lock from the callers of queue APIs

All drivers that use queue management APIs already depend on the netdev
lock. Ultimately, we want to have most of the paths that work with
specific netdev to be rtnl_lock-free (ethtool mostly in particular).
Queue API currently has a much smaller API surface, so start with
rtnl_lock from it:

- add mutex to each dmabuf binding (to replace rtnl_lock)
- move netdev lock management to the callers of netdev_rx_queue_restart
and drop rtnl_lock
====================

Link: https://patch.msgid.link/20250311144026.4154277-1-sdf@fomichev.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+52 -40
+2 -2
Documentation/netlink/specs/netdev.yaml
··· 745 745 - irq-suspend-timeout 746 746 747 747 kernel-family: 748 - headers: [ "linux/list.h"] 749 - sock-priv: struct list_head 748 + headers: [ "net/netdev_netlink.h"] 749 + sock-priv: struct netdev_nl_sock 750 750 751 751 mcast-groups: 752 752 list:
+2 -2
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 11381 11381 if (pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag)) 11382 11382 return; 11383 11383 11384 - rtnl_lock(); 11384 + netdev_lock(irq->bp->dev); 11385 11385 if (netif_running(irq->bp->dev)) { 11386 11386 err = netdev_rx_queue_restart(irq->bp->dev, irq->ring_nr); 11387 11387 if (err) 11388 11388 netdev_err(irq->bp->dev, 11389 11389 "RX queue restart failed: err=%d\n", err); 11390 11390 } 11391 - rtnl_unlock(); 11391 + netdev_unlock(irq->bp->dev); 11392 11392 } 11393 11393 11394 11394 static void bnxt_irq_affinity_release(struct kref *ref)
+2 -2
drivers/net/netdevsim/netdev.c
··· 787 787 if (ret != 2) 788 788 return -EINVAL; 789 789 790 - rtnl_lock(); 790 + netdev_lock(ns->netdev); 791 791 if (queue >= ns->netdev->real_num_rx_queues) { 792 792 ret = -EINVAL; 793 793 goto exit_unlock; ··· 801 801 802 802 ret = count; 803 803 exit_unlock: 804 - rtnl_unlock(); 804 + netdev_unlock(ns->netdev); 805 805 return ret; 806 806 } 807 807
+12
include/net/netdev_netlink.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __NET_NETDEV_NETLINK_H 3 + #define __NET_NETDEV_NETLINK_H 4 + 5 + #include <linux/list.h> 6 + 7 + struct netdev_nl_sock { 8 + struct mutex lock; 9 + struct list_head bindings; 10 + }; 11 + 12 + #endif /* __NET_NETDEV_NETLINK_H */
+2 -2
net/core/devmem.c
··· 25 25 26 26 /* Device memory support */ 27 27 28 - /* Protected by rtnl_lock() */ 29 28 static DEFINE_XARRAY_FLAGS(net_devmem_dmabuf_bindings, XA_FLAGS_ALLOC1); 30 29 31 30 static const struct memory_provider_ops dmabuf_devmem_ops; ··· 127 128 rxq->mp_params.mp_priv = NULL; 128 129 rxq->mp_params.mp_ops = NULL; 129 130 131 + netdev_lock(binding->dev); 130 132 rxq_idx = get_netdev_rx_queue_index(rxq); 131 - 132 133 WARN_ON(netdev_rx_queue_restart(binding->dev, rxq_idx)); 134 + netdev_unlock(binding->dev); 133 135 } 134 136 135 137 xa_erase(&net_devmem_dmabuf_bindings, binding->id);
+2 -2
net/core/netdev-genl-gen.c
··· 9 9 #include "netdev-genl-gen.h" 10 10 11 11 #include <uapi/linux/netdev.h> 12 - #include <linux/list.h> 12 + #include <net/netdev_netlink.h> 13 13 14 14 /* Integer value ranges */ 15 15 static const struct netlink_range_validation netdev_a_page_pool_id_range = { ··· 217 217 .n_split_ops = ARRAY_SIZE(netdev_nl_ops), 218 218 .mcgrps = netdev_nl_mcgrps, 219 219 .n_mcgrps = ARRAY_SIZE(netdev_nl_mcgrps), 220 - .sock_priv_size = sizeof(struct list_head), 220 + .sock_priv_size = sizeof(struct netdev_nl_sock), 221 221 .sock_priv_init = __netdev_nl_sock_priv_init, 222 222 .sock_priv_destroy = __netdev_nl_sock_priv_destroy, 223 223 };
+3 -3
net/core/netdev-genl-gen.h
··· 10 10 #include <net/genetlink.h> 11 11 12 12 #include <uapi/linux/netdev.h> 13 - #include <linux/list.h> 13 + #include <net/netdev_netlink.h> 14 14 15 15 /* Common nested types */ 16 16 extern const struct nla_policy netdev_page_pool_info_nl_policy[NETDEV_A_PAGE_POOL_IFINDEX + 1]; ··· 42 42 43 43 extern struct genl_family netdev_nl_family; 44 44 45 - void netdev_nl_sock_priv_init(struct list_head *priv); 46 - void netdev_nl_sock_priv_destroy(struct list_head *priv); 45 + void netdev_nl_sock_priv_init(struct netdev_nl_sock *priv); 46 + void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv); 47 47 48 48 #endif /* _LINUX_NETDEV_GEN_H */
+21 -17
net/core/netdev-genl.c
··· 829 829 { 830 830 struct nlattr *tb[ARRAY_SIZE(netdev_queue_id_nl_policy)]; 831 831 struct net_devmem_dmabuf_binding *binding; 832 - struct list_head *sock_binding_list; 833 832 u32 ifindex, dmabuf_fd, rxq_idx; 833 + struct netdev_nl_sock *priv; 834 834 struct net_device *netdev; 835 835 struct sk_buff *rsp; 836 836 struct nlattr *attr; ··· 845 845 ifindex = nla_get_u32(info->attrs[NETDEV_A_DEV_IFINDEX]); 846 846 dmabuf_fd = nla_get_u32(info->attrs[NETDEV_A_DMABUF_FD]); 847 847 848 - sock_binding_list = genl_sk_priv_get(&netdev_nl_family, 849 - NETLINK_CB(skb).sk); 850 - if (IS_ERR(sock_binding_list)) 851 - return PTR_ERR(sock_binding_list); 848 + priv = genl_sk_priv_get(&netdev_nl_family, NETLINK_CB(skb).sk); 849 + if (IS_ERR(priv)) 850 + return PTR_ERR(priv); 852 851 853 852 rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 854 853 if (!rsp) ··· 859 860 goto err_genlmsg_free; 860 861 } 861 862 862 - rtnl_lock(); 863 + mutex_lock(&priv->lock); 863 864 864 - netdev = __dev_get_by_index(genl_info_net(info), ifindex); 865 + netdev = netdev_get_by_index_lock(genl_info_net(info), ifindex); 865 866 if (!netdev || !netif_device_present(netdev)) { 866 867 err = -ENODEV; 867 - goto err_unlock; 868 + goto err_unlock_sock; 868 869 } 869 870 870 871 if (dev_xdp_prog_count(netdev)) { ··· 908 909 goto err_unbind; 909 910 } 910 911 911 - list_add(&binding->list, sock_binding_list); 912 + list_add(&binding->list, &priv->bindings); 912 913 913 914 nla_put_u32(rsp, NETDEV_A_DMABUF_ID, binding->id); 914 915 genlmsg_end(rsp, hdr); ··· 917 918 if (err) 918 919 goto err_unbind; 919 920 920 - rtnl_unlock(); 921 + netdev_unlock(netdev); 922 + 923 + mutex_unlock(&priv->lock); 921 924 922 925 return 0; 923 926 924 927 err_unbind: 925 928 net_devmem_unbind_dmabuf(binding); 926 929 err_unlock: 927 - rtnl_unlock(); 930 + netdev_unlock(netdev); 931 + err_unlock_sock: 932 + mutex_unlock(&priv->lock); 928 933 err_genlmsg_free: 929 934 nlmsg_free(rsp); 930 935 return err; 931 936 } 932 937 933 - void netdev_nl_sock_priv_init(struct list_head *priv) 938 + void netdev_nl_sock_priv_init(struct netdev_nl_sock *priv) 934 939 { 935 - INIT_LIST_HEAD(priv); 940 + INIT_LIST_HEAD(&priv->bindings); 941 + mutex_init(&priv->lock); 936 942 } 937 943 938 - void netdev_nl_sock_priv_destroy(struct list_head *priv) 944 + void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv) 939 945 { 940 946 struct net_devmem_dmabuf_binding *binding; 941 947 struct net_devmem_dmabuf_binding *temp; 942 948 943 - list_for_each_entry_safe(binding, temp, priv, list) { 944 - rtnl_lock(); 949 + mutex_lock(&priv->lock); 950 + list_for_each_entry_safe(binding, temp, &priv->bindings, list) { 945 951 net_devmem_unbind_dmabuf(binding); 946 - rtnl_unlock(); 947 952 } 953 + mutex_unlock(&priv->lock); 948 954 } 949 955 950 956 static int netdev_genl_netdevice_event(struct notifier_block *nb,
+6 -10
net/core/netdev_rx_queue.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 3 #include <linux/netdevice.h> 4 + #include <net/netdev_lock.h> 4 5 #include <net/netdev_queues.h> 5 6 #include <net/netdev_rx_queue.h> 6 7 #include <net/page_pool/memory_provider.h> ··· 19 18 !qops->ndo_queue_mem_alloc || !qops->ndo_queue_start) 20 19 return -EOPNOTSUPP; 21 20 22 - ASSERT_RTNL(); 21 + netdev_assert_locked(dev); 23 22 24 23 new_mem = kvzalloc(qops->ndo_queue_mem_size, GFP_KERNEL); 25 24 if (!new_mem) ··· 30 29 err = -ENOMEM; 31 30 goto err_free_new_mem; 32 31 } 33 - 34 - netdev_lock(dev); 35 32 36 33 err = qops->ndo_queue_mem_alloc(dev, new_mem, rxq_idx); 37 34 if (err) ··· 52 53 } 53 54 54 55 qops->ndo_queue_mem_free(dev, old_mem); 55 - 56 - netdev_unlock(dev); 57 56 58 57 kvfree(old_mem); 59 58 kvfree(new_mem); ··· 77 80 qops->ndo_queue_mem_free(dev, new_mem); 78 81 79 82 err_free_old_mem: 80 - netdev_unlock(dev); 81 83 kvfree(old_mem); 82 84 83 85 err_free_new_mem: ··· 114 118 { 115 119 int ret; 116 120 117 - rtnl_lock(); 121 + netdev_lock(dev); 118 122 ret = __net_mp_open_rxq(dev, ifq_idx, p); 119 - rtnl_unlock(); 123 + netdev_unlock(dev); 120 124 return ret; 121 125 } 122 126 ··· 149 153 void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx, 150 154 struct pp_memory_provider_params *old_p) 151 155 { 152 - rtnl_lock(); 156 + netdev_lock(dev); 153 157 __net_mp_close_rxq(dev, ifq_idx, old_p); 154 - rtnl_unlock(); 158 + netdev_unlock(dev); 155 159 }