summaryrefslogtreecommitdiffstats
path: root/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>2008-07-02 12:20:18 +0000
committer/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>2008-07-02 12:20:18 +0000
commit633b62df0104203591d5c427f6769857571b2540 (patch)
treec30e45a92d662906a92822e63b256010fec005ef /kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
parentcbbb94616299ae2d897cf8a8fd8d9ebf7af41be8 (diff)
Initial ipset release with kernel modules included.
Diffstat (limited to 'kernel/include/linux/netfilter_ipv4/ip_set_malloc.h')
-rw-r--r--kernel/include/linux/netfilter_ipv4/ip_set_malloc.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h b/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
new file mode 100644
index 0000000..30701f4
--- /dev/null
+++ b/kernel/include/linux/netfilter_ipv4/ip_set_malloc.h
@@ -0,0 +1,143 @@
+#ifndef _IP_SET_MALLOC_H
+#define _IP_SET_MALLOC_H
+
+#ifdef __KERNEL__
+
+static size_t max_malloc_size = 0, max_page_size = 0;
+
+static inline bool init_max_page_size(void)
+{
+ size_t page_size = 0;
+
+#define CACHE(x) if (max_page_size == 0 || x < max_page_size) \
+ page_size = x;
+#include <linux/kmalloc_sizes.h>
+#undef CACHE
+ if (page_size) {
+ if (max_malloc_size == 0)
+ max_malloc_size = page_size;
+
+ max_page_size = page_size;
+
+ return 1;
+ }
+ return 0;
+}
+
+struct harray {
+ size_t max_elements;
+ void *arrays[0];
+};
+
+static inline void *
+__harray_malloc(size_t hashsize, size_t typesize, int flags)
+{
+ struct harray *harray;
+ size_t max_elements, size, i, j;
+
+ BUG_ON(max_page_size == 0);
+
+ if (typesize > max_page_size)
+ return NULL;
+
+ max_elements = max_page_size/typesize;
+ size = hashsize/max_elements;
+ if (hashsize % max_elements)
+ size++;
+
+ /* Last pointer signals end of arrays */
+ harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
+ flags);
+
+ if (!harray)
+ return NULL;
+
+ for (i = 0; i < size - 1; i++) {
+ harray->arrays[i] = kmalloc(max_elements * typesize, flags);
+ if (!harray->arrays[i])
+ goto undo;
+ memset(harray->arrays[i], 0, max_elements * typesize);
+ }
+ harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize,
+ flags);
+ if (!harray->arrays[i])
+ goto undo;
+ memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
+
+ harray->max_elements = max_elements;
+ harray->arrays[size] = NULL;
+
+ return (void *)harray;
+
+ undo:
+ for (j = 0; j < i; j++) {
+ kfree(harray->arrays[j]);
+ }
+ kfree(harray);
+ return NULL;
+}
+
+static inline void *
+harray_malloc(size_t hashsize, size_t typesize, int flags)
+{
+ void *harray;
+
+ do {
+ harray = __harray_malloc(hashsize, typesize, flags|__GFP_NOWARN);
+ } while (harray == NULL && init_max_page_size());
+
+ return harray;
+}
+
+static inline void harray_free(void *h)
+{
+ struct harray *harray = (struct harray *) h;
+ size_t i;
+
+ for (i = 0; harray->arrays[i] != NULL; i++)
+ kfree(harray->arrays[i]);
+ kfree(harray);
+}
+
+static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
+{
+ struct harray *harray = (struct harray *) h;
+ size_t i;
+
+ for (i = 0; harray->arrays[i+1] != NULL; i++)
+ memset(harray->arrays[i], 0, harray->max_elements * typesize);
+ memset(harray->arrays[i], 0,
+ (hashsize - i * harray->max_elements) * typesize);
+}
+
+#define HARRAY_ELEM(h, type, which) \
+({ \
+ struct harray *__h = (struct harray *)(h); \
+ ((type)((__h)->arrays[(which)/(__h)->max_elements]) \
+ + (which)%(__h)->max_elements); \
+})
+
+/* General memory allocation and deallocation */
+static inline void * ip_set_malloc(size_t bytes)
+{
+ BUG_ON(max_malloc_size == 0);
+
+ if (bytes > max_malloc_size)
+ return vmalloc(bytes);
+ else
+ return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
+}
+
+static inline void ip_set_free(void * data, size_t bytes)
+{
+ BUG_ON(max_malloc_size == 0);
+
+ if (bytes > max_malloc_size)
+ vfree(data);
+ else
+ kfree(data);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_MALLOC_H*/