Commit 98917cf0 authored by Arjun Roy's avatar Arjun Roy Committed by Jakub Kicinski
Browse files

net-zerocopy: Refactor frag-is-remappable test.



Refactor frag-is-remappable test for tcp receive zerocopy. This is
part of a patch set that introduces short-circuited hybrid copies
for small receive operations, which results in roughly 33% fewer
syscalls for small RPC scenarios.

Signed-off-by: default avatarArjun Roy <arjunroy@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7fba5309
Loading
Loading
Loading
Loading
+26 −8
Original line number Diff line number Diff line
@@ -1780,6 +1780,26 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
	return frag;
}

static bool can_map_frag(const skb_frag_t *frag)
{
	return skb_frag_size(frag) == PAGE_SIZE && !skb_frag_off(frag);
}

static int find_next_mappable_frag(const skb_frag_t *frag,
				   int remaining_in_skb)
{
	int offset = 0;

	if (likely(can_map_frag(frag)))
		return 0;

	while (offset < remaining_in_skb && !can_map_frag(frag)) {
		offset += skb_frag_size(frag);
		++frag;
	}
	return offset;
}

static int tcp_copy_straggler_data(struct tcp_zerocopy_receive *zc,
				   struct sk_buff *skb, u32 copylen,
				   u32 *offset, u32 *seq)
@@ -1905,6 +1925,8 @@ static int tcp_zerocopy_receive(struct sock *sk,
	ret = 0;
	curr_addr = address;
	while (length + PAGE_SIZE <= zc->length) {
		int mappable_offset;

		if (zc->recv_skip_hint < PAGE_SIZE) {
			u32 offset_frag;

@@ -1932,15 +1954,11 @@ static int tcp_zerocopy_receive(struct sock *sk,
			if (!frags || offset_frag)
				break;
		}
		if (skb_frag_size(frags) != PAGE_SIZE || skb_frag_off(frags)) {
			int remaining = zc->recv_skip_hint;

			while (remaining && (skb_frag_size(frags) != PAGE_SIZE ||
					     skb_frag_off(frags))) {
				remaining -= skb_frag_size(frags);
				frags++;
			}
			zc->recv_skip_hint -= remaining;
		mappable_offset = find_next_mappable_frag(frags,
							  zc->recv_skip_hint);
		if (mappable_offset) {
			zc->recv_skip_hint = mappable_offset;
			break;
		}
		pages[pg_idx] = skb_frag_page(frags);