Merge branch 'for-3.9' of git://linux-nfs.org/~bfields/linux
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / sunrpc / xprtsock.c
index 37cbda63f45c5bef857f249854dd04a95327c150..c1d8476b76929b4300d967dd795aa6c2ce38f7a0 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/addr.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/xprtsock.h>
@@ -1867,13 +1868,9 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
  * @xprt: RPC transport to connect
  * @transport: socket transport to connect
  * @create_sock: function to create a socket of the correct type
- *
- * Invoked by a work queue tasklet.
  */
-static void xs_local_setup_socket(struct work_struct *work)
+static int xs_local_setup_socket(struct sock_xprt *transport)
 {
-       struct sock_xprt *transport =
-               container_of(work, struct sock_xprt, connect_worker.work);
        struct rpc_xprt *xprt = &transport->xprt;
        struct socket *sock;
        int status = -EIO;
@@ -1918,6 +1915,30 @@ out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
        current->flags &= ~PF_FSTRANS;
+       return status;
+}
+
+static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       int ret;
+
+        if (RPC_IS_ASYNC(task)) {
+               /*
+                * We want the AF_LOCAL connect to be resolved in the
+                * filesystem namespace of the process making the rpc
+                * call.  Thus we connect synchronously.
+                *
+                * If we want to support asynchronous AF_LOCAL calls,
+                * we'll need to figure out how to pass a namespace to
+                * connect.
+                */
+               rpc_exit(task, -ENOTCONN);
+               return;
+       }
+       ret = xs_local_setup_socket(transport);
+       if (ret && !RPC_IS_SOFTCONN(task))
+               msleep_interruptible(15000);
 }
 
 #ifdef CONFIG_SUNRPC_SWAP
@@ -2455,7 +2476,7 @@ static struct rpc_xprt_ops xs_local_ops = {
        .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = xs_local_rpcbind,
        .set_port               = xs_local_set_port,
-       .connect                = xs_connect,
+       .connect                = xs_local_connect,
        .buf_alloc              = rpc_malloc,
        .buf_free               = rpc_free,
        .send_request           = xs_local_send_request,
@@ -2628,8 +2649,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
                        goto out_err;
                }
                xprt_set_bound(xprt);
-               INIT_DELAYED_WORK(&transport->connect_worker,
-                                       xs_local_setup_socket);
                xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
                break;
        default: