Non-trivial part of socket namespaces: asynchronous events
should be run in proper context.

Signed-off-by: Andrey Savochkin <[EMAIL PROTECTED]>
---
 af_inet.c            |   10 ++++++++++
 inet_timewait_sock.c |    8 ++++++++
 tcp_timer.c          |    9 +++++++++
 3 files changed, 27 insertions(+)

--- ./net/ipv4/af_inet.c.venssock-asyn  Mon Aug 14 17:04:07 2006
+++ ./net/ipv4/af_inet.c        Tue Aug 15 13:45:44 2006
@@ -366,10 +366,17 @@ out_rcu_unlock:
 int inet_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
+       struct net_namespace *ns, *orig_net_ns;
 
        if (sk) {
                long timeout;
 
+               /* Need to change context here since protocol ->close
+                * operation may send packets.
+                */
+               ns = get_net_ns(sk->sk_net_ns);
+               push_net_ns(ns, orig_net_ns);
+
                /* Applications forget to leave groups before exiting */
                ip_mc_drop_socket(sk);
 
@@ -386,6 +393,9 @@ int inet_release(struct socket *sock)
                        timeout = sk->sk_lingertime;
                sock->sk = NULL;
                sk->sk_prot->close(sk, timeout);
+
+               pop_net_ns(orig_net_ns);
+               put_net_ns(ns);
        }
        return 0;
 }
--- ./net/ipv4/inet_timewait_sock.c.venssock-asyn       Tue Aug 15 13:45:44 2006
+++ ./net/ipv4/inet_timewait_sock.c     Tue Aug 15 13:45:44 2006
@@ -129,6 +129,7 @@ static int inet_twdr_do_twkill_work(stru
 {
        struct inet_timewait_sock *tw;
        struct hlist_node *node;
+       struct net_namespace *orig_net_ns;
        unsigned int killed;
        int ret;
 
@@ -140,8 +141,10 @@ static int inet_twdr_do_twkill_work(stru
         */
        killed = 0;
        ret = 0;
+       push_net_ns(current_net_ns, orig_net_ns);
 rescan:
        inet_twsk_for_each_inmate(tw, node, &twdr->cells[slot]) {
+               switch_net_ns(tw->tw_net_ns);
                __inet_twsk_del_dead_node(tw);
                spin_unlock(&twdr->death_lock);
                __inet_twsk_kill(tw, twdr->hashinfo);
@@ -164,6 +167,7 @@ rescan:
 
        twdr->tw_count -= killed;
        NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITED, killed);
+       pop_net_ns(orig_net_ns);
 
        return ret;
 }
@@ -338,10 +342,12 @@ void inet_twdr_twcal_tick(unsigned long 
        int n, slot;
        unsigned long j;
        unsigned long now = jiffies;
+       struct net_namespace *orig_net_ns;
        int killed = 0;
        int adv = 0;
 
        twdr = (struct inet_timewait_death_row *)data;
+       push_net_ns(current_net_ns, orig_net_ns);
 
        spin_lock(&twdr->death_lock);
        if (twdr->twcal_hand < 0)
@@ -357,6 +363,7 @@ void inet_twdr_twcal_tick(unsigned long 
 
                        inet_twsk_for_each_inmate_safe(tw, node, safe,
                                                       &twdr->twcal_row[slot]) {
+                               switch_net_ns(tw->tw_net_ns);
                                __inet_twsk_del_dead_node(tw);
                                __inet_twsk_kill(tw, twdr->hashinfo);
                                inet_twsk_put(tw);
@@ -384,6 +391,7 @@ out:
                del_timer(&twdr->tw_timer);
        NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITKILLED, killed);
        spin_unlock(&twdr->death_lock);
+       pop_net_ns(orig_net_ns);
 }
 
 EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
--- ./net/ipv4/tcp_timer.c.venssock-asyn        Mon Aug 14 16:43:51 2006
+++ ./net/ipv4/tcp_timer.c      Tue Aug 15 13:45:44 2006
@@ -171,7 +171,9 @@ static void tcp_delack_timer(unsigned lo
        struct sock *sk = (struct sock*)data;
        struct tcp_sock *tp = tcp_sk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
+       struct net_namespace *orig_net_ns;
 
+       push_net_ns(sk->sk_net_ns, orig_net_ns);
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
                /* Try again later. */
@@ -225,6 +227,7 @@ out:
 out_unlock:
        bh_unlock_sock(sk);
        sock_put(sk);
+       pop_net_ns(orig_net_ns);
 }
 
 static void tcp_probe_timer(struct sock *sk)
@@ -384,8 +387,10 @@ static void tcp_write_timer(unsigned lon
 {
        struct sock *sk = (struct sock*)data;
        struct inet_connection_sock *icsk = inet_csk(sk);
+       struct net_namespace *orig_net_ns;
        int event;
 
+       push_net_ns(sk->sk_net_ns, orig_net_ns);
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
                /* Try again later */
@@ -419,6 +424,7 @@ out:
 out_unlock:
        bh_unlock_sock(sk);
        sock_put(sk);
+       pop_net_ns(orig_net_ns);
 }
 
 /*
@@ -447,9 +453,11 @@ static void tcp_keepalive_timer (unsigne
 {
        struct sock *sk = (struct sock *) data;
        struct inet_connection_sock *icsk = inet_csk(sk);
+       struct net_namespace *orig_net_ns;
        struct tcp_sock *tp = tcp_sk(sk);
        __u32 elapsed;
 
+       push_net_ns(sk->sk_net_ns, orig_net_ns);
        /* Only process if socket is not in use. */
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
@@ -521,4 +529,5 @@ death:      
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
+       put_net_ns(orig_net_ns);
 }
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to