net/sunrpc/svcsock.c

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

File Facts

System
Linux kernel
Corpus path
net/sunrpc/svcsock.c
Extension
.c
Size
44379 bytes
Lines
1698
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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

tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
		iov_iter_revert(&msg.msg_iter, ret);
		ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
	}
	return ret;
}

static int
svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
{
	int ret;
	struct socket *sock = svsk->sk_sock;

	ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
	if (msg->msg_flags & MSG_CTRUNC) {
		msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
		if (ret == 0 || ret == -EIO)
			ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);
	}
	return ret;
}

#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek)
{
	struct bvec_iter bi = {
		.bi_size	= size + seek,
	};
	struct bio_vec bv;

	bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
	for_each_bvec(bv, bvec, bi, bi)
		flush_dcache_page(bv.bv_page);
}
#else
static inline void svc_flush_bvec(const struct bio_vec *bvec, size_t size,
				  size_t seek)
{
}
#endif

/*
 * Read from @rqstp's transport socket. The incoming message fills whole
 * pages in @rqstp's rq_pages array until the last page of the message
 * has been received into a partial page.
 */
static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
				size_t seek)
{
	struct svc_sock *svsk =
		container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
	struct bio_vec *bvec = rqstp->rq_bvec;
	struct msghdr msg = { NULL };
	unsigned int i;
	ssize_t len;
	size_t t;

	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);

	for (i = 0, t = 0; t < buflen; i++, t += PAGE_SIZE)
		bvec_set_page(&bvec[i], rqstp->rq_pages[i], PAGE_SIZE, 0);

	iov_iter_bvec(&msg.msg_iter, ITER_DEST, bvec, i, buflen);
	if (seek) {
		iov_iter_advance(&msg.msg_iter, seek);
		buflen -= seek;
	}
	len = svc_tcp_sock_recvmsg(svsk, &msg);
	if (len > 0)
		svc_flush_bvec(bvec, len, seek);

	/* If we read a full record, then assume there may be more
	 * data to read (stream based sockets only!)
	 */
	if (len == buflen)
		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);

	return len;
}

/*
 * Set socket snd and rcv buffer lengths
 */
static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
{
	unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
	struct socket *sock = svsk->sk_sock;

	nreqs = min(nreqs, INT_MAX / 2 / max_mesg);

Annotation

Implementation Notes