diff -u --recursive --new-file linux-2.4.20-14-fix_lockd4/net/sunrpc/xprt.c linux-2.4.20-15-xprt_fixes/net/sunrpc/xprt.c --- linux-2.4.20-14-fix_lockd4/net/sunrpc/xprt.c Thu Nov 21 18:44:07 2002 +++ linux-2.4.20-15-xprt_fixes/net/sunrpc/xprt.c Thu Nov 21 18:49:37 2002 @@ -372,6 +372,7 @@ if (!sk) return; + write_lock_bh(&sk->callback_lock); xprt->inet = NULL; xprt->sock = NULL; @@ -379,6 +380,7 @@ sk->data_ready = xprt->old_data_ready; sk->state_change = xprt->old_state_change; sk->write_space = xprt->old_write_space; + write_unlock_bh(&sk->callback_lock); xprt_disconnect(xprt); sk->no_check = 0; @@ -646,8 +648,9 @@ struct sk_buff *skb; int err, repsize, copied; + read_lock(&sk->callback_lock); dprintk("RPC: udp_data_ready...\n"); - if (!(xprt = xprt_from_sock(sk))) { + if (sk->dead || !(xprt = xprt_from_sock(sk))) { printk("RPC: udp_data_ready request not found!\n"); goto out; } @@ -696,6 +699,7 @@ out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); + read_unlock(&sk->callback_lock); } /* @@ -894,18 +898,21 @@ struct rpc_xprt *xprt; read_descriptor_t rd_desc; + read_lock(&sk->callback_lock); dprintk("RPC: tcp_data_ready...\n"); if (!(xprt = xprt_from_sock(sk))) { printk("RPC: tcp_data_ready socket info not found!\n"); - return; + goto out; } if (xprt->shutdown) - return; + goto out; /* We use rd_desc to pass struct xprt to tcp_data_recv */ rd_desc.buf = (char *)xprt; rd_desc.count = 65536; tcp_read_sock(sk, &rd_desc, tcp_data_recv); +out: + read_unlock(&sk->callback_lock); } static void @@ -913,6 +920,7 @@ { struct rpc_xprt *xprt; + read_lock(&sk->callback_lock); if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: tcp_state_change client %p...\n", xprt); @@ -946,6 +954,7 @@ out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible_all(sk->sleep); + read_unlock(&sk->callback_lock); } /* @@ -960,24 +969,25 @@ struct rpc_xprt *xprt; struct socket *sock; + read_lock(&sk->callback_lock); if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->socket)) - return; + goto out; if (xprt->shutdown) - return; + goto out; /* Wait until we have enough socket memory */ if (xprt->stream) { /* from net/ipv4/tcp.c:tcp_write_space */ if (tcp_wspace(sk) < tcp_min_write_space(sk)) - return; + goto out; } else { /* from net/core/sock.c:sock_def_write_space */ if (!sock_writeable(sk)) - return; + goto out; } if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)) - return; + goto out; spin_lock_bh(&xprt->sock_lock); if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending) @@ -985,6 +995,8 @@ spin_unlock_bh(&xprt->sock_lock); if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); +out: + read_unlock(&sk->callback_lock); } /* @@ -1382,6 +1394,7 @@ if (xprt->inet) return -EBUSY; + write_lock_bh(&sk->callback_lock); sk->user_data = xprt; xprt->old_data_ready = sk->data_ready; xprt->old_state_change = sk->state_change; @@ -1400,6 +1413,7 @@ /* Reset to new socket */ xprt->sock = sock; xprt->inet = sk; + write_unlock_bh(&sk->callback_lock); /* * TCP requires the rpc I/O daemon is present */