geoip: use vmalloc due to potential list size

The subnet list may become really large (United States: ~15000
entries), which means a use of roughly 120 KB, and kmalloc may fail
to find a contiguous block in physical memory. Virtual contiguity is
enough, so use vmalloc/vfree.

vfree may not be called within a spin_lock_bh area, so release the
lock first, it is safe to do so.
This commit is contained in:
Jan Engelhardt
2008-03-17 14:16:14 +01:00
parent 848484c08c
commit 65eeb7f1f6

View File

@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/netfilter/x_tables.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
@@ -40,7 +41,7 @@ static struct geoip_info *add_node(struct geoip_info *memcpy)
if (copy_from_user(p, memcpy, sizeof(struct geoip_info)) != 0)
goto free_p;
s = kmalloc(p->count * sizeof(struct geoip_subnet), GFP_KERNEL);
s = vmalloc(p->count * sizeof(struct geoip_subnet));
if (s == NULL)
goto free_p;
if (copy_from_user(s, p->subnets, p->count * sizeof(struct geoip_subnet)) != 0)
@@ -59,7 +60,7 @@ static struct geoip_info *add_node(struct geoip_info *memcpy)
spin_unlock_bh(&geoip_lock);
return p;
free_s:
kfree(s);
vfree(s);
free_p:
kfree(p);
return NULL;
@@ -88,11 +89,9 @@ static void geoip_try_remove_node(struct geoip_info *p)
/* So now am unlinked or the only one alive, right ?
* What are you waiting ? Free up some memory!
*/
kfree(p->subnets);
kfree(p);
spin_unlock_bh(&geoip_lock);
vfree(p->subnets);
kfree(p);
return;
}