block: Add flush after metadata writes
cover block: Add flush after metadata writes
This addresses the data integrity problems which are described for qcow at
http://wiki.qemu.org/Features/Qcow2DataIntegrity#Metadata_update_ordering.2C_Part_2
These problems are the same for all writable image formats, so this series contains a patch for each of them.
The only exception is VDI which uses AIO for writing its metadata. It needs a different fix.
Kevin Wolf (6):
block: Add bdrv_(p)write_sync
cow: Use bdrv_(p)write_sync for metadata writes
qcow: Use bdrv_(p)write_sync for metadata writes
qcow2: Use bdrv_(p)write_sync for metadata writes
vmdk: Use bdrv_(p)write_sync for metadata writes
vpc: Use bdrv_(p)write_sync for metadata writes
block.c | 37 +++++++++++++++++++++++++++++++++++++ block.h | 4 ++++ block/cow.c | 20 +++++++++++--------- block/qcow.c | 18 ++++++++++-------- block/qcow2-cluster.c | 24 ++++++++++++------------ block/qcow2-refcount.c | 24 ++++++++++++------------ block/qcow2-snapshot.c | 23 +++++++++++------------ block/qcow2.c | 10 +++++----- block/vmdk.c | 10 +++++----- block/vpc.c | 9 +++++---- 10 files changed, 112 insertions(+), 67 deletions(-)
PATCH 1/6 block: Add bdrv_(p)write_sync
Add new functions that write and flush the written data to disk immediately. This is what needs to be used for image format metadata to maintain integrity for cache=... modes that don't use O_DSYNC. (Actually, we only need barriers, and therefore the functions are defined as such, but flushes is what is implemented in this patch - we can try to change that later)
--- block.c | 37 +++++++++++++++++++++++++++++++++++++ block.h | 4 ++++ 2 files changed, 41 insertions(+), 0 deletions(-)
block.c +37 -0
@@ -1010,6 +1010,43 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,return count1; } +/* +* Writes to the file and ensures that no writes are reordered across this +* request (acts as a barrier) +* +* Returns 0 on success, -errno in error cases. +*/ +int bdrv_pwrite_sync (BlockDriverState *bs,int64_t offset, +const void *buf,int count) +{ +int ret; + + ret =bdrv_pwrite (bs, offset, buf, count); +if (ret <0 ) { +return ret; + } + +/* No flush needed for cache=writethrough, it uses O_DSYNC */ +if ((bs->open_flags &BDRV_O_CACHE_MASK ) !=0 ) { +bdrv_flush (bs); + } + +return 0 ; +} + +/* +* Writes to the file and ensures that no writes are reordered across this +* request (acts as a barrier) +* +* Returns 0 on success, -errno in error cases. +*/ +int bdrv_write_sync (BlockDriverState *bs,int64_t sector_num, +const uint8_t *buf,int nb_sectors) +{ +return bdrv_pwrite_sync (bs,BDRV_SECTOR_SIZE * sector_num, + buf,BDRV_SECTOR_SIZE * nb_sectors); +} +/** * Truncate file to 'offset' bytes (needed only for file protocols) */
block.h +4 -0
@@ -80,6 +80,10 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int count);int bdrv_pwrite (BlockDriverState *bs,int64_t offset,const void *buf,int count); +int bdrv_pwrite_sync (BlockDriverState *bs,int64_t offset, +const void *buf,int count); +int bdrv_write_sync (BlockDriverState *bs,int64_t sector_num, +const uint8_t *buf,int nb_sectors);int bdrv_truncate (BlockDriverState *bs,int64_t offset);int64_t bdrv_getlength (BlockDriverState *bs);void bdrv_get_geometry (BlockDriverState *bs,uint64_t *nb_sectors_ptr);
Signature · 1 line
1.6.6.1
PATCH 2/6 cow: Use bdrv_(p)write_sync for metadata writes
In reply to Kevin WolfUse bdrv_(p)write_sync to ensure metadata integrity in case of a crash. While at it, correct the wrong usage of errno.
--- block/cow.c | 20 +++++++++++--------- 1 files changed, 11 insertions(+), 9 deletions(-)
block/cow.c +11 -9
@@ -97,17 +97,18 @@ static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum) {uint64_t offset =sizeof (struct cow_header_v2 ) + bitnum /8 ;uint8_t bitmap; +int ret; -if (bdrv_pread (bs->file, offset, &bitmap,sizeof (bitmap)) != -sizeof (bitmap)) { -return -errno; + ret =bdrv_pread (bs->file, offset, &bitmap,sizeof (bitmap)); +if (ret <0 ) { +return ret; } bitmap |= (1 << (bitnum %8 )); -if (bdrv_pwrite (bs->file, offset, &bitmap,sizeof (bitmap)) != -sizeof (bitmap)) { -return -errno; + ret =bdrv_pwrite_sync (bs->file, offset, &bitmap,sizeof (bitmap)); +if (ret <0 ) { +return ret; }return 0 ; }
@@ -116,10 +117,11 @@ static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum) {uint64_t offset =sizeof (struct cow_header_v2 ) + bitnum /8 ;uint8_t bitmap; +int ret; -if (bdrv_pread (bs->file, offset, &bitmap,sizeof (bitmap)) != -sizeof (bitmap)) { -return -errno; + ret =bdrv_pread (bs->file, offset, &bitmap,sizeof (bitmap)); +if (ret <0 ) { +return ret; }return !!(bitmap & (1 << (bitnum %8 )));
Signature · 1 line
1.6.6.1
PATCH 3/6 qcow: Use bdrv_(p)write_sync for metadata writes
In reply to Kevin WolfUse bdrv_(p)write_sync to ensure metadata integrity in case of a crash.
--- block/qcow.c | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-)
block/qcow.c +10 -8
@@ -273,8 +273,9 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,/* update the L1 entry */ s->l1_table[l1_index] = l2_offset; tmp =cpu_to_be64 (l2_offset); -if (bdrv_pwrite (bs->file, s->l1_table_offset + l1_index *sizeof (tmp), - &tmp,sizeof (tmp)) !=sizeof (tmp)) +if (bdrv_pwrite_sync (bs->file, + s->l1_table_offset + l1_index *sizeof (tmp), + &tmp,sizeof (tmp)) <0 )return 0 ; new_l2_table =1 ; }
@@ -302,8 +303,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, l2_table = s->l2_cache + (min_index << s->l2_bits);if (new_l2_table) {memset (l2_table,0 , s->l2_size *sizeof (uint64_t )); -if (bdrv_pwrite (bs->file, l2_offset, l2_table, s->l2_size *sizeof (uint64_t )) != - s->l2_size *sizeof (uint64_t )) +if (bdrv_pwrite_sync (bs->file, l2_offset, l2_table, + s->l2_size *sizeof (uint64_t )) <0 )return 0 ; }else { if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
@@ -368,8 +369,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,/* update L2 table */ tmp =cpu_to_be64 (cluster_offset); l2_table[l2_index] = tmp; -if (bdrv_pwrite (bs->file, - l2_offset + l2_index *sizeof (tmp), &tmp,sizeof (tmp)) !=sizeof (tmp)) +if (bdrv_pwrite_sync (bs->file, l2_offset + l2_index *sizeof (tmp), + &tmp,sizeof (tmp)) <0 )return 0 ; }return cluster_offset;
@@ -835,8 +836,9 @@ static int qcow_make_empty(BlockDriverState *bs)int ret;memset (s->l1_table,0 , l1_length); -if (bdrv_pwrite (bs->file, s->l1_table_offset, s->l1_table, l1_length) <0 ) -return -1 ; +if (bdrv_pwrite_sync (bs->file, s->l1_table_offset, s->l1_table, + l1_length) <0 ) +return -1 ; ret =bdrv_truncate (bs->file, s->l1_table_offset + l1_length);if (ret <0 )return ret;
Signature · 1 line
1.6.6.1
PATCH 4/6 qcow2: Use bdrv_(p)write_sync for metadata writes
In reply to Kevin WolfUse bdrv_(p)write_sync to ensure metadata integrity in case of a crash.
--- block/qcow2-cluster.c | 24 ++++++++++++------------ block/qcow2-refcount.c | 24 ++++++++++++------------ block/qcow2-snapshot.c | 23 +++++++++++------------ block/qcow2.c | 10 +++++----- 4 files changed, 40 insertions(+), 41 deletions(-)
block/qcow2-cluster.c +12 -12
@@ -64,8 +64,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)BLKDBG_EVENT (bs->file,BLKDBG_L1_GROW_WRITE_TABLE );for (i =0 ; i < s->l1_size; i++) new_l1_table[i] =cpu_to_be64 (new_l1_table[i]); - ret =bdrv_pwrite (bs->file, new_l1_table_offset, new_l1_table, new_l1_size2); -if (ret != new_l1_size2) + ret =bdrv_pwrite_sync (bs->file, new_l1_table_offset, new_l1_table, new_l1_size2); +if (ret <0 ) goto fail;for (i =0 ; i < s->l1_size; i++) new_l1_table[i] =be64_to_cpu (new_l1_table[i]);
@@ -74,8 +74,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)BLKDBG_EVENT (bs->file,BLKDBG_L1_GROW_ACTIVATE_TABLE );cpu_to_be32w ((uint32_t *)data, new_l1_size);cpu_to_be64w ((uint64_t *)(data +4 ), new_l1_table_offset); - ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , l1_size), data,sizeof (data)); -if (ret !=sizeof (data)) { + ret =bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , l1_size), data,sizeof (data)); +if (ret <0 ) { goto fail; }qemu_free (s->l1_table);
@@ -87,7 +87,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size) fail:qemu_free (new_l1_table);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)
@@ -208,7 +208,7 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index) }BLKDBG_EVENT (bs->file,BLKDBG_L1_UPDATE ); - ret =bdrv_pwrite (bs->file, s->l1_table_offset +8 * l1_start_index, + ret =bdrv_pwrite_sync (bs->file, s->l1_table_offset +8 * l1_start_index, buf,sizeof (buf));if (ret <0 ) {return ret;
@@ -264,7 +264,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) }/* write the l2 table to the file */ BLKDBG_EVENT (bs->file,BLKDBG_L2_ALLOC_WRITE ); - ret =bdrv_pwrite (bs->file, l2_offset, l2_table, + ret =bdrv_pwrite_sync (bs->file, l2_offset, l2_table, s->l2_size *sizeof (uint64_t ));if (ret <0 ) { goto fail;
@@ -414,8 +414,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect, &s->aes_encrypt_key); }BLKDBG_EVENT (bs->file,BLKDBG_COW_WRITE ); - ret =bdrv_write (bs->file, (cluster_offset >>9 ) + n_start, - s->cluster_data, n); + ret =bdrv_write_sync (bs->file, (cluster_offset >>9 ) + n_start, + s->cluster_data, n);if (ret <0 )return ret;return 0 ;
@@ -632,10 +632,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,BLKDBG_EVENT (bs->file,BLKDBG_L2_UPDATE_COMPRESSED ); l2_table[l2_index] =cpu_to_be64 (cluster_offset); -if (bdrv_pwrite (bs->file, +if (bdrv_pwrite_sync (bs->file, l2_offset + l2_index *sizeof (uint64_t ), l2_table + l2_index, -sizeof (uint64_t )) !=sizeof (uint64_t )) +sizeof (uint64_t )) <0 )return 0 ;return cluster_offset;
@@ -656,7 +656,7 @@ static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,int ret;BLKDBG_EVENT (bs->file,BLKDBG_L2_UPDATE ); - ret =bdrv_pwrite (bs->file, l2_offset + start_offset, + ret =bdrv_pwrite_sync (bs->file, l2_offset + start_offset, &l2_table[l2_start_index], len);if (ret <0 ) {return ret;
block/qcow2-refcount.c +12 -12
@@ -44,8 +44,8 @@ static int write_refcount_block(BlockDriverState *bs) }BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_UPDATE ); -if (bdrv_pwrite (bs->file, s->refcount_block_cache_offset, - s->refcount_block_cache, size) != size) +if (bdrv_pwrite_sync (bs->file, s->refcount_block_cache_offset, + s->refcount_block_cache, size) <0 ) {return -EIO ; }
@@ -269,7 +269,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)/* Now the new refcount block needs to be written to disk */ BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_ALLOC_WRITE ); - ret =bdrv_pwrite (bs->file, new_block, s->refcount_block_cache, + ret =bdrv_pwrite_sync (bs->file, new_block, s->refcount_block_cache, s->cluster_size);if (ret <0 ) { goto fail_block;
@@ -279,7 +279,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)if (refcount_table_index < s->refcount_table_size) {uint64_t data64 =cpu_to_be64 (new_block);BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_ALLOC_HOOKUP ); - ret =bdrv_pwrite (bs->file, + ret =bdrv_pwrite_sync (bs->file, s->refcount_table_offset + refcount_table_index *sizeof (uint64_t ), &data64,sizeof (data64));if (ret <0 ) {
@@ -359,7 +359,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)/* Write refcount blocks to disk */ BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS ); - ret =bdrv_pwrite (bs->file, meta_offset, new_blocks, + ret =bdrv_pwrite_sync (bs->file, meta_offset, new_blocks, blocks_clusters * s->cluster_size);qemu_free (new_blocks);if (ret <0 ) {
@@ -372,7 +372,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) }BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE ); - ret =bdrv_pwrite (bs->file, table_offset, new_table, + ret =bdrv_pwrite_sync (bs->file, table_offset, new_table, table_size *sizeof (uint64_t ));if (ret <0 ) { goto fail_table;
@@ -387,7 +387,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)cpu_to_be64w ((uint64_t *)data, table_offset);cpu_to_be32w ((uint32_t *)(data +8 ), table_clusters);BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE ); - ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , refcount_table_offset), + ret =bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , refcount_table_offset), data,sizeof (data));if (ret <0 ) { goto fail_table;
@@ -444,7 +444,7 @@ static int write_refcount_block_entries(BlockDriverState *bs, size = (last_index - first_index) <<REFCOUNT_SHIFT ;BLKDBG_EVENT (bs->file,BLKDBG_REFBLOCK_UPDATE_PART ); - ret =bdrv_pwrite (bs->file, + ret =bdrv_pwrite_sync (bs->file, refcount_block_offset + (first_index <<REFCOUNT_SHIFT ), &s->refcount_block_cache[first_index], size);if (ret <0 ) {
@@ -826,8 +826,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } }if (l2_modified) { -if (bdrv_pwrite (bs->file, - l2_offset, l2_table, l2_size) != l2_size) +if (bdrv_pwrite_sync (bs->file, + l2_offset, l2_table, l2_size) <0 ) goto fail; }
@@ -850,8 +850,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,if (l1_modified) {for (i =0 ; i < l1_size; i++)cpu_to_be64s (&l1_table[i]); -if (bdrv_pwrite (bs->file, l1_table_offset, l1_table, - l1_size2) != l1_size2) +if (bdrv_pwrite_sync (bs->file, l1_table_offset, l1_table, + l1_size2) <0 ) goto fail;for (i =0 ; i < l1_size; i++)be64_to_cpus (&l1_table[i]);
block/qcow2-snapshot.c +11 -12
@@ -158,25 +158,25 @@ static int qcow_write_snapshots(BlockDriverState *bs) h.id_str_size =cpu_to_be16 (id_str_size); h.name_size =cpu_to_be16 (name_size); offset =align_offset (offset,8 ); -if (bdrv_pwrite (bs->file, offset, &h,sizeof (h)) !=sizeof (h)) +if (bdrv_pwrite_sync (bs->file, offset, &h,sizeof (h)) <0 ) goto fail; offset +=sizeof (h); -if (bdrv_pwrite (bs->file, offset, sn->id_str, id_str_size) != id_str_size) +if (bdrv_pwrite_sync (bs->file, offset, sn->id_str, id_str_size) <0 ) goto fail; offset += id_str_size; -if (bdrv_pwrite (bs->file, offset, sn->name, name_size) != name_size) +if (bdrv_pwrite_sync (bs->file, offset, sn->name, name_size) <0 ) goto fail; offset += name_size; }/* update the various header fields */ data64 =cpu_to_be64 (snapshots_offset); -if (bdrv_pwrite (bs->file, offsetof(QCowHeader , snapshots_offset), - &data64,sizeof (data64)) !=sizeof (data64)) +if (bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , snapshots_offset), + &data64,sizeof (data64)) <0 ) goto fail; data32 =cpu_to_be32 (s->nb_snapshots); -if (bdrv_pwrite (bs->file, offsetof(QCowHeader , nb_snapshots), - &data32,sizeof (data32)) !=sizeof (data32)) +if (bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , nb_snapshots), + &data32,sizeof (data32)) <0 ) goto fail;/* 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++) { l1_table[i] =cpu_to_be64 (s->l1_table[i]); } -if (bdrv_pwrite (bs->file, sn->l1_table_offset, - l1_table, s->l1_size *sizeof (uint64_t )) != - (s->l1_size *sizeof (uint64_t ))) +if (bdrv_pwrite_sync (bs->file, sn->l1_table_offset, + l1_table, s->l1_size *sizeof (uint64_t )) <0 ) goto fail;qemu_free (l1_table); l1_table =NULL ;
@@ -335,8 +334,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)if (bdrv_pread (bs->file, sn->l1_table_offset, s->l1_table, l1_size2) != l1_size2) goto fail; -if (bdrv_pwrite (bs->file, s->l1_table_offset, - s->l1_table, l1_size2) != l1_size2) +if (bdrv_pwrite_sync (bs->file, s->l1_table_offset, + s->l1_table, l1_size2) <0 ) goto fail;for (i =0 ;i < s->l1_size; i++) {be64_to_cpus (&s->l1_table[i]);
block/qcow2.c +5 -5
@@ -736,7 +736,7 @@ static int qcow2_update_ext_header(BlockDriverState *bs, backing_file_offset =sizeof (QCowHeader) + offset; } - ret =bdrv_pwrite (bs->file,sizeof (QCowHeader), buf, ext_size); + ret =bdrv_pwrite_sync (bs->file,sizeof (QCowHeader), buf, ext_size);if (ret <0 ) { goto fail; }
@@ -745,13 +745,13 @@ static int qcow2_update_ext_header(BlockDriverState *bs,uint64_t be_backing_file_offset =cpu_to_be64 (backing_file_offset);uint32_t be_backing_file_size =cpu_to_be32 (backing_file_len); - ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , backing_file_offset), + ret =bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , backing_file_offset), &be_backing_file_offset,sizeof (uint64_t ));if (ret <0 ) { goto fail; } - ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , backing_file_size), + ret =bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , backing_file_size), &be_backing_file_size,sizeof (uint32_t ));if (ret <0 ) { goto fail;
@@ -1035,8 +1035,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)/* write updated header.size */ offset =cpu_to_be64 (offset); - ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , size), - &offset,sizeof (uint64_t )); + ret =bdrv_pwrite_sync (bs->file, offsetof(QCowHeader , size), + &offset,sizeof (uint64_t ));if (ret <0 ) {return ret; }
Signature · 1 line
1.6.6.1
PATCH 5/6 vmdk: Use bdrv_(p)write_sync for metadata writes
In reply to Kevin WolfUse bdrv_(p)write_sync to ensure metadata integrity in case of a crash.
--- block/vmdk.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
block/vmdk.c +5 -5
@@ -150,7 +150,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)pstrcat (desc,sizeof (desc), tmp_desc); } -if (bdrv_pwrite (bs->file,0x200 , desc,DESC_SIZE ) !=DESC_SIZE ) +if (bdrv_pwrite_sync (bs->file,0x200 , desc,DESC_SIZE ) <0 )return -1 ;return 0 ; }
@@ -471,14 +471,14 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)BDRVVmdkState *s = bs->opaque;/* update L2 table */ -if (bdrv_pwrite (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), - &(m_data->offset),sizeof (m_data->offset)) !=sizeof (m_data->offset)) +if (bdrv_pwrite_sync (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), + &(m_data->offset),sizeof (m_data->offset)) <0 )return -1 ;/* update backup L2 table */ if (s->l1_backup_table_offset !=0 ) { m_data->l2_offset = s->l1_backup_table[m_data->l1_index]; -if (bdrv_pwrite (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), - &(m_data->offset),sizeof (m_data->offset)) !=sizeof (m_data->offset)) +if (bdrv_pwrite_sync (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), + &(m_data->offset),sizeof (m_data->offset)) <0 )return -1 ; }
Signature · 1 line
1.6.6.1
PATCH 6/6 vpc: Use bdrv_(p)write_sync for metadata writes
In reply to Kevin WolfUse bdrv_(p)write_sync to ensure metadata integrity in case of a crash.
--- block/vpc.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-)
block/vpc.c +5 -4
@@ -261,7 +261,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, s->last_bitmap_offset = bitmap_offset;memset (bitmap,0xff , s->bitmap_size); -bdrv_pwrite (bs->file, bitmap_offset, bitmap, s->bitmap_size); +bdrv_pwrite_sync (bs->file, bitmap_offset, bitmap, s->bitmap_size); }// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
@@ -311,7 +311,7 @@ static int rewrite_footer(BlockDriverState* bs)BDRVVPCState *s = bs->opaque;int64_t offset = s->free_data_block_offset; - ret =bdrv_pwrite (bs->file, offset, s->footer_buf,HEADER_SIZE ); + ret =bdrv_pwrite_sync (bs->file, offset, s->footer_buf,HEADER_SIZE );if (ret <0 )return ret;
@@ -346,7 +346,8 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)// Initialize the block's bitmap memset (bitmap,0xff , s->bitmap_size); -bdrv_pwrite (bs->file, s->free_data_block_offset, bitmap, s->bitmap_size); +bdrv_pwrite_sync (bs->file, s->free_data_block_offset, bitmap, + s->bitmap_size);// Write new footer (the old one will be overwritten) s->free_data_block_offset += s->block_size + s->bitmap_size;
@@ -357,7 +358,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)// Write BAT entry to disk bat_offset = s->bat_offset + (4 * index); bat_value =be32_to_cpu (s->pagetable[index]); - ret =bdrv_pwrite (bs->file, bat_offset, &bat_value,4 ); + ret =bdrv_pwrite_sync (bs->file, bat_offset, &bat_value,4 );if (ret <0 ) goto fail;
Signature · 1 line
1.6.6.1
Nice to see these patches :).
Stefan