Commit 643e5399bbb1dd6113e787c4d86c942a3a7c76ca

Authored by aliguori
1 parent a32ef786

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
Showing 1 changed file with 9 additions and 17 deletions
block-qcow2.c
@@ -429,8 +429,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size) @@ -429,8 +429,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
429 int new_l1_size, new_l1_size2, ret, i; 429 int new_l1_size, new_l1_size2, ret, i;
430 uint64_t *new_l1_table; 430 uint64_t *new_l1_table;
431 uint64_t new_l1_table_offset; 431 uint64_t new_l1_table_offset;
432 - uint64_t data64;  
433 - uint32_t data32; 432 + uint8_t data[12];
434 433
435 new_l1_size = s->l1_size; 434 new_l1_size = s->l1_size;
436 if (min_size <= new_l1_size) 435 if (min_size <= new_l1_size)
@@ -460,13 +459,10 @@ static int grow_l1_table(BlockDriverState *bs, int min_size) @@ -460,13 +459,10 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
460 new_l1_table[i] = be64_to_cpu(new_l1_table[i]); 459 new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
461 460
462 /* set new table */ 461 /* set new table */
463 - data64 = cpu_to_be64(new_l1_table_offset);  
464 - if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset),  
465 - &data64, sizeof(data64)) != sizeof(data64))  
466 - goto fail;  
467 - data32 = cpu_to_be32(new_l1_size);  
468 - if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size),  
469 - &data32, sizeof(data32)) != sizeof(data32)) 462 + cpu_to_be32w((uint32_t*)data, new_l1_size);
  463 + cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
  464 + if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,
  465 + sizeof(data)) != sizeof(data))
470 goto fail; 466 goto fail;
471 qemu_free(s->l1_table); 467 qemu_free(s->l1_table);
472 free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t)); 468 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) @@ -2281,8 +2277,7 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
2281 int new_table_size, new_table_size2, refcount_table_clusters, i, ret; 2277 int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
2282 uint64_t *new_table; 2278 uint64_t *new_table;
2283 int64_t table_offset; 2279 int64_t table_offset;
2284 - uint64_t data64;  
2285 - uint32_t data32; 2280 + uint8_t data[12];
2286 int old_table_size; 2281 int old_table_size;
2287 int64_t old_table_offset; 2282 int64_t old_table_offset;
2288 2283
@@ -2321,13 +2316,10 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size) @@ -2321,13 +2316,10 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
2321 for(i = 0; i < s->refcount_table_size; i++) 2316 for(i = 0; i < s->refcount_table_size; i++)
2322 be64_to_cpus(&new_table[i]); 2317 be64_to_cpus(&new_table[i]);
2323 2318
2324 - data64 = cpu_to_be64(table_offset); 2319 + cpu_to_be64w((uint64_t*)data, table_offset);
  2320 + cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
2325 if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset), 2321 if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
2326 - &data64, sizeof(data64)) != sizeof(data64))  
2327 - goto fail;  
2328 - data32 = cpu_to_be32(refcount_table_clusters);  
2329 - if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_clusters),  
2330 - &data32, sizeof(data32)) != sizeof(data32)) 2322 + data, sizeof(data)) != sizeof(data))
2331 goto fail; 2323 goto fail;
2332 qemu_free(s->refcount_table); 2324 qemu_free(s->refcount_table);
2333 old_table_offset = s->refcount_table_offset; 2325 old_table_offset = s->refcount_table_offset;