[PATCH 10/22] netfilter: ipset: Count non-static extension memory for userspace

2016-10-23 Thread Jozsef Kadlecsik
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.

Signed-off-by: Jozsef Kadlecsik 
---
 include/linux/netfilter/ipset/ip_set.h |  8 ++--
 include/linux/netfilter/ipset/ip_set_comment.h |  7 +--
 net/netfilter/ipset/ip_set_bitmap_gen.h|  5 +++--
 net/netfilter/ipset/ip_set_core.c  |  2 +-
 net/netfilter/ipset/ip_set_hash_gen.h  | 26 ++
 net/netfilter/ipset/ip_set_list_set.c  |  5 +++--
 6 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/include/linux/netfilter/ipset/ip_set.h 
b/include/linux/netfilter/ipset/ip_set.h
index 4671d74..8e42253 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -79,10 +79,12 @@ enum ip_set_ext_id {
IPSET_EXT_ID_MAX,
 };
 
+struct ip_set;
+
 /* Extension type */
 struct ip_set_ext_type {
/* Destroy extension private data (can be NULL) */
-   void (*destroy)(void *ext);
+   void (*destroy)(struct ip_set *set, void *ext);
enum ip_set_extension type;
enum ipset_cadt_flags flag;
/* Size and minimal alignment */
@@ -252,6 +254,8 @@ struct ip_set {
u32 timeout;
/* Number of elements (vs timeout) */
u32 elements;
+   /* Size of the dynamic extensions (vs timeout) */
+   size_t ext_size;
/* Element data size */
size_t dsize;
/* Offsets to extensions in elements */
@@ -268,7 +272,7 @@ struct ip_set {
 */
if (SET_WITH_COMMENT(set))
ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(
-   ext_comment(data, set));
+   set, ext_comment(data, set));
 }
 
 static inline int
diff --git a/include/linux/netfilter/ipset/ip_set_comment.h 
b/include/linux/netfilter/ipset/ip_set_comment.h
index 5444b1b..8e2bab1 100644
--- a/include/linux/netfilter/ipset/ip_set_comment.h
+++ b/include/linux/netfilter/ipset/ip_set_comment.h
@@ -20,13 +20,14 @@
  * The kadt functions don't use the comment extensions in any way.
  */
 static inline void
-ip_set_init_comment(struct ip_set_comment *comment,
+ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
const struct ip_set_ext *ext)
 {
struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1);
size_t len = ext->comment ? strlen(ext->comment) : 0;
 
if (unlikely(c)) {
+   set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
}
@@ -38,6 +39,7 @@
if (unlikely(!c))
return;
strlcpy(c->str, ext->comment, len + 1);
+   set->ext_size += sizeof(*c) + strlen(c->str) + 1;
rcu_assign_pointer(comment->c, c);
 }
 
@@ -58,13 +60,14 @@
  * of the set data anymore.
  */
 static inline void
-ip_set_comment_free(struct ip_set_comment *comment)
+ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment)
 {
struct ip_set_comment_rcu *c;
 
c = rcu_dereference_protected(comment->c, 1);
if (unlikely(!c))
return;
+   set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
 }
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h 
b/net/netfilter/ipset/ip_set_bitmap_gen.h
index 13a7021..5a9fa61 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -84,6 +84,7 @@
mtype_ext_cleanup(set);
memset(map->members, 0, map->memsize);
set->elements = 0;
+   set->ext_size = 0;
 }
 
 /* Calculate the actual memory size of the set data */
@@ -101,7 +102,7 @@
 {
const struct mtype *map = set->data;
struct nlattr *nested;
-   size_t memsize = mtype_memsize(map, set->dsize);
+   size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
 
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested)
@@ -175,7 +176,7 @@
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(x, set), ext);
if (SET_WITH_COMMENT(set))
-   ip_set_init_comment(ext_comment(x, set), ext);
+   ip_set_init_comment(set, ext_comment(x, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(x, set), ext);
 
diff --git a/net/netfilter/ipset/ip_set_core.c 
b/net/netfilter/ipset/ip_set_core.c
index 3bca341..cd8961e 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -324,7 +324,7 @@ static inline struct ip_set_net *ip_set_pernet(struct net 
*net)
 }
 EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
 
-typedef voi

[PATCH 10/22] netfilter: ipset: Count non-static extension memory for userspace

2016-10-17 Thread Jozsef Kadlecsik
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.

Signed-off-by: Jozsef Kadlecsik 
---
 include/linux/netfilter/ipset/ip_set.h |  8 ++--
 include/linux/netfilter/ipset/ip_set_comment.h |  7 +--
 net/netfilter/ipset/ip_set_bitmap_gen.h|  5 +++--
 net/netfilter/ipset/ip_set_core.c  |  2 +-
 net/netfilter/ipset/ip_set_hash_gen.h  | 26 ++
 net/netfilter/ipset/ip_set_list_set.c  |  5 +++--
 6 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/include/linux/netfilter/ipset/ip_set.h 
b/include/linux/netfilter/ipset/ip_set.h
index 4671d74..8e42253 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -79,10 +79,12 @@ enum ip_set_ext_id {
IPSET_EXT_ID_MAX,
 };
 
+struct ip_set;
+
 /* Extension type */
 struct ip_set_ext_type {
/* Destroy extension private data (can be NULL) */
-   void (*destroy)(void *ext);
+   void (*destroy)(struct ip_set *set, void *ext);
enum ip_set_extension type;
enum ipset_cadt_flags flag;
/* Size and minimal alignment */
@@ -252,6 +254,8 @@ struct ip_set {
u32 timeout;
/* Number of elements (vs timeout) */
u32 elements;
+   /* Size of the dynamic extensions (vs timeout) */
+   size_t ext_size;
/* Element data size */
size_t dsize;
/* Offsets to extensions in elements */
@@ -268,7 +272,7 @@ struct ip_set {
 */
if (SET_WITH_COMMENT(set))
ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(
-   ext_comment(data, set));
+   set, ext_comment(data, set));
 }
 
 static inline int
diff --git a/include/linux/netfilter/ipset/ip_set_comment.h 
b/include/linux/netfilter/ipset/ip_set_comment.h
index 5444b1b..8e2bab1 100644
--- a/include/linux/netfilter/ipset/ip_set_comment.h
+++ b/include/linux/netfilter/ipset/ip_set_comment.h
@@ -20,13 +20,14 @@
  * The kadt functions don't use the comment extensions in any way.
  */
 static inline void
-ip_set_init_comment(struct ip_set_comment *comment,
+ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
const struct ip_set_ext *ext)
 {
struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1);
size_t len = ext->comment ? strlen(ext->comment) : 0;
 
if (unlikely(c)) {
+   set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
}
@@ -38,6 +39,7 @@
if (unlikely(!c))
return;
strlcpy(c->str, ext->comment, len + 1);
+   set->ext_size += sizeof(*c) + strlen(c->str) + 1;
rcu_assign_pointer(comment->c, c);
 }
 
@@ -58,13 +60,14 @@
  * of the set data anymore.
  */
 static inline void
-ip_set_comment_free(struct ip_set_comment *comment)
+ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment)
 {
struct ip_set_comment_rcu *c;
 
c = rcu_dereference_protected(comment->c, 1);
if (unlikely(!c))
return;
+   set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
 }
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h 
b/net/netfilter/ipset/ip_set_bitmap_gen.h
index 13a7021..5a9fa61 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -84,6 +84,7 @@
mtype_ext_cleanup(set);
memset(map->members, 0, map->memsize);
set->elements = 0;
+   set->ext_size = 0;
 }
 
 /* Calculate the actual memory size of the set data */
@@ -101,7 +102,7 @@
 {
const struct mtype *map = set->data;
struct nlattr *nested;
-   size_t memsize = mtype_memsize(map, set->dsize);
+   size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
 
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested)
@@ -175,7 +176,7 @@
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(x, set), ext);
if (SET_WITH_COMMENT(set))
-   ip_set_init_comment(ext_comment(x, set), ext);
+   ip_set_init_comment(set, ext_comment(x, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(x, set), ext);
 
diff --git a/net/netfilter/ipset/ip_set_core.c 
b/net/netfilter/ipset/ip_set_core.c
index 3bca341..cd8961e 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -324,7 +324,7 @@ static inline struct ip_set_net *ip_set_pernet(struct net 
*net)
 }
 EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
 
-typedef voi