netfilter: nfnl_acct: remove data from struct net
authorWang Shanker <shankerwangmiao@gmail.com>
Mon, 16 Nov 2020 04:17:24 +0000 (12:17 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 1 Dec 2020 08:45:29 +0000 (09:45 +0100)
This patch removes nfnl_acct_list from struct net to reduce the default
memory footprint for the netns structure.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/net_namespace.h
net/netfilter/nfnetlink_acct.c

index 22bc07f..dc20a47 100644 (file)
@@ -151,9 +151,6 @@ struct net {
 #endif
        struct sock             *nfnl;
        struct sock             *nfnl_stash;
-#if IS_ENABLED(CONFIG_NETFILTER_NETLINK_ACCT)
-       struct list_head        nfnl_acct_list;
-#endif
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
        struct list_head        nfct_timeout_list;
 #endif
index 5e511df..0fa1653 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <net/netlink.h>
 #include <net/sock.h>
+#include <net/netns/generic.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -41,6 +42,17 @@ struct nfacct_filter {
        u32 mask;
 };
 
+struct nfnl_acct_net {
+       struct list_head        nfnl_acct_list;
+};
+
+static unsigned int nfnl_acct_net_id __read_mostly;
+
+static inline struct nfnl_acct_net *nfnl_acct_pernet(struct net *net)
+{
+       return net_generic(net, nfnl_acct_net_id);
+}
+
 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
 #define NFACCT_OVERQUOTA_BIT   2       /* NFACCT_F_OVERQUOTA */
 
@@ -49,6 +61,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
                         const struct nlattr * const tb[],
                         struct netlink_ext_ack *extack)
 {
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        struct nf_acct *nfacct, *matching = NULL;
        char *acct_name;
        unsigned int size = 0;
@@ -61,7 +74,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
        if (strlen(acct_name) == 0)
                return -EINVAL;
 
-       list_for_each_entry(nfacct, &net->nfnl_acct_list, head) {
+       list_for_each_entry(nfacct, &nfnl_acct_net->nfnl_acct_list, head) {
                if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
                        continue;
 
@@ -123,7 +136,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
                             be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
        }
        refcount_set(&nfacct->refcnt, 1);
-       list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list);
+       list_add_tail_rcu(&nfacct->head, &nfnl_acct_net->nfnl_acct_list);
        return 0;
 }
 
@@ -188,6 +201,7 @@ static int
 nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        struct nf_acct *cur, *last;
        const struct nfacct_filter *filter = cb->data;
 
@@ -199,7 +213,7 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
                cb->args[1] = 0;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) {
+       list_for_each_entry_rcu(cur, &nfnl_acct_net->nfnl_acct_list, head) {
                if (last) {
                        if (cur != last)
                                continue;
@@ -269,6 +283,7 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
                         const struct nlattr * const tb[],
                         struct netlink_ext_ack *extack)
 {
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        int ret = -ENOENT;
        struct nf_acct *cur;
        char *acct_name;
@@ -288,7 +303,7 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
                return -EINVAL;
        acct_name = nla_data(tb[NFACCT_NAME]);
 
-       list_for_each_entry(cur, &net->nfnl_acct_list, head) {
+       list_for_each_entry(cur, &nfnl_acct_net->nfnl_acct_list, head) {
                struct sk_buff *skb2;
 
                if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
@@ -342,19 +357,20 @@ static int nfnl_acct_del(struct net *net, struct sock *nfnl,
                         const struct nlattr * const tb[],
                         struct netlink_ext_ack *extack)
 {
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        struct nf_acct *cur, *tmp;
        int ret = -ENOENT;
        char *acct_name;
 
        if (!tb[NFACCT_NAME]) {
-               list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head)
+               list_for_each_entry_safe(cur, tmp, &nfnl_acct_net->nfnl_acct_list, head)
                        nfnl_acct_try_del(cur);
 
                return 0;
        }
        acct_name = nla_data(tb[NFACCT_NAME]);
 
-       list_for_each_entry(cur, &net->nfnl_acct_list, head) {
+       list_for_each_entry(cur, &nfnl_acct_net->nfnl_acct_list, head) {
                if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0)
                        continue;
 
@@ -402,10 +418,11 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT);
 
 struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
 {
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        struct nf_acct *cur, *acct = NULL;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) {
+       list_for_each_entry_rcu(cur, &nfnl_acct_net->nfnl_acct_list, head) {
                if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
                        continue;
 
@@ -488,16 +505,17 @@ EXPORT_SYMBOL_GPL(nfnl_acct_overquota);
 
 static int __net_init nfnl_acct_net_init(struct net *net)
 {
-       INIT_LIST_HEAD(&net->nfnl_acct_list);
+       INIT_LIST_HEAD(&nfnl_acct_pernet(net)->nfnl_acct_list);
 
        return 0;
 }
 
 static void __net_exit nfnl_acct_net_exit(struct net *net)
 {
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
        struct nf_acct *cur, *tmp;
 
-       list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) {
+       list_for_each_entry_safe(cur, tmp, &nfnl_acct_net->nfnl_acct_list, head) {
                list_del_rcu(&cur->head);
 
                if (refcount_dec_and_test(&cur->refcnt))
@@ -508,6 +526,8 @@ static void __net_exit nfnl_acct_net_exit(struct net *net)
 static struct pernet_operations nfnl_acct_ops = {
         .init   = nfnl_acct_net_init,
         .exit   = nfnl_acct_net_exit,
+        .id     = &nfnl_acct_net_id,
+        .size   = sizeof(struct nfnl_acct_net),
 };
 
 static int __init nfnl_acct_init(void)