Patchwork [9/9] virtio-blk: use QLIST for the list of requests

login
register
mail settings
Submitter Juan Quintela
Date March 16, 2010, 6:51 p.m.
Message ID <a047ea30f92e61d0c7f31b8c616f286a1ebffb7e.1268765204.git.quintela@redhat.com>
Download mbox | patch
Permalink /patch/47899/
State New
Headers show

Comments

Juan Quintela - March 16, 2010, 6:51 p.m.
viltio_blak_dma_restart_bh() was unsafe, it used req->next after having
(possible) put req in another list

Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hw/virtio-blk.c |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)

Patch

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index c2ee27d..e22a911 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -20,13 +20,14 @@ 
 #endif

 typedef struct VirtIOBlockReq VirtIOBlockReq;
+typedef QLIST_HEAD (,VirtIOBlockReq) VirtIOBlockReqHead;

 typedef struct VirtIOBlock
 {
     VirtIODevice vdev;
     BlockDriverState *bs;
     VirtQueue *vq;
-    VirtIOBlockReq *rq;
+    VirtIOBlockReqHead rq;
     QEMUBH *bh;
     BlockConf *conf;
 } VirtIOBlock;
@@ -39,7 +40,7 @@  struct VirtIOBlockReq
     struct virtio_blk_outhdr *out;
     struct virtio_scsi_inhdr *scsi;
     QEMUIOVector qiov;
-    struct VirtIOBlockReq *next;
+    QLIST_ENTRY(VirtIOBlockReq) next;
 };

 static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
@@ -67,8 +68,7 @@  static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,

     if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
             || action == BLOCK_ERR_STOP_ANY) {
-        req->next = s->rq;
-        s->rq = req;
+        QLIST_INSERT_HEAD(&s->rq, req, next);
         bdrv_mon_event(req->dev->bs, BDRV_ACTION_STOP, is_read);
         vm_stop(0);
     } else {
@@ -342,7 +342,8 @@  static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 static void virtio_blk_dma_restart_bh(void *opaque)
 {
     VirtIOBlock *s = opaque;
-    VirtIOBlockReq *req = s->rq;
+    VirtIOBlockReqHead rq_copy;
+    VirtIOBlockReq *req, *next_req;
     MultiReqBuffer mrb = {
         .num_writes = 0,
         .old_bs = NULL,
@@ -351,11 +352,12 @@  static void virtio_blk_dma_restart_bh(void *opaque)
     qemu_bh_delete(s->bh);
     s->bh = NULL;

-    s->rq = NULL;
+    QLIST_COPY_HEAD(&rq_copy, &s->rq);
+    QLIST_INIT(&s->rq);

-    while (req) {
+    QLIST_FOREACH_SAFE(req, &rq_copy, next, next_req) {
+        QLIST_REMOVE(req, next);
         virtio_blk_handle_request(req, &mrb);
-        req = req->next;
     }

     if (mrb.num_writes > 0) {
@@ -430,14 +432,13 @@  static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 static void virtio_blk_save(QEMUFile *f, void *opaque)
 {
     VirtIOBlock *s = opaque;
-    VirtIOBlockReq *req = s->rq;
+    VirtIOBlockReq *req;;

     virtio_save(&s->vdev, f);
-    
-    while (req) {
+
+    QLIST_FOREACH(req, &s->rq, next) {
         qemu_put_sbyte(f, 1);
         qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
-        req = req->next;
     }
     qemu_put_sbyte(f, 0);
 }
@@ -453,8 +454,7 @@  static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
     while (qemu_get_sbyte(f)) {
         VirtIOBlockReq *req = virtio_blk_alloc_request(s);
         qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
-        req->next = s->rq;
-        s->rq = req->next;
+        QLIST_INSERT_HEAD(&s->rq, req, next);
     }

     return 0;
@@ -476,7 +476,7 @@  VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vdev.reset = virtio_blk_reset;
     s->bs = conf->dinfo->bdrv;
     s->conf = conf;
-    s->rq = NULL;
+    QLIST_INIT(&s->rq);
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);