aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2020-12-18 15:12:46 -0700
committerJens Axboe <axboe@kernel.dk>2020-12-18 20:06:45 -0700
commit3880f5850d15782bebbc1a64460a737b9765fdd7 (patch)
treef219de7eb3f2ef1afbb65de5bd8ba0e378b575c2
parent4e86778464b953f286897c458d04c50e78d08739 (diff)
downloadlinux-block-io_uring-fops.tar.gz
net: wire up support for file_operations->uring_cmd()io_uring-fops
Support for SOCKET_URING_OP_SIOCINQ and SOCKET_URING_OP_SIOCOUTQ for tcp/udp/raw ipv4/ipv6. Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--include/net/raw.h3
-rw-r--r--include/net/sock.h3
-rw-r--r--include/net/tcp.h2
-rw-r--r--include/net/udp.h2
-rw-r--r--include/uapi/linux/net.h12
-rw-r--r--net/ipv4/raw.c23
-rw-r--r--net/ipv4/tcp.c33
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/udp.c14
-rw-r--r--net/ipv6/raw.c1
-rw-r--r--net/ipv6/tcp_ipv6.c1
-rw-r--r--net/ipv6/udp.c1
12 files changed, 96 insertions, 0 deletions
diff --git a/include/net/raw.h b/include/net/raw.h
index 8ad8df59485364..fbaa123c245857 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -82,4 +82,7 @@ static inline bool raw_sk_bound_dev_eq(struct net *net, int bound_dev_if,
#endif
}
+int raw_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags);
+
#endif /* _RAW_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index bdc4323ce53c95..c33f0b58a06f59 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1146,6 +1146,9 @@ struct proto {
int (*ioctl)(struct sock *sk, int cmd,
unsigned long arg);
+ int (*uring_cmd)(struct sock *sk,
+ struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags);
int (*init)(struct sock *sk);
void (*destroy)(struct sock *sk);
void (*shutdown)(struct sock *sk, int how);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 78d13c88720fda..8174d9752e52f5 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -350,6 +350,8 @@ void tcp_twsk_destructor(struct sock *sk);
ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags);
+int tcp_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags);
void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks);
static inline void tcp_dec_quickack_mode(struct sock *sk,
diff --git a/include/net/udp.h b/include/net/udp.h
index 877832bed4713a..362224fe83fe26 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -326,6 +326,8 @@ struct sock *__udp6_lib_lookup(struct net *net,
struct sk_buff *skb);
struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport);
+int udp_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags);
/* UDP uses skb->dev_scratch to cache as much information as possible and avoid
* possibly multiple cache miss on dequeue()
diff --git a/include/uapi/linux/net.h b/include/uapi/linux/net.h
index 4dabec6bd957d6..629e5df40858c4 100644
--- a/include/uapi/linux/net.h
+++ b/include/uapi/linux/net.h
@@ -55,4 +55,16 @@ typedef enum {
#define __SO_ACCEPTCON (1 << 16) /* performed a listen */
+enum {
+ SOCKET_URING_OP_SIOCINQ = 0,
+ SOCKET_URING_OP_SIOCOUTQ,
+};
+
+struct sock_uring_cmd {
+ __u16 op;
+ __u16 unused[13];
+ __u64 reserved; /* will be overwritten by core */
+ __u64 unused2;
+};
+
#endif /* _UAPI_LINUX_NET_H */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 50a73178d63a84..106200033a6024 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -878,6 +878,28 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
return do_raw_getsockopt(sk, level, optname, optval, optlen);
}
+int raw_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags)
+{
+ switch (scmd->op) {
+ case SIOCOUTQ:
+ return sk_wmem_alloc_get(sk);
+ case SIOCINQ: {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+ amount = skb->len;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return amount;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
switch (cmd) {
@@ -956,6 +978,7 @@ struct proto raw_prot = {
.release_cb = ip4_datagram_release_cb,
.hash = raw_hash_sk,
.unhash = raw_unhash_sk,
+ .uring_cmd = raw_uring_cmd,
.obj_size = sizeof(struct raw_sock),
.useroffset = offsetof(struct raw_sock, filter),
.usersize = sizeof_field(struct raw_sock, filter),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ed42d2193c5c76..f8bc786775c580 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -602,6 +602,39 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
}
EXPORT_SYMBOL(tcp_poll);
+int tcp_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ bool slow;
+ int ret;
+
+ switch (scmd->op) {
+ case SIOCINQ:
+ if (sk->sk_state == TCP_LISTEN)
+ return -EINVAL;
+
+ slow = lock_sock_fast(sk);
+ ret = tcp_inq(sk);
+ unlock_sock_fast(sk, slow);
+ break;
+ case SIOCOUTQ:
+ if (sk->sk_state == TCP_LISTEN)
+ return -EINVAL;
+
+ if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
+ ret = 0;
+ else
+ ret = READ_ONCE(tp->write_seq) - tp->snd_una;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
struct tcp_sock *tp = tcp_sk(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 58207c7769d056..bfb8c5aa05fcda 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2787,6 +2787,7 @@ struct proto tcp_prot = {
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
+ .uring_cmd = tcp_uring_cmd,
.init = tcp_v4_init_sock,
.destroy = tcp_v4_destroy_sock,
.shutdown = tcp_shutdown,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 7103b0a89756e2..2c6726361a121a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1676,6 +1676,19 @@ static int first_packet_length(struct sock *sk)
return res;
}
+int udp_uring_cmd(struct sock *sk, struct sock_uring_cmd *scmd,
+ enum io_uring_cmd_flags flags)
+{
+ switch (scmd->op) {
+ case SIOCOUTQ:
+ return sk_wmem_alloc_get(sk);
+ case SIOCINQ:
+ return max_t(int, 0, first_packet_length(sk));
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
/*
* IOCTL requests applicable to the UDP protocol
*/
@@ -2831,6 +2844,7 @@ struct proto udp_prot = {
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .uring_cmd = udp_uring_cmd,
.init = udp_init_sock,
.destroy = udp_destroy_sock,
.setsockopt = udp_setsockopt,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1f56d9aae5892b..50f1e818948239 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1235,6 +1235,7 @@ struct proto rawv6_prot = {
.connect = ip6_datagram_connect_v6_only,
.disconnect = __udp_disconnect,
.ioctl = rawv6_ioctl,
+ .uring_cmd = raw_uring_cmd,
.init = rawv6_init_sk,
.setsockopt = rawv6_setsockopt,
.getsockopt = rawv6_getsockopt,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 0e1509b02cb306..e86af3503a4bf1 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2116,6 +2116,7 @@ struct proto tcpv6_prot = {
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
+ .uring_cmd = tcp_uring_cmd,
.init = tcp_v6_init_sock,
.destroy = tcp_v6_destroy_sock,
.shutdown = tcp_shutdown,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b9f3dfdd238344..881ae4a1cdda09 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1701,6 +1701,7 @@ struct proto udpv6_prot = {
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .uring_cmd = udp_uring_cmd,
.init = udp_init_sock,
.destroy = udpv6_destroy_sock,
.setsockopt = udpv6_setsockopt,