From a9cd97d17e35ac5cfd4b4ea415135a14342f3742 Mon Sep 17 00:00:00 2001 From: Kevin Wolf <kwolf@redhat.com> Date: Fri, 22 Jan 2010 14:47:45 -0200 Subject: [PATCH 04/10] qcow2: Return 0/-errno in qcow2_alloc_cluster_offset RH-Author: Kevin Wolf <kwolf@redhat.com> Message-id: <1264171666-30186-2-git-send-email-kwolf@redhat.com> Patchwork-id: 6549 O-Subject: [RHEL-5.5 KVM PATCH v2 04/10] qcow2: Return 0/-errno in qcow2_alloc_cluster_offset Bugzilla: 537077 RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Gleb Natapov <gleb@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> Bugzilla: 537077 Upstream status: Submitted Returning 0/-errno allows it to distingush different errors classes. The cluster offset of newly allocated clusters is now returned in the QCowL2Meta struct. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- qemu/block-qcow2.c | 58 ++++++++++++++++++++++++++++++--------------------- 1 files changed, 34 insertions(+), 24 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/block-qcow2.c | 58 ++++++++++++++++++++++++++++++--------------------- 1 files changed, 34 insertions(+), 24 deletions(-) diff --git a/qemu/block-qcow2.c b/qemu/block-qcow2.c index 5cca34a..07a401f 100644 --- a/qemu/block-qcow2.c +++ b/qemu/block-qcow2.c @@ -1006,6 +1006,7 @@ static uint64_t alloc_compressed_cluster_offset(BlockDriverState *bs, typedef struct QCowL2Meta { uint64_t offset; + uint64_t cluster_offset; int n_start; int nb_available; int nb_clusters; @@ -1033,12 +1034,12 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table, return 0; } -static int alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset, - QCowL2Meta *m) +static int alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) { BDRVQcowState *s = bs->opaque; int i, j = 0, l2_index, ret; uint64_t *old_cluster, start_sect, l2_offset, *l2_table; + uint64_t cluster_offset = m->cluster_offset; if (m->nb_clusters == 0) return 0; @@ -1100,20 +1101,24 @@ err: /* * alloc_cluster_offset * - * For a given offset of the disk image, return cluster offset in - * qcow2 file. - * + * For a given offset of the disk image, return cluster offset in qcow2 file. * If the offset is not found, allocate a new cluster. * - * Return the cluster offset if successful, - * Return 0, otherwise. + * If the cluster was already allocated, m->nb_clusters is set to 0, + * m->depends_on is set to NULL and the other fields in m are meaningless. * + * If the cluster is newly allocated, m->nb_clusters is set to the number of + * contiguous clusters that have been allocated. This may be 0 if the request + * conflict with another write request in flight; in this case, m->depends_on + * is set and the remaining fields of m are meaningless. + * + * If m->nb_clusters is non-zero, the other fields of m are valid and contain + * information about the first allocated cluster. + * + * Return 0 on success and -errno in error cases */ - -static uint64_t alloc_cluster_offset(BlockDriverState *bs, - uint64_t offset, - int n_start, int n_end, - int *num, QCowL2Meta *m) +static int alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, + int n_start, int n_end, int *num, QCowL2Meta *m) { BDRVQcowState *s = bs->opaque; int l2_index, ret; @@ -1122,7 +1127,7 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs, ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); if (ret < 0) { - return 0; + return ret; } nb_clusters = size_to_clusters(s, n_end << 9); @@ -1179,10 +1184,11 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs, out: m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end); + m->cluster_offset = cluster_offset; *num = m->nb_available - n_start; - return cluster_offset; + return 0; } static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num, @@ -1319,11 +1325,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, if (s->crypt_method && n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; - cluster_offset = alloc_cluster_offset(bs, sector_num << 9, + ret = alloc_cluster_offset(bs, sector_num << 9, index_in_cluster, n_end, &n, &l2meta); - if (!cluster_offset) - return -1; + if (ret < 0) + return ret; + cluster_offset = l2meta.cluster_offset; + if (s->crypt_method) { encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1, &s->aes_encrypt_cipher); @@ -1332,7 +1340,7 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, } else { ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512); } - if (ret != n * 512 || alloc_cluster_link_l2(bs, cluster_offset, &l2meta) < 0) { + if (ret != n * 512 || alloc_cluster_link_l2(bs, &l2meta) < 0) { free_any_clusters(bs, cluster_offset, l2meta.nb_clusters); return -1; } @@ -1519,7 +1527,7 @@ static void qcow_aio_write_cb(void *opaque, int ret) return; } - if (alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta) < 0) { + if (alloc_cluster_link_l2(bs, &acb->l2meta) < 0) { free_any_clusters(bs, acb->cluster_offset, acb->l2meta.nb_clusters); goto fail; } @@ -1541,13 +1549,15 @@ static void qcow_aio_write_cb(void *opaque, int ret) n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; - acb->cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9, - index_in_cluster, - n_end, &acb->n, &acb->l2meta); - if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) { - ret = -EIO; + ret = alloc_cluster_offset(bs, acb->sector_num << 9, + index_in_cluster, n_end, &acb->n, &acb->l2meta); + if (ret < 0) { goto fail; } + + acb->cluster_offset = acb->l2meta.cluster_offset; + assert((acb->cluster_offset & 511) == 0); + if (s->crypt_method) { if (!acb->cluster_data) { acb->cluster_data = qemu_mallocz(QCOW_MAX_CRYPT_CLUSTERS * -- 1.6.3.rc4.29.g8146