qcow2: Update snapshot table information at once

Failing in the middle wouldn't help with the integrity of the image, so
doing everything in a single request seems better.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This commit is contained in:
Kevin Wolf 2011-11-18 18:27:00 +01:00
parent 07fd877900
commit d69969c404

View File

@ -137,8 +137,10 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
QCowSnapshot *sn; QCowSnapshot *sn;
QCowSnapshotHeader h; QCowSnapshotHeader h;
int i, name_size, id_str_size, snapshots_size; int i, name_size, id_str_size, snapshots_size;
uint64_t data64; struct {
uint32_t data32; uint32_t nb_snapshots;
uint64_t snapshots_offset;
} QEMU_PACKED header_data;
int64_t offset, snapshots_offset; int64_t offset, snapshots_offset;
int ret; int ret;
@ -200,24 +202,20 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
/* /*
* Update the header to point to the new snapshot table. This requires the * Update the header to point to the new snapshot table. This requires the
* new table and its refcounts to be stable on disk. * new table and its refcounts to be stable on disk.
*
* FIXME This should be done with a single write
*/ */
ret = bdrv_flush(bs); ret = bdrv_flush(bs);
if (ret < 0) { if (ret < 0) {
goto fail; goto fail;
} }
data64 = cpu_to_be64(snapshots_offset); QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, snapshots_offset), offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots));
&data64, sizeof(data64));
if (ret < 0) { header_data.nb_snapshots = cpu_to_be32(s->nb_snapshots);
goto fail; header_data.snapshots_offset = cpu_to_be64(snapshots_offset);
}
data32 = cpu_to_be32(s->nb_snapshots);
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots), ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
&data32, sizeof(data32)); &header_data, sizeof(header_data));
if (ret < 0) { if (ret < 0) {
goto fail; goto fail;
} }