net/sunrpc/xprtrdma/svc_rdma_transport.c

Source file repositories/reference/linux-study-clean/net/sunrpc/xprtrdma/svc_rdma_transport.c

File Facts

System
Linux kernel
Corpus path
net/sunrpc/xprtrdma/svc_rdma_transport.c
Extension
.c
Size
22343 bytes
Lines
693
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(listen_id)) {
			pr_err("Listener dead, address change failed for device %s\n",
				cma_id->device->name);
		} else
			cma_xprt->sc_cm_id = listen_id;
		return 1;
	default:
		break;
	}
	return 0;
}

/**
 * svc_rdma_cma_handler - Handle CM events on client connections
 * @cma_id: the server's listener rdma_cm_id
 * @event: details of the event
 *
 * Return values:
 *     %0: Do not destroy @cma_id
 *     %1: Destroy @cma_id (never returned here)
 */
static int svc_rdma_cma_handler(struct rdma_cm_id *cma_id,
				struct rdma_cm_event *event)
{
	struct svcxprt_rdma *rdma = cma_id->context;
	struct svc_xprt *xprt = &rdma->sc_xprt;

	switch (event->event) {
	case RDMA_CM_EVENT_ESTABLISHED:
		clear_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags);

		/* Handle any requests that were received while
		 * CONN_PENDING was set. */
		svc_xprt_enqueue(xprt);
		break;
	case RDMA_CM_EVENT_DISCONNECTED:
		svc_rdma_xprt_deferred_close(rdma);
		break;
	default:
		break;
	}
	return 0;
}

/*
 * Create a listening RDMA service endpoint.
 */
static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
					struct net *net,
					struct sockaddr *sa, int salen,
					int flags)
{
	struct rdma_cm_id *listen_id;
	struct svcxprt_rdma *cma_xprt;

	if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
		return ERR_PTR(-EAFNOSUPPORT);
	cma_xprt = svc_rdma_create_xprt(serv, net, NUMA_NO_NODE);
	if (!cma_xprt)
		return ERR_PTR(-ENOMEM);
	set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags);
	strcpy(cma_xprt->sc_xprt.xpt_remotebuf, "listener");

	listen_id = svc_rdma_create_listen_id(net, sa, cma_xprt);
	if (IS_ERR(listen_id)) {
		kfree(cma_xprt);
		return ERR_CAST(listen_id);
	}
	cma_xprt->sc_cm_id = listen_id;

	/*
	 * We need to use the address from the cm_id in case the
	 * caller specified 0 for the port number.
	 */
	sa = (struct sockaddr *)&cma_xprt->sc_cm_id->route.addr.src_addr;
	svc_xprt_set_local(&cma_xprt->sc_xprt, sa, salen);

	return &cma_xprt->sc_xprt;
}

static void svc_rdma_xprt_done(struct rpcrdma_notification *rn)
{
	struct svcxprt_rdma *rdma = container_of(rn, struct svcxprt_rdma,
						 sc_rn);
	struct rdma_cm_id *id = rdma->sc_cm_id;

	trace_svcrdma_device_removal(id);
	svc_xprt_close(&rdma->sc_xprt);
}

Annotation

Implementation Notes