Commit f0c5827d07cb unluckily causes a regression for the FIN packet, and the final read syscall gets an error rather than 0. Ideally, we would want to fix hvs_channel_readable_payload() so that it could return 0 in the FIN scenario, but it's not good for the hv_sock driver to use the VMBus ringbuffer's cached priv_read_index, which is internal data in the VMBus driver. Fix the regression in hv_sock by returning 0 rather than -EIO. Fixes: f0c5827d07cb ("hv_sock: Return the readable bytes in hvs_stream_has_data()") Cc: stable@vger.kernel.org Reported-by: Ben Hillis Reported-by: Mitchell Levy Signed-off-by: Dexuan Cui --- net/vmw_vsock/hyperv_transport.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index 069386a74557..63d3549125be 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c @@ -703,8 +703,22 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk) switch (hvs_channel_readable_payload(hvs->chan)) { case 1: need_refill = !hvs->recv_desc; - if (!need_refill) - return -EIO; + if (!need_refill) { + /* Here hvs->recv_data_len is 0, so hvs->recv_desc must + * be NULL unless it points to the 0-byte-payload FIN + * packet: see hvs_update_recv_data(). + * + * Here all the payload has been dequeued, but + * hvs_channel_readable_payload() still returns 1, + * because the VMBus ringbuffer's read_index is not + * updated for the FIN packet: hvs_stream_dequeue() -> + * hv_pkt_iter_next() updates the cached priv_read_index + * but has no opportunity to update the read_index in + * hv_pkt_iter_close() as hvs_stream_has_data() returns + * 0 for the FIN packet, so it won't get dequeued. + */ + return 0; + } hvs->recv_desc = hv_pkt_iter_first(hvs->chan); if (!hvs->recv_desc) -- 2.49.0