[ipset-5: 6/9] Resizing converted to run under read-locking of the set

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Signed-off-by: Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxxxxxx>
---
 kernel/include/linux/netfilter/ip_set_chash.h |  184 ++++++++++++++-----------
 kernel/ip_set_hash_ip.c                       |   16 ++-
 kernel/ip_set_hash_ipport.c                   |   15 ++-
 kernel/ip_set_hash_ipportip.c                 |   15 ++-
 kernel/ip_set_hash_ipportnet.c                |   15 ++-
 kernel/ip_set_hash_net.c                      |   15 ++-
 kernel/ip_set_hash_netport.c                  |   15 ++-
 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;
 }

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux