aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/qcow.c58
-rw-r--r--block/qcow2-cluster.c12
-rw-r--r--block/qcow2.c39
-rw-r--r--block/rbd.c4
-rw-r--r--block/vdi.c41
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;
}