Index: qemu/hw/virtio-blk.c
===================================================================
--- qemu.orig/hw/virtio-blk.c	2010-01-11 14:28:42.896010503 +0100
+++ qemu/hw/virtio-blk.c	2010-01-11 14:40:13.535256353 +0100
@@ -328,7 +328,15 @@ static void virtio_blk_handle_output(Vir
     int num_writes = 0;
     BlockDriverState *old_bs = NULL;
 
+    /*
+     * While we are processing requests there is no need to get further
+     * notifications from the guest - it'll just burn cpu cycles doing
+     * useless context switches into the host.
+     */
+    virtio_queue_set_notification(s->vq, 0);
+
     while ((req = virtio_blk_get_request(s))) {
+handle_request:
         if (req->elem.out_num < 1 || req->elem.in_num < 1) {
             fprintf(stderr, "virtio-blk missing headers\n");
             exit(1);
@@ -358,6 +366,18 @@ static void virtio_blk_handle_output(Vir
         }
     }
 
+    /*
+     * Once we're done processing all pending requests re-enable the queue
+     * notification.  If there's an entry pending after we enabled
+     * notification again we hit a race and need to process it before
+     * returning.
+     */
+    virtio_queue_set_notification(s->vq, 1);
+    req = virtio_blk_get_request(s);
+    if (req) {
+        goto handle_request;
+    }
+
     if (num_writes > 0) {
         do_multiwrite(old_bs, blkreq, num_writes);
     }
