Message ID | 20210208171917.1088230-13-atenart@kernel.org (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: xps: improve the xps maps handling | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 3 maintainers not CCed: christian.brauner@ubuntu.com alexanderduyck@fb.com edumazet@google.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 1 this patch: 1 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 133 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 1 this patch: 1 |
netdev/header_inline | success | Link |
netdev/stable | success | Stable not CCed |
On Mon, Feb 8, 2021 at 9:19 AM Antoine Tenart <atenart@kernel.org> wrote: > > Most of the xps_cpus_show and xps_rxqs_show functions share the same > logic. Having it in two different functions does not help maintenance. > This patch moves their common logic into a new function, xps_queue_show, > to improve this. > > Signed-off-by: Antoine Tenart <atenart@kernel.org> > --- > net/core/net-sysfs.c | 98 ++++++++++++++------------------------------ > 1 file changed, 31 insertions(+), 67 deletions(-) > > diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c > index 6ce5772e799e..984c15248483 100644 > --- a/net/core/net-sysfs.c > +++ b/net/core/net-sysfs.c > @@ -1314,35 +1314,31 @@ static const struct attribute_group dql_group = { > #endif /* CONFIG_BQL */ > > #ifdef CONFIG_XPS > -static ssize_t xps_cpus_show(struct netdev_queue *queue, > - char *buf) > +static ssize_t xps_queue_show(struct net_device *dev, unsigned int index, > + char *buf, enum xps_map_type type) > { > - struct net_device *dev = queue->dev; > struct xps_dev_maps *dev_maps; > - unsigned int index, nr_ids; > - int j, len, ret, tc = 0; > unsigned long *mask; > - > - if (!netif_is_multiqueue(dev)) > - return -ENOENT; > - > - index = get_netdev_queue_index(queue); > - > - /* If queue belongs to subordinate dev use its map */ > - dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev; > + unsigned int nr_ids; > + int j, len, tc = 0; > > tc = netdev_txq_to_tc(dev, index); > if (tc < 0) > return -EINVAL; > > rcu_read_lock(); > - dev_maps = rcu_dereference(dev->xps_maps[XPS_CPUS]); > - nr_ids = dev_maps ? dev_maps->nr_ids : nr_cpu_ids; > + dev_maps = rcu_dereference(dev->xps_maps[type]); > + > + /* Default to nr_cpu_ids/dev->num_rx_queues and do not just return 0 > + * when dev_maps hasn't been allocated yet, to be backward compatible. > + */ > + nr_ids = dev_maps ? dev_maps->nr_ids : > + (type == XPS_CPUS ? nr_cpu_ids : dev->num_rx_queues); > > mask = bitmap_zalloc(nr_ids, GFP_KERNEL); > if (!mask) { > - ret = -ENOMEM; > - goto err_rcu_unlock; > + rcu_read_unlock(); > + return -ENOMEM; > } > > if (!dev_maps || tc >= dev_maps->num_tc) > @@ -1368,11 +1364,24 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, > > len = bitmap_print_to_pagebuf(false, buf, mask, nr_ids); > bitmap_free(mask); > + > return len < PAGE_SIZE ? len : -EINVAL; > +} > > -err_rcu_unlock: > - rcu_read_unlock(); > - return ret; > +static ssize_t xps_cpus_show(struct netdev_queue *queue, char *buf) > +{ > + struct net_device *dev = queue->dev; > + unsigned int index; > + > + if (!netif_is_multiqueue(dev)) > + return -ENOENT; > + > + index = get_netdev_queue_index(queue); > + > + /* If queue belongs to subordinate dev use its map */ > + dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev; > + > + return xps_queue_show(dev, index, buf, XPS_CPUS); > } > > static ssize_t xps_cpus_store(struct netdev_queue *queue, So this patch has the same issue as the one that was removing the rtnl_lock. Basically the sb_dev needs to still be protected by the rtnl_lock. We might need to take the rtnl_lock and maybe make use of the get_device/put_device logic to make certain the device cannot be freed while you are passing it to xps_queue_show.
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 6ce5772e799e..984c15248483 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1314,35 +1314,31 @@ static const struct attribute_group dql_group = { #endif /* CONFIG_BQL */ #ifdef CONFIG_XPS -static ssize_t xps_cpus_show(struct netdev_queue *queue, - char *buf) +static ssize_t xps_queue_show(struct net_device *dev, unsigned int index, + char *buf, enum xps_map_type type) { - struct net_device *dev = queue->dev; struct xps_dev_maps *dev_maps; - unsigned int index, nr_ids; - int j, len, ret, tc = 0; unsigned long *mask; - - if (!netif_is_multiqueue(dev)) - return -ENOENT; - - index = get_netdev_queue_index(queue); - - /* If queue belongs to subordinate dev use its map */ - dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev; + unsigned int nr_ids; + int j, len, tc = 0; tc = netdev_txq_to_tc(dev, index); if (tc < 0) return -EINVAL; rcu_read_lock(); - dev_maps = rcu_dereference(dev->xps_maps[XPS_CPUS]); - nr_ids = dev_maps ? dev_maps->nr_ids : nr_cpu_ids; + dev_maps = rcu_dereference(dev->xps_maps[type]); + + /* Default to nr_cpu_ids/dev->num_rx_queues and do not just return 0 + * when dev_maps hasn't been allocated yet, to be backward compatible. + */ + nr_ids = dev_maps ? dev_maps->nr_ids : + (type == XPS_CPUS ? nr_cpu_ids : dev->num_rx_queues); mask = bitmap_zalloc(nr_ids, GFP_KERNEL); if (!mask) { - ret = -ENOMEM; - goto err_rcu_unlock; + rcu_read_unlock(); + return -ENOMEM; } if (!dev_maps || tc >= dev_maps->num_tc) @@ -1368,11 +1364,24 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, len = bitmap_print_to_pagebuf(false, buf, mask, nr_ids); bitmap_free(mask); + return len < PAGE_SIZE ? len : -EINVAL; +} -err_rcu_unlock: - rcu_read_unlock(); - return ret; +static ssize_t xps_cpus_show(struct netdev_queue *queue, char *buf) +{ + struct net_device *dev = queue->dev; + unsigned int index; + + if (!netif_is_multiqueue(dev)) + return -ENOENT; + + index = get_netdev_queue_index(queue); + + /* If queue belongs to subordinate dev use its map */ + dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev; + + return xps_queue_show(dev, index, buf, XPS_CPUS); } static ssize_t xps_cpus_store(struct netdev_queue *queue, @@ -1419,56 +1428,11 @@ static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf) { struct net_device *dev = queue->dev; - struct xps_dev_maps *dev_maps; - unsigned int index, nr_ids; - int j, len, ret, tc = 0; - unsigned long *mask; + unsigned int index; index = get_netdev_queue_index(queue); - tc = netdev_txq_to_tc(dev, index); - if (tc < 0) - return -EINVAL; - - rcu_read_lock(); - dev_maps = rcu_dereference(dev->xps_maps[XPS_RXQS]); - nr_ids = dev_maps ? dev_maps->nr_ids : dev->num_rx_queues; - - mask = bitmap_zalloc(nr_ids, GFP_KERNEL); - if (!mask) { - ret = -ENOMEM; - goto err_rcu_unlock; - } - - if (!dev_maps || tc >= dev_maps->num_tc) - goto out_no_maps; - - for (j = 0; j < nr_ids; j++) { - int i, tci = j * dev_maps->num_tc + tc; - struct xps_map *map; - - map = rcu_dereference(dev_maps->attr_map[tci]); - if (!map) - continue; - - for (i = map->len; i--;) { - if (map->queues[i] == index) { - set_bit(j, mask); - break; - } - } - } -out_no_maps: - rcu_read_unlock(); - - len = bitmap_print_to_pagebuf(false, buf, mask, nr_ids); - bitmap_free(mask); - - return len < PAGE_SIZE ? len : -EINVAL; - -err_rcu_unlock: - rcu_read_unlock(); - return ret; + return xps_queue_show(dev, index, buf, XPS_RXQS); } static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
Most of the xps_cpus_show and xps_rxqs_show functions share the same logic. Having it in two different functions does not help maintenance. This patch moves their common logic into a new function, xps_queue_show, to improve this. Signed-off-by: Antoine Tenart <atenart@kernel.org> --- net/core/net-sysfs.c | 98 ++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 67 deletions(-)