summaryrefslogtreecommitdiff
path: root/block-qcow2.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-02 20:10:14 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-02 20:10:14 +0000
commit643e5399bbb1dd6113e787c4d86c942a3a7c76ca (patch)
treeb2f647bf1481647e0d2cebef8b9e6238a74b831c /block-qcow2.c
parenta32ef786f4556ebb5e4b7329ac80810ebaa58a81 (diff)
downloadqemu-643e5399bbb1dd6113e787c4d86c942a3a7c76ca.tar.gz
Write table offset and size in one syscall (Gleb Natapov)
Otherwise if VM is killed between two writes data may be lost. But if offset and size fields are at the same disk block one write should update them both simultaneously. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5859 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'block-qcow2.c')
-rw-r--r--block-qcow2.c26
1 files changed, 9 insertions, 17 deletions
diff --git a/block-qcow2.c b/block-qcow2.c
index f55a4e4792..a65a10d69b 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -429,8 +429,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
int new_l1_size, new_l1_size2, ret, i;
uint64_t *new_l1_table;
uint64_t new_l1_table_offset;
- uint64_t data64;
- uint32_t data32;
+ uint8_t data[12];
new_l1_size = s->l1_size;
if (min_size <= new_l1_size)
@@ -460,13 +459,10 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
/* set new table */
- data64 = cpu_to_be64(new_l1_table_offset);
- if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset),
- &data64, sizeof(data64)) != sizeof(data64))
- goto fail;
- data32 = cpu_to_be32(new_l1_size);
- if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size),
- &data32, sizeof(data32)) != sizeof(data32))
+ cpu_to_be32w((uint32_t*)data, new_l1_size);
+ cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
+ if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,
+ sizeof(data)) != sizeof(data))
goto fail;
qemu_free(s->l1_table);
free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
@@ -2281,8 +2277,7 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
uint64_t *new_table;
int64_t table_offset;
- uint64_t data64;
- uint32_t data32;
+ uint8_t data[12];
int old_table_size;
int64_t old_table_offset;
@@ -2321,13 +2316,10 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
for(i = 0; i < s->refcount_table_size; i++)
be64_to_cpus(&new_table[i]);
- data64 = cpu_to_be64(table_offset);
+ cpu_to_be64w((uint64_t*)data, table_offset);
+ cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
- &data64, sizeof(data64)) != sizeof(data64))
- goto fail;
- data32 = cpu_to_be32(refcount_table_clusters);
- if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_clusters),
- &data32, sizeof(data32)) != sizeof(data32))
+ data, sizeof(data)) != sizeof(data))
goto fail;
qemu_free(s->refcount_table);
old_table_offset = s->refcount_table_offset;