summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-10-30 18:52:53 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-10-30 18:52:53 +0200
commit3f8f60c2115992ecf6678fb6ce24d46dbb09e5f8 (patch)
treeb7bf4a865ac507037e034ddd3df3d8ededb12a9b /kernel
parenta9bfa58f6b893d14cd4ffff7ef14084fcdc0ebe9 (diff)
Resizing converted to run under read-locking of the set
With restricting resizing so that it can be triggered by an add from userspace only, we can modify it so that it uses read-locking instead of write-locking. Thus the matching in the set can run parallel with resizing.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/include/linux/netfilter/ip_set_chash.h184
-rw-r--r--kernel/ip_set_hash_ip.c16
-rw-r--r--kernel/ip_set_hash_ipport.c15
-rw-r--r--kernel/ip_set_hash_ipportip.c15
-rw-r--r--kernel/ip_set_hash_ipportnet.c15
-rw-r--r--kernel/ip_set_hash_net.c15
-rw-r--r--kernel/ip_set_hash_netport.c15
7 files changed, 157 insertions, 118 deletions
diff --git a/kernel/include/linux/netfilter/ip_set_chash.h b/kernel/include/linux/netfilter/ip_set_chash.h
index f0ef580..f223275 100644
--- a/kernel/include/linux/netfilter/ip_set_chash.h
+++ b/kernel/include/linux/netfilter/ip_set_chash.h
@@ -23,14 +23,18 @@ struct chash_nets {
u32 nets; /* number of elements per cidr */
};
+struct htable {
+ u8 htable_bits; /* size of hash table == 2^htable_bits */
+ struct slist htable[0]; /* hashtable of single linked lists */
+};
+
struct chash {
- struct slist *htable; /* Hashtable of single linked lists */
- u32 maxelem; /* Max elements in the hash */
- u32 elements; /* Current element (vs timeout) */
+ struct htable *table; /* the hash table */
+ u32 maxelem; /* max elements in the hash */
+ u32 elements; /* current element (vs timeout) */
u32 initval; /* random jhash init value */
u32 timeout; /* timeout value, if enabled */
struct timer_list gc; /* garbage collection when timeout enabled */
- u8 htable_bits; /* size of hash table == 2^htable_bits */
u8 array_size; /* number of elements in an array */
u8 chain_limit; /* max number of arrays */
#ifdef IP_SET_HASH_WITH_NETMASK
@@ -105,17 +109,17 @@ del_cidr(struct chash *h, u8 cidr, u8 host_mask)
/* Destroy the hashtable part of the set */
static void
-chash_destroy(struct slist *t, u8 htable_bits)
+chash_destroy(struct htable *ht)
{
struct slist *n, *tmp;
u32 i;
- for (i = 0; i < jhash_size(htable_bits); i++)
- slist_for_each_safe(n, tmp, &t[i])
+ for (i = 0; i < jhash_size(ht->htable_bits); i++)
+ slist_for_each_safe(n, tmp, &ht->htable[i])
/* FIXME: use slab cache */
kfree(n);
- ip_set_free(t);
+ ip_set_free(ht);
}
/* Calculate the actual memory size of the set data */
@@ -124,14 +128,15 @@ chash_memsize(const struct chash *h, size_t dsize, u8 host_mask)
{
struct slist *n;
u32 i;
+ struct htable *ht = h->table;
size_t memsize = sizeof(*h)
#ifdef IP_SET_HASH_WITH_NETS
+ sizeof(struct chash_nets) * host_mask
#endif
- + jhash_size(h->htable_bits) * sizeof(struct slist);
+ + jhash_size(ht->htable_bits) * sizeof(struct slist);
- for (i = 0; i < jhash_size(h->htable_bits); i++)
- slist_for_each(n, &h->htable[i])
+ for (i = 0; i < jhash_size(ht->htable_bits); i++)
+ slist_for_each(n, &ht->htable[i])
memsize += sizeof(struct slist)
+ h->array_size * dsize;
@@ -143,14 +148,15 @@ static void
ip_set_hash_flush(struct ip_set *set)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
struct slist *n, *tmp;
u32 i;
- for (i = 0; i < jhash_size(h->htable_bits); i++) {
- slist_for_each_safe(n, tmp, &h->htable[i])
+ for (i = 0; i < jhash_size(ht->htable_bits); i++) {
+ slist_for_each_safe(n, tmp, &ht->htable[i])
/* FIXME: slab cache */
kfree(n);
- h->htable[i].next = NULL;
+ ht->htable[i].next = NULL;
}
#ifdef IP_SET_HASH_WITH_NETS
memset(h->nets, 0, sizeof(struct chash_nets)
@@ -168,7 +174,7 @@ ip_set_hash_destroy(struct ip_set *set)
if (with_timeout(h->timeout))
del_timer_sync(&h->gc);
- chash_destroy(h->htable, h->htable_bits);
+ chash_destroy(h->table);
kfree(h);
set->data = NULL;
@@ -241,16 +247,17 @@ ip_set_hash_destroy(struct ip_set *set)
/* Add an element to the hash table when resizing the set:
* we spare the maintenance of the internal counters. */
static int
-type_pf_chash_readd(struct chash *h, struct slist *t, u8 htable_bits,
- const struct type_pf_elem *value, gfp_t gfp_flags)
+type_pf_chash_readd(struct chash *h, struct htable *ht,
+ const struct type_pf_elem *value,
+ gfp_t gfp_flags)
{
struct slist *n, *prev;
struct type_pf_elem *data;
void *tmp;
int i = 0, j = 0;
- u32 hash = JHASH2(value, h->initval, htable_bits);
+ u32 hash = JHASH2(value, h->initval, ht->htable_bits);
- slist_for_each_prev(prev, n, &t[hash]) {
+ slist_for_each_prev(prev, n, &ht->htable[hash]) {
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data)) {
@@ -325,8 +332,9 @@ static int
type_pf_resize(struct ip_set *set, gfp_t gfp_flags, bool retried)
{
struct chash *h = set->data;
- u8 htable_bits = h->htable_bits;
- struct slist *t, *n;
+ struct htable *ht, *orig = h->table;
+ u8 htable_bits = orig->htable_bits;
+ struct slist *n;
const struct type_pf_elem *data;
u32 i, j;
int ret;
@@ -337,26 +345,28 @@ retry:
if (!htable_bits)
/* In case we have plenty of memory :-) */
return -IPSET_ERR_HASH_FULL;
- t = ip_set_alloc(jhash_size(htable_bits) * sizeof(struct slist),
- GFP_KERNEL);
- if (!t)
+ ht = ip_set_alloc(sizeof(*ht)
+ + jhash_size(htable_bits) * sizeof(struct slist),
+ GFP_KERNEL);
+ if (!ht)
return -ENOMEM;
+ ht->htable_bits = htable_bits;
- write_lock_bh(&set->lock);
+ read_lock_bh(&set->lock);
next_slot:
- for (; i < jhash_size(h->htable_bits); i++) {
- slist_for_each(n, &h->htable[i]) {
+ for (; i < jhash_size(orig->htable_bits); i++) {
+ slist_for_each(n, &orig->htable[i]) {
for (j = 0; j < h->array_size; j++) {
data = chash_data(n, j);
if (type_pf_data_isnull(data)) {
i++;
goto next_slot;
}
- ret = type_pf_chash_readd(h, t, htable_bits,
+ ret = type_pf_chash_readd(h, ht,
data, gfp_flags);
if (ret < 0) {
- write_unlock_bh(&set->lock);
- chash_destroy(t, htable_bits);
+ read_unlock_bh(&set->lock);
+ chash_destroy(ht);
if (ret == -EAGAIN)
goto retry;
return ret;
@@ -365,14 +375,13 @@ next_slot:
}
}
- n = h->htable;
- i = h->htable_bits;
+ h->table = ht;
+ read_unlock_bh(&set->lock);
- h->htable = t;
- h->htable_bits = htable_bits;
- write_unlock_bh(&set->lock);
+ /* Give time to other users of the set */
+ synchronize_net();
- chash_destroy(n, i);
+ chash_destroy(orig);
return 0;
}
@@ -385,7 +394,8 @@ type_pf_chash_add(struct ip_set *set, void *value,
{
struct chash *h = set->data;
const struct type_pf_elem *d = value;
- struct slist *n, *prev, *t = h->htable;
+ struct slist *n, *prev;
+ struct htable *ht = h->table;
struct type_pf_elem *data;
void *tmp;
int i = 0, j = 0;
@@ -394,8 +404,8 @@ type_pf_chash_add(struct ip_set *set, void *value,
if (h->elements >= h->maxelem)
return -IPSET_ERR_HASH_FULL;
- hash = JHASH2(value, h->initval, h->htable_bits);
- slist_for_each_prev(prev, n, &t[hash]) {
+ hash = JHASH2(value, h->initval, ht->htable_bits);
+ slist_for_each_prev(prev, n, &ht->htable[hash]) {
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data)) {
@@ -434,12 +444,13 @@ type_pf_chash_del(struct ip_set *set, void *value,
{
struct chash *h = set->data;
const struct type_pf_elem *d = value;
+ struct htable *ht = h->table;
struct slist *n, *prev;
int i;
struct type_pf_elem *data;
- u32 hash = JHASH2(value, h->initval, h->htable_bits);
+ u32 hash = JHASH2(value, h->initval, ht->htable_bits);
- slist_for_each_prev(prev, n, &h->htable[hash])
+ slist_for_each_prev(prev, n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data))
@@ -463,6 +474,7 @@ type_pf_chash_test_cidrs(struct ip_set *set,
gfp_t gfp_flags, u32 timeout)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
struct slist *n;
const struct type_pf_elem *data;
int i, j = 0;
@@ -473,8 +485,8 @@ retry:
pr_debug("test by nets");
for (; j < host_mask && h->nets[j].cidr; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
- hash = JHASH2(d, h->initval, h->htable_bits);
- slist_for_each(n, &h->htable[hash])
+ hash = JHASH2(d, h->initval, ht->htable_bits);
+ slist_for_each(n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data)) {
@@ -495,6 +507,7 @@ type_pf_chash_test(struct ip_set *set, void *value,
gfp_t gfp_flags, u32 timeout)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
struct type_pf_elem *d = value;
struct slist *n;
const struct type_pf_elem *data;
@@ -508,8 +521,8 @@ type_pf_chash_test(struct ip_set *set, void *value,
return type_pf_chash_test_cidrs(set, d, gfp_flags, timeout);
#endif
- hash = JHASH2(d, h->initval, h->htable_bits);
- slist_for_each(n, &h->htable[hash])
+ hash = JHASH2(d, h->initval, ht->htable_bits);
+ slist_for_each(n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data))
@@ -539,7 +552,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
if (!nested)
goto nla_put_failure;
NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,
- htonl(jhash_size(h->htable_bits)));
+ htonl(jhash_size(h->table->htable_bits)));
NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));
#ifdef IP_SET_HASH_WITH_NETMASK
if (h->netmask != HOST_MASK)
@@ -563,6 +576,7 @@ type_pf_list(struct ip_set *set,
struct sk_buff *skb, struct netlink_callback *cb)
{
const struct chash *h = set->data;
+ const struct htable *ht = h->table;
struct nlattr *atd, *nested;
struct slist *n;
const struct type_pf_elem *data;
@@ -575,9 +589,9 @@ type_pf_list(struct ip_set *set,
if (!atd)
return -EFAULT;
pr_debug("list hash set %s", set->name);
- for (; cb->args[2] < jhash_size(h->htable_bits); cb->args[2]++) {
+ for (; cb->args[2] < jhash_size(ht->htable_bits); cb->args[2]++) {
incomplete = skb_tail_pointer(skb);
- slist_for_each(n, &h->htable[cb->args[2]]) {
+ slist_for_each(n, &ht->htable[cb->args[2]]) {
for (i = 0; i < h->array_size; i++) {
data = chash_data(n, i);
if (type_pf_data_isnull(data))
@@ -681,7 +695,7 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
}
static int
-type_pf_chash_treadd(struct chash *h, struct slist *t, u8 htable_bits,
+type_pf_chash_treadd(struct chash *h, struct htable *ht,
const struct type_pf_elem *value,
gfp_t gfp_flags, u32 timeout)
{
@@ -689,9 +703,9 @@ type_pf_chash_treadd(struct chash *h, struct slist *t, u8 htable_bits,
struct type_pf_elem *data;
void *tmp;
int i = 0, j = 0;
- u32 hash = JHASH2(value, h->initval, htable_bits);
+ u32 hash = JHASH2(value, h->initval, ht->htable_bits);
- slist_for_each_prev(prev, n, &t[hash]) {
+ slist_for_each_prev(prev, n, &ht->htable[hash]) {
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
if (type_pf_data_isnull(data)) {
@@ -764,13 +778,14 @@ type_pf_chash_del_telem(struct chash *h, struct slist *prev,
static void
type_pf_chash_expire(struct chash *h)
{
+ struct htable *ht = h->table;
struct slist *n, *prev;
struct type_pf_elem *data;
u32 i;
int j;
- for (i = 0; i < jhash_size(h->htable_bits); i++)
- slist_for_each_prev(prev, n, &h->htable[i])
+ for (i = 0; i < jhash_size(ht->htable_bits); i++)
+ slist_for_each_prev(prev, n, &ht->htable[i])
for (j = 0; j < h->array_size; j++) {
data = chash_tdata(n, j);
if (type_pf_data_isnull(data))
@@ -786,8 +801,9 @@ static int
type_pf_tresize(struct ip_set *set, gfp_t gfp_flags, bool retried)
{
struct chash *h = set->data;
- u8 htable_bits = h->htable_bits;
- struct slist *t, *n;
+ struct htable *ht, *orig = h->table;
+ u8 htable_bits = orig->htable_bits;
+ struct slist *n;
const struct type_pf_elem *data;
u32 i, j;
int ret;
@@ -808,27 +824,29 @@ retry:
if (!htable_bits)
/* In case we have plenty of memory :-) */
return -IPSET_ERR_HASH_FULL;
- t = ip_set_alloc(jhash_size(htable_bits) * sizeof(struct slist),
+ ht = ip_set_alloc(sizeof(*ht)
+ + jhash_size(htable_bits) * sizeof(struct slist),
GFP_KERNEL);
- if (!t)
+ if (!ht)
return -ENOMEM;
+ ht->htable_bits = htable_bits;
- write_lock_bh(&set->lock);
+ read_lock_bh(&set->lock);
next_slot:
- for (; i < jhash_size(h->htable_bits); i++) {
- slist_for_each(n, &h->htable[i]) {
+ for (; i < jhash_size(orig->htable_bits); i++) {
+ slist_for_each(n, &orig->htable[i]) {
for (j = 0; j < h->array_size; j++) {
data = chash_tdata(n, j);
if (type_pf_data_isnull(data)) {
i++;
goto next_slot;
}
- ret = type_pf_chash_treadd(h, t, htable_bits,
+ ret = type_pf_chash_treadd(h, ht,
data, gfp_flags,
type_pf_data_timeout(data));
if (ret < 0) {
- write_unlock_bh(&set->lock);
- chash_destroy(t, htable_bits);
+ read_unlock_bh(&set->lock);
+ chash_destroy(ht);
if (ret == -EAGAIN)
goto retry;
return ret;
@@ -837,14 +855,13 @@ next_slot:
}
}
- n = h->htable;
- i = h->htable_bits;
-
- h->htable = t;
- h->htable_bits = htable_bits;
- write_unlock_bh(&set->lock);
+ h->table = ht;
+ read_unlock_bh(&set->lock);
- chash_destroy(n, i);
+ /* Give time to other users of the set */
+ synchronize_net();
+
+ chash_destroy(orig);
return 0;
}
@@ -855,7 +872,8 @@ type_pf_chash_tadd(struct ip_set *set, void *value,
{
struct chash *h = set->data;
const struct type_pf_elem *d = value;
- struct slist *n, *prev, *t = h->htable;
+ struct slist *n, *prev;
+ struct htable *ht = h->table;
struct type_pf_elem *data;
void *tmp;
int i = 0, j = 0;
@@ -867,8 +885,8 @@ type_pf_chash_tadd(struct ip_set *set, void *value,
if (h->elements >= h->maxelem)
return -IPSET_ERR_HASH_FULL;
- hash = JHASH2(d, h->initval, h->htable_bits);
- slist_for_each_prev(prev, n, &t[hash]) {
+ hash = JHASH2(d, h->initval, ht->htable_bits);
+ slist_for_each_prev(prev, n, &ht->htable[hash]) {
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
if (type_pf_data_isnull(data)
@@ -911,13 +929,14 @@ type_pf_chash_tdel(struct ip_set *set, void *value,
gfp_t gfp_flags, u32 timeout)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
const struct type_pf_elem *d = value;
struct slist *n, *prev;
int i, ret = 0;
struct type_pf_elem *data;
- u32 hash = JHASH2(value, h->initval, h->htable_bits);
+ u32 hash = JHASH2(value, h->initval, ht->htable_bits);
- slist_for_each_prev(prev, n, &h->htable[hash])
+ slist_for_each_prev(prev, n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
if (type_pf_data_isnull(data))
@@ -940,6 +959,7 @@ type_pf_chash_ttest_cidrs(struct ip_set *set,
gfp_t gfp_flags, u32 timeout)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
struct type_pf_elem *data;
struct slist *n;
int i, j = 0;
@@ -949,8 +969,8 @@ type_pf_chash_ttest_cidrs(struct ip_set *set,
retry:
for (; j < host_mask && h->nets[j].cidr; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
- hash = JHASH2(d, h->initval, h->htable_bits);
- slist_for_each(n, &h->htable[hash])
+ hash = JHASH2(d, h->initval, ht->htable_bits);
+ slist_for_each(n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
if (type_pf_data_isnull(data)) {
@@ -970,6 +990,7 @@ type_pf_chash_ttest(struct ip_set *set, void *value,
gfp_t gfp_flags, u32 timeout)
{
struct chash *h = set->data;
+ struct htable *ht = h->table;
struct type_pf_elem *data, *d = value;
struct slist *n;
int i;
@@ -980,8 +1001,8 @@ type_pf_chash_ttest(struct ip_set *set, void *value,
return type_pf_chash_ttest_cidrs(set, d, gfp_flags,
timeout);
#endif
- hash = JHASH2(d, h->initval, h->htable_bits);
- slist_for_each(n, &h->htable[hash])
+ hash = JHASH2(d, h->initval, ht->htable_bits);
+ slist_for_each(n, &ht->htable[hash])
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
if (type_pf_data_isnull(data))
@@ -997,6 +1018,7 @@ type_pf_tlist(struct ip_set *set,
struct sk_buff *skb, struct netlink_callback *cb)
{
const struct chash *h = set->data;
+ const struct htable *ht = h->table;
struct nlattr *atd, *nested;
struct slist *n;
const struct type_pf_elem *data;
@@ -1008,9 +1030,9 @@ type_pf_tlist(struct ip_set *set,
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!atd)
return -EFAULT;
- for (; cb->args[2] < jhash_size(h->htable_bits); cb->args[2]++) {
+ for (; cb->args[2] < jhash_size(ht->htable_bits); cb->args[2]++) {
incomplete = skb_tail_pointer(skb);
- slist_for_each(n, &h->htable[cb->args[2]]) {
+ slist_for_each(n, &ht->htable[cb->args[2]]) {
for (i = 0; i < h->array_size; i++) {
data = chash_tdata(n, i);
pr_debug("list %p %u", n, i);
diff --git a/kernel/ip_set_hash_ip.c b/kernel/ip_set_hash_ip.c
index 6fad300..32093fc 100644
--- a/kernel/ip_set_hash_ip.c
+++ b/kernel/ip_set_hash_ip.c
@@ -387,7 +387,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
{
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 netmask;
+ u8 netmask, hbits;
struct chash *h;
if (!(set->family == AF_INET || set->family == AF_INET6))
@@ -424,19 +424,21 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
h->maxelem = maxelem;
h->netmask = netmask;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -456,8 +458,8 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
diff --git a/kernel/ip_set_hash_ipport.c b/kernel/ip_set_hash_ipport.c
index 1dd8187..ddd0d28 100644
--- a/kernel/ip_set_hash_ipport.c
+++ b/kernel/ip_set_hash_ipport.c
@@ -416,6 +416,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
struct chash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+ u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
@@ -438,19 +439,21 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
return -ENOMEM;
h->maxelem = maxelem;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -470,8 +473,8 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
diff --git a/kernel/ip_set_hash_ipportip.c b/kernel/ip_set_hash_ipportip.c
index a20f1ef..0e46268 100644
--- a/kernel/ip_set_hash_ipportip.c
+++ b/kernel/ip_set_hash_ipportip.c
@@ -437,6 +437,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
struct chash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+ u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
@@ -459,19 +460,21 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
return -ENOMEM;
h->maxelem = maxelem;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -491,8 +494,8 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
diff --git a/kernel/ip_set_hash_ipportnet.c b/kernel/ip_set_hash_ipportnet.c
index 3904168..4151135 100644
--- a/kernel/ip_set_hash_ipportnet.c
+++ b/kernel/ip_set_hash_ipportnet.c
@@ -500,6 +500,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
struct chash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+ u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
@@ -524,19 +525,21 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
return -ENOMEM;
h->maxelem = maxelem;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -557,8 +560,8 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
diff --git a/kernel/ip_set_hash_net.c b/kernel/ip_set_hash_net.c
index 27191f2..4cb57ac 100644
--- a/kernel/ip_set_hash_net.c
+++ b/kernel/ip_set_hash_net.c
@@ -399,6 +399,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
struct chash *h;
+ u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
@@ -423,19 +424,21 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
return -ENOMEM;
h->maxelem = maxelem;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -455,8 +458,8 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
diff --git a/kernel/ip_set_hash_netport.c b/kernel/ip_set_hash_netport.c
index f7f43b8..db4d2f5 100644
--- a/kernel/ip_set_hash_netport.c
+++ b/kernel/ip_set_hash_netport.c
@@ -477,6 +477,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
struct chash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+ u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
@@ -501,19 +502,21 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
return -ENOMEM;
h->maxelem = maxelem;
- h->htable_bits = htable_bits(hashsize);
h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
- h->htable = ip_set_alloc(
- jhash_size(h->htable_bits) * sizeof(struct slist),
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct slist),
GFP_KERNEL);
- if (!h->htable) {
+ if (!h->table) {
kfree(h);
return -ENOMEM;
}
+ h->table->htable_bits = hbits;
set->data = h;
@@ -533,8 +536,8 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
- set->name, jhash_size(h->htable_bits),
- h->htable_bits, h->maxelem, set->data, h->htable);
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}