qcow2: Use bdrv_(p)write_sync for metadata writes
Use bdrv_(p)write_sync to ensure metadata integrity in case of a crash.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 8b3b720620
)
Conflicts:
block/qcow2-cluster.c
block/qcow2-refcount.c
block/qcow2-snapshot.c
block/qcow2.c
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
@@ -62,8 +62,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
|||||||
|
|
||||||
for(i = 0; i < s->l1_size; i++)
|
for(i = 0; i < s->l1_size; i++)
|
||||||
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
|
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
|
||||||
ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
|
ret = bdrv_pwrite_sync(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
|
||||||
if (ret != new_l1_size2)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
for(i = 0; i < s->l1_size; i++)
|
for(i = 0; i < s->l1_size; i++)
|
||||||
new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
|
new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
|
||||||
@@ -71,8 +71,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
|||||||
/* set new table */
|
/* set new table */
|
||||||
cpu_to_be32w((uint32_t*)data, new_l1_size);
|
cpu_to_be32w((uint32_t*)data, new_l1_size);
|
||||||
cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
|
cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
|
||||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
|
ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
|
||||||
if (ret != sizeof(data)) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
qemu_free(s->l1_table);
|
qemu_free(s->l1_table);
|
||||||
@@ -84,7 +84,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
|||||||
fail:
|
fail:
|
||||||
qemu_free(new_l1_table);
|
qemu_free(new_l1_table);
|
||||||
qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
|
qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
|
||||||
return ret < 0 ? ret : -EIO;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcow2_l2_cache_reset(BlockDriverState *bs)
|
void qcow2_l2_cache_reset(BlockDriverState *bs)
|
||||||
@@ -188,17 +188,17 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
|
|||||||
{
|
{
|
||||||
uint64_t buf[L1_ENTRIES_PER_SECTOR];
|
uint64_t buf[L1_ENTRIES_PER_SECTOR];
|
||||||
int l1_start_index;
|
int l1_start_index;
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
|
l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
|
||||||
for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
|
for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
|
||||||
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
|
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
|
ret = bdrv_pwrite_sync(s->hd, s->l1_table_offset + 8 * l1_start_index,
|
||||||
buf, sizeof(buf)) != sizeof(buf))
|
buf, sizeof(buf));
|
||||||
{
|
if (ret < 0) {
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -221,6 +221,7 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
|
|||||||
uint64_t old_l2_offset;
|
uint64_t old_l2_offset;
|
||||||
uint64_t *l2_table;
|
uint64_t *l2_table;
|
||||||
int64_t l2_offset;
|
int64_t l2_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
old_l2_offset = s->l1_table[l1_index];
|
old_l2_offset = s->l1_table[l1_index];
|
||||||
|
|
||||||
@@ -247,10 +248,11 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* write the l2 table to the file */
|
/* write the l2 table to the file */
|
||||||
if (bdrv_pwrite(s->hd, l2_offset,
|
ret = bdrv_pwrite_sync(s->hd, l2_offset, l2_table,
|
||||||
l2_table, s->l2_size * sizeof(uint64_t)) !=
|
s->l2_size * sizeof(uint64_t));
|
||||||
s->l2_size * sizeof(uint64_t))
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* update the L1 entry */
|
/* update the L1 entry */
|
||||||
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
|
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
|
||||||
@@ -384,8 +386,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
|
|||||||
s->cluster_data, n, 1,
|
s->cluster_data, n, 1,
|
||||||
&s->aes_encrypt_key);
|
&s->aes_encrypt_key);
|
||||||
}
|
}
|
||||||
ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
|
ret = bdrv_write_sync(s->hd, (cluster_offset >> 9) + n_start,
|
||||||
s->cluster_data, n);
|
s->cluster_data, n);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -597,10 +599,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
|||||||
/* compressed clusters never have the copied flag */
|
/* compressed clusters never have the copied flag */
|
||||||
|
|
||||||
l2_table[l2_index] = cpu_to_be64(cluster_offset);
|
l2_table[l2_index] = cpu_to_be64(cluster_offset);
|
||||||
if (bdrv_pwrite(s->hd,
|
if (bdrv_pwrite_sync(s->hd,
|
||||||
l2_offset + l2_index * sizeof(uint64_t),
|
l2_offset + l2_index * sizeof(uint64_t),
|
||||||
l2_table + l2_index,
|
l2_table + l2_index,
|
||||||
sizeof(uint64_t)) != sizeof(uint64_t))
|
sizeof(uint64_t)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return cluster_offset;
|
return cluster_offset;
|
||||||
@@ -618,11 +620,12 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
|
|||||||
int start_offset = (8 * l2_index) & ~511;
|
int start_offset = (8 * l2_index) & ~511;
|
||||||
int end_offset = (8 * (l2_index + num) + 511) & ~511;
|
int end_offset = (8 * (l2_index + num) + 511) & ~511;
|
||||||
size_t len = end_offset - start_offset;
|
size_t len = end_offset - start_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index],
|
ret = bdrv_pwrite_sync(s->hd, l2_offset + start_offset,
|
||||||
len) != len)
|
&l2_table[l2_start_index], len);
|
||||||
{
|
if (ret < 0) {
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -42,8 +42,8 @@ static int write_refcount_block(BDRVQcowState *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
|
if (bdrv_pwrite_sync(s->hd, s->refcount_block_cache_offset,
|
||||||
s->refcount_block_cache, size) != size)
|
s->refcount_block_cache, size) < 0)
|
||||||
{
|
{
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now the new refcount block needs to be written to disk */
|
/* Now the new refcount block needs to be written to disk */
|
||||||
ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
|
ret = bdrv_pwrite_sync(s->hd, new_block, s->refcount_block_cache,
|
||||||
s->cluster_size);
|
s->cluster_size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail_block;
|
goto fail_block;
|
||||||
@@ -255,7 +255,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
/* If the refcount table is big enough, just hook the block up there */
|
/* If the refcount table is big enough, just hook the block up there */
|
||||||
if (refcount_table_index < s->refcount_table_size) {
|
if (refcount_table_index < s->refcount_table_size) {
|
||||||
uint64_t data64 = cpu_to_be64(new_block);
|
uint64_t data64 = cpu_to_be64(new_block);
|
||||||
ret = bdrv_pwrite(s->hd,
|
ret = bdrv_pwrite_sync(s->hd,
|
||||||
s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
|
s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
|
||||||
&data64, sizeof(data64));
|
&data64, sizeof(data64));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -332,7 +332,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write refcount blocks to disk */
|
/* Write refcount blocks to disk */
|
||||||
ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
|
ret = bdrv_pwrite_sync(s->hd, meta_offset, new_blocks,
|
||||||
blocks_clusters * s->cluster_size);
|
blocks_clusters * s->cluster_size);
|
||||||
qemu_free(new_blocks);
|
qemu_free(new_blocks);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -344,7 +344,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
cpu_to_be64s(&new_table[i]);
|
cpu_to_be64s(&new_table[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_pwrite(s->hd, table_offset, new_table,
|
ret = bdrv_pwrite_sync(s->hd, table_offset, new_table,
|
||||||
table_size * sizeof(uint64_t));
|
table_size * sizeof(uint64_t));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail_table;
|
goto fail_table;
|
||||||
@@ -358,7 +358,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
uint8_t data[12];
|
uint8_t data[12];
|
||||||
cpu_to_be64w((uint64_t*)data, table_offset);
|
cpu_to_be64w((uint64_t*)data, table_offset);
|
||||||
cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
|
cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
|
||||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
||||||
data, sizeof(data));
|
data, sizeof(data));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail_table;
|
goto fail_table;
|
||||||
@@ -397,6 +397,7 @@ static int write_refcount_block_entries(BDRVQcowState *s,
|
|||||||
int64_t refcount_block_offset, int first_index, int last_index)
|
int64_t refcount_block_offset, int first_index, int last_index)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (cache_refcount_updates) {
|
if (cache_refcount_updates) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -411,11 +412,11 @@ static int write_refcount_block_entries(BDRVQcowState *s,
|
|||||||
& ~(REFCOUNTS_PER_SECTOR - 1);
|
& ~(REFCOUNTS_PER_SECTOR - 1);
|
||||||
|
|
||||||
size = (last_index - first_index) << REFCOUNT_SHIFT;
|
size = (last_index - first_index) << REFCOUNT_SHIFT;
|
||||||
if (bdrv_pwrite(s->hd,
|
ret = bdrv_pwrite_sync(s->hd,
|
||||||
refcount_block_offset + (first_index << REFCOUNT_SHIFT),
|
refcount_block_offset + (first_index << REFCOUNT_SHIFT),
|
||||||
&s->refcount_block_cache[first_index], size) != size)
|
&s->refcount_block_cache[first_index], size);
|
||||||
{
|
if (ret < 0) {
|
||||||
return -EIO;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -771,8 +772,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (l2_modified) {
|
if (l2_modified) {
|
||||||
if (bdrv_pwrite(s->hd,
|
if (bdrv_pwrite_sync(s->hd,
|
||||||
l2_offset, l2_table, l2_size) != l2_size)
|
l2_offset, l2_table, l2_size) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -793,8 +794,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
|||||||
if (l1_modified) {
|
if (l1_modified) {
|
||||||
for(i = 0; i < l1_size; i++)
|
for(i = 0; i < l1_size; i++)
|
||||||
cpu_to_be64s(&l1_table[i]);
|
cpu_to_be64s(&l1_table[i]);
|
||||||
if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
|
if (bdrv_pwrite_sync(s->hd, l1_table_offset, l1_table,
|
||||||
l1_size2) != l1_size2)
|
l1_size2) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
for(i = 0; i < l1_size; i++)
|
for(i = 0; i < l1_size; i++)
|
||||||
be64_to_cpus(&l1_table[i]);
|
be64_to_cpus(&l1_table[i]);
|
||||||
|
@@ -158,25 +158,25 @@ static int qcow_write_snapshots(BlockDriverState *bs)
|
|||||||
h.id_str_size = cpu_to_be16(id_str_size);
|
h.id_str_size = cpu_to_be16(id_str_size);
|
||||||
h.name_size = cpu_to_be16(name_size);
|
h.name_size = cpu_to_be16(name_size);
|
||||||
offset = align_offset(offset, 8);
|
offset = align_offset(offset, 8);
|
||||||
if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
|
if (bdrv_pwrite_sync(s->hd, offset, &h, sizeof(h)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
offset += sizeof(h);
|
offset += sizeof(h);
|
||||||
if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
|
if (bdrv_pwrite_sync(s->hd, offset, sn->id_str, id_str_size) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
offset += id_str_size;
|
offset += id_str_size;
|
||||||
if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
|
if (bdrv_pwrite_sync(s->hd, offset, sn->name, name_size) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
offset += name_size;
|
offset += name_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the various header fields */
|
/* update the various header fields */
|
||||||
data64 = cpu_to_be64(snapshots_offset);
|
data64 = cpu_to_be64(snapshots_offset);
|
||||||
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
|
if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, snapshots_offset),
|
||||||
&data64, sizeof(data64)) != sizeof(data64))
|
&data64, sizeof(data64)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
data32 = cpu_to_be32(s->nb_snapshots);
|
data32 = cpu_to_be32(s->nb_snapshots);
|
||||||
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
|
if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, nb_snapshots),
|
||||||
&data32, sizeof(data32)) != sizeof(data32))
|
&data32, sizeof(data32)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* free the old snapshot table */
|
/* free the old snapshot table */
|
||||||
@@ -284,9 +284,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
|||||||
for(i = 0; i < s->l1_size; i++) {
|
for(i = 0; i < s->l1_size; i++) {
|
||||||
l1_table[i] = cpu_to_be64(s->l1_table[i]);
|
l1_table[i] = cpu_to_be64(s->l1_table[i]);
|
||||||
}
|
}
|
||||||
if (bdrv_pwrite(s->hd, sn->l1_table_offset,
|
if (bdrv_pwrite_sync(s->hd, sn->l1_table_offset,
|
||||||
l1_table, s->l1_size * sizeof(uint64_t)) !=
|
l1_table, s->l1_size * sizeof(uint64_t)) < 0)
|
||||||
(s->l1_size * sizeof(uint64_t)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
qemu_free(l1_table);
|
qemu_free(l1_table);
|
||||||
l1_table = NULL;
|
l1_table = NULL;
|
||||||
@@ -335,8 +334,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
|||||||
if (bdrv_pread(s->hd, sn->l1_table_offset,
|
if (bdrv_pread(s->hd, sn->l1_table_offset,
|
||||||
s->l1_table, l1_size2) != l1_size2)
|
s->l1_table, l1_size2) != l1_size2)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (bdrv_pwrite(s->hd, s->l1_table_offset,
|
if (bdrv_pwrite_sync(s->hd, s->l1_table_offset,
|
||||||
s->l1_table, l1_size2) != l1_size2)
|
s->l1_table, l1_size2) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
for(i = 0;i < s->l1_size; i++) {
|
for(i = 0;i < s->l1_size; i++) {
|
||||||
be64_to_cpus(&s->l1_table[i]);
|
be64_to_cpus(&s->l1_table[i]);
|
||||||
|
Reference in New Issue
Block a user