SUNRPC: make AF_LOCAL connect synchronous
authorJ. Bruce Fields <bfields@redhat.com>
Wed, 20 Feb 2013 22:52:19 +0000 (17:52 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 28 Feb 2013 17:47:17 +0000 (09:47 -0800)
It doesn't appear that anyone actually needs to connect asynchronously.

Also, using a workqueue for the connect means we lose the namespace
information from the original process.  This is a problem since there's
no way to explicitly pass in a filesystem namespace for resolution of an
AF_LOCAL address.

Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/xprtsock.c

index bbc0915..4dc8eb2 100644 (file)
@@ -1866,13 +1866,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;
@@ -1917,6 +1913,31 @@ out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
        current->flags &= ~PF_FSTRANS;
+       return status;
+}
+
+static void xs_local_connect(struct rpc_task *task)
+{
+       struct rpc_xprt *xprt = task->tk_xprt;
+       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
@@ -2454,7 +2475,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,
@@ -2627,8 +2648,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: