]> Pileus Git - ~andy/linux/blobdiff - net/ipv4/inet_timewait_sock.c
Merge branch 'kmemleak' of git://linux-arm.org/linux-2.6
[~andy/linux] / net / ipv4 / inet_timewait_sock.c
index 0fdf45e4c90c8c8475cfd28feb9830d65ebfc204..cc94cc2d8b2d8825d909266b501afb1c6ea03cab 100644 (file)
 #include <net/ip.h>
 
 
-/*
- * unhash a timewait socket from established hash
- * lock must be hold by caller
+/**
+ *     inet_twsk_unhash - unhash a timewait socket from established hash
+ *     @tw: timewait socket
+ *
+ *     unhash a timewait socket from established hash, if hashed.
+ *     ehash lock must be held by caller.
+ *     Returns 1 if caller should call inet_twsk_put() after lock release.
  */
 int inet_twsk_unhash(struct inet_timewait_sock *tw)
 {
@@ -26,6 +30,37 @@ int inet_twsk_unhash(struct inet_timewait_sock *tw)
 
        hlist_nulls_del_rcu(&tw->tw_node);
        sk_nulls_node_init(&tw->tw_node);
+       /*
+        * We cannot call inet_twsk_put() ourself under lock,
+        * caller must call it for us.
+        */
+       return 1;
+}
+
+/**
+ *     inet_twsk_bind_unhash - unhash a timewait socket from bind hash
+ *     @tw: timewait socket
+ *     @hashinfo: hashinfo pointer
+ *
+ *     unhash a timewait socket from bind hash, if hashed.
+ *     bind hash lock must be held by caller.
+ *     Returns 1 if caller should call inet_twsk_put() after lock release.
+ */
+int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
+                         struct inet_hashinfo *hashinfo)
+{
+       struct inet_bind_bucket *tb = tw->tw_tb;
+
+       if (!tb)
+               return 0;
+
+       __hlist_del(&tw->tw_bind_node);
+       tw->tw_tb = NULL;
+       inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+       /*
+        * We cannot call inet_twsk_put() ourself under lock,
+        * caller must call it for us.
+        */
        return 1;
 }
 
@@ -34,7 +69,6 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
                             struct inet_hashinfo *hashinfo)
 {
        struct inet_bind_hashbucket *bhead;
-       struct inet_bind_bucket *tb;
        int refcnt;
        /* Unlink from established hashes. */
        spinlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash);
@@ -46,15 +80,11 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
        /* Disassociate with bind bucket. */
        bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), tw->tw_num,
                        hashinfo->bhash_size)];
+
        spin_lock(&bhead->lock);
-       tb = tw->tw_tb;
-       if (tb) {
-               __hlist_del(&tw->tw_bind_node);
-               tw->tw_tb = NULL;
-               inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
-               refcnt++;
-       }
+       refcnt += inet_twsk_bind_unhash(tw, hashinfo);
        spin_unlock(&bhead->lock);
+
 #ifdef SOCK_REFCNT_DEBUG
        if (atomic_read(&tw->tw_refcnt) != 1) {
                printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n",
@@ -126,7 +156,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        /*
         * Notes :
-        * - We initially set tw_refcnt to 0 in inet_twsk_alloc()
+        * - We initially set tw_refcnt to 0 in inet_twsk_alloc()
         * - We add one reference for the bhash link
         * - We add one reference for the ehash link
         * - We want this refcnt update done before allowing other
@@ -136,7 +166,6 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        spin_unlock(lock);
 }
-
 EXPORT_SYMBOL_GPL(__inet_twsk_hashdance);
 
 struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state)
@@ -177,7 +206,6 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
 
        return tw;
 }
-
 EXPORT_SYMBOL_GPL(inet_twsk_alloc);
 
 /* Returns non-zero if quota exceeded.  */
@@ -256,7 +284,6 @@ void inet_twdr_hangman(unsigned long data)
 out:
        spin_unlock(&twdr->death_lock);
 }
-
 EXPORT_SYMBOL_GPL(inet_twdr_hangman);
 
 void inet_twdr_twkill_work(struct work_struct *work)
@@ -287,7 +314,6 @@ void inet_twdr_twkill_work(struct work_struct *work)
                spin_unlock_bh(&twdr->death_lock);
        }
 }
-
 EXPORT_SYMBOL_GPL(inet_twdr_twkill_work);
 
 /* These are always called from BH context.  See callers in
@@ -307,7 +333,6 @@ void inet_twsk_deschedule(struct inet_timewait_sock *tw,
        spin_unlock(&twdr->death_lock);
        __inet_twsk_kill(tw, twdr->hashinfo);
 }
-
 EXPORT_SYMBOL(inet_twsk_deschedule);
 
 void inet_twsk_schedule(struct inet_timewait_sock *tw,
@@ -388,7 +413,6 @@ void inet_twsk_schedule(struct inet_timewait_sock *tw,
                mod_timer(&twdr->tw_timer, jiffies + twdr->period);
        spin_unlock(&twdr->death_lock);
 }
-
 EXPORT_SYMBOL_GPL(inet_twsk_schedule);
 
 void inet_twdr_twcal_tick(unsigned long data)
@@ -449,7 +473,6 @@ out:
 #endif
        spin_unlock(&twdr->death_lock);
 }
-
 EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
 
 void inet_twsk_purge(struct inet_hashinfo *hashinfo,