net/ceph/messenger_v2.c

Source file repositories/reference/linux-study-clean/net/ceph/messenger_v2.c

File Facts

System
Linux kernel
Corpus path
net/ceph/messenger_v2.c
Extension
.c
Size
99753 bytes
Lines
3815
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 (ret <= 0) {
			if (ret == -EAGAIN)
				ret = 0;
			return ret;
		}

		iov_iter_advance(it, ret);
	}

	WARN_ON(msg_data_left(&msg));
	return 1;
}

/*
 * Read as much as possible.
 *
 * Return:
 *   1 - done, nothing (else) to read
 *   0 - socket is empty, need to wait
 *  <0 - error
 */
static int ceph_tcp_recv(struct ceph_connection *con)
{
	int ret;

	dout("%s con %p %s %zu\n", __func__, con,
	     iov_iter_is_discard(&con->v2.in_iter) ? "discard" : "need",
	     iov_iter_count(&con->v2.in_iter));
	ret = do_recvmsg(con->sock, &con->v2.in_iter);
	dout("%s con %p ret %d left %zu\n", __func__, con, ret,
	     iov_iter_count(&con->v2.in_iter));
	return ret;
}

static int do_sendmsg(struct socket *sock, struct iov_iter *it)
{
	struct msghdr msg = { .msg_flags = CEPH_MSG_FLAGS };
	int ret;

	msg.msg_iter = *it;
	while (iov_iter_count(it)) {
		ret = sock_sendmsg(sock, &msg);
		if (ret <= 0) {
			if (ret == -EAGAIN)
				ret = 0;
			return ret;
		}

		iov_iter_advance(it, ret);
	}

	WARN_ON(msg_data_left(&msg));
	return 1;
}

static int do_try_sendpage(struct socket *sock, struct iov_iter *it)
{
	struct msghdr msg = { .msg_flags = CEPH_MSG_FLAGS };
	struct bio_vec bv;
	int ret;

	if (WARN_ON(!iov_iter_is_bvec(it)))
		return -EINVAL;

	while (iov_iter_count(it)) {
		/* iov_iter_iovec() for ITER_BVEC */
		bvec_set_page(&bv, it->bvec->bv_page,
			      min(iov_iter_count(it),
				  it->bvec->bv_len - it->iov_offset),
			      it->bvec->bv_offset + it->iov_offset);

		/*
		 * MSG_SPLICE_PAGES cannot properly handle pages with
		 * page_count == 0, we need to fall back to sendmsg if
		 * that's the case.
		 *
		 * Same goes for slab pages: skb_can_coalesce() allows
		 * coalescing neighboring slab objects into a single frag
		 * which triggers one of hardened usercopy checks.
		 */
		if (sendpage_ok(bv.bv_page))
			msg.msg_flags |= MSG_SPLICE_PAGES;
		else
			msg.msg_flags &= ~MSG_SPLICE_PAGES;

		iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bv, 1, bv.bv_len);
		ret = sock_sendmsg(sock, &msg);
		if (ret <= 0) {
			if (ret == -EAGAIN)
				ret = 0;

Annotation

Implementation Notes