From 5a5688893ae312faf2574e7c707a78c225256973 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 26 Jun 2015 09:40:14 +0200 Subject: Count non-static extension memory into the set memory size for userspace Non-static (i.e. comment) extension was not counted into the memory size. A new internal counter is introduced for this. In the case of the hash types the sizes of the arrays are counted there as well so that we can avoid to scan the whole set when just the header data is requested. --- kernel/net/netfilter/ipset/ip_set_hash_gen.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'kernel/net/netfilter/ipset/ip_set_hash_gen.h') diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h index 191707d..d9a6699 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h @@ -340,21 +340,13 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) /* Calculate the actual memory size of the set data */ static size_t mtype_ahash_memsize(const struct htype *h, const struct htable *t, - u8 nets_length, size_t dsize) + u8 nets_length) { - u32 i; - struct hbucket *n; size_t memsize = sizeof(*h) + sizeof(*t); #ifdef IP_SET_HASH_WITH_NETS memsize += sizeof(struct net_prefixes) * nets_length; #endif - for (i = 0; i < jhash_size(t->htable_bits); i++) { - n = rcu_dereference_bh(hbucket(t, i)); - if (!n) - continue; - memsize += sizeof(struct hbucket) + n->size * dsize; - } return memsize; } @@ -397,6 +389,7 @@ mtype_flush(struct ip_set *set) memset(h->nets, 0, sizeof(struct net_prefixes) * NLEN(set->family)); #endif set->elements = 0; + set->ext_size = 0; } /* Destroy the hashtable part of the set */ @@ -523,6 +516,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize) d++; } tmp->pos = d; + set->ext_size -= AHASH_INIT_SIZE * dsize; rcu_assign_pointer(hbucket(t, i), tmp); kfree_rcu(n, rcu); } @@ -554,7 +548,7 @@ mtype_resize(struct ip_set *set, bool retried) struct htype *h = set->data; struct htable *t, *orig; u8 htable_bits; - size_t dsize = set->dsize; + size_t extsize, dsize = set->dsize; #ifdef IP_SET_HASH_WITH_NETS u8 flags; struct mtype_elem *tmp; @@ -597,6 +591,7 @@ retry: /* There can't be another parallel resizing, but dumping is possible */ atomic_set(&orig->ref, 1); atomic_inc(&orig->uref); + extsize = 0; pr_debug("attempt to resize set %s from %u to %u, t %p\n", set->name, orig->htable_bits, htable_bits, orig); for (i = 0; i < jhash_size(orig->htable_bits); i++) { @@ -627,6 +622,7 @@ retry: goto cleanup; } m->size = AHASH_INIT_SIZE; + extsize = sizeof(*m) + AHASH_INIT_SIZE * dsize; RCU_INIT_POINTER(hbucket(t, key), m); } else if (m->pos >= m->size) { struct hbucket *ht; @@ -646,6 +642,7 @@ retry: memcpy(ht, m, sizeof(struct hbucket) + m->size * dsize); ht->size = m->size + AHASH_INIT_SIZE; + extsize += AHASH_INIT_SIZE * dsize; kfree(m); m = ht; RCU_INIT_POINTER(hbucket(t, key), ht); @@ -659,6 +656,7 @@ retry: } } rcu_assign_pointer(h->table, t); + set->ext_size = extsize; spin_unlock_bh(&set->lock); @@ -732,6 +730,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, if (!n) return -ENOMEM; n->size = AHASH_INIT_SIZE; + set->ext_size += sizeof(*n) + AHASH_INIT_SIZE * set->dsize; goto copy_elem; } for (i = 0; i < n->pos; i++) { @@ -795,6 +794,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, memcpy(n, old, sizeof(struct hbucket) + old->size * set->dsize); n->size = old->size + AHASH_INIT_SIZE; + set->ext_size += AHASH_INIT_SIZE * set->dsize; } copy_elem: @@ -815,7 +815,7 @@ overwrite_extensions: if (SET_WITH_COUNTER(set)) ip_set_init_counter(ext_counter(data, set), ext); if (SET_WITH_COMMENT(set)) - ip_set_init_comment(ext_comment(data, set), ext); + ip_set_init_comment(set, ext_comment(data, set), ext); if (SET_WITH_SKBINFO(set)) ip_set_init_skbinfo(ext_skbinfo(data, set), ext); /* Must come last for the case when timed out entry is reused */ @@ -887,6 +887,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, k++; } if (n->pos == 0 && k == 0) { + set->ext_size -= sizeof(*n) + n->size * dsize; rcu_assign_pointer(hbucket(t, key), NULL); kfree_rcu(n, rcu); } else if (k >= AHASH_INIT_SIZE) { @@ -905,6 +906,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, k++; } tmp->pos = k; + set->ext_size -= AHASH_INIT_SIZE * dsize; rcu_assign_pointer(hbucket(t, key), tmp); kfree_rcu(n, rcu); } @@ -1053,7 +1055,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) rcu_read_lock_bh(); t = rcu_dereference_bh_nfnl(h->table, NFNL_SUBSYS_IPSET); - memsize = mtype_ahash_memsize(h, t, NLEN(set->family), set->dsize); + memsize = mtype_ahash_memsize(h, t, NLEN(set->family)) + set->ext_size; htable_bits = t->htable_bits; rcu_read_unlock_bh(); -- cgit v1.2.3