Current implementation of __dev_alloc_name uses a custom bitmap of a single page to iterate network device id's and allocate an unused id. This leads to a upper limit of 8 * PAGE_SIZE network device id's (for each name format i.e eth0).
This patch uses the kernel's IDA as a replacement to the page based bitmap. This has the effect of simplifying the code and removing the upper limit. Signed-off-by: Tobin C. Harding <m...@tobin.cc> --- net/core/dev.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 29101c9..b16ea84 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1025,39 +1025,31 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf) { int i = 0; const char *p; - const int max_netdevices = 8*PAGE_SIZE; - unsigned long *inuse; struct net_device *d; + DEFINE_IDA(ida); + const int end = 0; p = strnchr(name, IFNAMSIZ-1, '%'); if (p) { - /* - * Verify the string as this thing may have come from + /* Verify the string as this thing may have come from * the user. There must be either one "%d" and no other "%" * characters. */ if (p[1] != 'd' || strchr(p + 2, '%')) return -EINVAL; - /* Use one page as a bit array of possible slots */ - inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC); - if (!inuse) - return -ENOMEM; - for_each_netdev(net, d) { if (!sscanf(d->name, name, &i)) continue; - if (i < 0 || i >= max_netdevices) + if (i < 0) continue; /* avoid cases where sscanf is not exact inverse of printf */ snprintf(buf, IFNAMSIZ, name, i); if (!strncmp(buf, d->name, IFNAMSIZ)) - set_bit(i, inuse); + ida_simple_get(&ida, i, end, GFP_KERNEL); } - - i = find_first_zero_bit(inuse, max_netdevices); - free_page((unsigned long) inuse); + i = ida_simple_get(&ida, 0, end, GFP_KERNEL); } if (buf != name) -- 2.7.4