diff options
-rw-r--r-- | block-qcow.c | 231 | ||||
-rw-r--r-- | block-qcow2.c | 242 | ||||
-rw-r--r-- | block-raw.c | 280 | ||||
-rw-r--r-- | block.c | 237 | ||||
-rw-r--r-- | block_int.h | 27 | ||||
-rw-r--r-- | vl.h | 14 |
6 files changed, 483 insertions, 548 deletions
diff --git a/block-qcow.c b/block-qcow.c index 151ec85d2c..d5333b379d 100644 --- a/block-qcow.c +++ b/block-qcow.c @@ -522,7 +522,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, return 0; } -typedef struct { +typedef struct QCowAIOCB { + BlockDriverAIOCB common; int64_t sector_num; uint8_t *buf; int nb_sectors; @@ -530,223 +531,198 @@ typedef struct { uint64_t cluster_offset; uint8_t *cluster_data; BlockDriverAIOCB *hd_aiocb; - BlockDriverAIOCB *backing_hd_aiocb; } QCowAIOCB; -static void qcow_aio_delete(BlockDriverAIOCB *acb); - -static int qcow_aio_new(BlockDriverAIOCB *acb) -{ - BlockDriverState *bs = acb->bs; - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1; - acb1 = qemu_mallocz(sizeof(QCowAIOCB)); - if (!acb1) - return -1; - acb->opaque = acb1; - acb1->hd_aiocb = bdrv_aio_new(s->hd); - if (!acb1->hd_aiocb) - goto fail; - if (bs->backing_hd) { - acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd); - if (!acb1->backing_hd_aiocb) - goto fail; - } - return 0; - fail: - qcow_aio_delete(acb); - return -1; -} - static void qcow_aio_read_cb(void *opaque, int ret) { - BlockDriverAIOCB *acb = opaque; - BlockDriverState *bs = acb->bs; + QCowAIOCB *acb = opaque; + BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1 = acb->opaque; int index_in_cluster; + acb->hd_aiocb = NULL; if (ret < 0) { fail: - acb->cb(acb->cb_opaque, ret); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); return; } redo: /* post process the read buffer */ - if (!acb1->cluster_offset) { + if (!acb->cluster_offset) { /* nothing to do */ - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) { + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* nothing to do */ } else { if (s->crypt_method) { - encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf, - acb1->n, 0, + encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, + acb->n, 0, &s->aes_decrypt_key); } } - acb1->nb_sectors -= acb1->n; - acb1->sector_num += acb1->n; - acb1->buf += acb1->n * 512; + acb->nb_sectors -= acb->n; + acb->sector_num += acb->n; + acb->buf += acb->n * 512; - if (acb1->nb_sectors == 0) { + if (acb->nb_sectors == 0) { /* request completed */ - acb->cb(acb->cb_opaque, 0); + acb->common.cb(acb->common.opaque, 0); + qemu_aio_release(acb); return; } /* prepare next AIO request */ - acb1->cluster_offset = get_cluster_offset(bs, - acb1->sector_num << 9, - 0, 0, 0, 0); - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1); - acb1->n = s->cluster_sectors - index_in_cluster; - if (acb1->n > acb1->nb_sectors) - acb1->n = acb1->nb_sectors; - - if (!acb1->cluster_offset) { + acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, + 0, 0, 0, 0); + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); + acb->n = s->cluster_sectors - index_in_cluster; + if (acb->n > acb->nb_sectors) + acb->n = acb->nb_sectors; + + if (!acb->cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, - acb1->buf, acb1->n, qcow_aio_read_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, + acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } else { /* Note: in this case, no need to wait */ - memset(acb1->buf, 0, 512 * acb1->n); + memset(acb->buf, 0, 512 * acb->n); goto redo; } - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) { + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ - if (decompress_cluster(s, acb1->cluster_offset) < 0) + if (decompress_cluster(s, acb->cluster_offset) < 0) goto fail; - memcpy(acb1->buf, - s->cluster_cache + index_in_cluster * 512, 512 * acb1->n); + memcpy(acb->buf, + s->cluster_cache + index_in_cluster * 512, 512 * acb->n); goto redo; } else { - if ((acb1->cluster_offset & 511) != 0) { + if ((acb->cluster_offset & 511) != 0) { ret = -EIO; goto fail; } - ret = bdrv_aio_read(acb1->hd_aiocb, - (acb1->cluster_offset >> 9) + index_in_cluster, - acb1->buf, acb1->n, qcow_aio_read_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_read(s->hd, + (acb->cluster_offset >> 9) + index_in_cluster, + acb->buf, acb->n, qcow_aio_read_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } } -static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - QCowAIOCB *acb1 = acb->opaque; - - acb1->sector_num = sector_num; - acb1->buf = buf; - acb1->nb_sectors = nb_sectors; - acb1->n = 0; - acb1->cluster_offset = 0; + QCowAIOCB *acb; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->hd_aiocb = NULL; + acb->sector_num = sector_num; + acb->buf = buf; + acb->nb_sectors = nb_sectors; + acb->n = 0; + acb->cluster_offset = 0; qcow_aio_read_cb(acb, 0); - return 0; + return &acb->common; } static void qcow_aio_write_cb(void *opaque, int ret) { - BlockDriverAIOCB *acb = opaque; - BlockDriverState *bs = acb->bs; + QCowAIOCB *acb = opaque; + BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1 = acb->opaque; int index_in_cluster; uint64_t cluster_offset; const uint8_t *src_buf; - + + acb->hd_aiocb = NULL; + if (ret < 0) { fail: - acb->cb(acb->cb_opaque, ret); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); return; } - acb1->nb_sectors -= acb1->n; - acb1->sector_num += acb1->n; - acb1->buf += acb1->n * 512; + acb->nb_sectors -= acb->n; + acb->sector_num += acb->n; + acb->buf += acb->n * 512; - if (acb1->nb_sectors == 0) { + if (acb->nb_sectors == 0) { /* request completed */ - acb->cb(acb->cb_opaque, 0); + acb->common.cb(acb->common.opaque, 0); + qemu_aio_release(acb); return; } - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1); - acb1->n = s->cluster_sectors - index_in_cluster; - if (acb1->n > acb1->nb_sectors) - acb1->n = acb1->nb_sectors; - cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0, + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); + acb->n = s->cluster_sectors - index_in_cluster; + if (acb->n > acb->nb_sectors) + acb->n = acb->nb_sectors; + cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, index_in_cluster, - index_in_cluster + acb1->n); + index_in_cluster + acb->n); if (!cluster_offset || (cluster_offset & 511) != 0) { ret = -EIO; goto fail; } if (s->crypt_method) { - if (!acb1->cluster_data) { - acb1->cluster_data = qemu_mallocz(s->cluster_size); - if (!acb1->cluster_data) { + if (!acb->cluster_data) { + acb->cluster_data = qemu_mallocz(s->cluster_size); + if (!acb->cluster_data) { ret = -ENOMEM; goto fail; } } - encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf, - acb1->n, 1, &s->aes_encrypt_key); - src_buf = acb1->cluster_data; + encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, + acb->n, 1, &s->aes_encrypt_key); + src_buf = acb->cluster_data; } else { - src_buf = acb1->buf; + src_buf = acb->buf; } - ret = bdrv_aio_write(acb1->hd_aiocb, - (cluster_offset >> 9) + index_in_cluster, - src_buf, acb1->n, - qcow_aio_write_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_write(s->hd, + (cluster_offset >> 9) + index_in_cluster, + src_buf, acb->n, + qcow_aio_write_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } -static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - QCowAIOCB *acb1 = acb->opaque; - BlockDriverState *bs = acb->bs; BDRVQcowState *s = bs->opaque; + QCowAIOCB *acb; s->cluster_cache_offset = -1; /* disable compressed cache */ - acb1->sector_num = sector_num; - acb1->buf = (uint8_t *)buf; - acb1->nb_sectors = nb_sectors; - acb1->n = 0; + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->hd_aiocb = NULL; + acb->sector_num = sector_num; + acb->buf = (uint8_t *)buf; + acb->nb_sectors = nb_sectors; + acb->n = 0; qcow_aio_write_cb(acb, 0); - return 0; -} - -static void qcow_aio_cancel(BlockDriverAIOCB *acb) -{ - QCowAIOCB *acb1 = acb->opaque; - if (acb1->hd_aiocb) - bdrv_aio_cancel(acb1->hd_aiocb); - if (acb1->backing_hd_aiocb) - bdrv_aio_cancel(acb1->backing_hd_aiocb); + return &acb->common; } -static void qcow_aio_delete(BlockDriverAIOCB *acb) +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb) { - QCowAIOCB *acb1 = acb->opaque; - if (acb1->hd_aiocb) - bdrv_aio_delete(acb1->hd_aiocb); - if (acb1->backing_hd_aiocb) - bdrv_aio_delete(acb1->backing_hd_aiocb); - qemu_free(acb1->cluster_data); - qemu_free(acb1); + QCowAIOCB *acb = (QCowAIOCB *)blockacb; + if (acb->hd_aiocb) + bdrv_aio_cancel(acb->hd_aiocb); + qemu_aio_release(acb); } static void qcow_close(BlockDriverState *bs) @@ -920,11 +896,10 @@ BlockDriver bdrv_qcow = { qcow_set_key, qcow_make_empty, - .bdrv_aio_new = qcow_aio_new, .bdrv_aio_read = qcow_aio_read, .bdrv_aio_write = qcow_aio_write, .bdrv_aio_cancel = qcow_aio_cancel, - .bdrv_aio_delete = qcow_aio_delete, + .aiocb_size = sizeof(QCowAIOCB), .bdrv_write_compressed = qcow_write_compressed, .bdrv_get_info = qcow_get_info, }; diff --git a/block-qcow2.c b/block-qcow2.c index bc2aa14bb2..a876ea2e2d 100644 --- a/block-qcow2.c +++ b/block-qcow2.c @@ -791,7 +791,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, return 0; } -typedef struct { +typedef struct QCowAIOCB { + BlockDriverAIOCB common; int64_t sector_num; uint8_t *buf; int nb_sectors; @@ -799,229 +800,211 @@ typedef struct { uint64_t cluster_offset; uint8_t *cluster_data; BlockDriverAIOCB *hd_aiocb; - BlockDriverAIOCB *backing_hd_aiocb; } QCowAIOCB; -static void qcow_aio_delete(BlockDriverAIOCB *acb); - -static int qcow_aio_new(BlockDriverAIOCB *acb) -{ - BlockDriverState *bs = acb->bs; - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1; - acb1 = qemu_mallocz(sizeof(QCowAIOCB)); - if (!acb1) - return -1; - acb->opaque = acb1; - acb1->hd_aiocb = bdrv_aio_new(s->hd); - if (!acb1->hd_aiocb) - goto fail; - if (bs->backing_hd) { - acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd); - if (!acb1->backing_hd_aiocb) - goto fail; - } - return 0; - fail: - qcow_aio_delete(acb); - return -1; -} - static void qcow_aio_read_cb(void *opaque, int ret) { - BlockDriverAIOCB *acb = opaque; - BlockDriverState *bs = acb->bs; + QCowAIOCB *acb = opaque; + BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1 = acb->opaque; int index_in_cluster, n1; + acb->hd_aiocb = NULL; if (ret < 0) { fail: - acb->cb(acb->cb_opaque, ret); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); return; } redo: /* post process the read buffer */ - if (!acb1->cluster_offset) { + if (!acb->cluster_offset) { /* nothing to do */ - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) { + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* nothing to do */ } else { if (s->crypt_method) { - encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf, - acb1->n, 0, + encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, + acb->n, 0, &s->aes_decrypt_key); } } - acb1->nb_sectors -= acb1->n; - acb1->sector_num += acb1->n; - acb1->buf += acb1->n * 512; + acb->nb_sectors -= acb->n; + acb->sector_num += acb->n; + acb->buf += acb->n * 512; - if (acb1->nb_sectors == 0) { + if (acb->nb_sectors == 0) { /* request completed */ - acb->cb(acb->cb_opaque, 0); + acb->common.cb(acb->common.opaque, 0); + qemu_aio_release(acb); return; } /* prepare next AIO request */ - acb1->cluster_offset = get_cluster_offset(bs, - acb1->sector_num << 9, - 0, 0, 0, 0); - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1); - acb1->n = s->cluster_sectors - index_in_cluster; - if (acb1->n > acb1->nb_sectors) - acb1->n = acb1->nb_sectors; - - if (!acb1->cluster_offset) { + acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, + 0, 0, 0, 0); + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); + acb->n = s->cluster_sectors - index_in_cluster; + if (acb->n > acb->nb_sectors) + acb->n = acb->nb_sectors; + + if (!acb->cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - n1 = backing_read1(bs->backing_hd, acb1->sector_num, - acb1->buf, acb1->n); + n1 = backing_read1(bs->backing_hd, acb->sector_num, + acb->buf, acb->n); if (n1 > 0) { - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, - acb1->buf, n1, qcow_aio_read_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num, + acb->buf, acb->n, qcow_aio_read_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } else { goto redo; } } else { /* Note: in this case, no need to wait */ - memset(acb1->buf, 0, 512 * acb1->n); + memset(acb->buf, 0, 512 * acb->n); goto redo; } - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) { + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ - if (decompress_cluster(s, acb1->cluster_offset) < 0) + if (decompress_cluster(s, acb->cluster_offset) < 0) goto fail; - memcpy(acb1->buf, - s->cluster_cache + index_in_cluster * 512, 512 * acb1->n); + memcpy(acb->buf, + s->cluster_cache + index_in_cluster * 512, 512 * acb->n); goto redo; } else { - if ((acb1->cluster_offset & 511) != 0) { + if ((acb->cluster_offset & 511) != 0) { ret = -EIO; goto fail; } - ret = bdrv_aio_read(acb1->hd_aiocb, - (acb1->cluster_offset >> 9) + index_in_cluster, - acb1->buf, acb1->n, qcow_aio_read_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_read(s->hd, + (acb->cluster_offset >> 9) + index_in_cluster, + acb->buf, acb->n, qcow_aio_read_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } } -static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - QCowAIOCB *acb1 = acb->opaque; - - acb1->sector_num = sector_num; - acb1->buf = buf; - acb1->nb_sectors = nb_sectors; - acb1->n = 0; - acb1->cluster_offset = 0; + QCowAIOCB *acb; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->hd_aiocb = NULL; + acb->sector_num = sector_num; + acb->buf = buf; + acb->nb_sectors = nb_sectors; + acb->n = 0; + acb->cluster_offset = 0; + return acb; +} + +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + QCowAIOCB *acb; + + acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; qcow_aio_read_cb(acb, 0); - return 0; + return &acb->common; } static void qcow_aio_write_cb(void *opaque, int ret) { - BlockDriverAIOCB *acb = opaque; - BlockDriverState *bs = acb->bs; + QCowAIOCB *acb = opaque; + BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb1 = acb->opaque; int index_in_cluster; uint64_t cluster_offset; const uint8_t *src_buf; - + + acb->hd_aiocb = NULL; + if (ret < 0) { fail: - acb->cb(acb->cb_opaque, ret); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); return; } - acb1->nb_sectors -= acb1->n; - acb1->sector_num += acb1->n; - acb1->buf += acb1->n * 512; + acb->nb_sectors -= acb->n; + acb->sector_num += acb->n; + acb->buf += acb->n * 512; - if (acb1->nb_sectors == 0) { + if (acb->nb_sectors == 0) { /* request completed */ - acb->cb(acb->cb_opaque, 0); + acb->common.cb(acb->common.opaque, 0); + qemu_aio_release(acb); return; } - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1); - acb1->n = s->cluster_sectors - index_in_cluster; - if (acb1->n > acb1->nb_sectors) - acb1->n = acb1->nb_sectors; - cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0, + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); + acb->n = s->cluster_sectors - index_in_cluster; + if (acb->n > acb->nb_sectors) + acb->n = acb->nb_sectors; + cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, index_in_cluster, - index_in_cluster + acb1->n); + index_in_cluster + acb->n); if (!cluster_offset || (cluster_offset & 511) != 0) { ret = -EIO; goto fail; } if (s->crypt_method) { - if (!acb1->cluster_data) { - acb1->cluster_data = qemu_mallocz(s->cluster_size); - if (!acb1->cluster_data) { + if (!acb->cluster_data) { + acb->cluster_data = qemu_mallocz(s->cluster_size); + if (!acb->cluster_data) { ret = -ENOMEM; goto fail; } } - encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf, - acb1->n, 1, &s->aes_encrypt_key); - src_buf = acb1->cluster_data; + encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, + acb->n, 1, &s->aes_encrypt_key); + src_buf = acb->cluster_data; } else { - src_buf = acb1->buf; + src_buf = acb->buf; } - ret = bdrv_aio_write(acb1->hd_aiocb, - (cluster_offset >> 9) + index_in_cluster, - src_buf, acb1->n, - qcow_aio_write_cb, acb); - if (ret < 0) + acb->hd_aiocb = bdrv_aio_write(s->hd, + (cluster_offset >> 9) + index_in_cluster, + src_buf, acb->n, + qcow_aio_write_cb, acb); + if (acb->hd_aiocb == NULL) goto fail; } -static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - QCowAIOCB *acb1 = acb->opaque; - BlockDriverState *bs = acb->bs; BDRVQcowState *s = bs->opaque; + QCowAIOCB *acb; s->cluster_cache_offset = -1; /* disable compressed cache */ - acb1->sector_num = sector_num; - acb1->buf = (uint8_t *)buf; - acb1->nb_sectors = nb_sectors; - acb1->n = 0; + acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; qcow_aio_write_cb(acb, 0); - return 0; -} - -static void qcow_aio_cancel(BlockDriverAIOCB *acb) -{ - QCowAIOCB *acb1 = acb->opaque; - if (acb1->hd_aiocb) - bdrv_aio_cancel(acb1->hd_aiocb); - if (acb1->backing_hd_aiocb) - bdrv_aio_cancel(acb1->backing_hd_aiocb); + return &acb->common; } -static void qcow_aio_delete(BlockDriverAIOCB *acb) +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb) { - QCowAIOCB *acb1 = acb->opaque; - if (acb1->hd_aiocb) - bdrv_aio_delete(acb1->hd_aiocb); - if (acb1->backing_hd_aiocb) - bdrv_aio_delete(acb1->backing_hd_aiocb); - qemu_free(acb1->cluster_data); - qemu_free(acb1); + QCowAIOCB *acb = (QCowAIOCB *)blockacb; + if (acb->hd_aiocb) + bdrv_aio_cancel(acb->hd_aiocb); + qemu_aio_release(acb); } static void qcow_close(BlockDriverState *bs) @@ -2249,11 +2232,10 @@ BlockDriver bdrv_qcow2 = { qcow_set_key, qcow_make_empty, - .bdrv_aio_new = qcow_aio_new, .bdrv_aio_read = qcow_aio_read, .bdrv_aio_write = qcow_aio_write, .bdrv_aio_cancel = qcow_aio_cancel, - .bdrv_aio_delete = qcow_aio_delete, + .aiocb_size = sizeof(QCowAIOCB), .bdrv_write_compressed = qcow_write_compressed, .bdrv_snapshot_create = qcow_snapshot_create, diff --git a/block-raw.c b/block-raw.c index adb3d39add..a64564dc76 100644 --- a/block-raw.c +++ b/block-raw.c @@ -200,13 +200,13 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, /* Unix AOP using POSIX AIO */ typedef struct RawAIOCB { + BlockDriverAIOCB common; struct aiocb aiocb; - int busy; /* only used for debugging */ - BlockDriverAIOCB *next; + struct RawAIOCB *next; } RawAIOCB; static int aio_sig_num = SIGUSR2; -static BlockDriverAIOCB *first_aio; /* AIO issued */ +static RawAIOCB *first_aio; /* AIO issued */ static int aio_initialized = 0; static void aio_signal_handler(int signum) @@ -249,8 +249,7 @@ void qemu_aio_init(void) void qemu_aio_poll(void) { - BlockDriverAIOCB *acb, **pacb; - RawAIOCB *acb1; + RawAIOCB *acb, **pacb; int ret; for(;;) { @@ -259,17 +258,16 @@ void qemu_aio_poll(void) acb = *pacb; if (!acb) goto the_end; - acb1 = acb->opaque; - ret = aio_error(&acb1->aiocb); + ret = aio_error(&acb->aiocb); if (ret == ECANCELED) { /* remove the request */ - acb1->busy = 0; - *pacb = acb1->next; + *pacb = acb->next; + qemu_aio_release(acb); } else if (ret != EINPROGRESS) { /* end of aio */ if (ret == 0) { - ret = aio_return(&acb1->aiocb); - if (ret == acb1->aiocb.aio_nbytes) + ret = aio_return(&acb->aiocb); + if (ret == acb->aiocb.aio_nbytes) ret = 0; else ret = -1; @@ -277,13 +275,13 @@ void qemu_aio_poll(void) ret = -ret; } /* remove the request */ - acb1->busy = 0; - *pacb = acb1->next; + *pacb = acb->next; /* call the callback */ - acb->cb(acb->cb_opaque, ret); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); break; } else { - pacb = &acb1->next; + pacb = &acb->next; } } } @@ -324,70 +322,70 @@ void qemu_aio_wait_end(void) sigprocmask(SIG_SETMASK, &wait_oset, NULL); } -static int raw_aio_new(BlockDriverAIOCB *acb) +static RawAIOCB *raw_aio_setup(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - RawAIOCB *acb1; - BDRVRawState *s = acb->bs->opaque; - - acb1 = qemu_mallocz(sizeof(RawAIOCB)); - if (!acb1) - return -1; - acb->opaque = acb1; - acb1->aiocb.aio_fildes = s->fd; - acb1->aiocb.aio_sigevent.sigev_signo = aio_sig_num; - acb1->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; - return 0; + BDRVRawState *s = bs->opaque; + RawAIOCB *acb; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->aiocb.aio_fildes = s->fd; + acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num; + acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + acb->aiocb.aio_buf = buf; + acb->aiocb.aio_nbytes = nb_sectors * 512; + acb->aiocb.aio_offset = sector_num * 512; + acb->next = first_aio; + first_aio = acb; + return acb; } -static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - RawAIOCB *acb1 = acb->opaque; + RawAIOCB *acb; - assert(acb1->busy == 0); - acb1->busy = 1; - acb1->aiocb.aio_buf = buf; - acb1->aiocb.aio_nbytes = nb_sectors * 512; - acb1->aiocb.aio_offset = sector_num * 512; - acb1->next = first_aio; - first_aio = acb; - if (aio_read(&acb1->aiocb) < 0) { - acb1->busy = 0; - return -errno; + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + if (aio_read(&acb->aiocb) < 0) { + qemu_aio_release(acb); + return NULL; } - return 0; + return &acb->common; } -static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - RawAIOCB *acb1 = acb->opaque; + RawAIOCB *acb; - assert(acb1->busy == 0); - acb1->busy = 1; - acb1->aiocb.aio_buf = (uint8_t *)buf; - acb1->aiocb.aio_nbytes = nb_sectors * 512; - acb1->aiocb.aio_offset = sector_num * 512; - acb1->next = first_aio; - first_aio = acb; - if (aio_write(&acb1->aiocb) < 0) { - acb1->busy = 0; - return -errno; + acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + if (aio_write(&acb->aiocb) < 0) { + qemu_aio_release(acb); + return NULL; } - return 0; + return &acb->common; } -static void raw_aio_cancel(BlockDriverAIOCB *acb) +static void raw_aio_cancel(BlockDriverAIOCB *blockacb) { - RawAIOCB *acb1 = acb->opaque; int ret; - BlockDriverAIOCB **pacb; + RawAIOCB *acb = (RawAIOCB *)blockacb; + RawAIOCB **pacb; - ret = aio_cancel(acb1->aiocb.aio_fildes, &acb1->aiocb); + ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); if (ret == AIO_NOTCANCELED) { /* fail safe: if the aio could not be canceled, we wait for it */ - while (aio_error(&acb1->aiocb) == EINPROGRESS); + while (aio_error(&acb->aiocb) == EINPROGRESS); } /* remove the callback from the queue */ @@ -396,22 +394,14 @@ static void raw_aio_cancel(BlockDriverAIOCB *acb) if (*pacb == NULL) { break; } else if (*pacb == acb) { - acb1->busy = 0; - *pacb = acb1->next; + *pacb = acb->next; + qemu_aio_release(acb); break; } - acb1 = (*pacb)->opaque; - pacb = &acb1->next; + pacb = &acb->next; } } -static void raw_aio_delete(BlockDriverAIOCB *acb) -{ - RawAIOCB *acb1 = acb->opaque; - raw_aio_cancel(acb); - qemu_free(acb1); -} - static void raw_close(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; @@ -508,11 +498,10 @@ BlockDriver bdrv_raw = { raw_create, raw_flush, - .bdrv_aio_new = raw_aio_new, .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, - .bdrv_aio_delete = raw_aio_delete, + .aiocb_size = sizeof(RawAIOCB), .protocol_name = "file", .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, @@ -530,6 +519,7 @@ typedef struct BDRVRawState { } BDRVRawState; typedef struct RawAIOCB { + BlockDriverAIOCB common; HANDLE hEvent; OVERLAPPED ov; int count; @@ -574,6 +564,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; int access_flags, create_flags; + DWORD overlapped; if ((flags & BDRV_O_ACCESS) == O_RDWR) { access_flags = GENERIC_READ | GENERIC_WRITE; @@ -585,9 +576,14 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) } else { create_flags = OPEN_EXISTING; } +#ifdef QEMU_TOOL + overlapped = 0; +#else + overlapped = FILE_FLAG_OVERLAPPED; +#endif s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, - create_flags, FILE_FLAG_OVERLAPPED, 0); + create_flags, overlapped, 0); if (s->hfile == INVALID_HANDLE_VALUE) return -1; return 0; @@ -637,104 +633,107 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, return ret_count; } -static int raw_aio_new(BlockDriverAIOCB *acb) -{ - RawAIOCB *acb1; - - acb1 = qemu_mallocz(sizeof(RawAIOCB)); - if (!acb1) - return -ENOMEM; - acb->opaque = acb1; - acb1->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!acb1->hEvent) - return -ENOMEM; - return 0; -} #ifndef QEMU_TOOL static void raw_aio_cb(void *opaque) { - BlockDriverAIOCB *acb = opaque; - BlockDriverState *bs = acb->bs; + RawAIOCB *acb = opaque; + BlockDriverState *bs = acb->common.bs; BDRVRawState *s = bs->opaque; - RawAIOCB *acb1 = acb->opaque; DWORD ret_count; int ret; - ret = GetOverlappedResult(s->hfile, &acb1->ov, &ret_count, TRUE); - if (!ret || ret_count != acb1->count) { - acb->cb(acb->cb_opaque, -EIO); + ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE); + if (!ret || ret_count != acb->count) { + acb->common.cb(acb->common.opaque, -EIO); } else { - acb->cb(acb->cb_opaque, 0); + acb->common.cb(acb->common.opaque, 0); } } #endif -static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) + +static RawAIOCB *raw_aio_setup(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverState *bs = acb->bs; - BDRVRawState *s = bs->opaque; - RawAIOCB *acb1 = acb->opaque; - int ret; + RawAIOCB *acb; int64_t offset; - memset(&acb1->ov, 0, sizeof(acb1->ov)); + acb = qemu_aio_get(bs, cb, opaque); + if (acb->hEvent) { + acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!acb->hEvent) { + qemu_aio_release(acb); + return NULL; + } + } + memset(&acb->ov, 0, sizeof(acb->ov)); offset = sector_num * 512; - acb1->ov.Offset = offset; - acb1->ov.OffsetHigh = offset >> 32; - acb1->ov.hEvent = acb1->hEvent; - acb1->count = nb_sectors * 512; + acb->ov.Offset = offset; + acb->ov.OffsetHigh = offset >> 32; + acb->ov.hEvent = acb->hEvent; + acb->count = nb_sectors * 512; #ifndef QEMU_TOOL - qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb); + qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb); #endif - ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov); - if (!ret) - return -EIO; - return 0; + return acb; } -static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverState *bs = acb->bs; BDRVRawState *s = bs->opaque; - RawAIOCB *acb1 = acb->opaque; + RawAIOCB *acb; int ret; - int64_t offset; - memset(&acb1->ov, 0, sizeof(acb1->ov)); - offset = sector_num * 512; - acb1->ov.Offset = offset; - acb1->ov.OffsetHigh = offset >> 32; - acb1->ov.hEvent = acb1->hEvent; - acb1->count = nb_sectors * 512; -#ifndef QEMU_TOOL - qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb); + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov); + if (!ret) { + qemu_aio_release(acb); + return NULL; + } +#ifdef QEMU_TOOL + qemu_aio_release(acb); #endif - ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov); - if (!ret) - return -EIO; - return 0; + return (BlockDriverAIOCB *)acb; } -static void raw_aio_cancel(BlockDriverAIOCB *acb) +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverState *bs = acb->bs; BDRVRawState *s = bs->opaque; -#ifndef QEMU_TOOL - RawAIOCB *acb1 = acb->opaque; + RawAIOCB *acb; + int ret; - qemu_del_wait_object(acb1->ov.hEvent, raw_aio_cb, acb); + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov); + if (!ret) { + qemu_aio_release(acb); + return NULL; + } +#ifdef QEMU_TOOL + qemu_aio_release(acb); #endif - /* XXX: if more than one async I/O it is not correct */ - CancelIo(s->hfile); + return (BlockDriverAIOCB *)acb; } -static void raw_aio_delete(BlockDriverAIOCB *acb) +static void raw_aio_cancel(BlockDriverAIOCB *blockacb) { - RawAIOCB *acb1 = acb->opaque; - raw_aio_cancel(acb); - CloseHandle(acb1->hEvent); - qemu_free(acb1); +#ifndef QEMU_TOOL + RawAIOCB *acb = (RawAIOCB *)blockacb; + BlockDriverState *bs = acb->common.bs; + BDRVRawState *s = bs->opaque; + + qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb); + /* XXX: if more than one async I/O it is not correct */ + CancelIo(s->hfile); + qemu_aio_release(acb); +#endif } static void raw_flush(BlockDriverState *bs) @@ -823,11 +822,10 @@ BlockDriver bdrv_raw = { raw_flush, #if 0 - .bdrv_aio_new = raw_aio_new, .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, - .bdrv_aio_delete = raw_aio_delete, + .aiocb_size = sizeof(RawAIOCB); #endif .protocol_name = "file", .bdrv_pread = raw_pread, @@ -35,13 +35,13 @@ #define SECTOR_BITS 9 #define SECTOR_SIZE (1 << SECTOR_BITS) -static int bdrv_aio_new_em(BlockDriverAIOCB *acb); -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors); -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors); +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb); -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb); static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, @@ -106,13 +106,11 @@ void path_combine(char *dest, int dest_size, void bdrv_register(BlockDriver *bdrv) { - if (!bdrv->bdrv_aio_new) { + if (!bdrv->bdrv_aio_read) { /* add AIO emulation layer */ - bdrv->bdrv_aio_new = bdrv_aio_new_em; bdrv->bdrv_aio_read = bdrv_aio_read_em; bdrv->bdrv_aio_write = bdrv_aio_write_em; bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em; - bdrv->bdrv_aio_delete = bdrv_aio_delete_em; } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) { /* add synchronous IO emulation layer */ bdrv->bdrv_read = bdrv_read_em; @@ -964,7 +962,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); } else { ti = sn->date_sec; +#ifndef _WIN32 localtime_r(&ti, &tm); +#endif strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm); secs = sn->vm_clock_nsec / 1000000000; @@ -988,31 +988,14 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) /**************************************************************/ /* async I/Os */ -BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs) +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; - BlockDriverAIOCB *acb; - acb = qemu_mallocz(sizeof(BlockDriverAIOCB)); - if (!acb) - return NULL; - - acb->bs = bs; - if (drv->bdrv_aio_new(acb) < 0) { - qemu_free(acb); - return NULL; - } - return acb; -} - -int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - BlockDriverState *bs = acb->bs; - BlockDriver *drv = bs->drv; if (!bs->inserted) - return -1; + return NULL; /* XXX: we assume that nb_sectors == 0 is suppored by the async read */ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { @@ -1022,141 +1005,114 @@ int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, buf += 512; } - acb->cb = cb; - acb->cb_opaque = opaque; - return drv->bdrv_aio_read(acb, sector_num, buf, nb_sectors); + return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque); } -int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverState *bs = acb->bs; BlockDriver *drv = bs->drv; if (!bs->inserted) - return -1; + return NULL; if (bs->read_only) - return -1; + return NULL; if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { memcpy(bs->boot_sector_data, buf, 512); } - acb->cb = cb; - acb->cb_opaque = opaque; - return drv->bdrv_aio_write(acb, sector_num, buf, nb_sectors); + return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); } void bdrv_aio_cancel(BlockDriverAIOCB *acb) - { - BlockDriverState *bs = acb->bs; - BlockDriver *drv = bs->drv; - - drv->bdrv_aio_cancel(acb); - } - -void bdrv_aio_delete(BlockDriverAIOCB *acb) { - BlockDriverState *bs = acb->bs; - BlockDriver *drv = bs->drv; + BlockDriver *drv = acb->bs->drv; - drv->bdrv_aio_delete(acb); - qemu_free(acb); + drv->bdrv_aio_cancel(acb); } + /**************************************************************/ /* async block device emulation */ #ifdef QEMU_TOOL -static int bdrv_aio_new_em(BlockDriverAIOCB *acb) -{ - return 0; -} - -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { int ret; - ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors); - acb->cb(acb->cb_opaque, ret); - return 0; + ret = bdrv_read(bs, sector_num, buf, nb_sectors); + cb(opaque, ret); + return NULL; } -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { int ret; - ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors); - acb->cb(acb->cb_opaque, ret); - return 0; + ret = bdrv_write(bs, sector_num, buf, nb_sectors); + cb(opaque, ret); + return NULL; } static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb) { } - -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb) -{ -} #else typedef struct BlockDriverAIOCBSync { + BlockDriverAIOCB common; QEMUBH *bh; int ret; } BlockDriverAIOCBSync; -static void bdrv_aio_bh_cb(void *opaque) -{ - BlockDriverAIOCB *acb = opaque; - BlockDriverAIOCBSync *acb1 = acb->opaque; - acb->cb(acb->cb_opaque, acb1->ret); -} +static BlockDriverAIOCBSync *free_acb = NULL; -static int bdrv_aio_new_em(BlockDriverAIOCB *acb) +static void bdrv_aio_bh_cb(void *opaque) { - BlockDriverAIOCBSync *acb1; - - acb1 = qemu_mallocz(sizeof(BlockDriverAIOCBSync)); - if (!acb1) - return -1; - acb->opaque = acb1; - acb1->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); - return 0; + BlockDriverAIOCBSync *acb = opaque; + acb->common.cb(acb->common.opaque, acb->ret); + qemu_aio_release(acb); } -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverAIOCBSync *acb1 = acb->opaque; + BlockDriverAIOCBSync *acb; int ret; - - ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors); - acb1->ret = ret; - qemu_bh_schedule(acb1->bh); - return 0; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb->bh) + acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); + ret = bdrv_read(bs, sector_num, buf, nb_sectors); + acb->ret = ret; + qemu_bh_schedule(acb->bh); + return &acb->common; } -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverAIOCBSync *acb1 = acb->opaque; + BlockDriverAIOCBSync *acb; int ret; - - ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors); - acb1->ret = ret; - qemu_bh_schedule(acb1->bh); - return 0; -} -static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb) -{ - BlockDriverAIOCBSync *acb1 = acb->opaque; - qemu_bh_cancel(acb1->bh); + acb = qemu_aio_get(bs, cb, opaque); + if (!acb->bh) + acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); + ret = bdrv_write(bs, sector_num, buf, nb_sectors); + acb->ret = ret; + qemu_bh_schedule(acb->bh); + return &acb->common; } -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb) +static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) { - BlockDriverAIOCBSync *acb1 = acb->opaque; - qemu_bh_delete(acb1->bh); + BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb; + qemu_bh_cancel(acb->bh); + qemu_aio_release(acb); } #endif /* !QEMU_TOOL */ @@ -1173,20 +1129,16 @@ static void bdrv_rw_em_cb(void *opaque, int ret) static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { - int async_ret, ret; + int async_ret; + BlockDriverAIOCB *acb; - if (!bs->sync_aiocb) { - bs->sync_aiocb = bdrv_aio_new(bs); - if (!bs->sync_aiocb) - return -1; - } async_ret = NOT_DONE; qemu_aio_wait_start(); - ret = bdrv_aio_read(bs->sync_aiocb, sector_num, buf, nb_sectors, + acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, bdrv_rw_em_cb, &async_ret); - if (ret < 0) { + if (acb == NULL) { qemu_aio_wait_end(); - return ret; + return -1; } while (async_ret == NOT_DONE) { qemu_aio_wait(); @@ -1198,20 +1150,16 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { - int async_ret, ret; + int async_ret; + BlockDriverAIOCB *acb; - if (!bs->sync_aiocb) { - bs->sync_aiocb = bdrv_aio_new(bs); - if (!bs->sync_aiocb) - return -1; - } async_ret = NOT_DONE; qemu_aio_wait_start(); - ret = bdrv_aio_write(bs->sync_aiocb, sector_num, buf, nb_sectors, + acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, bdrv_rw_em_cb, &async_ret); - if (ret < 0) { + if (acb == NULL) { qemu_aio_wait_end(); - return ret; + return -1; } while (async_ret == NOT_DONE) { qemu_aio_wait(); @@ -1235,3 +1183,32 @@ void bdrv_init(void) bdrv_register(&bdrv_vvfat); bdrv_register(&bdrv_qcow2); } + +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb, + void *opaque) +{ + BlockDriver *drv; + BlockDriverAIOCB *acb; + + drv = bs->drv; + if (drv->free_aiocb) { + acb = drv->free_aiocb; + drv->free_aiocb = acb->next; + } else { + acb = qemu_mallocz(drv->aiocb_size); + if (!acb) + return NULL; + } + acb->bs = bs; + acb->cb = cb; + acb->opaque = opaque; + return acb; +} + +void qemu_aio_release(void *p) +{ + BlockDriverAIOCB *acb = p; + BlockDriver *drv = acb->bs->drv; + acb->next = drv->free_aiocb; + drv->free_aiocb = acb; +} diff --git a/block_int.h b/block_int.h index 26cc4ffbac..8fd241f2a9 100644 --- a/block_int.h +++ b/block_int.h @@ -42,13 +42,14 @@ struct BlockDriver { int (*bdrv_set_key)(BlockDriverState *bs, const char *key); int (*bdrv_make_empty)(BlockDriverState *bs); /* aio */ - int (*bdrv_aio_new)(BlockDriverAIOCB *acb); - int (*bdrv_aio_read)(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors); - int (*bdrv_aio_write)(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors); + BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); + BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb); - void (*bdrv_aio_delete)(BlockDriverAIOCB *acb); + int aiocb_size; const char *protocol_name; int (*bdrv_pread)(BlockDriverState *bs, int64_t offset, @@ -69,6 +70,7 @@ struct BlockDriver { QEMUSnapshotInfo **psn_info); int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); + BlockDriverAIOCB *free_aiocb; struct BlockDriver *next; }; @@ -96,9 +98,9 @@ struct BlockDriverState { int is_temporary; BlockDriverState *backing_hd; - /* sync read/write emulation */ + /* async read/write emulation */ - BlockDriverAIOCB *sync_aiocb; + void *sync_aiocb; /* NOTE: the following infos are only hints for real hardware drivers. They are not used by the block driver */ @@ -111,11 +113,14 @@ struct BlockDriverState { struct BlockDriverAIOCB { BlockDriverState *bs; BlockDriverCompletionFunc *cb; - void *cb_opaque; - - void *opaque; /* driver opaque */ + void *opaque; + BlockDriverAIOCB *next; }; void get_tmp_filename(char *filename, int size); +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb, + void *opaque); +void qemu_aio_release(void *p); + #endif /* BLOCK_INT_H */ @@ -569,15 +569,13 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); -BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs); -int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, - uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, - const uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); -void bdrv_aio_delete(BlockDriverAIOCB *acb); void qemu_aio_init(void); void qemu_aio_poll(void); |