diff options
author | Eric Dumazet <edumazet@google.com> | 2013-10-30 16:10:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-03 23:19:00 -0500 |
commit | 74d332c13b2148ae934ea94dac1745ae92efe8e5 (patch) | |
tree | 4f8f287774deaba28fa4c85d085d587ae7515aaf /net | |
parent | b397f99921827e114d7f5600447e172a99c50165 (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.c | 22 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 2 |
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 | } |
6197 | EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); | 6197 | EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); |
6198 | 6198 | ||
6199 | void 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 | ||
6304 | free_p: | 6316 | free_dev: |
6305 | kfree(p); | 6317 | netdev_freemem(dev); |
6306 | return NULL; | 6318 | return NULL; |
6307 | } | 6319 | } |
6308 | EXPORT_SYMBOL(alloc_netdev_mqs); | 6320 | EXPORT_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 | ||
1269 | static const void *net_namespace(struct device *d) | 1269 | static const void *net_namespace(struct device *d) |