diff options
Diffstat (limited to 'block/qed.c')
-rw-r--r-- | block/qed.c | 70 |
1 files changed, 32 insertions, 38 deletions
diff --git a/block/qed.c b/block/qed.c index 86cad2188c..5792796315 100644 --- a/block/qed.c +++ b/block/qed.c @@ -982,40 +982,12 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb) BDRVQEDState *s = acb_to_s(acb); uint64_t offset = acb->cur_cluster + qed_offset_into_cluster(s, acb->cur_pos); - int ret; trace_qed_aio_write_main(s, acb, 0, offset, acb->cur_qiov.size); BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO); - ret = bdrv_co_pwritev(s->bs->file, offset, acb->cur_qiov.size, - &acb->cur_qiov, 0); - if (ret < 0) { - return ret; - } - - if (acb->find_cluster_ret != QED_CLUSTER_FOUND) { - 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_co_flush(s->bs->file->bs); - if (ret < 0) { - return ret; - } - } - ret = qed_aio_write_l2_update(acb, acb->cur_cluster); - if (ret < 0) { - return ret; - } - } - return 0; + return bdrv_co_pwritev(s->bs->file, offset, acb->cur_qiov.size, + &acb->cur_qiov, 0); } /** @@ -1050,7 +1022,29 @@ static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb) return ret; } - return qed_aio_write_main(acb); + ret = qed_aio_write_main(acb); + if (ret < 0) { + return ret; + } + + 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_co_flush(s->bs->file->bs); + if (ret < 0) { + return ret; + } + } + + return 0; } /** @@ -1103,6 +1097,7 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len) if (acb->find_cluster_ret == QED_CLUSTER_ZERO) { return 0; } + acb->cur_cluster = 1; } else { acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters); } @@ -1115,15 +1110,14 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len) } } - if (acb->flags & QED_AIOCB_ZERO) { - ret = qed_aio_write_l2_update(acb, 1); - } else { + if (!(acb->flags & QED_AIOCB_ZERO)) { ret = qed_aio_write_cow(acb); + if (ret < 0) { + return ret; + } } - if (ret < 0) { - return ret; - } - return 0; + + return qed_aio_write_l2_update(acb, acb->cur_cluster); } /** |