diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/qcow.c | 58 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 12 | ||||
-rw-r--r-- | block/qcow2.c | 39 | ||||
-rw-r--r-- | block/rbd.c | 4 | ||||
-rw-r--r-- | block/vdi.c | 41 |
5 files changed, 130 insertions, 24 deletions
diff --git a/block/qcow.c b/block/qcow.c index a26c88620f..227b104e36 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -496,6 +496,8 @@ typedef struct QCowAIOCB { uint64_t cluster_offset; uint8_t *cluster_data; struct iovec hd_iov; + bool is_write; + QEMUBH *bh; QEMUIOVector hd_qiov; BlockDriverAIOCB *hd_aiocb; } QCowAIOCB; @@ -525,6 +527,8 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, acb->hd_aiocb = NULL; acb->sector_num = sector_num; acb->qiov = qiov; + acb->is_write = is_write; + if (qiov->niov > 1) { acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size); if (is_write) @@ -538,6 +542,38 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, return acb; } +static void qcow_aio_read_cb(void *opaque, int ret); +static void qcow_aio_write_cb(void *opaque, int ret); + +static void qcow_aio_rw_bh(void *opaque) +{ + QCowAIOCB *acb = opaque; + qemu_bh_delete(acb->bh); + acb->bh = NULL; + + if (acb->is_write) { + qcow_aio_write_cb(opaque, 0); + } else { + qcow_aio_read_cb(opaque, 0); + } +} + +static int qcow_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb) +{ + if (acb->bh) { + return -EIO; + } + + acb->bh = qemu_bh_new(cb, acb); + if (!acb->bh) { + return -EIO; + } + + qemu_bh_schedule(acb->bh); + + return 0; +} + static void qcow_aio_read_cb(void *opaque, int ret) { QCowAIOCB *acb = opaque; @@ -640,12 +676,21 @@ static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { QCowAIOCB *acb; + int ret; acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); if (!acb) return NULL; - qcow_aio_read_cb(acb, 0); + ret = qcow_schedule_bh(qcow_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } @@ -725,6 +770,7 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; QCowAIOCB *acb; + int ret; s->cluster_cache_offset = -1; /* disable compressed cache */ @@ -733,7 +779,15 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, return NULL; - qcow_aio_write_cb(acb, 0); + ret = qcow_schedule_bh(qcow_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index c9e7bbd9d6..882f50a80b 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -796,8 +796,8 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, m->depends_on = old_alloc; m->nb_clusters = 0; *num = 0; - ret = 0; - goto fail; + + goto out_wait_dependency; } } } @@ -812,7 +812,6 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size); if (cluster_offset < 0) { - QLIST_REMOVE(m, next_in_flight); ret = cluster_offset; goto fail; } @@ -825,7 +824,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, out: ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { - return ret; + goto fail_put; } m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end); @@ -835,8 +834,13 @@ out: return 0; +out_wait_dependency: + return qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + fail: qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); +fail_put: + QLIST_REMOVE(m, next_in_flight); return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 8451ded9a3..2c51e7ccbd 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -378,6 +378,7 @@ typedef struct QCowAIOCB { uint64_t bytes_done; uint64_t cluster_offset; uint8_t *cluster_data; + bool is_write; BlockDriverAIOCB *hd_aiocb; QEMUIOVector hd_qiov; QEMUBH *bh; @@ -399,12 +400,19 @@ static AIOPool qcow2_aio_pool = { }; static void qcow2_aio_read_cb(void *opaque, int ret); -static void qcow2_aio_read_bh(void *opaque) +static void qcow2_aio_write_cb(void *opaque, int ret); + +static void qcow2_aio_rw_bh(void *opaque) { QCowAIOCB *acb = opaque; qemu_bh_delete(acb->bh); acb->bh = NULL; - qcow2_aio_read_cb(opaque, 0); + + if (acb->is_write) { + qcow2_aio_write_cb(opaque, 0); + } else { + qcow2_aio_read_cb(opaque, 0); + } } static int qcow2_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb) @@ -493,14 +501,14 @@ static void qcow2_aio_read_cb(void *opaque, int ret) goto done; } } else { - ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb); + ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb); if (ret < 0) goto done; } } else { /* Note: in this case, no need to wait */ qemu_iovec_memset(&acb->hd_qiov, 0, 512 * acb->cur_nr_sectors); - ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb); + ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb); if (ret < 0) goto done; } @@ -515,7 +523,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret) s->cluster_cache + index_in_cluster * 512, 512 * acb->cur_nr_sectors); - ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb); + ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb); if (ret < 0) goto done; } else { @@ -572,6 +580,7 @@ static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num, acb->hd_aiocb = NULL; acb->sector_num = sector_num; acb->qiov = qiov; + acb->is_write = is_write; qemu_iovec_init(&acb->hd_qiov, qiov->niov); @@ -591,17 +600,22 @@ static BlockDriverAIOCB *qcow2_aio_readv(BlockDriverState *bs, void *opaque) { QCowAIOCB *acb; + int ret; acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); if (!acb) return NULL; - qcow2_aio_read_cb(acb, 0); + ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb); + if (ret < 0) { + qemu_iovec_destroy(&acb->hd_qiov); + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } -static void qcow2_aio_write_cb(void *opaque, int ret); - static void run_dependent_requests(QCowL2Meta *m) { QCowAIOCB *req; @@ -724,6 +738,7 @@ static BlockDriverAIOCB *qcow2_aio_writev(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; QCowAIOCB *acb; + int ret; s->cluster_cache_offset = -1; /* disable compressed cache */ @@ -731,7 +746,13 @@ static BlockDriverAIOCB *qcow2_aio_writev(BlockDriverState *bs, if (!acb) return NULL; - qcow2_aio_write_cb(acb, 0); + ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb); + if (ret < 0) { + qemu_iovec_destroy(&acb->hd_qiov); + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } diff --git a/block/rbd.c b/block/rbd.c index bdc448aa9f..d5659cdf19 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -227,7 +227,6 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) char name[RBD_MAX_IMAGE_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; - char *snap = NULL; rados_t cluster; rados_ioctx_t io_ctx; int ret; @@ -238,9 +237,6 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) conf, sizeof(conf)) < 0) { return -EINVAL; } - if (snap_buf[0] != '\0') { - snap = snap_buf; - } /* Read out options */ while (options && options->name) { diff --git a/block/vdi.c b/block/vdi.c index 4c9e201c33..261cf9b98d 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -152,6 +152,7 @@ typedef struct { /* Buffer for new allocated block. */ void *block_buffer; void *orig_buf; + bool is_write; int header_modified; BlockDriverAIOCB *hd_aiocb; struct iovec hd_iov; @@ -504,6 +505,8 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num, acb->hd_aiocb = NULL; acb->sector_num = sector_num; acb->qiov = qiov; + acb->is_write = is_write; + if (qiov->niov > 1) { acb->buf = qemu_blockalign(bs, qiov->size); acb->orig_buf = acb->buf; @@ -542,14 +545,20 @@ static int vdi_schedule_bh(QEMUBHFunc *cb, VdiAIOCB *acb) } static void vdi_aio_read_cb(void *opaque, int ret); +static void vdi_aio_write_cb(void *opaque, int ret); -static void vdi_aio_read_bh(void *opaque) +static void vdi_aio_rw_bh(void *opaque) { VdiAIOCB *acb = opaque; logout("\n"); qemu_bh_delete(acb->bh); acb->bh = NULL; - vdi_aio_read_cb(opaque, 0); + + if (acb->is_write) { + vdi_aio_write_cb(opaque, 0); + } else { + vdi_aio_read_cb(opaque, 0); + } } static void vdi_aio_read_cb(void *opaque, int ret) @@ -597,7 +606,7 @@ static void vdi_aio_read_cb(void *opaque, int ret) if (bmap_entry == VDI_UNALLOCATED) { /* Block not allocated, return zeros, no need to wait. */ memset(acb->buf, 0, n_sectors * SECTOR_SIZE); - ret = vdi_schedule_bh(vdi_aio_read_bh, acb); + ret = vdi_schedule_bh(vdi_aio_rw_bh, acb); if (ret < 0) { goto done; } @@ -630,12 +639,23 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { VdiAIOCB *acb; + int ret; + logout("\n"); acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); if (!acb) { return NULL; } - vdi_aio_read_cb(acb, 0); + + ret = vdi_schedule_bh(vdi_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } @@ -789,12 +809,23 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { VdiAIOCB *acb; + int ret; + logout("\n"); acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); if (!acb) { return NULL; } - vdi_aio_write_cb(acb, 0); + + ret = vdi_schedule_bh(vdi_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } |