aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-10-30 16:10:44 -0400
committerDavid S. Miller <davem@davemloft.net>2013-11-03 23:19:00 -0500
commit74d332c13b2148ae934ea94dac1745ae92efe8e5 (patch)
tree4f8f287774deaba28fa4c85d085d587ae7515aaf /net
parentb397f99921827e114d7f5600447e172a99c50165 (diff)
net: extend net_device allocation to vmalloc()
Joby Poriyath provided a xen-netback patch to reduce the size of xenvif structure as some netdev allocation could fail under memory pressure/fragmentation. This patch is handling the problem at the core level, allowing any netdev structures to use vmalloc() if kmalloc() failed. As vmalloc() adds overhead on a critical network path, add __GFP_REPEAT to kzalloc() flags to do this fallback only when really needed. Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Joby Poriyath <joby.poriyath@citrix.com> Cc: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c22
-rw-r--r--net/core/net-sysfs.c2
2 files changed, 18 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 0054c8c75f50..0e6136546a8c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6196,6 +6196,16 @@ void netdev_set_default_ethtool_ops(struct net_device *dev,
6196} 6196}
6197EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); 6197EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops);
6198 6198
6199void netdev_freemem(struct net_device *dev)
6200{
6201 char *addr = (char *)dev - dev->padded;
6202
6203 if (is_vmalloc_addr(addr))
6204 vfree(addr);
6205 else
6206 kfree(addr);
6207}
6208
6199/** 6209/**
6200 * alloc_netdev_mqs - allocate network device 6210 * alloc_netdev_mqs - allocate network device
6201 * @sizeof_priv: size of private data to allocate space for 6211 * @sizeof_priv: size of private data to allocate space for
@@ -6239,7 +6249,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
6239 /* ensure 32-byte alignment of whole construct */ 6249 /* ensure 32-byte alignment of whole construct */
6240 alloc_size += NETDEV_ALIGN - 1; 6250 alloc_size += NETDEV_ALIGN - 1;
6241 6251
6242 p = kzalloc(alloc_size, GFP_KERNEL); 6252 p = kzalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
6253 if (!p)
6254 p = vzalloc(alloc_size);
6243 if (!p) 6255 if (!p)
6244 return NULL; 6256 return NULL;
6245 6257
@@ -6248,7 +6260,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
6248 6260
6249 dev->pcpu_refcnt = alloc_percpu(int); 6261 dev->pcpu_refcnt = alloc_percpu(int);
6250 if (!dev->pcpu_refcnt) 6262 if (!dev->pcpu_refcnt)
6251 goto free_p; 6263 goto free_dev;
6252 6264
6253 if (dev_addr_init(dev)) 6265 if (dev_addr_init(dev))
6254 goto free_pcpu; 6266 goto free_pcpu;
@@ -6301,8 +6313,8 @@ free_pcpu:
6301 kfree(dev->_rx); 6313 kfree(dev->_rx);
6302#endif 6314#endif
6303 6315
6304free_p: 6316free_dev:
6305 kfree(p); 6317 netdev_freemem(dev);
6306 return NULL; 6318 return NULL;
6307} 6319}
6308EXPORT_SYMBOL(alloc_netdev_mqs); 6320EXPORT_SYMBOL(alloc_netdev_mqs);
@@ -6339,7 +6351,7 @@ void free_netdev(struct net_device *dev)
6339 6351
6340 /* Compatibility with error handling in drivers */ 6352 /* Compatibility with error handling in drivers */
6341 if (dev->reg_state == NETREG_UNINITIALIZED) { 6353 if (dev->reg_state == NETREG_UNINITIALIZED) {
6342 kfree((char *)dev - dev->padded); 6354 netdev_freemem(dev);
6343 return; 6355 return;
6344 } 6356 }
6345 6357
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index d954b56b4e47..d03f2c9750fa 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1263,7 +1263,7 @@ static void netdev_release(struct device *d)
1263 BUG_ON(dev->reg_state != NETREG_RELEASED); 1263 BUG_ON(dev->reg_state != NETREG_RELEASED);
1264 1264
1265 kfree(dev->ifalias); 1265 kfree(dev->ifalias);
1266 kfree((char *)dev - dev->padded); 1266 netdev_freemem(dev);
1267} 1267}
1268 1268
1269static const void *net_namespace(struct device *d) 1269static const void *net_namespace(struct device *d)