From: Matias Ezequiel Vara Larsen <hidden> Date: 2019-09-26 18:24:02
This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.
Signed-off-by: Matias Ezequiel Vara Larsen <redacted>
---
net/vmw_vsock/virtio_transport_common.c | 50 +++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 3 deletions(-)
@@ -264,6 +264,50 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,}staticssize_t+virtio_transport_stream_do_peek(structvsock_sock*vsk,+structmsghdr*msg,+size_tlen)+{+structvirtio_vsock_sock*vvs=vsk->trans;+structvirtio_vsock_pkt*pkt;+size_tbytes,total=0;+interr=-EFAULT;++spin_lock_bh(&vvs->rx_lock);++list_for_each_entry(pkt,&vvs->rx_queue,list){+if(total==len)+break;++bytes=len-total;+if(bytes>pkt->len-pkt->off)+bytes=pkt->len-pkt->off;++/* sk_lock is held by caller so no one else can dequeue.+*Unlockrx_locksincememcpy_to_msg()maysleep.+*/+spin_unlock_bh(&vvs->rx_lock);++err=memcpy_to_msg(msg,pkt->buf+pkt->off,bytes);+if(err)+gotoout;++spin_lock_bh(&vvs->rx_lock);++total+=bytes;+}++spin_unlock_bh(&vvs->rx_lock);++returntotal;++out:+if(total)+err=total;+returnerr;+}++staticssize_tvirtio_transport_stream_do_dequeue(structvsock_sock*vsk,structmsghdr*msg,size_tlen)
From: Eric Dumazet <hidden> Date: 2019-09-26 19:33:41
On 9/26/19 11:23 AM, Matias Ezequiel Vara Larsen wrote:
quoted hunk
This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.
Signed-off-by: Matias Ezequiel Vara Larsen <redacted>
---
net/vmw_vsock/virtio_transport_common.c | 50 +++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 3 deletions(-)
@@ -264,6 +264,50 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,}staticssize_t+virtio_transport_stream_do_peek(structvsock_sock*vsk,+structmsghdr*msg,+size_tlen)+{+structvirtio_vsock_sock*vvs=vsk->trans;+structvirtio_vsock_pkt*pkt;+size_tbytes,total=0;+interr=-EFAULT;++spin_lock_bh(&vvs->rx_lock);++list_for_each_entry(pkt,&vvs->rx_queue,list){+if(total==len)+break;++bytes=len-total;+if(bytes>pkt->len-pkt->off)+bytes=pkt->len-pkt->off;++/* sk_lock is held by caller so no one else can dequeue.+*Unlockrx_locksincememcpy_to_msg()maysleep.+*/+spin_unlock_bh(&vvs->rx_lock);++err=memcpy_to_msg(msg,pkt->buf+pkt->off,bytes);+if(err)+gotoout;++spin_lock_bh(&vvs->rx_lock);++total+=bytes;+}++spin_unlock_bh(&vvs->rx_lock);++returntotal;++out:+if(total)+err=total;+returnerr;+}
This seems buggy to me.
virtio_transport_recv_enqueue() seems to be able to add payload to the last packet in the queue.
The loop you wrote here would miss newly added chunks while the vvs->rx_lock spinlock has been released.
virtio_transport_stream_do_dequeue() is ok, because it makes sure pkt->off == pkt->len
before cleaning the packet from the queue.
On Thu, Sep 26, 2019 at 12:33:36PM -0700, Eric Dumazet wrote:
On 9/26/19 11:23 AM, Matias Ezequiel Vara Larsen wrote:
quoted
This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.
Signed-off-by: Matias Ezequiel Vara Larsen <redacted>
---
net/vmw_vsock/virtio_transport_common.c | 50 +++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 3 deletions(-)
@@ -264,6 +264,50 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,}staticssize_t+virtio_transport_stream_do_peek(structvsock_sock*vsk,+structmsghdr*msg,+size_tlen)+{+structvirtio_vsock_sock*vvs=vsk->trans;+structvirtio_vsock_pkt*pkt;+size_tbytes,total=0;+interr=-EFAULT;++spin_lock_bh(&vvs->rx_lock);++list_for_each_entry(pkt,&vvs->rx_queue,list){+if(total==len)+break;++bytes=len-total;+if(bytes>pkt->len-pkt->off)+bytes=pkt->len-pkt->off;++/* sk_lock is held by caller so no one else can dequeue.+*Unlockrx_locksincememcpy_to_msg()maysleep.+*/+spin_unlock_bh(&vvs->rx_lock);++err=memcpy_to_msg(msg,pkt->buf+pkt->off,bytes);+if(err)+gotoout;++spin_lock_bh(&vvs->rx_lock);++total+=bytes;+}++spin_unlock_bh(&vvs->rx_lock);++returntotal;++out:+if(total)+err=total;+returnerr;+}
This seems buggy to me.
virtio_transport_recv_enqueue() seems to be able to add payload to the last packet in the queue.
The loop you wrote here would miss newly added chunks while the vvs->rx_lock spinlock has been released.
virtio_transport_stream_do_dequeue() is ok, because it makes sure pkt->off == pkt->len
before cleaning the packet from the queue.
Good catch!
Maybe we can solve in this way:
list_for_each_entry(pkt, &vvs->rx_queue, list) {
size_t off = pkt->off;
if (total == len)
break;
while (total < len && off < pkt->len) {
/* using 'off' instead of 'pkt->off' */
...
total += bytes;
off += bytes;
}
}
What do you think?
Cheers,
Stefano
From: Eric Dumazet <hidden> Date: 2019-09-27 13:37:04
On 9/27/19 1:55 AM, Stefano Garzarella wrote:
Good catch!
Maybe we can solve in this way:
list_for_each_entry(pkt, &vvs->rx_queue, list) {
size_t off = pkt->off;
if (total == len)
break;
while (total < len && off < pkt->len) {
/* using 'off' instead of 'pkt->off' */
...
total += bytes;
off += bytes;
}
}
What do you think?
Maybe, but I need to see a complete patch, evil is in the details :)
From: Matias Ezequiel Vara Larsen <hidden> Date: 2019-09-27 15:39:01
On Fri, Sep 27, 2019 at 06:37:00AM -0700, Eric Dumazet wrote:
On 9/27/19 1:55 AM, Stefano Garzarella wrote:
quoted
Good catch!
Maybe we can solve in this way:
list_for_each_entry(pkt, &vvs->rx_queue, list) {
size_t off = pkt->off;
if (total == len)
break;
while (total < len && off < pkt->len) {
/* using 'off' instead of 'pkt->off' */
...
total += bytes;
off += bytes;
}
}
What do you think?
Maybe, but I need to see a complete patch, evil is in the details :)
Thanks both for your comments, I will take them into account and submit
a second version.
Matias
From: Matias Ezequiel Vara Larsen <hidden> Date: 2019-09-27 16:45:12
This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.
Signed-off-by: Matias Ezequiel Vara Larsen <redacted>
---
net/vmw_vsock/virtio_transport_common.c | 55 +++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 3 deletions(-)
@@ -264,6 +264,55 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,}staticssize_t+virtio_transport_stream_do_peek(structvsock_sock*vsk,+structmsghdr*msg,+size_tlen)+{+structvirtio_vsock_sock*vvs=vsk->trans;+structvirtio_vsock_pkt*pkt;+size_tbytes,total=0,off;+interr=-EFAULT;++spin_lock_bh(&vvs->rx_lock);++list_for_each_entry(pkt,&vvs->rx_queue,list){+off=pkt->off;++if(total==len)+break;++while(total<len&&off<pkt->len){+bytes=len-total;+if(bytes>pkt->len-off)+bytes=pkt->len-off;++/* sk_lock is held by caller so no one else can dequeue.+*Unlockrx_locksincememcpy_to_msg()maysleep.+*/+spin_unlock_bh(&vvs->rx_lock);++err=memcpy_to_msg(msg,pkt->buf+off,bytes);+if(err)+gotoout;++spin_lock_bh(&vvs->rx_lock);++total+=bytes;+off+=bytes;+}+}++spin_unlock_bh(&vvs->rx_lock);++returntotal;++out:+if(total)+err=total;+returnerr;+}++staticssize_tvirtio_transport_stream_do_dequeue(structvsock_sock*vsk,structmsghdr*msg,size_tlen)
Hi Matias,
On Fri, Sep 27, 2019 at 04:44:23PM +0000, Matias Ezequiel Vara Larsen wrote:
This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.
Signed-off-by: Matias Ezequiel Vara Larsen <redacted>
---
net/vmw_vsock/virtio_transport_common.c | 55 +++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 3 deletions(-)
The patch LGTM. As David pointed out, this patch should go into net-next.
Since now net-next is open, you can resend with net-next tag [1] and
with:
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
Thanks,
Stefano
[1] https://www.kernel.org/doc/Documentation/networking/netdev-FAQ.txt
@@ -264,6 +264,55 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,}staticssize_t+virtio_transport_stream_do_peek(structvsock_sock*vsk,+structmsghdr*msg,+size_tlen)+{+structvirtio_vsock_sock*vvs=vsk->trans;+structvirtio_vsock_pkt*pkt;+size_tbytes,total=0,off;+interr=-EFAULT;++spin_lock_bh(&vvs->rx_lock);++list_for_each_entry(pkt,&vvs->rx_queue,list){+off=pkt->off;++if(total==len)+break;++while(total<len&&off<pkt->len){+bytes=len-total;+if(bytes>pkt->len-off)+bytes=pkt->len-off;++/* sk_lock is held by caller so no one else can dequeue.+*Unlockrx_locksincememcpy_to_msg()maysleep.+*/+spin_unlock_bh(&vvs->rx_lock);++err=memcpy_to_msg(msg,pkt->buf+off,bytes);+if(err)+gotoout;++spin_lock_bh(&vvs->rx_lock);++total+=bytes;+off+=bytes;+}+}++spin_unlock_bh(&vvs->rx_lock);++returntotal;++out:+if(total)+err=total;+returnerr;+}++staticssize_tvirtio_transport_stream_do_dequeue(structvsock_sock*vsk,structmsghdr*msg,size_tlen)