net/sunrpc/xprtrdma/rpc_rdma.c

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

File Facts

System
Linux kernel
Corpus path
net/sunrpc/xprtrdma/rpc_rdma.c
Extension
.c
Size
39828 bytes
Lines
1465
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

while (remaining) {
			remaining -= min_t(unsigned int,
					   PAGE_SIZE - offset, remaining);
			offset = 0;
			if (++count > ep->re_attr.cap.max_send_sge)
				return false;
		}
	}

	return true;
}

/* The client can't know how large the actual reply will be. Thus it
 * plans for the largest possible reply for that particular ULP
 * operation. If the maximum combined reply message size exceeds that
 * limit, the client must provide a write list or a reply chunk for
 * this request.
 */
static bool rpcrdma_results_inline(struct rpcrdma_xprt *r_xprt,
				   struct rpc_rqst *rqst)
{
	return rqst->rq_rcv_buf.buflen <= r_xprt->rx_ep->re_max_inline_recv;
}

/* The client is required to provide a Reply chunk if the maximum
 * size of the non-payload part of the RPC Reply is larger than
 * the inline threshold.
 */
static bool
rpcrdma_nonpayload_inline(const struct rpcrdma_xprt *r_xprt,
			  const struct rpc_rqst *rqst)
{
	const struct xdr_buf *buf = &rqst->rq_rcv_buf;

	return (buf->head[0].iov_len + buf->tail[0].iov_len) <
		r_xprt->rx_ep->re_max_inline_recv;
}

/* ACL likes to be lazy in allocating pages. For TCP, these
 * pages can be allocated during receive processing. Not true
 * for RDMA, which must always provision receive buffers
 * up front.
 */
static noinline int
rpcrdma_alloc_sparse_pages(struct xdr_buf *buf)
{
	struct page **ppages;
	int len;

	len = buf->page_len;
	ppages = buf->pages + (buf->page_base >> PAGE_SHIFT);
	while (len > 0) {
		if (!*ppages)
			*ppages = alloc_page(GFP_NOWAIT);
		if (!*ppages)
			return -ENOBUFS;
		ppages++;
		len -= PAGE_SIZE;
	}

	return 0;
}

static void
rpcrdma_xdr_cursor_init(struct rpcrdma_xdr_cursor *cur,
			const struct xdr_buf *xdrbuf,
			unsigned int pos, enum rpcrdma_chunktype type)
{
	cur->xc_buf = xdrbuf;
	cur->xc_page_offset = 0;
	cur->xc_flags = 0;

	if (pos != 0)
		cur->xc_flags |= XC_HEAD_DONE;
	if (!xdrbuf->page_len)
		cur->xc_flags |= XC_PAGES_DONE;
	if (type == rpcrdma_readch || type == rpcrdma_writech ||
	    !xdrbuf->tail[0].iov_len)
		cur->xc_flags |= XC_TAIL_DONE;
}

static bool
rpcrdma_xdr_cursor_done(const struct rpcrdma_xdr_cursor *cur)
{
	return (cur->xc_flags & (XC_HEAD_DONE | XC_PAGES_DONE |
				 XC_TAIL_DONE)) ==
	       (XC_HEAD_DONE | XC_PAGES_DONE | XC_TAIL_DONE);
}

static int

Annotation

Implementation Notes