diff options
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r-- | net/ipv4/inet_hashtables.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 1aba606f6bbb..2023d37b2708 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -35,7 +35,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep, struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC); if (tb != NULL) { - tb->ib_net = net; + tb->ib_net = hold_net(net); tb->port = snum; tb->fastreuse = 0; INIT_HLIST_HEAD(&tb->owners); @@ -51,6 +51,7 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket { if (hlist_empty(&tb->owners)) { __hlist_del(&tb->node); + release_net(tb->ib_net); kmem_cache_free(cachep, tb); } } @@ -68,7 +69,7 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, */ static void __inet_put_port(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size); struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; struct inet_bind_bucket *tb; @@ -91,6 +92,22 @@ void inet_put_port(struct sock *sk) EXPORT_SYMBOL(inet_put_port); +void __inet_inherit_port(struct sock *sk, struct sock *child) +{ + struct inet_hashinfo *table = sk->sk_prot->h.hashinfo; + const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size); + struct inet_bind_hashbucket *head = &table->bhash[bhash]; + struct inet_bind_bucket *tb; + + spin_lock(&head->lock); + tb = inet_csk(sk)->icsk_bind_hash; + sk_add_bind_node(child, &tb->owners); + inet_csk(child)->icsk_bind_hash = tb; + spin_unlock(&head->lock); +} + +EXPORT_SYMBOL_GPL(__inet_inherit_port); + /* * This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP. * Look, when several writers sleep and reader wakes them up, all but one @@ -139,7 +156,7 @@ static struct sock *inet_lookup_listener_slow(struct net *net, sk_for_each(sk, node, head) { const struct inet_sock *inet = inet_sk(sk); - if (sk->sk_net == net && inet->num == hnum && + if (net_eq(sock_net(sk), net) && inet->num == hnum && !ipv6_only_sock(sk)) { const __be32 rcv_saddr = inet->rcv_saddr; int score = sk->sk_family == PF_INET ? 1 : 0; @@ -182,7 +199,7 @@ struct sock *__inet_lookup_listener(struct net *net, if (inet->num == hnum && !sk->sk_node.next && (!inet->rcv_saddr || inet->rcv_saddr == daddr) && (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && - !sk->sk_bound_dev_if && sk->sk_net == net) + !sk->sk_bound_dev_if && net_eq(sock_net(sk), net)) goto sherry_cache; sk = inet_lookup_listener_slow(net, head, daddr, hnum, dif); } @@ -254,7 +271,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; - struct net *net = sk->sk_net; + struct net *net = sock_net(sk); prefetch(head->chain.first); write_lock(lock); @@ -288,7 +305,7 @@ unique: sk->sk_hash = hash; BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); - sock_prot_inuse_add(sk->sk_prot, 1); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock(lock); if (twp) { @@ -318,7 +335,7 @@ static inline u32 inet_sk_port_offset(const struct sock *sk) void __inet_hash_nolisten(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_head *list; rwlock_t *lock; struct inet_ehash_bucket *head; @@ -332,14 +349,14 @@ void __inet_hash_nolisten(struct sock *sk) write_lock(lock); __sk_add_node(sk, list); - sock_prot_inuse_add(sk->sk_prot, 1); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock(lock); } EXPORT_SYMBOL_GPL(__inet_hash_nolisten); static void __inet_hash(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_head *list; rwlock_t *lock; @@ -354,7 +371,7 @@ static void __inet_hash(struct sock *sk) inet_listen_wlock(hashinfo); __sk_add_node(sk, list); - sock_prot_inuse_add(sk->sk_prot, 1); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock(lock); wake_up(&hashinfo->lhash_wait); } @@ -372,7 +389,7 @@ EXPORT_SYMBOL_GPL(inet_hash); void inet_unhash(struct sock *sk) { rwlock_t *lock; - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; if (sk_unhashed(sk)) goto out; @@ -387,7 +404,7 @@ void inet_unhash(struct sock *sk) } if (__sk_del_node_init(sk)) - sock_prot_inuse_add(sk->sk_prot, -1); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); write_unlock_bh(lock); out: if (sk->sk_state == TCP_LISTEN) @@ -406,7 +423,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct inet_bind_hashbucket *head; struct inet_bind_bucket *tb; int ret; - struct net *net = sk->sk_net; + struct net *net = sock_net(sk); if (!snum) { int i, remaining, low, high, port; |