On 22/09/2023 14:07, Tudor Cretu wrote:
From: Harry Ramsey harry.ramsey@arm.com
Introduce a compat version of the struct tcp_zerocopy_receive structure. Also, implement helper functions that convert between the compat version and the native version of the struct.
A subsequent patch is going to change the struct tcp_zerocopy_receive to enable it to support new architectures. On such architectures, the current struct layout still needs to be supported for compat tasks.
I would replace "compat" with "compat64" everywhere to avoid any confusion.
Signed-off-by: Harry Ramsey harry.ramsey@arm.com Co-developed-by: Tudor Cretu tudor.cretu@arm.com Signed-off-by: Tudor Cretu tudor.cretu@arm.com
net/ipv4/tcp.c | 130 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 21 deletions(-)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 90526625671b..8690ce837cfb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1940,6 +1940,100 @@ static int find_next_mappable_frag(const skb_frag_t *frag, return offset; } +struct compat_tcp_zerocopy_receive {
- __u64 address;
- __u32 length;
- __u32 recv_skip_hint;
- __u32 inq;
- __s32 err;
- __u64 copybuf_address;
- __s32 copybuf_len;
- __u32 flags;
- __u64 msg_control;
- __u64 msg_controllen;
- __u32 msg_flags;
- __u32 reserved;
+};
+static inline bool in_compat64(void) +{
- return IS_ENABLED(CONFIG_COMPAT64) && in_compat_syscall();
+}
+static inline size_t tcp_zerocopy_receive_size(void) +{
- if (in_compat64())
return sizeof(struct compat_tcp_zerocopy_receive);
- return sizeof(struct tcp_zerocopy_receive);
+}
Considering this is used in only one spot, we don't really need a function - just set a local variable to that value there. Bonus point is that it improves readability (avoids calling 4 times a mysterious function that takes no argument).
+static int get_compat64_tcp_zerocopy_receive(struct tcp_zerocopy_receive *zc,
sockptr_t src, size_t size)
+{
- struct compat_tcp_zerocopy_receive compat_zc = {};
- if (copy_from_sockptr(&compat_zc, src, size))
return -EFAULT;
- zc->address = compat_zc.address;
- zc->length = compat_zc.length;
- zc->recv_skip_hint = compat_zc.recv_skip_hint;
- zc->inq = compat_zc.inq;
- zc->err = compat_zc.err;
- zc->copybuf_address = compat_zc.copybuf_address;
- zc->copybuf_len = compat_zc.copybuf_len;
- zc->flags = compat_zc.flags;
- zc->msg_control = compat_zc.msg_control;
- zc->msg_controllen = compat_zc.msg_controllen;
- zc->msg_flags = compat_zc.msg_flags;
- zc->reserved = compat_zc.reserved;
- return 0;
+}
+static int copy_tcp_zerocopy_receive_from_sockptr(struct tcp_zerocopy_receive *zc,
sockptr_t src, size_t size)
+{
- if (in_compat64())
return get_compat64_tcp_zerocopy_receive(zc, src, size);
- if (copy_from_sockptr(zc, src, size))
return -EFAULT;
- return 0;
+}
+static int set_compat64_tcp_zerocopy_receive(sockptr_t dst,
struct tcp_zerocopy_receive *zc,
size_t size)
+{
- struct compat_tcp_zerocopy_receive compat_zc = {};
- compat_zc.address = zc->address;
- compat_zc.length = zc->length;
- compat_zc.recv_skip_hint = zc->recv_skip_hint;
- compat_zc.inq = zc->inq;
- compat_zc.err = zc->err;
- compat_zc.copybuf_address = zc->copybuf_address;
- compat_zc.copybuf_len = zc->copybuf_len;
- compat_zc.flags = zc->flags;
- compat_zc.msg_control = zc->msg_control;
- compat_zc.msg_controllen = zc->msg_controllen;
- compat_zc.msg_flags = zc->msg_flags;
- compat_zc.reserved = zc->reserved;
In this specific case we can make this more compact by directly initialising the struct:
struct ... compat_zc = { .address = zc->address, ... };
A small bonus is that this way we don't zero-init first, though in practice I expect the compiler to optimise out.
Kevin