summaryrefslogtreecommitdiffstats
path: root/kernel/net/netfilter/ipset/ip_set_hash_gen.h
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2015-06-26 09:40:14 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2015-06-26 09:40:14 +0200
commit5a5688893ae312faf2574e7c707a78c225256973 (patch)
treeb870b69f3db9f4ff0fd1722230aada6801332d73 /kernel/net/netfilter/ipset/ip_set_hash_gen.h
parentff0f4b65fb95474890301c2c10133f2d071ad360 (diff)
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.
Diffstat (limited to 'kernel/net/netfilter/ipset/ip_set_hash_gen.h')
-rw-r--r--kernel/net/netfilter/ipset/ip_set_hash_gen.h26
1 files changed, 14 insertions, 12 deletions
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();