diff options
Diffstat (limited to 'net/core/net-sysfs.c')
| -rw-r--r-- | net/core/net-sysfs.c | 29 | 
1 files changed, 22 insertions, 7 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 7cc15dec1717..65886bfbf822 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1317,8 +1317,8 @@ static const struct attribute_group dql_group = {  static ssize_t xps_cpus_show(struct netdev_queue *queue,  			     char *buf)  { +	int cpu, len, ret, num_tc = 1, tc = 0;  	struct net_device *dev = queue->dev; -	int cpu, len, num_tc = 1, tc = 0;  	struct xps_dev_maps *dev_maps;  	cpumask_var_t mask;  	unsigned long index; @@ -1328,22 +1328,31 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,  	index = get_netdev_queue_index(queue); +	if (!rtnl_trylock()) +		return restart_syscall(); +  	if (dev->num_tc) {  		/* Do not allow XPS on subordinate device directly */  		num_tc = dev->num_tc; -		if (num_tc < 0) -			return -EINVAL; +		if (num_tc < 0) { +			ret = -EINVAL; +			goto err_rtnl_unlock; +		}  		/* If queue belongs to subordinate dev use its map */  		dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;  		tc = netdev_txq_to_tc(dev, index); -		if (tc < 0) -			return -EINVAL; +		if (tc < 0) { +			ret = -EINVAL; +			goto err_rtnl_unlock; +		}  	} -	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) -		return -ENOMEM; +	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { +		ret = -ENOMEM; +		goto err_rtnl_unlock; +	}  	rcu_read_lock();  	dev_maps = rcu_dereference(dev->xps_cpus_map); @@ -1366,9 +1375,15 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,  	}  	rcu_read_unlock(); +	rtnl_unlock(); +  	len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));  	free_cpumask_var(mask);  	return len < PAGE_SIZE ? len : -EINVAL; + +err_rtnl_unlock: +	rtnl_unlock(); +	return ret;  }  static ssize_t xps_cpus_store(struct netdev_queue *queue,  | 
