[NET]: Cleanup INET_REFCNT_DEBUG code
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>
Wed, 10 Aug 2005 02:45:38 +0000 (19:45 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 22:37:29 +0000 (15:37 -0700)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
13 files changed:
include/net/inet_common.h
include/net/ipv6.h
include/net/sock.h
include/net/tcp.h
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/tcp.c
net/ipv4/tcp_minisocks.c
net/ipv6/af_inet6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/tcp_ipv6.c
net/sctp/ipv6.c
net/sctp/protocol.c

index fbc1f4d140d82c1d7fe05092a8e12296ccff7284..1fbd94d8a3162786e5d7a927c3bf1ad799397ded 100644 (file)
@@ -29,7 +29,6 @@ extern unsigned int           inet_poll(struct file * file, struct socket *sock, struct p
 extern int                     inet_listen(struct socket *sock, int backlog);
 
 extern void                    inet_sock_destruct(struct sock *sk);
-extern atomic_t                        inet_sock_nr;
 
 extern int                     inet_bind(struct socket *sock, 
                                          struct sockaddr *uaddr, int addr_len);
index 533fc074ed901d8a2f46057c9a1b3d3f0bd05479..c5a02ddc594a48e94230024788cbcb81ab97332c 100644 (file)
@@ -145,7 +145,6 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
 #define UDP6_INC_STATS(field)          SNMP_INC_STATS(udp_stats_in6, field)
 #define UDP6_INC_STATS_BH(field)       SNMP_INC_STATS_BH(udp_stats_in6, field)
 #define UDP6_INC_STATS_USER(field)     SNMP_INC_STATS_USER(udp_stats_in6, field)
-extern atomic_t                        inet6_sock_nr;
 
 int snmp6_register_dev(struct inet6_dev *idev);
 int snmp6_unregister_dev(struct inet6_dev *idev);
index e9b1dbab90d007fec58e666d98205c1b8ca6a114..11b81551041ebd078199c2273973d91c182d70c5 100644 (file)
@@ -491,6 +491,9 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
 
 struct request_sock_ops;
 
+/* Here is the right place to enable sock refcounting debugging */
+#define SOCK_REFCNT_DEBUG
+
 /* Networking protocol blocks we attach to sockets.
  * socket layer -> transport layer interface
  * transport -> network interface is defined by struct inet_proto
@@ -561,7 +564,9 @@ struct proto {
        char                    name[32];
 
        struct list_head        node;
-
+#ifdef SOCK_REFCNT_DEBUG
+       atomic_t                socks;
+#endif
        struct {
                int inuse;
                u8  __pad[SMP_CACHE_BYTES - sizeof(int)];
@@ -571,6 +576,31 @@ struct proto {
 extern int proto_register(struct proto *prot, int alloc_slab);
 extern void proto_unregister(struct proto *prot);
 
+#ifdef SOCK_REFCNT_DEBUG
+static inline void sk_refcnt_debug_inc(struct sock *sk)
+{
+       atomic_inc(&sk->sk_prot->socks);
+}
+
+static inline void sk_refcnt_debug_dec(struct sock *sk)
+{
+       atomic_dec(&sk->sk_prot->socks);
+       printk(KERN_DEBUG "%s socket %p released, %d are still alive\n",
+              sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks));
+}
+
+static inline void sk_refcnt_debug_release(const struct sock *sk)
+{
+       if (atomic_read(&sk->sk_refcnt) != 1)
+               printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
+                      sk->sk_prot->name, sk, atomic_read(&sk->sk_refcnt));
+}
+#else /* SOCK_REFCNT_DEBUG */
+#define sk_refcnt_debug_inc(sk) do { } while (0)
+#define sk_refcnt_debug_dec(sk) do { } while (0)
+#define sk_refcnt_debug_release(sk) do { } while (0)
+#endif /* SOCK_REFCNT_DEBUG */
+
 /* Called with local bh disabled */
 static __inline__ void sock_prot_inc_use(struct proto *prot)
 {
index 5010f0c5a56e32c8492723d8342b99bde0df7d67..31984733777bc6dda7c6ecc05bd5e1681c44d320 100644 (file)
@@ -306,7 +306,7 @@ extern kmem_cache_t *tcp_timewait_cachep;
 static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
 {
        if (atomic_dec_and_test(&tw->tw_refcnt)) {
-#ifdef INET_REFCNT_DEBUG
+#ifdef SOCK_REFCNT_DEBUG
                printk(KERN_DEBUG "tw_bucket %p released\n", tw);
 #endif
                kmem_cache_free(tcp_timewait_cachep, tw);
index 51a5e7ddee8511cc4aa884548d48a29507e13ebb..a1a23be10aa3777471781c99f6d7c8c3a8bee896 100644 (file)
@@ -1367,11 +1367,7 @@ void sk_common_release(struct sock *sk)
 
        xfrm_sk_free_policy(sk);
 
-#ifdef INET_REFCNT_DEBUG
-       if (atomic_read(&sk->sk_refcnt) != 1)
-               printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n",
-                      sk, atomic_read(&sk->sk_refcnt));
-#endif
+       sk_refcnt_debug_release(sk);
        sock_put(sk);
 }
 
index 163ae4068b5f3acfb70c1434bfd0e82c94478cb4..9e83d7773d8f29a79ef5cfa1d248130d78fbe138 100644 (file)
 
 DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
 
-#ifdef INET_REFCNT_DEBUG
-atomic_t inet_sock_nr;
-#endif
-
 extern void ip_mc_drop_socket(struct sock *sk);
 
 /* The inetsw table contains everything that inet_create needs to
@@ -153,11 +149,7 @@ void inet_sock_destruct(struct sock *sk)
        if (inet->opt)
                kfree(inet->opt);
        dst_release(sk->sk_dst_cache);
-#ifdef INET_REFCNT_DEBUG
-       atomic_dec(&inet_sock_nr);
-       printk(KERN_DEBUG "INET socket %p released, %d are still alive\n",
-              sk, atomic_read(&inet_sock_nr));
-#endif
+       sk_refcnt_debug_dec(sk);
 }
 
 /*
@@ -317,9 +309,7 @@ static int inet_create(struct socket *sock, int protocol)
        inet->mc_index  = 0;
        inet->mc_list   = NULL;
 
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet_sock_nr);
-#endif
+       sk_refcnt_debug_inc(sk);
 
        if (inet->num) {
                /* It assumes that any protocol which allows
@@ -1205,7 +1195,3 @@ EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_unregister_protosw);
 EXPORT_SYMBOL(net_statistics);
 EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
-
-#ifdef INET_REFCNT_DEBUG
-EXPORT_SYMBOL(inet_sock_nr);
-#endif
index 42a2e2ccd4303852e27eb6ef8a582e37294765f6..20159a3dafb375166e6c61893f99a97a86bc2402 100644 (file)
@@ -1580,12 +1580,7 @@ void tcp_destroy_sock(struct sock *sk)
 
        xfrm_sk_free_policy(sk);
 
-#ifdef INET_REFCNT_DEBUG
-       if (atomic_read(&sk->sk_refcnt) != 1) {
-               printk(KERN_DEBUG "Destruction TCP %p delayed, c=%d\n",
-                      sk, atomic_read(&sk->sk_refcnt));
-       }
-#endif
+       sk_refcnt_debug_release(sk);
 
        atomic_dec(&tcp_orphan_count);
        sock_put(sk);
index f42a284164b794aefec97bb296a115bc5dbc231a..f8e288c8d69374a22f1bfc1cc3cc753a76672696 100644 (file)
@@ -84,7 +84,7 @@ static void tcp_timewait_kill(struct tcp_tw_bucket *tw)
        tcp_bucket_destroy(tb);
        spin_unlock(&bhead->lock);
 
-#ifdef INET_REFCNT_DEBUG
+#ifdef SOCK_REFCNT_DEBUG
        if (atomic_read(&tw->tw_refcnt) != 1) {
                printk(KERN_DEBUG "tw_bucket %p refcnt=%d\n", tw,
                       atomic_read(&tw->tw_refcnt));
@@ -799,9 +799,21 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newsk->sk_err = 0;
                newsk->sk_priority = 0;
                atomic_set(&newsk->sk_refcnt, 2);
-#ifdef INET_REFCNT_DEBUG
-               atomic_inc(&inet_sock_nr);
-#endif
+
+               /*
+                * Increment the counter in the same struct proto as the master
+                * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that
+                * is the same as sk->sk_prot->socks, as this field was copied
+                * with memcpy), same rationale as the first comment in this
+                * function.
+                *
+                * This _changes_ the previous behaviour, where
+                * tcp_create_openreq_child always was incrementing the
+                * equivalent to tcp_prot->socks (inet_sock_nr), so this have
+                * to be taken into account in all callers. -acme
+                */
+               sk_refcnt_debug_inc(newsk);
+
                atomic_inc(&tcp_sockets_allocated);
 
                if (sock_flag(newsk, SOCK_KEEPOPEN))
index 574047353628580b761f540d0b42608b9a4f6591..7df2ccb380d9bdf575e26fabb21c41cd30655c66 100644 (file)
@@ -86,26 +86,12 @@ extern void if6_proc_exit(void);
 
 int sysctl_ipv6_bindv6only;
 
-#ifdef INET_REFCNT_DEBUG
-atomic_t inet6_sock_nr;
-EXPORT_SYMBOL(inet6_sock_nr);
-#endif
-
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
  */
 static struct list_head inetsw6[SOCK_MAX];
 static DEFINE_SPINLOCK(inetsw6_lock);
 
-static void inet6_sock_destruct(struct sock *sk)
-{
-       inet_sock_destruct(sk);
-
-#ifdef INET_REFCNT_DEBUG
-       atomic_dec(&inet6_sock_nr);
-#endif
-}
-
 static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
 {
        const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
@@ -186,7 +172,7 @@ static int inet6_create(struct socket *sock, int protocol)
                        inet->hdrincl = 1;
        }
 
-       sk->sk_destruct         = inet6_sock_destruct;
+       sk->sk_destruct         = inet_sock_destruct;
        sk->sk_family           = PF_INET6;
        sk->sk_protocol         = protocol;
 
@@ -213,12 +199,17 @@ static int inet6_create(struct socket *sock, int protocol)
                inet->pmtudisc = IP_PMTUDISC_DONT;
        else
                inet->pmtudisc = IP_PMTUDISC_WANT;
+       /* 
+        * Increment only the relevant sk_prot->socks debug field, this changes
+        * the previous behaviour of incrementing both the equivalent to
+        * answer->prot->socks (inet6_sock_nr) and inet_sock_nr.
+        *
+        * This allows better debug granularity as we'll know exactly how many
+        * UDPv6, TCPv6, etc socks were allocated, not the sum of all IPv6
+        * transport protocol socks. -acme
+        */
+       sk_refcnt_debug_inc(sk);
 
-
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet6_sock_nr);
-       atomic_inc(&inet_sock_nr);
-#endif
        if (inet->num) {
                /* It assumes that any protocol which allows
                 * the user to assign a number at socket
index 3bc144a79fa5cf454908b83bd32537139212b54b..76fe23925d777a202c29c42633b856e857fc1e9b 100644 (file)
@@ -163,6 +163,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
                        fl6_free_socklist(sk);
                        ipv6_sock_mc_close(sk);
 
+                       /*
+                        * Sock is moving from IPv6 to IPv4 (sk_prot), so
+                        * remove it from the refcnt debug socks count in the
+                        * original family...
+                        */
+                       sk_refcnt_debug_dec(sk);
+
                        if (sk->sk_protocol == IPPROTO_TCP) {
                                struct tcp_sock *tp = tcp_sk(sk);
 
@@ -192,9 +199,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
                                kfree_skb(pktopt);
 
                        sk->sk_destruct = inet_sock_destruct;
-#ifdef INET_REFCNT_DEBUG
-                       atomic_dec(&inet6_sock_nr);
-#endif
+                       /*
+                        * ... and add it to the refcnt debug socks count
+                        * in the new family. -acme
+                        */
+                       sk_refcnt_debug_inc(sk);
                        module_put(THIS_MODULE);
                        retv = 0;
                        break;
index ef29cfd936d3bed8f094f89627e8e67932529886..885e05bd99f6412de4c14388e904666ecf81b969 100644 (file)
@@ -1407,12 +1407,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                newnp->mcast_oif   = tcp_v6_iif(skb);
                newnp->mcast_hops  = skb->nh.ipv6h->hop_limit;
 
-               /* Charge newly allocated IPv6 socket. Though it is mapped,
-                * it is IPv6 yet.
+               /*
+                * No need to charge this sock to the relevant IPv6 refcnt debug socks count
+                * here, tcp_create_openreq_child now does this for us, see the comment in
+                * that function for the gory details. -acme
                 */
-#ifdef INET_REFCNT_DEBUG
-               atomic_inc(&inet6_sock_nr);
-#endif
 
                /* It is tricky place. Until this moment IPv4 tcp
                   worked with IPv6 af_tcp.af_specific.
@@ -1467,10 +1466,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        if (newsk == NULL)
                goto out;
 
-       /* Charge newly allocated IPv6 socket */
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet6_sock_nr);
-#endif
+       /*
+        * No need to charge this sock to the relevant IPv6 refcnt debug socks
+        * count here, tcp_create_openreq_child now does this for us, see the
+        * comment in that function for the gory details. -acme
+        */
 
        ip6_dst_store(newsk, dst, NULL);
        newsk->sk_route_caps = dst->dev->features &
index e9b2fd480d6153edd54d6e045140bb4e023bcefd..4a6421a9fcab5a97a50b9b3474e7af213ccac810 100644 (file)
@@ -641,10 +641,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
        else
                newinet->pmtudisc = IP_PMTUDISC_WANT;
 
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet6_sock_nr);
-       atomic_inc(&inet_sock_nr);
-#endif
+       sk_refcnt_debug_inc(newsk);
 
        if (newsk->sk_prot->init(newsk)) {
                sk_common_release(newsk);
index ce9245e71fca9b0694c473c4cc21b7eb8c5ba058..8d3f8096b8735e307bff00ab5c5befe6fac18212 100644 (file)
@@ -593,9 +593,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
        newinet->mc_index = 0;
        newinet->mc_list = NULL;
 
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet_sock_nr);
-#endif
+       sk_refcnt_debug_inc(newsk);
 
        if (newsk->sk_prot->init(newsk)) {
                sk_common_release(newsk);