Commit dec22cdc authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Linus Torvalds

o net: make sk_{add,del}_node functions take care of sock refcounting

With this we make it easier to write correct network families as less
details need to be taken into account, as well in the current state we
make the non-refcounting protocols (the ones still keeping deliver_to_old_ones
in the tree) suck less. 8)

Left a WARN_ON in sk_del_node_init for a while, so that we can catch cases
where we're using __sock_put on a struct sock that has refcnt == 1, which
is not the case for all the ones I tested.
parent 2d00c1cc
......@@ -289,21 +289,53 @@ static __inline__ void sk_node_init(struct hlist_node *node)
node->pprev = NULL;
}
static __inline__ int sk_del_node_init(struct sock *sk)
static __inline__ void __sk_del_node(struct sock *sk)
{
if (sk_hashed(sk)) {
__hlist_del(&sk->sk_node);
}
static __inline__ int __sk_del_node_init(struct sock *sk)
{
if (sk_hashed(sk)) {
__sk_del_node(sk);
sk_node_init(&sk->sk_node);
return 1;
}
return 0;
}
static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list)
static inline void __sock_put(struct sock *sk);
static __inline__ int sk_del_node_init(struct sock *sk)
{
int rc = __sk_del_node_init(sk);
if (rc) {
/* paranoid for a while -acme */
WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
__sock_put(sk);
}
return rc;
}
static __inline__ void __sk_add_node(struct sock *sk, struct hlist_head *list)
{
hlist_add_head(&sk->sk_node, list);
}
static inline void sock_hold(struct sock *sk);
static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list)
{
sock_hold(sk);
__sk_add_node(sk, list);
}
static __inline__ void __sk_del_bind_node(struct sock *sk)
{
__hlist_del(&sk->sk_bind_node);
}
static __inline__ void sk_add_bind_node(struct sock *sk,
struct hlist_head *list)
{
......
......@@ -143,15 +143,13 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
{
write_lock_bh(&l->lock);
sk_add_node(sk, &l->head);
sock_hold(sk);
write_unlock_bh(&l->lock);
}
void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
{
write_lock_bh(&l->lock);
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
write_unlock_bh(&l->lock);
}
......
......@@ -276,7 +276,7 @@ static void dn_rehash_sock(struct sock *sk)
return;
write_lock_bh(&dn_hash_lock);
hlist_del(&sk->sk_node);
sk_del_node_init(sk);
DN_SK(sk)->addrloc = 0;
list = listen_hash(&DN_SK(sk)->addr);
sk_add_node(sk, list);
......
......@@ -96,8 +96,7 @@ struct ec_cb
static void econet_remove_socket(struct hlist_head *list, struct sock *sk)
{
write_lock_bh(&econet_lock);
if (sk_del_node_init(sk))
sock_put(sk);
sk_del_node_init(sk);
write_unlock_bh(&econet_lock);
}
......@@ -105,7 +104,6 @@ static void econet_insert_socket(struct hlist_head *list, struct sock *sk)
{
write_lock_bh(&econet_lock);
sk_add_node(sk, list);
sock_hold(sk);
write_unlock_bh(&econet_lock);
}
......
......@@ -91,17 +91,14 @@ static void raw_v4_hash(struct sock *sk)
write_lock_bh(&raw_v4_lock);
sk_add_node(sk, head);
sock_prot_inc_use(sk->sk_prot);
sock_hold(sk);
write_unlock_bh(&raw_v4_lock);
}
static void raw_v4_unhash(struct sock *sk)
{
write_lock_bh(&raw_v4_lock);
if (sk_del_node_init(sk)) {
if (sk_del_node_init(sk))
sock_prot_dec_use(sk->sk_prot);
__sock_put(sk);
}
write_unlock_bh(&raw_v4_lock);
}
......
......@@ -302,7 +302,7 @@ static void __tcp_put_port(struct sock *sk)
spin_lock(&head->lock);
tb = tcp_sk(sk)->bind_hash;
__hlist_del(&sk->sk_bind_node);
__sk_del_bind_node(sk);
tcp_sk(sk)->bind_hash = NULL;
inet->num = 0;
tcp_bucket_destroy(tb);
......@@ -359,7 +359,7 @@ static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
lock = &tcp_ehash[sk->sk_hashent].lock;
write_lock(lock);
}
sk_add_node(sk, list);
__sk_add_node(sk, list);
sock_prot_inc_use(sk->sk_prot);
write_unlock(lock);
if (listen_possible && sk->sk_state == TCP_LISTEN)
......@@ -392,7 +392,7 @@ void tcp_unhash(struct sock *sk)
write_lock_bh(&head->lock);
}
if (sk_del_node_init(sk))
if (__sk_del_node_init(sk))
sock_prot_dec_use(sk->sk_prot);
write_unlock_bh(lock);
......@@ -608,7 +608,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
inet->sport = htons(lport);
sk->sk_hashent = hash;
BUG_TRAP(sk_unhashed(sk));
sk_add_node(sk, &head->chain);
__sk_add_node(sk, &head->chain);
sock_prot_inc_use(sk->sk_prot);
write_unlock(&head->lock);
......
......@@ -309,7 +309,7 @@ static void __tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *tw)
write_lock(&ehead->lock);
/* Step 2: Remove SK from established hash. */
if (sk_del_node_init(sk))
if (__sk_del_node_init(sk))
sock_prot_dec_use(sk->sk_prot);
/* Step 3: Hash TW into TIMEWAIT half of established hash table. */
......
......@@ -189,7 +189,6 @@ static int udp_v4_get_port(struct sock *sk, unsigned short snum)
sk_add_node(sk, h);
sock_prot_inc_use(sk->sk_prot);
sock_hold(sk);
}
write_unlock_bh(&udp_hash_lock);
return 0;
......@@ -210,7 +209,6 @@ static void udp_v4_unhash(struct sock *sk)
if (sk_del_node_init(sk)) {
inet_sk(sk)->num = 0;
sock_prot_dec_use(sk->sk_prot);
__sock_put(sk);
}
write_unlock_bh(&udp_hash_lock);
}
......
......@@ -64,17 +64,14 @@ static void raw_v6_hash(struct sock *sk)
write_lock_bh(&raw_v6_lock);
sk_add_node(sk, list);
sock_prot_inc_use(sk->sk_prot);
sock_hold(sk);
write_unlock_bh(&raw_v6_lock);
}
static void raw_v6_unhash(struct sock *sk)
{
write_lock_bh(&raw_v6_lock);
if (sk_del_node_init(sk)) {
if (sk_del_node_init(sk))
sock_prot_dec_use(sk->sk_prot);
__sock_put(sk);
}
write_unlock_bh(&raw_v6_lock);
}
......
......@@ -160,7 +160,6 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum)
if (sk_unhashed(sk)) {
sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]);
sock_prot_inc_use(sk->sk_prot);
sock_hold(sk);
}
write_unlock_bh(&udp_hash_lock);
return 0;
......@@ -181,7 +180,6 @@ static void udp_v6_unhash(struct sock *sk)
if (sk_del_node_init(sk)) {
inet_sk(sk)->num = 0;
sock_prot_dec_use(sk->sk_prot);
__sock_put(sk);
}
write_unlock_bh(&udp_hash_lock);
}
......
......@@ -142,7 +142,6 @@ static void ipx_remove_socket(struct sock *sk)
spin_lock_bh(&intrfc->if_sklist_lock);
sk_del_node_init(sk);
spin_unlock_bh(&intrfc->if_sklist_lock);
sock_put(sk);
ipxitf_put(intrfc);
out:
return;
......@@ -229,7 +228,6 @@ struct ipx_interface *ipxitf_find_using_net(__u32 net)
static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk)
{
ipxitf_hold(intrfc);
sock_hold(sk);
spin_lock_bh(&intrfc->if_sklist_lock);
ipx_sk(sk)->intrfc = intrfc;
sk_add_node(sk, &intrfc->if_sklist);
......
......@@ -115,15 +115,13 @@ static void pfkey_insert(struct sock *sk)
{
pfkey_table_grab();
sk_add_node(sk, &pfkey_table);
sock_hold(sk);
pfkey_table_ungrab();
}
static void pfkey_remove(struct sock *sk)
{
pfkey_table_grab();
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
pfkey_table_ungrab();
}
......
......@@ -35,7 +35,6 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
write_lock_bh(&sap->sk_list.lock);
llc_sk(sk)->sap = sap;
sk_add_node(sk, &sap->sk_list.list);
sock_hold(sk);
write_unlock_bh(&sap->sk_list.lock);
}
......@@ -50,8 +49,7 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
{
write_lock_bh(&sap->sk_list.lock);
if (sk_del_node_init(sk))
sock_put(sk);
sk_del_node_init(sk);
write_unlock_bh(&sap->sk_list.lock);
}
......
......@@ -193,7 +193,6 @@ static int netlink_insert(struct sock *sk, u32 pid)
if (nlk_sk(sk)->pid == 0) {
nlk_sk(sk)->pid = pid;
sk_add_node(sk, &nl_table[sk->sk_protocol]);
sock_hold(sk);
err = 0;
}
}
......@@ -204,8 +203,7 @@ static int netlink_insert(struct sock *sk, u32 pid)
static void netlink_remove(struct sock *sk)
{
netlink_table_grab();
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
netlink_table_ungrab();
}
......
......@@ -758,8 +758,7 @@ static int packet_release(struct socket *sock)
return 0;
write_lock_bh(&packet_sklist_lock);
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
write_unlock_bh(&packet_sklist_lock);
/*
......@@ -984,7 +983,6 @@ static int packet_create(struct socket *sock, int protocol)
write_lock_bh(&packet_sklist_lock);
sk_add_node(sk, &packet_sklist);
sock_hold(sk);
write_unlock_bh(&packet_sklist_lock);
return(0);
......
......@@ -3346,7 +3346,7 @@ static __inline__ void __sctp_put_port(struct sock *sk)
sctp_spin_lock(&head->lock);
pp = sctp_sk(sk)->bind_hash;
hlist_del(&sk->sk_bind_node);
__sk_del_bind_node(sk);
sctp_sk(sk)->bind_hash = NULL;
inet_sk(sk)->num = 0;
sctp_bucket_destroy(pp);
......
......@@ -211,15 +211,13 @@ static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp)
static void __unix_remove_socket(struct sock *sk)
{
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
}
static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
{
BUG_TRAP(sk_unhashed(sk));
sk_add_node(sk, list);
sock_hold(sk);
}
static inline void unix_remove_socket(struct sock *sk)
......
......@@ -982,8 +982,7 @@ static int wanpipe_release(struct socket *sock)
set_bit(1,&wanpipe_tx_critical);
write_lock(&wanpipe_sklist_lock);
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
write_unlock(&wanpipe_sklist_lock);
clear_bit(1,&wanpipe_tx_critical);
......@@ -1143,8 +1142,7 @@ static void wanpipe_kill_sock_timer (unsigned long data)
}
write_lock(&wanpipe_sklist_lock);
if (sk_del_node_init(sk))
__sock_put(sk);
sk_del_node_init(sk);
write_unlock(&wanpipe_sklist_lock);
......@@ -1206,8 +1204,7 @@ static void wanpipe_kill_sock_accept (struct sock *sk)
* appropriate locks */
write_lock(&wanpipe_sklist_lock);
if (sk_del_node_init(init))
__sock_put(sk);
sk_del_node_init(sk);
write_unlock(&wanpipe_sklist_lock);
sk->sk_socket = NULL;
......@@ -1536,7 +1533,6 @@ static int wanpipe_create(struct socket *sock, int protocol)
set_bit(1,&wanpipe_tx_critical);
write_lock(&wanpipe_sklist_lock);
sk_add_node(sk, &wanpipe_sklist);
sock_hold(sk);
write_unlock(&wanpipe_sklist_lock);
clear_bit(1,&wanpipe_tx_critical);
......@@ -2434,7 +2430,6 @@ static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags
set_bit(1,&wanpipe_tx_critical);
write_lock(&wanpipe_sklist_lock);
sk_add_node(newsk, &wanpipe_sklist);
sock_hold(sk);
write_unlock(&wanpipe_sklist_lock);
clear_bit(1,&wanpipe_tx_critical);
......
......@@ -154,8 +154,7 @@ int x25_addr_aton(unsigned char *p, struct x25_address *called_addr,
static void x25_remove_socket(struct sock *sk)
{
write_lock_bh(&x25_list_lock);
if (sk_del_node_init(sk))
sock_put(sk);
sk_del_node_init(sk);
write_unlock_bh(&x25_list_lock);
}
......@@ -219,7 +218,6 @@ static void x25_insert_socket(struct sock *sk)
{
write_lock_bh(&x25_list_lock);
sk_add_node(sk, &x25_list);
sock_hold(sk);
write_unlock_bh(&x25_list_lock);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment