sock: add SOCK_ZEROCOPY sockopt
authorWillem de Bruijn <willemb@google.com>
Thu, 3 Aug 2017 20:29:40 +0000 (16:29 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Aug 2017 04:37:29 +0000 (21:37 -0700)
The send call ignores unknown flags. Legacy applications may already
unwittingly pass MSG_ZEROCOPY. Continue to ignore this flag unless a
socket opts in to zerocopy.

Introduce socket option SO_ZEROCOPY to enable MSG_ZEROCOPY processing.
Processes can also query this socket option to detect kernel support
for the feature. Older kernels will return ENOPROTOOPT.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
13 files changed:
arch/alpha/include/uapi/asm/socket.h
arch/frv/include/uapi/asm/socket.h
arch/ia64/include/uapi/asm/socket.h
arch/m32r/include/uapi/asm/socket.h
arch/mips/include/uapi/asm/socket.h
arch/mn10300/include/uapi/asm/socket.h
arch/parisc/include/uapi/asm/socket.h
arch/s390/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/socket.h
arch/xtensa/include/uapi/asm/socket.h
include/uapi/asm-generic/socket.h
net/core/skbuff.c
net/core/sock.c

index 7b285dd..c6133a0 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _UAPI_ASM_SOCKET_H */
index f1e3b20..9abf02d 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _ASM_SOCKET_H */
 
index 5dd5c5d..002eb85 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _ASM_IA64_SOCKET_H */
index f8f7b47..e268e51 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _ASM_M32R_SOCKET_H */
index 882823b..6c755bc 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _UAPI_ASM_SOCKET_H */
index c710db3..ac82a3f 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _ASM_SOCKET_H */
index a0d4dc9..3b2bf7a 100644 (file)
 
 #define SO_PEERGROUPS          0x4034
 
+#define SO_ZEROCOPY            0x4035
+
 #endif /* _UAPI_ASM_SOCKET_H */
index 52a63f4..a56916c 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _ASM_SOCKET_H */
index 186fd81..b2f5c50 100644 (file)
@@ -98,6 +98,8 @@
 
 #define SO_PEERGROUPS          0x003d
 
+#define SO_ZEROCOPY            0x003e
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index 3eed276..2200599 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* _XTENSA_SOCKET_H */
index 9861be8..e47c9e4 100644 (file)
 
 #define SO_PEERGROUPS          59
 
+#define SO_ZEROCOPY            60
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index 0603e44..29e34bc 100644 (file)
@@ -922,6 +922,9 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
 
        WARN_ON_ONCE(!in_task());
 
+       if (!sock_flag(sk, SOCK_ZEROCOPY))
+               return NULL;
+
        skb = sock_omalloc(sk, 0, GFP_KERNEL);
        if (!skb)
                return NULL;
index e8b6968..9ea988d 100644 (file)
@@ -1055,6 +1055,20 @@ set_rcvbuf:
                if (val == 1)
                        dst_negative_advice(sk);
                break;
+
+       case SO_ZEROCOPY:
+               if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
+                       ret = -ENOTSUPP;
+               else if (sk->sk_protocol != IPPROTO_TCP)
+                       ret = -ENOTSUPP;
+               else if (sk->sk_state != TCP_CLOSE)
+                       ret = -EBUSY;
+               else if (val < 0 || val > 1)
+                       ret = -EINVAL;
+               else
+                       sock_valbool_flag(sk, SOCK_ZEROCOPY, valbool);
+               break;
+
        default:
                ret = -ENOPROTOOPT;
                break;
@@ -1383,6 +1397,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                v.val64 = sock_gen_cookie(sk);
                break;
 
+       case SO_ZEROCOPY:
+               v.val = sock_flag(sk, SOCK_ZEROCOPY);
+               break;
+
        default:
                /* We implement the SO_SNDLOWAT etc to not be settable
                 * (1003.1g 7).