hv_sock: Report EOF instead of -EIO for FIN
Subsystems (7)
Dexuan Cui
maintainerPATCH v3 1/1 hv_sock: Report EOF instead of -EIO for FIN
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.
In case we see a malformed/short packet, we still return -EIO.
---
Changes since v1:
Removed the local variable 'need_refill' to make the code more readable. Stefano, thanks!
No other change.
Changes since v2:
Added code to test the flag SEND_SHUTDOWN. Copilot, thanks! Updated the comment and the commit messages accordingly.
net/vmw_vsock/hyperv_transport.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-)
net/vmw_vsock/hyperv_transport.c +25 -4
@@ -694,7 +694,6 @@ static ssize_t hvs_stream_enqueue(struct vsock_sock *vsk, struct msghdr *msg,static s64 hvs_stream_has_data (struct vsock_sock *vsk) {struct hvsock *hvs = vsk->trans; -bool need_refill;s64 ret;if (hvs->recv_data_len >0 )
@@ -702,9 +701,31 @@ 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 (hvs->recv_desc) { +/* Here hvs->recv_data_len is 0, so hvs->recv_desc must +* be NULL unless it points to the 0-byte-payload FIN +* packet or a malformed/short packet: see +* hvs_update_recv_data(). +* +* If hvs->recv_desc points to the FIN packet, here all +* the payload has been dequeued and the peer_shutdown +* flag is set, 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. +* +* In case hvs->recv_desc points to a malformed/short +* packet, return -EIO. +*/ +if (hvs->vsk->peer_shutdown &SEND_SHUTDOWN ) +return 0 ; +else +return -EIO ; + } hvs->recv_desc =hv_pkt_iter_first (hvs->chan);if (!hvs->recv_desc)
Signature · 1 line
2.49.0
Dexuan Cui
maintainerQuoted 2 lines
From: Dexuan Cui
Sent: Monday, April 20, 2026 8:00 PM
Please ignore the email, as I just posted an incremental patch here:
https://lore.kernel.org/linux-hyperv/[email protected]/T/#u
See the link for more context:
https://lore.kernel.org/linux-hyperv/177672238581.1802062.15838493180057695674.git-patchwork-notify@kernel.org/T/#t