Merge branch 'for-2.6.37' of git://linux-nfs.org/~bfields/linux
[pandora-kernel.git] / net / sunrpc / xprtsock.c
index bc57861..dfcab5a 100644 (file)
@@ -799,7 +799,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        u32 _xid;
        __be32 *xp;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        dprintk("RPC:       xs_udp_data_ready...\n");
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
@@ -851,7 +851,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
  dropit:
        skb_free_datagram(sk, skb);
  out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
@@ -1228,7 +1228,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
 
        dprintk("RPC:       xs_tcp_data_ready...\n");
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        if (xprt->shutdown)
@@ -1247,7 +1247,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
                read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
        } while (read > 0);
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /*
@@ -1300,7 +1300,7 @@ static void xs_tcp_state_change(struct sock *sk)
 {
        struct rpc_xprt *xprt;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
@@ -1312,7 +1312,7 @@ static void xs_tcp_state_change(struct sock *sk)
 
        switch (sk->sk_state) {
        case TCP_ESTABLISHED:
-               spin_lock_bh(&xprt->transport_lock);
+               spin_lock(&xprt->transport_lock);
                if (!xprt_test_and_set_connected(xprt)) {
                        struct sock_xprt *transport = container_of(xprt,
                                        struct sock_xprt, xprt);
@@ -1326,7 +1326,7 @@ static void xs_tcp_state_change(struct sock *sk)
 
                        xprt_wake_pending_tasks(xprt, -EAGAIN);
                }
-               spin_unlock_bh(&xprt->transport_lock);
+               spin_unlock(&xprt->transport_lock);
                break;
        case TCP_FIN_WAIT1:
                /* The client initiated a shutdown of the socket */
@@ -1364,7 +1364,7 @@ static void xs_tcp_state_change(struct sock *sk)
                xs_sock_mark_closed(xprt);
        }
  out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1375,7 +1375,7 @@ static void xs_error_report(struct sock *sk)
 {
        struct rpc_xprt *xprt;
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
        dprintk("RPC:       %s client %p...\n"
@@ -1383,7 +1383,7 @@ static void xs_error_report(struct sock *sk)
                        __func__, xprt, sk->sk_err);
        xprt_wake_pending_tasks(xprt, -EAGAIN);
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_write_space(struct sock *sk)
@@ -1415,13 +1415,13 @@ static void xs_write_space(struct sock *sk)
  */
 static void xs_udp_write_space(struct sock *sk)
 {
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
 
        /* from net/core/sock.c:sock_def_write_space */
        if (sock_writeable(sk))
                xs_write_space(sk);
 
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1436,13 +1436,13 @@ static void xs_udp_write_space(struct sock *sk)
  */
 static void xs_tcp_write_space(struct sock *sk)
 {
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
 
        /* from net/core/stream.c:sk_stream_write_space */
        if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
                xs_write_space(sk);
 
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
@@ -1558,7 +1558,7 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock)
                        nloop++;
        } while (err == -EADDRINUSE && nloop != 2);
 
-       if (myaddr.ss_family == PF_INET)
+       if (myaddr.ss_family == AF_INET)
                dprintk("RPC:       %s %pI4:%u: %s (%d)\n", __func__,
                                &((struct sockaddr_in *)&myaddr)->sin_addr,
                                port, err ? "failed" : "ok", err);
@@ -1594,10 +1594,14 @@ static inline void xs_reclassify_socket6(struct socket *sock)
 
 static inline void xs_reclassify_socket(int family, struct socket *sock)
 {
-       if (family == PF_INET)
+       switch (family) {
+       case AF_INET:
                xs_reclassify_socket4(sock);
-       else
+               break;
+       case AF_INET6:
                xs_reclassify_socket6(sock);
+               break;
+       }
 }
 #else
 static inline void xs_reclassify_socket4(struct socket *sock)
@@ -1625,7 +1629,6 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt,
                                protocol, -err);
                goto out;
        }
-       transport->srcaddr.ss_family = family;
        xs_reclassify_socket(family, sock);
 
        if (xs_bind(transport, sock)) {
@@ -2132,6 +2135,31 @@ static struct rpc_xprt_ops bc_tcp_ops = {
        .print_stats            = xs_tcp_print_stats,
 };
 
+static int xs_init_anyaddr(const int family, struct sockaddr *sap)
+{
+       static const struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+               .sin_addr.s_addr        = htonl(INADDR_ANY),
+       };
+       static const struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+       };
+
+       switch (family) {
+       case AF_INET:
+               memcpy(sap, &sin, sizeof(sin));
+               break;
+       case AF_INET6:
+               memcpy(sap, &sin6, sizeof(sin6));
+               break;
+       default:
+               dprintk("RPC:       %s: Bad address family\n", __func__);
+               return -EAFNOSUPPORT;
+       }
+       return 0;
+}
+
 static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
                                      unsigned int slot_table_size)
 {
@@ -2155,6 +2183,13 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
        xprt->addrlen = args->addrlen;
        if (args->srcaddr)
                memcpy(&new->srcaddr, args->srcaddr, args->addrlen);
+       else {
+               int err;
+               err = xs_init_anyaddr(args->dstaddr->sa_family,
+                                       (struct sockaddr *)&new->srcaddr);
+               if (err != 0)
+                       return ERR_PTR(err);
+       }
 
        return xprt;
 }
@@ -2366,15 +2401,10 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
                goto out_err;
        }
 
-       if (xprt_bound(xprt))
-               dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
-                               xprt->address_strings[RPC_DISPLAY_ADDR],
-                               xprt->address_strings[RPC_DISPLAY_PORT],
-                               xprt->address_strings[RPC_DISPLAY_PROTO]);
-       else
-               dprintk("RPC:       set up xprt to %s (autobind) via %s\n",
-                               xprt->address_strings[RPC_DISPLAY_ADDR],
-                               xprt->address_strings[RPC_DISPLAY_PROTO]);
+       dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
+                       xprt->address_strings[RPC_DISPLAY_ADDR],
+                       xprt->address_strings[RPC_DISPLAY_PORT],
+                       xprt->address_strings[RPC_DISPLAY_PROTO]);
 
        /*
         * Since we don't want connections for the backchannel, we set