Changes: * Move from open-coded lists to QTAILQ macros. * Move the struct elements to the common data structures (SCSIDevice + SCSIRequest). * Drop free request pools. * Fix request cleanup in the destroy callback.
Signed-off-by: Gerd Hoffmann <kra...@redhat.com> --- hw/scsi-bus.c | 1 + hw/scsi-disk.c | 67 +++++++++++++++------------------------------- hw/scsi-generic.c | 76 +++++++++++----------------------------------------- hw/scsi.h | 2 + 4 files changed, 41 insertions(+), 105 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 641db81..801922b 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -50,6 +50,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base) bus->devs[dev->id] = dev; dev->info = info; + QTAILQ_INIT(&dev->requests); rc = dev->info->init(dev); if (rc != 0) { bus->devs[dev->id] = NULL; diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 142d81d..997eef6 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -55,7 +55,6 @@ typedef struct SCSIDiskReq { uint32_t sector_count; struct iovec iov; QEMUIOVector qiov; - struct SCSIDiskReq *next; uint32_t status; } SCSIDiskReq; @@ -63,7 +62,6 @@ struct SCSIDiskState { SCSIDevice qdev; DriveInfo *dinfo; - SCSIDiskReq *requests; /* The qemu block layer uses a fixed 512 byte sector size. This is the number of 512 byte blocks in a single scsi sector. */ int cluster_size; @@ -73,64 +71,37 @@ struct SCSIDiskState QEMUBH *bh; }; -/* Global pool of SCSIRequest structures. */ -static SCSIDiskReq *free_requests = NULL; - static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag) { - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); SCSIDiskReq *r; - if (free_requests) { - r = free_requests; - free_requests = r->next; - } else { - r = qemu_malloc(sizeof(SCSIDiskReq)); - r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE); - } + r = qemu_mallocz(sizeof(SCSIDiskReq)); + r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE); r->req.bus = scsi_bus_from_device(d); r->req.dev = d; r->req.tag = tag; - r->sector_count = 0; - r->iov.iov_len = 0; - r->req.aiocb = NULL; - r->status = 0; - r->next = s->requests; - s->requests = r; + QTAILQ_INSERT_TAIL(&d->requests, &r->req, next); return r; } static void scsi_remove_request(SCSIDiskReq *r) { - SCSIDiskReq *last; - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - - if (s->requests == r) { - s->requests = r->next; - } else { - last = s->requests; - while (last && last->next != r) - last = last->next; - if (last) { - last->next = r->next; - } else { - BADF("Orphaned request\n"); - } - } - r->next = free_requests; - free_requests = r; + qemu_free(r->iov.iov_base); + QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next); + qemu_free(r); } static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag) { - SCSIDiskReq *r; - - r = s->requests; - while (r && r->req.tag != tag) - r = r->next; + SCSIRequest *req; - return r; + QTAILQ_FOREACH(req, &s->qdev.requests, next) { + if (req->tag == tag) { + return DO_UPCAST(SCSIDiskReq, req, req); + } + } + return NULL; } /* Helper function for command completion. */ @@ -310,17 +281,18 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag) static void scsi_dma_restart_bh(void *opaque) { SCSIDiskState *s = opaque; - SCSIDiskReq *r = s->requests; + SCSIRequest *req; + SCSIDiskReq *r; qemu_bh_delete(s->bh); s->bh = NULL; - while (r) { + QTAILQ_FOREACH(req, &s->qdev.requests, next) { + r = DO_UPCAST(SCSIDiskReq, req, req); if (r->status & SCSI_REQ_STATUS_RETRY) { r->status &= ~SCSI_REQ_STATUS_RETRY; scsi_write_request(r); } - r = r->next; } } @@ -959,7 +931,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, static void scsi_destroy(SCSIDevice *dev) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + SCSIDiskReq *r; + while (!QTAILQ_EMPTY(&s->qdev.requests)) { + r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests)); + scsi_remove_request(r); + } drive_uninit(s->dinfo); } diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 89f3080..1fa9d33 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -56,7 +56,6 @@ typedef struct SCSIGenericState SCSIGenericState; typedef struct SCSIGenericReq { SCSIRequest req; - struct SCSIGenericReq *next; uint8_t cmd[SCSI_CMD_BUF_SIZE]; int cmdlen; uint8_t *buf; @@ -68,7 +67,6 @@ typedef struct SCSIGenericReq { struct SCSIGenericState { SCSIDevice qdev; - SCSIGenericReq *requests; DriveInfo *dinfo; int type; int blocksize; @@ -78,68 +76,36 @@ struct SCSIGenericState uint8_t senselen; }; -/* Global pool of SCSIGenericReq structures. */ -static SCSIGenericReq *free_requests = NULL; - static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag) { - SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d); SCSIGenericReq *r; - if (free_requests) { - r = free_requests; - free_requests = r->next; - } else { - r = qemu_malloc(sizeof(SCSIGenericReq)); - r->buf = NULL; - r->buflen = 0; - } + r = qemu_mallocz(sizeof(SCSIGenericReq)); r->req.bus = scsi_bus_from_device(d); r->req.dev = d; r->req.tag = tag; - memset(r->cmd, 0, sizeof(r->cmd)); - memset(&r->io_header, 0, sizeof(r->io_header)); - r->cmdlen = 0; - r->len = 0; - r->req.aiocb = NULL; - /* link */ - - r->next = s->requests; - s->requests = r; + QTAILQ_INSERT_TAIL(&d->requests, &r->req, next); return r; } static void scsi_remove_request(SCSIGenericReq *r) { - SCSIGenericReq *last; - SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev); - - if (s->requests == r) { - s->requests = r->next; - } else { - last = s->requests; - while (last && last->next != r) - last = last->next; - if (last) { - last->next = r->next; - } else { - BADF("Orphaned request\n"); - } - } - r->next = free_requests; - free_requests = r; + qemu_free(r->buf); + QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next); + qemu_free(r); } static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag) { - SCSIGenericReq *r; - - r = s->requests; - while (r && r->req.tag != tag) - r = r->next; + SCSIRequest *req; - return r; + QTAILQ_FOREACH(req, &s->qdev.requests, next) { + if (req->tag == tag) { + return DO_UPCAST(SCSIGenericReq, req, req); + } + } + return NULL; } /* Helper function for command completion. */ @@ -653,22 +619,12 @@ static int get_stream_blocksize(BlockDriverState *bdrv) static void scsi_destroy(SCSIDevice *d) { SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d); - SCSIGenericReq *r, *n; - - r = s->requests; - while (r) { - n = r->next; - qemu_free(r); - r = n; - } + SCSIGenericReq *r; - r = free_requests; - while (r) { - n = r->next; - qemu_free(r); - r = n; + while (!QTAILQ_EMPTY(&s->qdev.requests)) { + r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests)); + scsi_remove_request(r); } - drive_uninit(s->dinfo); } diff --git a/hw/scsi.h b/hw/scsi.h index 7906877..a9b846c 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -21,6 +21,7 @@ typedef struct SCSIRequest { SCSIDevice *dev; uint32_t tag; BlockDriverAIOCB *aiocb; + QTAILQ_ENTRY(SCSIRequest) next; } SCSIRequest; struct SCSIDevice @@ -28,6 +29,7 @@ struct SCSIDevice DeviceState qdev; uint32_t id; SCSIDeviceInfo *info; + QTAILQ_HEAD(, SCSIRequest) requests; }; /* cdrom.c */ -- 1.6.2.5