Message ID | 20210704190252.11866-4-xiyou.wangcong@gmail.com |
---|---|
State | New |
Headers | show |
Series | sockmap: add sockmap support for unix datagram socket | expand |
Cong Wang wrote: > From: Cong Wang <cong.wang@bytedance.com> > > Implement ->read_sock() for AF_UNIX datagram socket, it is > pretty much similar to udp_read_sock(). > > Cc: John Fastabend <john.fastabend@gmail.com> > Cc: Daniel Borkmann <daniel@iogearbox.net> > Cc: Jakub Sitnicki <jakub@cloudflare.com> > Cc: Lorenz Bauer <lmb@cloudflare.com> > Signed-off-by: Cong Wang <cong.wang@bytedance.com> > --- [...] > +static int unix_read_sock(struct sock *sk, read_descriptor_t *desc, > + sk_read_actor_t recv_actor) > +{ > + int copied = 0; > + > + while (1) { > + struct unix_sock *u = unix_sk(sk); > + struct sk_buff *skb; > + int used, err; > + > + mutex_lock(&u->iolock); > + skb = skb_recv_datagram(sk, 0, 1, &err); > + mutex_unlock(&u->iolock); > + if (!skb) > + return err; > + > + used = recv_actor(desc, skb, 0, skb->len); > + if (used <= 0) { > + if (!copied) > + copied = used; > + kfree_skb(skb); Is it OK to drop a unix dgram? I think the sockets likely wouldn't expect this? Anyways I'll have a proposed fix for TCP side shortly. And we can extend it here as well if needed. > + break; > + } else if (used <= skb->len) { > + copied += used; > + } > + > + kfree_skb(skb); > + if (!desc->count) > + break; > + } > + > + return copied; > +} > + > /* > * Sleep until more data has arrived. But check for races.. > */ > -- > 2.27.0 >
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 23c92ad15c61..38863468768a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -669,6 +669,8 @@ static ssize_t unix_stream_splice_read(struct socket *, loff_t *ppos, unsigned int flags); static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t); static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int); +static int unix_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t recv_actor); static int unix_dgram_connect(struct socket *, struct sockaddr *, int, int); static int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t); @@ -746,6 +748,7 @@ static const struct proto_ops unix_dgram_ops = { .listen = sock_no_listen, .shutdown = unix_shutdown, .sendmsg = unix_dgram_sendmsg, + .read_sock = unix_read_sock, .recvmsg = unix_dgram_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, @@ -2188,6 +2191,40 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, return err; } +static int unix_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t recv_actor) +{ + int copied = 0; + + while (1) { + struct unix_sock *u = unix_sk(sk); + struct sk_buff *skb; + int used, err; + + mutex_lock(&u->iolock); + skb = skb_recv_datagram(sk, 0, 1, &err); + mutex_unlock(&u->iolock); + if (!skb) + return err; + + used = recv_actor(desc, skb, 0, skb->len); + if (used <= 0) { + if (!copied) + copied = used; + kfree_skb(skb); + break; + } else if (used <= skb->len) { + copied += used; + } + + kfree_skb(skb); + if (!desc->count) + break; + } + + return copied; +} + /* * Sleep until more data has arrived. But check for races.. */