Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 3160499aacb81f6735941eb4c372d87a > files > 540

kvm-83-164.el5_5.30.src.rpm

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