qed: Make qed_aio_write_main() synchronous

Note that this code is generally not running in coroutine context, so
this is an actual blocking synchronous operation. We'll fix this in a
moment.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Kevin Wolf 2016-11-14 14:56:32 +01:00
parent 3e248cdcd9
commit a4d8f1aee1
1 changed files with 22 additions and 45 deletions

View File

@ -260,13 +260,6 @@ static void qed_aio_start_io(QEDAIOCB *acb)
qed_aio_next_io(acb, 0); qed_aio_next_io(acb, 0);
} }
static void qed_aio_next_io_cb(void *opaque, int ret)
{
QEDAIOCB *acb = opaque;
qed_aio_next_io(acb, ret);
}
static void qed_plug_allocating_write_reqs(BDRVQEDState *s) static void qed_plug_allocating_write_reqs(BDRVQEDState *s)
{ {
assert(!s->allocating_write_reqs_plugged); assert(!s->allocating_write_reqs_plugged);
@ -1042,31 +1035,6 @@ err:
qed_aio_complete(acb, ret); qed_aio_complete(acb, ret);
} }
static void qed_aio_write_l2_update_cb(void *opaque, int ret)
{
QEDAIOCB *acb = opaque;
qed_aio_write_l2_update(acb, ret, acb->cur_cluster);
}
/**
* Flush new data clusters before updating the L2 table
*
* This flush is necessary when a backing file is in use. A crash during an
* allocating write could result in empty clusters in the image. If the write
* only touched a subregion of the cluster, then backing image sectors have
* been lost in the untouched region. The solution is to flush after writing a
* new data cluster and before updating the L2 table.
*/
static void qed_aio_write_flush_before_l2_update(void *opaque, int ret)
{
QEDAIOCB *acb = opaque;
BDRVQEDState *s = acb_to_s(acb);
if (!bdrv_aio_flush(s->bs->file->bs, qed_aio_write_l2_update_cb, opaque)) {
qed_aio_complete(acb, -EIO);
}
}
/** /**
* Write data to the image file * Write data to the image file
*/ */
@ -1076,7 +1044,6 @@ static void qed_aio_write_main(void *opaque, int ret)
BDRVQEDState *s = acb_to_s(acb); BDRVQEDState *s = acb_to_s(acb);
uint64_t offset = acb->cur_cluster + uint64_t offset = acb->cur_cluster +
qed_offset_into_cluster(s, acb->cur_pos); qed_offset_into_cluster(s, acb->cur_pos);
BlockCompletionFunc *next_fn;
trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size); trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size);
@ -1085,20 +1052,30 @@ static void qed_aio_write_main(void *opaque, int ret)
return; return;
} }
if (acb->find_cluster_ret == QED_CLUSTER_FOUND) { BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
next_fn = qed_aio_next_io_cb; ret = bdrv_pwritev(s->bs->file, offset, &acb->cur_qiov);
} else { if (ret >= 0) {
if (s->bs->backing) { ret = 0;
next_fn = qed_aio_write_flush_before_l2_update;
} else {
next_fn = qed_aio_write_l2_update_cb;
}
} }
BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO); if (acb->find_cluster_ret == QED_CLUSTER_FOUND) {
bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE, qed_aio_next_io(acb, ret);
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE, } else {
next_fn, acb); if (s->bs->backing) {
/*
* Flush new data clusters before updating the L2 table
*
* This flush is necessary when a backing file is in use. A crash
* during an allocating write could result in empty clusters in the
* image. If the write only touched a subregion of the cluster,
* then backing image sectors have been lost in the untouched
* region. The solution is to flush after writing a new data
* cluster and before updating the L2 table.
*/
ret = bdrv_flush(s->bs->file->bs);
}
qed_aio_write_l2_update(acb, ret, acb->cur_cluster);
}
} }
/** /**