aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2013-01-10 03:57:35 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-11 01:47:04 -0500
commit01c5f864e62b1c1ee72fb492c6c5e47a162a507b (patch)
tree9608d6d4ac7be1b868fa65dd139e8b12c074b9d2
parent10cdc3f3cd541bfeaaf1c6e1710b1500ca19aa7f (diff)
net: Rewrite netif_set_xps_queues to address several issues
This change is meant to address several issues I found within the netif_set_xps_queues function. If the allocation of one of the maps to be assigned to new_dev_maps failed we could end up with the device map in an inconsistent state since we had already worked through a number of CPUs and removed or added the queue. To address that I split the process into several steps. The first of which is just the allocation of updated maps for CPUs that will need larger maps to store the queue. By doing this we can fail gracefully without actually altering the contents of the current device map. The second issue I found was the fact that we were always allocating a new device map even if we were not adding any queues. I have updated the code so that we only allocate a new device map if we are adding queues, otherwise if we are not adding any queues to CPUs we just skip to the removal process. The last change I made was to reuse the code from remove_xps_queue to remove the queue from the CPU. By making this change we can be consistent in how we go about adding and removing the queues from the CPUs. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/dev.c183
1 files changed, 117 insertions, 66 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 231de8738149..41d5120df469 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1915,107 +1915,158 @@ out_no_maps:
1915 mutex_unlock(&xps_map_mutex); 1915 mutex_unlock(&xps_map_mutex);
1916} 1916}
1917 1917
1918static struct xps_map *expand_xps_map(struct xps_map *map,
1919 int cpu, u16 index)
1920{
1921 struct xps_map *new_map;
1922 int alloc_len = XPS_MIN_MAP_ALLOC;
1923 int i, pos;
1924
1925 for (pos = 0; map && pos < map->len; pos++) {
1926 if (map->queues[pos] != index)
1927 continue;
1928 return map;
1929 }
1930
1931 /* Need to add queue to this CPU's existing map */
1932 if (map) {
1933 if (pos < map->alloc_len)
1934 return map;
1935
1936 alloc_len = map->alloc_len * 2;
1937 }
1938
1939 /* Need to allocate new map to store queue on this CPU's map */
1940 new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len), GFP_KERNEL,
1941 cpu_to_node(cpu));
1942 if (!new_map)
1943 return NULL;
1944
1945 for (i = 0; i < pos; i++)
1946 new_map->queues[i] = map->queues[i];
1947 new_map->alloc_len = alloc_len;
1948 new_map->len = pos;
1949
1950 return new_map;
1951}
1952
1918int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index) 1953int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
1919{ 1954{
1920 int i, cpu, pos, map_len, alloc_len, need_set; 1955 struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
1921 struct xps_map *map, *new_map; 1956 struct xps_map *map, *new_map;
1922 struct xps_dev_maps *dev_maps, *new_dev_maps;
1923 int nonempty = 0;
1924 int numa_node_id = -2;
1925 int maps_sz = max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES); 1957 int maps_sz = max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES);
1926 1958 int cpu, numa_node_id = -2;
1927 new_dev_maps = kzalloc(maps_sz, GFP_KERNEL); 1959 bool active = false;
1928 if (!new_dev_maps)
1929 return -ENOMEM;
1930 1960
1931 mutex_lock(&xps_map_mutex); 1961 mutex_lock(&xps_map_mutex);
1932 1962
1933 dev_maps = xmap_dereference(dev->xps_maps); 1963 dev_maps = xmap_dereference(dev->xps_maps);
1934 1964
1965 /* allocate memory for queue storage */
1966 for_each_online_cpu(cpu) {
1967 if (!cpumask_test_cpu(cpu, mask))
1968 continue;
1969
1970 if (!new_dev_maps)
1971 new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
1972 if (!new_dev_maps)
1973 return -ENOMEM;
1974
1975 map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
1976 NULL;
1977
1978 map = expand_xps_map(map, cpu, index);
1979 if (!map)
1980 goto error;
1981
1982 RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
1983 }
1984
1985 if (!new_dev_maps)
1986 goto out_no_new_maps;
1987
1935 for_each_possible_cpu(cpu) { 1988 for_each_possible_cpu(cpu) {
1936 map = dev_maps ? 1989 if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu)) {
1937 xmap_dereference(dev_maps->cpu_map[cpu]) : NULL; 1990 /* add queue to CPU maps */
1938 new_map = map; 1991 int pos = 0;
1939 if (map) {
1940 for (pos = 0; pos < map->len; pos++)
1941 if (map->queues[pos] == index)
1942 break;
1943 map_len = map->len;
1944 alloc_len = map->alloc_len;
1945 } else
1946 pos = map_len = alloc_len = 0;
1947 1992
1948 need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu); 1993 map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
1994 while ((pos < map->len) && (map->queues[pos] != index))
1995 pos++;
1996
1997 if (pos == map->len)
1998 map->queues[map->len++] = index;
1949#ifdef CONFIG_NUMA 1999#ifdef CONFIG_NUMA
1950 if (need_set) {
1951 if (numa_node_id == -2) 2000 if (numa_node_id == -2)
1952 numa_node_id = cpu_to_node(cpu); 2001 numa_node_id = cpu_to_node(cpu);
1953 else if (numa_node_id != cpu_to_node(cpu)) 2002 else if (numa_node_id != cpu_to_node(cpu))
1954 numa_node_id = -1; 2003 numa_node_id = -1;
1955 }
1956#endif 2004#endif
1957 if (need_set && pos >= map_len) { 2005 } else if (dev_maps) {
1958 /* Need to add queue to this CPU's map */ 2006 /* fill in the new device map from the old device map */
1959 if (map_len >= alloc_len) { 2007 map = xmap_dereference(dev_maps->cpu_map[cpu]);
1960 alloc_len = alloc_len ? 2008 RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
1961 2 * alloc_len : XPS_MIN_MAP_ALLOC;
1962 new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len),
1963 GFP_KERNEL,
1964 cpu_to_node(cpu));
1965 if (!new_map)
1966 goto error;
1967 new_map->alloc_len = alloc_len;
1968 for (i = 0; i < map_len; i++)
1969 new_map->queues[i] = map->queues[i];
1970 new_map->len = map_len;
1971 }
1972 new_map->queues[new_map->len++] = index;
1973 } else if (!need_set && pos < map_len) {
1974 /* Need to remove queue from this CPU's map */
1975 if (map_len > 1)
1976 new_map->queues[pos] =
1977 new_map->queues[--new_map->len];
1978 else
1979 new_map = NULL;
1980 } 2009 }
1981 RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], new_map); 2010
1982 } 2011 }
1983 2012
2013 rcu_assign_pointer(dev->xps_maps, new_dev_maps);
2014
1984 /* Cleanup old maps */ 2015 /* Cleanup old maps */
1985 for_each_possible_cpu(cpu) { 2016 if (dev_maps) {
1986 map = dev_maps ? 2017 for_each_possible_cpu(cpu) {
1987 xmap_dereference(dev_maps->cpu_map[cpu]) : NULL; 2018 new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
1988 if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map) 2019 map = xmap_dereference(dev_maps->cpu_map[cpu]);
1989 kfree_rcu(map, rcu); 2020 if (map && map != new_map)
1990 if (new_dev_maps->cpu_map[cpu]) 2021 kfree_rcu(map, rcu);
1991 nonempty = 1; 2022 }
1992 }
1993 2023
1994 if (nonempty) { 2024 kfree_rcu(dev_maps, rcu);
1995 rcu_assign_pointer(dev->xps_maps, new_dev_maps);
1996 } else {
1997 kfree(new_dev_maps);
1998 RCU_INIT_POINTER(dev->xps_maps, NULL);
1999 } 2025 }
2000 2026
2001 if (dev_maps) 2027 dev_maps = new_dev_maps;
2002 kfree_rcu(dev_maps, rcu); 2028 active = true;
2003 2029
2030out_no_new_maps:
2031 /* update Tx queue numa node */
2004 netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index), 2032 netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
2005 (numa_node_id >= 0) ? numa_node_id : 2033 (numa_node_id >= 0) ? numa_node_id :
2006 NUMA_NO_NODE); 2034 NUMA_NO_NODE);
2007 2035
2036 if (!dev_maps)
2037 goto out_no_maps;
2038
2039 /* removes queue from unused CPUs */
2040 for_each_possible_cpu(cpu) {
2041 if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu))
2042 continue;
2043
2044 if (remove_xps_queue(dev_maps, cpu, index))
2045 active = true;
2046 }
2047
2048 /* free map if not active */
2049 if (!active) {
2050 RCU_INIT_POINTER(dev->xps_maps, NULL);
2051 kfree_rcu(dev_maps, rcu);
2052 }
2053
2054out_no_maps:
2008 mutex_unlock(&xps_map_mutex); 2055 mutex_unlock(&xps_map_mutex);
2009 2056
2010 return 0; 2057 return 0;
2011error: 2058error:
2059 /* remove any maps that we added */
2060 for_each_possible_cpu(cpu) {
2061 new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
2062 map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
2063 NULL;
2064 if (new_map && new_map != map)
2065 kfree(new_map);
2066 }
2067
2012 mutex_unlock(&xps_map_mutex); 2068 mutex_unlock(&xps_map_mutex);
2013 2069
2014 if (new_dev_maps)
2015 for_each_possible_cpu(i)
2016 kfree(rcu_dereference_protected(
2017 new_dev_maps->cpu_map[i],
2018 1));
2019 kfree(new_dev_maps); 2070 kfree(new_dev_maps);
2020 return -ENOMEM; 2071 return -ENOMEM;
2021} 2072}