Commit 76851d12 authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller

sock: add SOCK_ZEROCOPY sockopt

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: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 52267790
...@@ -109,4 +109,6 @@ ...@@ -109,4 +109,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _UAPI_ASM_SOCKET_H */ #endif /* _UAPI_ASM_SOCKET_H */
...@@ -102,5 +102,7 @@ ...@@ -102,5 +102,7 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */
...@@ -111,4 +111,6 @@ ...@@ -111,4 +111,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _ASM_IA64_SOCKET_H */ #endif /* _ASM_IA64_SOCKET_H */
...@@ -102,4 +102,6 @@ ...@@ -102,4 +102,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _ASM_M32R_SOCKET_H */ #endif /* _ASM_M32R_SOCKET_H */
...@@ -120,4 +120,6 @@ ...@@ -120,4 +120,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _UAPI_ASM_SOCKET_H */ #endif /* _UAPI_ASM_SOCKET_H */
...@@ -102,4 +102,6 @@ ...@@ -102,4 +102,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */
...@@ -101,4 +101,6 @@ ...@@ -101,4 +101,6 @@
#define SO_PEERGROUPS 0x4034 #define SO_PEERGROUPS 0x4034
#define SO_ZEROCOPY 0x4035
#endif /* _UAPI_ASM_SOCKET_H */ #endif /* _UAPI_ASM_SOCKET_H */
...@@ -108,4 +108,6 @@ ...@@ -108,4 +108,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */
...@@ -98,6 +98,8 @@ ...@@ -98,6 +98,8 @@
#define SO_PEERGROUPS 0x003d #define SO_PEERGROUPS 0x003d
#define SO_ZEROCOPY 0x003e
/* Security levels - as per NRL IPv6 - don't actually do anything */ /* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
......
...@@ -113,4 +113,6 @@ ...@@ -113,4 +113,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* _XTENSA_SOCKET_H */ #endif /* _XTENSA_SOCKET_H */
...@@ -104,4 +104,6 @@ ...@@ -104,4 +104,6 @@
#define SO_PEERGROUPS 59 #define SO_PEERGROUPS 59
#define SO_ZEROCOPY 60
#endif /* __ASM_GENERIC_SOCKET_H */ #endif /* __ASM_GENERIC_SOCKET_H */
...@@ -922,6 +922,9 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size) ...@@ -922,6 +922,9 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
WARN_ON_ONCE(!in_task()); WARN_ON_ONCE(!in_task());
if (!sock_flag(sk, SOCK_ZEROCOPY))
return NULL;
skb = sock_omalloc(sk, 0, GFP_KERNEL); skb = sock_omalloc(sk, 0, GFP_KERNEL);
if (!skb) if (!skb)
return NULL; return NULL;
......
...@@ -1055,6 +1055,20 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1055,6 +1055,20 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
if (val == 1) if (val == 1)
dst_negative_advice(sk); dst_negative_advice(sk);
break; 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: default:
ret = -ENOPROTOOPT; ret = -ENOPROTOOPT;
break; break;
...@@ -1383,6 +1397,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -1383,6 +1397,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
v.val64 = sock_gen_cookie(sk); v.val64 = sock_gen_cookie(sk);
break; break;
case SO_ZEROCOPY:
v.val = sock_flag(sk, SOCK_ZEROCOPY);
break;
default: default:
/* We implement the SO_SNDLOWAT etc to not be settable /* We implement the SO_SNDLOWAT etc to not be settable
* (1003.1g 7). * (1003.1g 7).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment