viltio_blak_dma_restart_bh() was unsafe, it used req->next after having (possible) put req in another list
Signed-off-by: Juan Quintela <quint...@redhat.com> --- hw/virtio-blk.c | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) 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); -- 1.6.6.1