static DEFINE_MUTEX(proto_list_mutex);
 static LIST_HEAD(proto_list);
 
+static void sock_inuse_add(struct net *net, int val);
+
 /**
  * sk_ns_capable - General socket capability test
  * @sk: Socket to use a capability on or through
                sk->sk_kern_sock = kern;
                sock_lock_init(sk);
                sk->sk_net_refcnt = kern ? 0 : 1;
-               if (likely(sk->sk_net_refcnt))
+               if (likely(sk->sk_net_refcnt)) {
                        get_net(net);
+                       sock_inuse_add(net, 1);
+               }
+
                sock_net_set(sk, net);
                refcount_set(&sk->sk_wmem_alloc, 1);
 
 
 static void __sk_free(struct sock *sk)
 {
+       if (likely(sk->sk_net_refcnt))
+               sock_inuse_add(sock_net(sk), -1);
+
        if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt))
                sock_diag_broadcast_destroy(sk);
        else
                newsk->sk_priority = 0;
                newsk->sk_incoming_cpu = raw_smp_processor_id();
                atomic64_set(&newsk->sk_cookie, 0);
+               if (likely(newsk->sk_net_refcnt))
+                       sock_inuse_add(sock_net(newsk), 1);
 
                /*
                 * Before updating sk_refcnt, we must commit prior changes to memory
 }
 EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
 
+static void sock_inuse_add(struct net *net, int val)
+{
+       this_cpu_add(*net->core.sock_inuse, val);
+}
+
+int sock_inuse_get(struct net *net)
+{
+       int cpu, res = 0;
+
+       for_each_possible_cpu(cpu)
+               res += *per_cpu_ptr(net->core.sock_inuse, cpu);
+
+       return res;
+}
+
+EXPORT_SYMBOL_GPL(sock_inuse_get);
+
 static int __net_init sock_inuse_init_net(struct net *net)
 {
        net->core.prot_inuse = alloc_percpu(struct prot_inuse);
-       return net->core.prot_inuse ? 0 : -ENOMEM;
+       if (net->core.prot_inuse == NULL)
+               return -ENOMEM;
+
+       net->core.sock_inuse = alloc_percpu(int);
+       if (net->core.sock_inuse == NULL)
+               goto out;
+
+       return 0;
+
+out:
+       free_percpu(net->core.prot_inuse);
+       return -ENOMEM;
 }
 
 static void __net_exit sock_inuse_exit_net(struct net *net)
 {
        free_percpu(net->core.prot_inuse);
+       free_percpu(net->core.sock_inuse);
 }
 
 static struct pernet_operations net_inuse_ops = {
 static inline void release_proto_idx(struct proto *prot)
 {
 }
+
+static void sock_inuse_add(struct net *net, int val)
+{
+}
 #endif
 
 static void req_prot_cleanup(struct request_sock_ops *rsk_prot)
 
 static DEFINE_SPINLOCK(net_family_lock);
 static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
 
-/*
- *     Statistics counters of the socket lists
- */
-
-static DEFINE_PER_CPU(int, sockets_in_use);
-
 /*
  * Support routines.
  * Move socket addresses back and forth across the kernel/user
        inode->i_gid = current_fsgid();
        inode->i_op = &sockfs_inode_ops;
 
-       this_cpu_add(sockets_in_use, 1);
        return sock;
 }
 EXPORT_SYMBOL(sock_alloc);
        if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
                pr_err("%s: fasync list not empty!\n", __func__);
 
-       this_cpu_sub(sockets_in_use, 1);
        if (!sock->file) {
                iput(SOCK_INODE(sock));
                return;
 #ifdef CONFIG_PROC_FS
 void socket_seq_show(struct seq_file *seq)
 {
-       int cpu;
-       int counter = 0;
-
-       for_each_possible_cpu(cpu)
-           counter += per_cpu(sockets_in_use, cpu);
-
-       /* It can be negative, by the way. 8) */
-       if (counter < 0)
-               counter = 0;
-
-       seq_printf(seq, "sockets: used %d\n", counter);
+       seq_printf(seq, "sockets: used %d\n",
+                  sock_inuse_get(seq->private));
 }
 #endif                         /* CONFIG_PROC_FS */