Block patches
The following changes since commit cada87c432e3b9cd55869a24055baf2b7bc0b70c:
Blue Swirl (1):
Update OpenBIOS images
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-anthony
Christoph Hellwig (1):
block: fix physical_block_size calculation
Eduardo Habkost (1):
monitor: allow device to be ejected if no disk is inserted
Kevin Wolf (8):
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
qcow2: Fix qemu-img check segfault on corrupted images
qcow2: Don't try to check tables that couldn't be loaded
MORITA Kazutaka (1):
qemu-io: check registered fds in command_loop()
Nicholas Bellinger (2):
scsi-bus: Add PERSISTENT_RESERVE_OUT SCSIRequest->cmd.mode setup
scsi-bus: Add MAINTENANCE_IN and MAINTENANCE_OUT SCSIRequest xfer and mode assignments
Yoshiaki Tamura (1):
virtio-blk: fix the list operation in virtio_blk_load().
block.c | 37 +++++++++++++++++++++++++++++++++++++ block.h | 4 ++++ block/cow.c | 20 +++++++++++--------- block/qcow.c | 18 ++++++++++-------- block/qcow2-cluster.c | 24 ++++++++++++------------ block/qcow2-refcount.c | 39 ++++++++++++++++++++++++--------------- block/qcow2-snapshot.c | 23 +++++++++++------------ block/qcow2.c | 10 +++++----- block/vmdk.c | 10 +++++----- block/vpc.c | 9 +++++---- block_int.h | 4 +++- blockdev.c | 22 ++++++++++------------ cmd.c | 33 ++++++++++++++++++++++++++++++--- hw/scsi-bus.c | 11 +++++++++++ hw/scsi-defs.h | 2 ++ hw/virtio-blk.c | 2 +- 16 files changed, 181 insertions(+), 87 deletions(-)
PATCH 1/14 scsi-bus: Add PERSISTENT_RESERVE_OUT SCSIRequest->cmd.mode setup
From: Nicholas Bellinger <[email protected]>
This patch updates hw/scsi-bus.c to add the PERSISTENT_RESERVE_OUT cdb case in scsi_req_xfer_mode() to set SCSI_XFER_TO_DEV for outgoing WRITE data.
--- hw/scsi-bus.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
hw/scsi-bus.c +1 -0
@@ -306,6 +306,7 @@ static void scsi_req_xfer_mode(SCSIRequest *req)case MEDIUM_SCAN :case SEND_VOLUME_TAG :case WRITE_LONG_2 : +case PERSISTENT_RESERVE_OUT : req->cmd.mode =SCSI_XFER_TO_DEV ;break ;default :
Signature · 1 line
1.6.6.1
PATCH 2/14 scsi-bus: Add MAINTENANCE_IN and MAINTENANCE_OUT SCSIRequest xfer and mode assignments
In reply to Kevin WolfFrom: Nicholas Bellinger <[email protected]>
This patch updates hw/scsi-bus.c to add MAINTENANCE_IN and MAINTENANCE_OUT case in scsi_req_length() for TYPE_ROM with MMC commands. It also adds the MAINTENANCE_OUT case in scsi_req_xfer_mode() to set SCSI_XFER_TO_DEV for outgoing write data.
--- hw/scsi-bus.c | 10 ++++++++++ hw/scsi-defs.h | 2 ++ 2 files changed, 12 insertions(+), 0 deletions(-)
hw/scsi-bus.c +10 -0
@@ -242,6 +242,13 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)case INQUIRY : req->cmd.xfer = cmd[4 ] | (cmd[3 ] <<8 );break ; +case MAINTENANCE_OUT : +case MAINTENANCE_IN : +if (req->dev->type ==TYPE_ROM ) { +/* GPCMD_REPORT_KEY and GPCMD_SEND_KEY from multi media commands */ + req->cmd.xfer = cmd[9 ] | (cmd[8 ] <<8 ); + } +break ; }return 0 ; }
@@ -307,6 +314,7 @@ static void scsi_req_xfer_mode(SCSIRequest *req)case SEND_VOLUME_TAG :case WRITE_LONG_2 :case PERSISTENT_RESERVE_OUT : +case MAINTENANCE_OUT : req->cmd.mode =SCSI_XFER_TO_DEV ;break ;default :
@@ -387,6 +395,8 @@ static const char *scsi_command_name(uint8_t cmd) [ SPACE ] = "SPACE", [ INQUIRY ] = "INQUIRY", [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA", + [ MAINTENANCE_IN ] = "MAINTENANCE_IN", + [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT", [ MODE_SELECT ] = "MODE_SELECT", [ RESERVE ] = "RESERVE", [ RELEASE ] = "RELEASE",
hw/scsi-defs.h +2 -0
@@ -84,6 +84,8 @@#define MODE_SENSE_10 0x5a#define PERSISTENT_RESERVE_IN 0x5e#define PERSISTENT_RESERVE_OUT 0x5f +#define MAINTENANCE_IN 0xa3 +#define MAINTENANCE_OUT 0xa4#define MOVE_MEDIUM 0xa5#define READ_12 0xa8#define WRITE_12 0xaa
Signature · 1 line
1.6.6.1
PATCH 3/14 block: fix physical_block_size calculation
In reply to Kevin WolfFrom: Christoph Hellwig <[email protected]>
Both SCSI and virtio expect the physical block size relative to the logical block size. So get the factor first before calculating the log2.
--- block_int.h | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
block_int.h +3 -1
@@ -224,7 +224,9 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) {unsigned int exp =0 , size; -for (size = conf->physical_block_size; size >512 ; size >>=1 ) { +for (size = conf->physical_block_size; + size > conf->logical_block_size; + size >>=1 ) { exp++; }
Signature · 1 line
1.6.6.1
PATCH 4/14 monitor: allow device to be ejected if no disk is inserted
In reply to Kevin WolfFrom: Eduardo Habkost <[email protected]>
This changes the monitor eject_device() function to not check for bdrv_is_inserted().
Example run where the bug manifests itself:
(output of 'info block' is stripped to include only the CD-ROM device)
(qemu) info block
ide1-cd0: type=cdrom removable=1 locked=0 [not inserted]
(qemu) change ide1-cd0 /dev/cdrom host_cdrom
(qemu) info block
ide1-cd0: type=cdrom removable=1 locked=0 file=/dev/cdrom ro=1 drv=host_cdrom encrypted=0 (qemu) eject ide1-cd0
(qemu) info block
ide1-cd0: type=cdrom removable=1 locked=0 file=/dev/cdrom ro=1 drv=host_cdrom encrypted=0
# at this point, a disk was inserted on the host CD-ROM drive
(qemu) info block
ide1-cd0: type=cdrom removable=1 locked=0 file=/dev/cdrom ro=1 drv=host_cdrom encrypted=0 (qemu) eject ide1-cd0
(qemu) info block
ide1-cd0: type=cdrom removable=1 locked=0 [not inserted]
(qemu)
The first eject command didn't work because the is_inserted() check failed.
I have no clue why the code had the is_inserted() check, as it doesn't matter if there is a disk present at the host drive, when the user wants the virtual device to be disconnected from the host device.
The is_inserted() check has another side effect: a memory leak if the "change" command is used multiple times, as do_change() calls eject_device() before re-opening the block device, but bdrv_close() is never called.
--- blockdev.c | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-)
blockdev.c +10 -12
@@ -503,20 +503,18 @@ void do_commit(Monitor *mon, const QDict *qdict)static int eject_device (Monitor *mon,BlockDriverState *bs,int force) { -if (bdrv_is_inserted (bs)) { -if (!force) { -if (!bdrv_is_removable (bs)) { -qerror_report (QERR_DEVICE_NOT_REMOVABLE , -bdrv_get_device_name (bs)); -return -1 ; - } -if (bdrv_is_locked (bs)) { -qerror_report (QERR_DEVICE_LOCKED ,bdrv_get_device_name (bs)); -return -1 ; - } +if (!force) { +if (!bdrv_is_removable (bs)) { +qerror_report (QERR_DEVICE_NOT_REMOVABLE , +bdrv_get_device_name (bs)); +return -1 ; + } +if (bdrv_is_locked (bs)) { +qerror_report (QERR_DEVICE_LOCKED ,bdrv_get_device_name (bs)); +return -1 ; } -bdrv_close (bs); } +bdrv_close (bs);return 0 ; }
Signature · 1 line
1.6.6.1
PATCH 5/14 block: Add bdrv_(p)write_sync
In reply to Kevin WolfAdd 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 6/14 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 7/14 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 8/14 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)
@@ -207,7 +207,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;
@@ -263,7 +263,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;
@@ -413,8 +413,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 ;
@@ -631,10 +631,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;
@@ -655,7 +655,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
@@ -735,7 +735,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; }
@@ -744,13 +744,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;
@@ -1131,8 +1131,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 9/14 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 10/14 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
PATCH 11/14 qemu-io: check registered fds in command_loop()
In reply to Kevin WolfFrom: MORITA Kazutaka <[email protected]>
Some block drivers use an aio handler and do I/O completion routines in it. However, the handler is not invoked if we only do aio_read/write, because registered fds are not checked at all.
This patch registers an aio handler of STDIO to checks whether we can read a command without blocking, and calls qemu_aio_wait() in command_loop(). Any other handlers can be invoked when user input is idle.
--- cmd.c | 33 ++++++++++++++++++++++++++++++--- 1 files changed, 30 insertions(+), 3 deletions(-)
cmd.c +30 -3
@@ -24,6 +24,7 @@#include <getopt.h> #include "cmd.h" +#include "qemu-aio.h" #define _ (x) x/* not gettext support yet */
@@ -149,10 +150,20 @@ add_args_command( args_func = af; } +static void prep_fetchline (void *opaque) +{ +int *fetchable = opaque; + +qemu_aio_set_fd_handler (STDIN_FILENO ,NULL ,NULL ,NULL ,NULL ,NULL ); + *fetchable=1 ; +} + +static char *get_prompt (void ); +void command_loop (void ) { -int c, i, j =0 , done =0 ; +int c, i, j =0 , done =0 , fetchable =0 , prompted =0 ;char *input;char **v;const cmdinfo_t *ct;
@@ -186,7 +197,21 @@ command_loop(void)free (cmdline);return ; } +while (!done) { +if (!prompted) { +printf ("%s" ,get_prompt ()); +fflush (stdout); +qemu_aio_set_fd_handler (STDIN_FILENO , prep_fetchline,NULL ,NULL , +NULL , &fetchable); + prompted =1 ; + } + +qemu_aio_wait (); + +if (!fetchable) { +continue ; + }if ((input =fetchline ()) ==NULL )break ; v =breakline (input, &c);
@@ -199,7 +224,11 @@ command_loop(void) v[0]); }doneline (input, v); + + prompted =0 ; + fetchable =0 ; } +qemu_aio_set_fd_handler (STDIN_FILENO ,NULL ,NULL ,NULL ,NULL ,NULL ); }/* from libxcmd/input.c */
@@ -270,8 +299,6 @@ fetchline(void)if (!line)return NULL ; -printf ("%s" ,get_prompt ()); -fflush (stdout);if (!fgets (line,MAXREADLINESZ , stdin)) {free (line);return NULL ;
Signature · 1 line
1.6.6.1
PATCH 12/14 virtio-blk: fix the list operation in virtio_blk_load().
In reply to Kevin WolfFrom: Yoshiaki Tamura <[email protected]>
Although it is really rare to get in to the while loop, the list operation in the loop is obviously wrong.
--- hw/virtio-blk.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
hw/virtio-blk.c +1 -1
@@ -470,7 +470,7 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)VirtIOBlockReq *req =virtio_blk_alloc_request (s);qemu_get_buffer (f, (unsigned char *)&req->elem,sizeof (req->elem)); req->next = s->rq; - s->rq = req->next; + s->rq = req; }return 0 ;
Signature · 1 line
1.6.6.1
PATCH 13/14 qcow2: Fix qemu-img check segfault on corrupted images
In reply to Kevin WolfWith corrupted images, we can easily get an cluster index that exceeds the array size of the temporary refcount table.
--- block/qcow2-refcount.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
block/qcow2-refcount.c +11 -3
@@ -1140,22 +1140,30 @@ int qcow2_check_refcounts(BlockDriverState *bs) s->refcount_table_offset, s->refcount_table_size * sizeof(uint64_t));for (i =0 ; i < s->refcount_table_size; i++) { -int64_t offset; +uint64_t offset, cluster; offset = s->refcount_table[i]; + cluster = offset >> s->cluster_bits;/* Refcount blocks are cluster aligned */ if (offset & (s->cluster_size -1 )) {fprintf (stderr,"ERROR refcount block %d is not " "cluster aligned; refcount table entry corrupted\n" , i); errors++; +continue ; + } + +if (cluster >= nb_clusters) { +fprintf (stderr,"ERROR refcount block %d is outside image\n" , i); + errors++; +continue ; }if (offset !=0 ) { errors +=inc_refcounts (bs, refcount_table, nb_clusters, offset, s->cluster_size); -if (refcount_table[offset / s->cluster_size] !=1 ) { +if (refcount_table[cluster] !=1 ) {fprintf (stderr,"ERROR refcount block %d refcount=%d\n" , - i, refcount_table[offset / s->cluster_size]); + i, refcount_table[cluster]); } } }
Signature · 1 line
1.6.6.1
PATCH 14/14 qcow2: Don't try to check tables that couldn't be loaded
In reply to Kevin WolfTrying to check them leads to a second error message which is more confusing than helpful:
Can't get refcount for cluster 0: Invalid argument ERROR cluster 0 refcount=-22 reference=1
--- block/qcow2-refcount.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
block/qcow2-refcount.c +1 -0
@@ -1174,6 +1174,7 @@ int qcow2_check_refcounts(BlockDriverState *bs)if (refcount1 <0 ) {fprintf (stderr,"Can't get refcount for cluster %d: %s\n" , i,strerror (-refcount1)); +continue ; } refcount2 = refcount_table[i];
Signature · 1 line
1.6.6.1