/* It shouldn't matter if the number of backchannel session slots
 * doesn't match the number of RPC/RDMA credits. That just means
 * one or the other will have extra slots that aren't used.
 */
static struct rpc_xprt *
xprt_setup_rdma_bc(struct xprt_create *args)
{
	struct rpc_xprt *xprt;
	struct rpcrdma_xprt *new_xprt;

	if (args->addrlen > sizeof(xprt->addr)) {
		dprintk("RPC:       %s: address too large\n", __func__);
		return ERR_PTR(-EBADF);
	}

	xprt = xprt_alloc(args->net, sizeof(*new_xprt),
			  RPCRDMA_MAX_BC_REQUESTS,
			  RPCRDMA_MAX_BC_REQUESTS);
	if (!xprt) {
		dprintk("RPC:       %s: couldn't allocate rpc_xprt\n",
			__func__);
		return ERR_PTR(-ENOMEM);
	}

	xprt->timeout = &xprt_rdma_bc_timeout;
	xprt_set_bound(xprt);
	xprt_set_connected(xprt);
	xprt->bind_timeout = RPCRDMA_BIND_TO;
	xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO;
	xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO;

	xprt->prot = XPRT_TRANSPORT_BC_RDMA;
	xprt->tsh_size = RPCRDMA_HDRLEN_MIN / sizeof(__be32);
	xprt->ops = &xprt_rdma_bc_procs;

	memcpy(&xprt->addr, args->dstaddr, args->addrlen);
	xprt->addrlen = args->addrlen;
	xprt_rdma_format_addresses(xprt, (struct sockaddr *)&xprt->addr);
	xprt->resvport = 0;

	xprt->max_payload = xprt_rdma_max_inline_read;

	new_xprt = rpcx_to_rdmax(xprt);
	new_xprt->rx_buf.rb_bc_max_requests = xprt->max_reqs;

	xprt_get(xprt);
	args->bc_xprt->xpt_bc_xprt = xprt;
	xprt->bc_xprt = args->bc_xprt;

	if (!try_module_get(THIS_MODULE))
		goto out_fail;

	/* Final put for backchannel xprt is in __svc_rdma_free */
	xprt_get(xprt);
	return xprt;

out_fail:
	xprt_rdma_free_addresses(xprt);
	args->bc_xprt->xpt_bc_xprt = NULL;
	args->bc_xprt->xpt_bc_xps = NULL;
	xprt_put(xprt);
	xprt_free(xprt);
	return ERR_PTR(-EINVAL);
}
Esempio n. 2
0
/**
 * xs_udp_connect_worker - set up a UDP socket
 * @args: RPC transport to connect
 *
 * Invoked by a work queue tasklet.
 */
static void xs_udp_connect_worker(void *args)
{
    struct rpc_xprt *xprt = (struct rpc_xprt *) args;
    struct socket *sock = xprt->sock;
    int err, status = -EIO;

    if (xprt->shutdown || xprt->addr.sin_port == 0)
        goto out;

    dprintk("RPC:      xs_udp_connect_worker for xprt %p\n", xprt);

    /* Start by resetting any existing state */
    xs_close(xprt);

    if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
        dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
        goto out;
    }
    xs_reclassify_socket(sock);

    if (xs_bind(xprt, sock)) {
        sock_release(sock);
        goto out;
    }

    if (!xprt->inet) {
        struct sock *sk = sock->sk;

        write_lock_bh(&sk->sk_callback_lock);

        sk->sk_user_data = xprt;
        xprt->old_data_ready = sk->sk_data_ready;
        xprt->old_state_change = sk->sk_state_change;
        xprt->old_write_space = sk->sk_write_space;
        sk->sk_data_ready = xs_udp_data_ready;
        sk->sk_write_space = xs_udp_write_space;
        sk->sk_no_check = UDP_CSUM_NORCV;
        sk->sk_allocation = GFP_ATOMIC;

        xprt_set_connected(xprt);

        /* Reset to new socket */
        xprt->sock = sock;
        xprt->inet = sk;

        write_unlock_bh(&sk->sk_callback_lock);
    }
    xs_udp_do_set_buffer_size(xprt);
    status = 0;
out:
    xprt_wake_pending_tasks(xprt, status);
    xprt_clear_connecting(xprt);
}