diff mbox

[V4,4/6] qcow2: cancel the modification on fail in qcow2_snapshot_create()

Message ID 1381787553-12497-5-git-send-email-xiawenc@linux.vnet.ibm.com
State New
Headers show

Commit Message

Wayne Xia Oct. 14, 2013, 9:52 p.m. UTC
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 block/qcow2-snapshot.c |   25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)

Comments

Max Reitz Nov. 2, 2013, 1:11 p.m. UTC | #1
On 14.10.2013 23:52, Wenchao Xia wrote:
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---

Reviewed-by: Max Reitz <mreitz@redhat.com>
diff mbox

Patch

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index c933b7f..6d0ffd4 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -404,6 +404,7 @@  void qcow2_snapshot_create(BlockDriverState *bs,
     int i, ret;
     uint64_t *l1_table = NULL;
     int64_t l1_table_offset;
+    Error *err = NULL;
 
     memset(sn, 0, sizeof(*sn));
 
@@ -453,7 +454,7 @@  void qcow2_snapshot_create(BlockDriverState *bs,
                    PRIu64 " with size %" PRIu64 ": %d (%s)",
                    sn->l1_table_offset, s->l1_size * sizeof(uint64_t),
                    ret, strerror(-ret));
-        goto fail;
+        goto dealloc_cluster;
     }
 
     ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
@@ -463,7 +464,7 @@  void qcow2_snapshot_create(BlockDriverState *bs,
                    PRIu64 " with size %" PRIu64 ": %d (%s)",
                    sn->l1_table_offset, s->l1_size * sizeof(uint64_t),
                    ret, strerror(-ret));
-        goto fail;
+        goto dealloc_cluster;
     }
 
     g_free(l1_table);
@@ -479,7 +480,7 @@  void qcow2_snapshot_create(BlockDriverState *bs,
         error_setg(errp, "Failed in update of refcount for snapshot at %"
                    PRIu64 " with size %d: %d (%s)",
                    s->l1_table_offset, s->l1_size,  ret, strerror(-ret));
-        goto fail;
+        goto dealloc_cluster;
     }
 
     /* Append the new snapshot to the snapshot list */
@@ -497,7 +498,7 @@  void qcow2_snapshot_create(BlockDriverState *bs,
         g_free(s->snapshots);
         s->snapshots = old_snapshot_list;
         s->nb_snapshots--;
-        goto fail;
+        goto restore_refcount;
     }
 
     g_free(old_snapshot_list);
@@ -517,6 +518,22 @@  void qcow2_snapshot_create(BlockDriverState *bs,
 #endif
     return;
 
+restore_refcount:
+    if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1)
+        < 0 && errp) {
+        /* Nothing can be done now, need image check later */
+        error_setg(&err, "%s\nqcow2: Error in restoring refcount in snapshot",
+                   error_get_pretty(*errp));
+        error_free(*errp);
+        *errp = NULL;
+        error_propagate(errp, err);
+    }
+
+dealloc_cluster:
+    qcow2_free_clusters(bs, sn->l1_table_offset,
+                        sn->l1_size * sizeof(uint64_t),
+                        QCOW2_DISCARD_ALWAYS);
+
 fail:
     g_free(sn->id_str);
     g_free(sn->name);