lguest: Don't block after timeout

By adding a flag to handle_output() when it's called because we timed out,
we can avoid blocking further notifications when there are pending packets
in this case:

Guest -> Host 1GB TCP:
Before: Seconds 8.96367 xmit 207004 recv 16992 timeout 205142
After: Seconds 8.53821 xmit 339394 recv 1507 timeout 169669

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 Documentation/lguest/lguest.c |   22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff -r 95df2714aff4 Documentation/lguest/lguest.c
--- a/Documentation/lguest/lguest.c	Tue Jul 01 14:00:59 2008 +1000
+++ b/Documentation/lguest/lguest.c	Tue Jul 01 14:03:57 2008 +1000
@@ -156,8 +156,8 @@ struct virtqueue
 	/* The actual ring of buffers. */
 	struct vring vring;
 
-	/* The routine to call when the Guest pings us. */
-	void (*handle_output)(int fd, struct virtqueue *me);
+	/* The routine to call when the Guest pings us, or timeout. */
+	void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
 
 	/* Outstanding buffers */
 	unsigned int inflight;
@@ -879,7 +885,7 @@ static bool handle_console_input(int fd,
 
 /* Handling output for console is simple: we just get all the output buffers
  * and write them to stdout. */
-static void handle_console_output(int fd, struct virtqueue *vq)
+static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
 {
 	unsigned int head, out, in;
 	int len;
@@ -916,7 +922,7 @@ static void block_vq(struct virtqueue *v
  * and write them (ignoring the first element) to this device's file descriptor
  * (/dev/net/tun).
  */
-static void handle_net_output(int fd, struct virtqueue *vq)
+static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
 {
 	unsigned int head, out, in, num = 0;
 	int len;
@@ -936,7 +942,7 @@ static void handle_net_output(int fd, st
 	}
 
 	/* Block further kicks, and set up a timer if we saw anything. */
-	if (num)
+	if (!timeout && num)
 		block_vq(vq);
 }
 
@@ -984,14 +990,14 @@ static bool handle_tun_input(int fd, str
 /*L:215 This is the callback attached to the network and console input
  * virtqueues: it ensures we try again, in case we stopped console or net
  * delivery because Guest didn't have any buffers. */
-static void enable_fd(int fd, struct virtqueue *vq)
+static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
 {
 	add_device_fd(vq->dev->fd);
 	/* Tell waker to listen to it again */
 	write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
 }
 
-static void net_enable_fd(int fd, struct virtqueue *vq)
+static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
 {
 	/* We don't need to know again when Guest refills receive buffer. */
 	vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
@@ -1067,7 +1073,7 @@ static void handle_output(int fd, unsign
 			if (strcmp(vq->dev->name, "console") != 0)
 				verbose("Output to %s\n", vq->dev->name);
 			if (vq->handle_output)
-				vq->handle_output(fd, vq);
+				vq->handle_output(fd, vq, false);
 			return;
 		}
 	}
@@ -1099,7 +1105,7 @@ static void handle_timeout(int fd)
 			vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
 			vq->blocked = false;
 			if (vq->handle_output)
-				vq->handle_output(fd, vq);
+				vq->handle_output(fd, vq, true);
 		}
 	}
 }
@@ -1197,7 +1203,7 @@ static struct lguest_device_desc *new_de
 /* Each device descriptor is followed by the description of its virtqueues.  We
  * specify how many descriptors the virtqueue is to have. */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
-			  void (*handle_output)(int fd, struct virtqueue *me))
+			  void (*handle_output)(int, struct virtqueue *, bool))
 {
 	unsigned int pages;
 	struct virtqueue **i, *vq = malloc(sizeof(*vq));
@@ -1744,7 +1752,7 @@ static bool handle_io_finish(int fd, str
 }
 
 /* When the Guest submits some I/O, we just need to wake the I/O thread. */
-static void handle_virtblk_output(int fd, struct virtqueue *vq)
+static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
 {
 	struct vblk_info *vblk = vq->dev->priv;
 	char c = 0;
