summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Carlier <devnexen@gmail.com>2026-10-16 14:27:14 +0100
committerPaolo Abeni <pabeni@redhat.com>2026-10-21 11:58:21 +0200
commita006b921ad32940676993bfae460b9f57547b79b (patch)
tree7a798fdb9f1b2c7e483860a6a1aaca8486081f42
parent66123066d8736d8f034d4d3ae23be3ef82dff78c (diff)
vsock: move SOL_SOCKET options to vsock_sol_socket_setsockopt()
SO_ZEROCOPY is handled inline in vsock_connectible_setsockopt(). Move it to a helper with a switch on optname, so other SOL_SOCKET options can be added as new cases. The value parsing goes to its own helper too, so each option can do its own checks before it. No functional change. Signed-off-by: David Carlier <devnexen@gmail.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20261016132716.272018-2-devnexen@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--net/vmw_vsock/af_vsock.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 483af15a5109..847afbebef01 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -2013,6 +2013,66 @@ static void vsock_update_buffer_size(struct vsock_sock *vsk,
vsk->buffer_size = val;
}
+static bool vsock_sol_socket_custom(int optname)
+{
+ switch (optname) {
+ case SO_ZEROCOPY:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int vsock_sol_socket_get_bool(sockptr_t optval, unsigned int optlen,
+ int *val)
+{
+ /* Use 'int' type here, because variable to set these options usually
+ * has this type.
+ */
+ if (optlen < sizeof(*val))
+ return -EINVAL;
+
+ if (copy_from_sockptr(val, optval, sizeof(*val)))
+ return -EFAULT;
+
+ if (*val < 0 || *val > 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int vsock_sol_socket_setsockopt(struct sock *sk, int optname,
+ sockptr_t optval, unsigned int optlen)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+ int err;
+ int val;
+
+ lock_sock(sk);
+
+ switch (optname) {
+ case SO_ZEROCOPY:
+ err = vsock_sol_socket_get_bool(optval, optlen, &val);
+ if (err)
+ break;
+
+ if (vsk->transport && !vsock_msgzerocopy_allow(vsk->transport)) {
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ sock_valbool_flag(sk, SOCK_ZEROCOPY, val);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ release_sock(sk);
+ return err;
+}
+
static int vsock_connectible_setsockopt(struct socket *sock,
int level,
int optname,
@@ -2044,36 +2104,16 @@ static int vsock_connectible_setsockopt(struct socket *sock,
sk = sock->sk;
vsk = vsock_sk(sk);
- lock_sock(sk);
-
- transport = vsk->transport;
-
if (level == SOL_SOCKET) {
- int zerocopy;
-
- if (optname != SO_ZEROCOPY) {
- release_sock(sk);
+ if (!vsock_sol_socket_custom(optname))
return sock_setsockopt(sock, level, optname, optval, optlen);
- }
-
- /* Use 'int' type here, because variable to
- * set this option usually has this type.
- */
- COPY_IN(zerocopy);
- if (zerocopy < 0 || zerocopy > 1) {
- err = -EINVAL;
- goto exit;
- }
+ return vsock_sol_socket_setsockopt(sk, optname, optval, optlen);
+ }
- if (transport && !vsock_msgzerocopy_allow(transport)) {
- err = -EOPNOTSUPP;
- goto exit;
- }
+ lock_sock(sk);
- sock_valbool_flag(sk, SOCK_ZEROCOPY, zerocopy);
- goto exit;
- }
+ transport = vsk->transport;
switch (optname) {
case SO_VM_SOCKETS_BUFFER_SIZE: