From: Max Vozeler Date: Wed, 12 Jan 2011 13:02:04 +0000 (+0200) Subject: staging: usbip: vhci: handle EAGAIN from SO_RCVTIMEO X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=bd65f6233f6bc3233e7910752689fe3a45dc2e0c;p=deliverable%2Flinux.git staging: usbip: vhci: handle EAGAIN from SO_RCVTIMEO If there is a receive timeout without any active requests, we can tell the connection was idle and ignore the timeout. If there are active requests for which we expect to receive a reply we close the connection. This makes it possible to set an upper bound on the time a usbip device may be unresponsive. This is a workaround for the lack of heart-beat messages in the USBIP protocol. Extending the protocol would break compatibility with all previous stub versions, so this seems like the lesser evil. Signed-off-by: Max Vozeler Tested-by: Mark Wehby Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index ac15cea75396..bf6991470941 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -193,6 +193,19 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } +static int vhci_priv_tx_empty(struct vhci_device *vdev) +{ + int empty = 0; + + spin_lock(&vdev->priv_lock); + + empty = list_empty(&vdev->priv_rx); + + spin_unlock(&vdev->priv_lock); + + return empty; +} + /* recv a pdu */ static void vhci_rx_pdu(struct usbip_device *ud) { @@ -210,8 +223,14 @@ static void vhci_rx_pdu(struct usbip_device *ud) if (ret < 0) { if (ret == -ECONNRESET) usbip_uinfo("connection reset by peer\n"); - else if (ret != -ERESTARTSYS) + else if (ret == -EAGAIN) { + /* ignore if connection was idle */ + if (vhci_priv_tx_empty(vdev)) + return; + usbip_uinfo("connection timed out with pending urbs\n"); + } else if (ret != -ERESTARTSYS) usbip_uinfo("xmit failed %d\n", ret); + usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return; }