Block layer patches

- qemu-img info: Show protocol-level information
 - Move more functions to coroutines
 - Make coroutine annotations ready for static analysis
 - qemu-img: Fix exit code for errors closing the image
 - qcow2 bitmaps: Fix theoretical corruption in error path
 - pflash: Only load non-zero parts of backend image to save memory
 - Code cleanup and test case improvements
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmPajLURHGt3b2xmQHJl
 ZGhhdC5jb20ACgkQfwmycsiPL9aLjg//bk2uodtEZ1X1y/vU3Lmcqd2wh9gv4f9L
 csFFf17rrxce/m+4daVISHAzS+Zrwpgixt+vMm2dP+jQTZOg0G7/rcaRYYAYa29Y
 Lepr2Qsz0V6HnNpuvUE5hrXiJXU7w5InikLlnoTnwa2H2Nr/wMlzkPX1wh4OdaBy
 5KG/sjGVsaotrIdYjI3HnTvU/eytn1IcvLwqcTP2M7u8UMNyZkALyDjbC5QxBkwh
 TPVXNGCeDrD6atDOvsmBCkNM3kTmfsGoP5mYyJK5V6iARYV19Nt8tdmt094EFmHk
 VBgeY9y+Q6BctcDe31961+oFqGrsLnT3J7mHDhAoaO0BM8wwWCHfCA7yasmGjCj5
 HGE7/UJ8DYwGQ9T9N8gsx8NmsfyWgIcyRQGuzld72B4FTzES9NXS1JTUFAZHrDUl
 IIaL5bh8aycBKprDBTwvz07a6sDkvmxiR2G0TuS7kFev5O7+qW9dH517PWOWbsRA
 3+ICzsHCUE2GLi83KkRkBEqRW0CnNmA9qzWNdPdQ0egsEAtNqmJGaFPRLYqQ0ZwR
 gbu7+eK4kUyfqpqieeFxBY53THLE4yxZ3lcg4yFoQWQfKdTCYo69qUNK5AV1hvKY
 TzNAuNbOsipL06dRWy4jInbhzenbiYechyEuoqFv0PpHe1D+JrL8QA2hI/JHDwls
 enNpKYXdkn4=
 =Wf8w
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging

Block layer patches

- qemu-img info: Show protocol-level information
- Move more functions to coroutines
- Make coroutine annotations ready for static analysis
- qemu-img: Fix exit code for errors closing the image
- qcow2 bitmaps: Fix theoretical corruption in error path
- pflash: Only load non-zero parts of backend image to save memory
- Code cleanup and test case improvements

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmPajLURHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9aLjg//bk2uodtEZ1X1y/vU3Lmcqd2wh9gv4f9L
# csFFf17rrxce/m+4daVISHAzS+Zrwpgixt+vMm2dP+jQTZOg0G7/rcaRYYAYa29Y
# Lepr2Qsz0V6HnNpuvUE5hrXiJXU7w5InikLlnoTnwa2H2Nr/wMlzkPX1wh4OdaBy
# 5KG/sjGVsaotrIdYjI3HnTvU/eytn1IcvLwqcTP2M7u8UMNyZkALyDjbC5QxBkwh
# TPVXNGCeDrD6atDOvsmBCkNM3kTmfsGoP5mYyJK5V6iARYV19Nt8tdmt094EFmHk
# VBgeY9y+Q6BctcDe31961+oFqGrsLnT3J7mHDhAoaO0BM8wwWCHfCA7yasmGjCj5
# HGE7/UJ8DYwGQ9T9N8gsx8NmsfyWgIcyRQGuzld72B4FTzES9NXS1JTUFAZHrDUl
# IIaL5bh8aycBKprDBTwvz07a6sDkvmxiR2G0TuS7kFev5O7+qW9dH517PWOWbsRA
# 3+ICzsHCUE2GLi83KkRkBEqRW0CnNmA9qzWNdPdQ0egsEAtNqmJGaFPRLYqQ0ZwR
# gbu7+eK4kUyfqpqieeFxBY53THLE4yxZ3lcg4yFoQWQfKdTCYo69qUNK5AV1hvKY
# TzNAuNbOsipL06dRWy4jInbhzenbiYechyEuoqFv0PpHe1D+JrL8QA2hI/JHDwls
# enNpKYXdkn4=
# =Wf8w
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 01 Feb 2023 16:00:53 GMT
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (38 commits)
  qemu-img: Change info key names for protocol nodes
  qemu-img: Let info print block graph
  iotests/106, 214, 308: Read only one size line
  iotests: Filter child node information
  block/qapi: Add indentation to bdrv_node_info_dump()
  block/qapi: Introduce BlockGraphInfo
  block/qapi: Let bdrv_query_image_info() recurse
  qemu-img: Use BlockNodeInfo
  block: Split BlockNodeInfo off of ImageInfo
  block/vmdk: Change extent info type
  block/file: Add file-specific image info
  block: Improve empty format-specific info dump
  block/nbd: Add missing <qemu/bswap.h> include
  block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate()
  block: Convert bdrv_debug_event() to co_wrapper_mixed
  block: Convert bdrv_lock_medium() to co_wrapper
  block: Convert bdrv_eject() to co_wrapper
  block: Convert bdrv_get_info() to co_wrapper_mixed
  block: Convert bdrv_get_allocated_file_size() to co_wrapper
  block: use bdrv_co_refresh_total_sectors when possible
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-02-03 12:43:10 +00:00
commit 5736527050
69 changed files with 1208 additions and 551 deletions

88
block.c
View File

@ -1035,7 +1035,8 @@ static int find_image_format(BlockBackend *file, const char *filename,
* Set the current 'total_sectors' value * Set the current 'total_sectors' value
* Return 0 on success, -errno on error. * Return 0 on success, -errno on error.
*/ */
int refresh_total_sectors(BlockDriverState *bs, int64_t hint) int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
int64_t hint)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
@ -1044,13 +1045,13 @@ int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
return -ENOMEDIUM; return -ENOMEDIUM;
} }
/* Do not attempt drv->bdrv_getlength() on scsi-generic devices */ /* Do not attempt drv->bdrv_co_getlength() on scsi-generic devices */
if (bdrv_is_sg(bs)) if (bdrv_is_sg(bs))
return 0; return 0;
/* query actual device if possible, otherwise just trust the hint */ /* query actual device if possible, otherwise just trust the hint */
if (drv->bdrv_getlength) { if (drv->bdrv_co_getlength) {
int64_t length = drv->bdrv_getlength(bs); int64_t length = drv->bdrv_co_getlength(bs);
if (length < 0) { if (length < 0) {
return length; return length;
} }
@ -1601,6 +1602,11 @@ out:
g_free(gen_node_name); g_free(gen_node_name);
} }
/*
* The caller must always hold @bs AioContext lock, because this function calls
* bdrv_refresh_total_sectors() which polls when called from non-coroutine
* context.
*/
static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
const char *node_name, QDict *options, const char *node_name, QDict *options,
int open_flags, Error **errp) int open_flags, Error **errp)
@ -1652,7 +1658,7 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
bs->supported_read_flags |= BDRV_REQ_REGISTERED_BUF; bs->supported_read_flags |= BDRV_REQ_REGISTERED_BUF;
bs->supported_write_flags |= BDRV_REQ_REGISTERED_BUF; bs->supported_write_flags |= BDRV_REQ_REGISTERED_BUF;
ret = refresh_total_sectors(bs, bs->total_sectors); ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count"); error_setg_errno(errp, -ret, "Could not refresh total sector count");
return ret; return ret;
@ -3796,6 +3802,10 @@ out:
* The reference parameter may be used to specify an existing block device which * The reference parameter may be used to specify an existing block device which
* should be opened. If specified, neither options nor a filename may be given, * should be opened. If specified, neither options nor a filename may be given,
* nor can an existing BDS be reused (that is, *pbs has to be NULL). * nor can an existing BDS be reused (that is, *pbs has to be NULL).
*
* The caller must always hold @filename AioContext lock, because this
* function eventually calls bdrv_refresh_total_sectors() which polls
* when called from non-coroutine context.
*/ */
static BlockDriverState *bdrv_open_inherit(const char *filename, static BlockDriverState *bdrv_open_inherit(const char *filename,
const char *reference, const char *reference,
@ -4084,6 +4094,11 @@ close_and_fail:
return NULL; return NULL;
} }
/*
* The caller must always hold @filename AioContext lock, because this
* function eventually calls bdrv_refresh_total_sectors() which polls
* when called from non-coroutine context.
*/
BlockDriverState *bdrv_open(const char *filename, const char *reference, BlockDriverState *bdrv_open(const char *filename, const char *reference,
QDict *options, int flags, Error **errp) QDict *options, int flags, Error **errp)
{ {
@ -5705,7 +5720,7 @@ exit:
} }
/** /**
* Implementation of BlockDriver.bdrv_get_allocated_file_size() that * Implementation of BlockDriver.bdrv_co_get_allocated_file_size() that
* sums the size of all data-bearing children. (This excludes backing * sums the size of all data-bearing children. (This excludes backing
* children.) * children.)
*/ */
@ -5718,7 +5733,7 @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA | if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
BDRV_CHILD_FILTERED)) BDRV_CHILD_FILTERED))
{ {
child_size = bdrv_get_allocated_file_size(child->bs); child_size = bdrv_co_get_allocated_file_size(child->bs);
if (child_size < 0) { if (child_size < 0) {
return child_size; return child_size;
} }
@ -5733,7 +5748,7 @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
* Length of a allocated file in bytes. Sparse files are counted by actual * Length of a allocated file in bytes. Sparse files are counted by actual
* allocated space. Return < 0 if error or unknown. * allocated space. Return < 0 if error or unknown.
*/ */
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs) int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
@ -5741,8 +5756,8 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
if (drv->bdrv_get_allocated_file_size) { if (drv->bdrv_co_get_allocated_file_size) {
return drv->bdrv_get_allocated_file_size(bs); return drv->bdrv_co_get_allocated_file_size(bs);
} }
if (drv->bdrv_file_open) { if (drv->bdrv_file_open) {
@ -5754,7 +5769,7 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
return -ENOTSUP; return -ENOTSUP;
} else if (drv->is_filter) { } else if (drv->is_filter) {
/* Filter drivers default to the size of their filtered child */ /* Filter drivers default to the size of their filtered child */
return bdrv_get_allocated_file_size(bdrv_filter_bs(bs)); return bdrv_co_get_allocated_file_size(bdrv_filter_bs(bs));
} else { } else {
/* Other drivers default to summing their children's sizes */ /* Other drivers default to summing their children's sizes */
return bdrv_sum_allocated_file_size(bs); return bdrv_sum_allocated_file_size(bs);
@ -5800,7 +5815,7 @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
/** /**
* Return number of sectors on success, -errno on error. * Return number of sectors on success, -errno on error.
*/ */
int64_t bdrv_nb_sectors(BlockDriverState *bs) int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
@ -5809,7 +5824,7 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
return -ENOMEDIUM; return -ENOMEDIUM;
if (drv->has_variable_length) { if (drv->has_variable_length) {
int ret = refresh_total_sectors(bs, bs->total_sectors); int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -5821,11 +5836,12 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
* Return length in bytes on success, -errno on error. * Return length in bytes on success, -errno on error.
* The length is always a multiple of BDRV_SECTOR_SIZE. * The length is always a multiple of BDRV_SECTOR_SIZE.
*/ */
int64_t bdrv_getlength(BlockDriverState *bs) int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
{ {
int64_t ret = bdrv_nb_sectors(bs); int64_t ret;
IO_CODE(); IO_CODE();
ret = bdrv_co_nb_sectors(bs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -6285,7 +6301,7 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
pstrcpy(filename, filename_size, bs->backing_file); pstrcpy(filename, filename_size, bs->backing_file);
} }
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
int ret; int ret;
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
@ -6294,15 +6310,15 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
if (!drv->bdrv_get_info) { if (!drv->bdrv_co_get_info) {
BlockDriverState *filtered = bdrv_filter_bs(bs); BlockDriverState *filtered = bdrv_filter_bs(bs);
if (filtered) { if (filtered) {
return bdrv_get_info(filtered, bdi); return bdrv_co_get_info(filtered, bdi);
} }
return -ENOTSUP; return -ENOTSUP;
} }
memset(bdi, 0, sizeof(*bdi)); memset(bdi, 0, sizeof(*bdi));
ret = drv->bdrv_get_info(bs, bdi); ret = drv->bdrv_co_get_info(bs, bdi);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -6335,14 +6351,14 @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
return drv->bdrv_get_specific_stats(bs); return drv->bdrv_get_specific_stats(bs);
} }
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event) void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
{ {
IO_CODE(); IO_CODE();
if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) { if (!bs || !bs->drv || !bs->drv->bdrv_co_debug_event) {
return; return;
} }
bs->drv->bdrv_debug_event(bs, event); bs->drv->bdrv_co_debug_event(bs, event);
} }
static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs) static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
@ -6591,7 +6607,7 @@ int bdrv_activate(BlockDriverState *bs, Error **errp)
bdrv_dirty_bitmap_skip_store(bm, false); bdrv_dirty_bitmap_skip_store(bm, false);
} }
ret = refresh_total_sectors(bs, bs->total_sectors); ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) { if (ret < 0) {
bs->open_flags |= BDRV_O_INACTIVE; bs->open_flags |= BDRV_O_INACTIVE;
error_setg_errno(errp, -ret, "Could not refresh total sector count"); error_setg_errno(errp, -ret, "Could not refresh total sector count");
@ -6782,7 +6798,7 @@ out:
/** /**
* Return TRUE if the media is present * Return TRUE if the media is present
*/ */
bool bdrv_is_inserted(BlockDriverState *bs) bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
BdrvChild *child; BdrvChild *child;
@ -6791,11 +6807,11 @@ bool bdrv_is_inserted(BlockDriverState *bs)
if (!drv) { if (!drv) {
return false; return false;
} }
if (drv->bdrv_is_inserted) { if (drv->bdrv_co_is_inserted) {
return drv->bdrv_is_inserted(bs); return drv->bdrv_co_is_inserted(bs);
} }
QLIST_FOREACH(child, &bs->children, next) { QLIST_FOREACH(child, &bs->children, next) {
if (!bdrv_is_inserted(child->bs)) { if (!bdrv_co_is_inserted(child->bs)) {
return false; return false;
} }
} }
@ -6805,13 +6821,13 @@ bool bdrv_is_inserted(BlockDriverState *bs)
/** /**
* If eject_flag is TRUE, eject the media. Otherwise, close the tray * If eject_flag is TRUE, eject the media. Otherwise, close the tray
*/ */
void bdrv_eject(BlockDriverState *bs, bool eject_flag) void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
if (drv && drv->bdrv_eject) { if (drv && drv->bdrv_co_eject) {
drv->bdrv_eject(bs, eject_flag); drv->bdrv_co_eject(bs, eject_flag);
} }
} }
@ -6819,14 +6835,14 @@ void bdrv_eject(BlockDriverState *bs, bool eject_flag)
* Lock or unlock the media (if it is locked, the user won't be able * Lock or unlock the media (if it is locked, the user won't be able
* to eject it manually). * to eject it manually).
*/ */
void bdrv_lock_medium(BlockDriverState *bs, bool locked) void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
trace_bdrv_lock_medium(bs, locked); trace_bdrv_lock_medium(bs, locked);
if (drv && drv->bdrv_lock_medium) { if (drv && drv->bdrv_co_lock_medium) {
drv->bdrv_lock_medium(bs, locked); drv->bdrv_co_lock_medium(bs, locked);
} }
} }
@ -7178,12 +7194,6 @@ void coroutine_fn bdrv_co_unlock(BlockDriverState *bs)
} }
} }
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
{
IO_CODE();
aio_co_enter(bdrv_get_aio_context(bs), co);
}
static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban) static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
{ {
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();

View File

@ -836,7 +836,8 @@ static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
} }
} }
static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event) static void coroutine_fn
blkdebug_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
{ {
BDRVBlkdebugState *s = bs->opaque; BDRVBlkdebugState *s = bs->opaque;
struct BlkdebugRule *rule, *next; struct BlkdebugRule *rule, *next;
@ -966,9 +967,9 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
return false; return false;
} }
static int64_t blkdebug_getlength(BlockDriverState *bs) static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static void blkdebug_refresh_filename(BlockDriverState *bs) static void blkdebug_refresh_filename(BlockDriverState *bs)
@ -1075,7 +1076,7 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_reopen_prepare = blkdebug_reopen_prepare, .bdrv_reopen_prepare = blkdebug_reopen_prepare,
.bdrv_child_perm = blkdebug_child_perm, .bdrv_child_perm = blkdebug_child_perm,
.bdrv_getlength = blkdebug_getlength, .bdrv_co_getlength = blkdebug_co_getlength,
.bdrv_refresh_filename = blkdebug_refresh_filename, .bdrv_refresh_filename = blkdebug_refresh_filename,
.bdrv_refresh_limits = blkdebug_refresh_limits, .bdrv_refresh_limits = blkdebug_refresh_limits,
@ -1086,7 +1087,7 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_co_pdiscard = blkdebug_co_pdiscard, .bdrv_co_pdiscard = blkdebug_co_pdiscard,
.bdrv_co_block_status = blkdebug_co_block_status, .bdrv_co_block_status = blkdebug_co_block_status,
.bdrv_debug_event = blkdebug_debug_event, .bdrv_co_debug_event = blkdebug_co_debug_event,
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint, .bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
.bdrv_debug_remove_breakpoint .bdrv_debug_remove_breakpoint
= blkdebug_debug_remove_breakpoint, = blkdebug_debug_remove_breakpoint,

View File

@ -479,7 +479,7 @@ static int coroutine_fn blkio_co_pwrite_zeroes(BlockDriverState *bs,
return cod.ret; return cod.ret;
} }
static void blkio_io_unplug(BlockDriverState *bs) static void coroutine_fn blkio_co_io_unplug(BlockDriverState *bs)
{ {
BDRVBlkioState *s = bs->opaque; BDRVBlkioState *s = bs->opaque;
@ -839,7 +839,7 @@ static void blkio_close(BlockDriverState *bs)
} }
} }
static int64_t blkio_getlength(BlockDriverState *bs) static int64_t coroutine_fn blkio_co_getlength(BlockDriverState *bs)
{ {
BDRVBlkioState *s = bs->opaque; BDRVBlkioState *s = bs->opaque;
uint64_t capacity; uint64_t capacity;
@ -867,7 +867,7 @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
return -ENOTSUP; return -ENOTSUP;
} }
current_length = blkio_getlength(bs); current_length = blkio_co_getlength(bs);
if (offset > current_length) { if (offset > current_length) {
error_setg(errp, "Cannot grow device"); error_setg(errp, "Cannot grow device");
@ -880,7 +880,8 @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
return 0; return 0;
} }
static int blkio_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
blkio_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
return 0; return 0;
} }
@ -998,9 +999,9 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
.instance_size = sizeof(BDRVBlkioState), \ .instance_size = sizeof(BDRVBlkioState), \
.bdrv_file_open = blkio_file_open, \ .bdrv_file_open = blkio_file_open, \
.bdrv_close = blkio_close, \ .bdrv_close = blkio_close, \
.bdrv_getlength = blkio_getlength, \ .bdrv_co_getlength = blkio_co_getlength, \
.bdrv_co_truncate = blkio_truncate, \ .bdrv_co_truncate = blkio_truncate, \
.bdrv_get_info = blkio_get_info, \ .bdrv_co_get_info = blkio_co_get_info, \
.bdrv_attach_aio_context = blkio_attach_aio_context, \ .bdrv_attach_aio_context = blkio_attach_aio_context, \
.bdrv_detach_aio_context = blkio_detach_aio_context, \ .bdrv_detach_aio_context = blkio_detach_aio_context, \
.bdrv_co_pdiscard = blkio_co_pdiscard, \ .bdrv_co_pdiscard = blkio_co_pdiscard, \
@ -1008,7 +1009,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
.bdrv_co_pwritev = blkio_co_pwritev, \ .bdrv_co_pwritev = blkio_co_pwritev, \
.bdrv_co_flush_to_disk = blkio_co_flush, \ .bdrv_co_flush_to_disk = blkio_co_flush, \
.bdrv_co_pwrite_zeroes = blkio_co_pwrite_zeroes, \ .bdrv_co_pwrite_zeroes = blkio_co_pwrite_zeroes, \
.bdrv_io_unplug = blkio_io_unplug, \ .bdrv_co_io_unplug = blkio_co_io_unplug, \
.bdrv_refresh_limits = blkio_refresh_limits, \ .bdrv_refresh_limits = blkio_refresh_limits, \
.bdrv_register_buf = blkio_register_buf, \ .bdrv_register_buf = blkio_register_buf, \
.bdrv_unregister_buf = blkio_unregister_buf, \ .bdrv_unregister_buf = blkio_unregister_buf, \

View File

@ -267,9 +267,9 @@ static void blk_log_writes_close(BlockDriverState *bs)
s->log_file = NULL; s->log_file = NULL;
} }
static int64_t blk_log_writes_getlength(BlockDriverState *bs) static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
@ -498,7 +498,7 @@ static BlockDriver bdrv_blk_log_writes = {
.bdrv_open = blk_log_writes_open, .bdrv_open = blk_log_writes_open,
.bdrv_close = blk_log_writes_close, .bdrv_close = blk_log_writes_close,
.bdrv_getlength = blk_log_writes_getlength, .bdrv_co_getlength = blk_log_writes_co_getlength,
.bdrv_child_perm = blk_log_writes_child_perm, .bdrv_child_perm = blk_log_writes_child_perm,
.bdrv_refresh_limits = blk_log_writes_refresh_limits, .bdrv_refresh_limits = blk_log_writes_refresh_limits,

View File

@ -40,9 +40,9 @@ fail:
return ret; return ret;
} }
static int64_t blkreplay_getlength(BlockDriverState *bs) static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
/* This bh is used for synchronization of return from coroutines. /* This bh is used for synchronization of return from coroutines.
@ -136,7 +136,7 @@ static BlockDriver bdrv_blkreplay = {
.bdrv_open = blkreplay_open, .bdrv_open = blkreplay_open,
.bdrv_child_perm = bdrv_default_perms, .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = blkreplay_getlength, .bdrv_co_getlength = blkreplay_co_getlength,
.bdrv_co_preadv = blkreplay_co_preadv, .bdrv_co_preadv = blkreplay_co_preadv,
.bdrv_co_pwritev = blkreplay_co_pwritev, .bdrv_co_pwritev = blkreplay_co_pwritev,

View File

@ -155,11 +155,11 @@ static void blkverify_close(BlockDriverState *bs)
s->test_file = NULL; s->test_file = NULL;
} }
static int64_t blkverify_getlength(BlockDriverState *bs) static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
{ {
BDRVBlkverifyState *s = bs->opaque; BDRVBlkverifyState *s = bs->opaque;
return bdrv_getlength(s->test_file->bs); return bdrv_co_getlength(s->test_file->bs);
} }
static void coroutine_fn blkverify_do_test_req(void *opaque) static void coroutine_fn blkverify_do_test_req(void *opaque)
@ -314,7 +314,7 @@ static BlockDriver bdrv_blkverify = {
.bdrv_file_open = blkverify_open, .bdrv_file_open = blkverify_open,
.bdrv_close = blkverify_close, .bdrv_close = blkverify_close,
.bdrv_child_perm = bdrv_default_perms, .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = blkverify_getlength, .bdrv_co_getlength = blkverify_co_getlength,
.bdrv_refresh_filename = blkverify_refresh_filename, .bdrv_refresh_filename = blkverify_refresh_filename,
.bdrv_dirname = blkverify_dirname, .bdrv_dirname = blkverify_dirname,

View File

@ -1235,8 +1235,8 @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
blk->disable_request_queuing = disable; blk->disable_request_queuing = disable;
} }
static int blk_check_byte_request(BlockBackend *blk, int64_t offset, static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
int64_t bytes) int64_t offset, int64_t bytes)
{ {
int64_t len; int64_t len;
@ -1253,7 +1253,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
} }
if (!blk->allow_write_beyond_eof) { if (!blk->allow_write_beyond_eof) {
len = blk_getlength(blk); len = bdrv_co_getlength(blk_bs(blk));
if (len < 0) { if (len < 0) {
return len; return len;
} }
@ -1555,7 +1555,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
acb->has_returned = false; acb->has_returned = false;
co = qemu_coroutine_create(co_entry, acb); co = qemu_coroutine_create(co_entry, acb);
bdrv_coroutine_enter(blk_bs(blk), co); aio_co_enter(blk_get_aio_context(blk), co);
acb->has_returned = true; acb->has_returned = true;
if (acb->rwco.ret != NOT_DONE) { if (acb->rwco.ret != NOT_DONE) {
@ -1599,14 +1599,15 @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
flags | BDRV_REQ_ZERO_WRITE, cb, opaque); flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
} }
int64_t blk_getlength(BlockBackend *blk) int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
{ {
IO_CODE(); IO_CODE();
if (!blk_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
return bdrv_getlength(blk_bs(blk)); return bdrv_co_getlength(blk_bs(blk));
} }
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr) void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
@ -1619,14 +1620,15 @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
} }
} }
int64_t blk_nb_sectors(BlockBackend *blk) int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
{ {
IO_CODE(); IO_CODE();
if (!blk_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
return bdrv_nb_sectors(blk_bs(blk)); return bdrv_co_nb_sectors(blk_bs(blk));
} }
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
@ -1983,12 +1985,12 @@ void blk_activate(BlockBackend *blk, Error **errp)
bdrv_activate(bs, errp); bdrv_activate(bs, errp);
} }
bool blk_is_inserted(BlockBackend *blk) bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
return bs && bdrv_is_inserted(bs); return bs && bdrv_co_is_inserted(bs);
} }
bool blk_is_available(BlockBackend *blk) bool blk_is_available(BlockBackend *blk)
@ -1997,24 +1999,24 @@ bool blk_is_available(BlockBackend *blk)
return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk); return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
} }
void blk_lock_medium(BlockBackend *blk, bool locked) void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
if (bs) { if (bs) {
bdrv_lock_medium(bs, locked); bdrv_co_lock_medium(bs, locked);
} }
} }
void blk_eject(BlockBackend *blk, bool eject_flag) void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
char *id; char *id;
IO_CODE(); IO_CODE();
if (bs) { if (bs) {
bdrv_eject(bs, eject_flag); bdrv_co_eject(bs, eject_flag);
} }
/* Whether or not we ejected on the backend, /* Whether or not we ejected on the backend,
@ -2315,23 +2317,23 @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
notifier_list_add(&blk->insert_bs_notifiers, notify); notifier_list_add(&blk->insert_bs_notifiers, notify);
} }
void blk_io_plug(BlockBackend *blk) void coroutine_fn blk_co_io_plug(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
if (bs) { if (bs) {
bdrv_io_plug(bs); bdrv_co_io_plug(bs);
} }
} }
void blk_io_unplug(BlockBackend *blk) void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
if (bs) { if (bs) {
bdrv_io_unplug(bs); bdrv_co_io_unplug(bs);
} }
} }

View File

@ -123,13 +123,13 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
QEMU_AUTO_VFREE void *buf = NULL; QEMU_AUTO_VFREE void *buf = NULL;
int64_t len, base_len; int64_t len, base_len;
len = blk_getlength(s->top); len = blk_co_getlength(s->top);
if (len < 0) { if (len < 0) {
return len; return len;
} }
job_progress_set_remaining(&s->common.job, len); job_progress_set_remaining(&s->common.job, len);
base_len = blk_getlength(s->base); base_len = blk_co_getlength(s->base);
if (base_len < 0) { if (base_len < 0) {
return base_len; return base_len;
} }

View File

@ -121,9 +121,9 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
} }
static int64_t cor_getlength(BlockDriverState *bs) static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
@ -217,15 +217,15 @@ static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
} }
static void cor_eject(BlockDriverState *bs, bool eject_flag) static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
bdrv_eject(bs->file->bs, eject_flag); bdrv_co_eject(bs->file->bs, eject_flag);
} }
static void cor_lock_medium(BlockDriverState *bs, bool locked) static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
bdrv_lock_medium(bs->file->bs, locked); bdrv_co_lock_medium(bs->file->bs, locked);
} }
@ -250,7 +250,7 @@ static BlockDriver bdrv_copy_on_read = {
.bdrv_close = cor_close, .bdrv_close = cor_close,
.bdrv_child_perm = cor_child_perm, .bdrv_child_perm = cor_child_perm,
.bdrv_getlength = cor_getlength, .bdrv_co_getlength = cor_co_getlength,
.bdrv_co_preadv_part = cor_co_preadv_part, .bdrv_co_preadv_part = cor_co_preadv_part,
.bdrv_co_pwritev_part = cor_co_pwritev_part, .bdrv_co_pwritev_part = cor_co_pwritev_part,
@ -258,8 +258,8 @@ static BlockDriver bdrv_copy_on_read = {
.bdrv_co_pdiscard = cor_co_pdiscard, .bdrv_co_pdiscard = cor_co_pdiscard,
.bdrv_co_pwritev_compressed = cor_co_pwritev_compressed, .bdrv_co_pwritev_compressed = cor_co_pwritev_compressed,
.bdrv_eject = cor_eject, .bdrv_co_eject = cor_co_eject,
.bdrv_lock_medium = cor_lock_medium, .bdrv_co_lock_medium = cor_co_lock_medium,
.has_variable_length = true, .has_variable_length = true,
.is_filter = true, .is_filter = true,

View File

@ -531,10 +531,10 @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
} }
static int64_t block_crypto_getlength(BlockDriverState *bs) static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
{ {
BlockCrypto *crypto = bs->opaque; BlockCrypto *crypto = bs->opaque;
int64_t len = bdrv_getlength(bs->file->bs); int64_t len = bdrv_co_getlength(bs->file->bs);
uint64_t offset = qcrypto_block_get_payload_offset(crypto->block); uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
assert(offset < INT64_MAX); assert(offset < INT64_MAX);
@ -737,13 +737,13 @@ fail:
return ret; return ret;
} }
static int block_crypto_get_info_luks(BlockDriverState *bs, static int coroutine_fn
BlockDriverInfo *bdi) block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BlockDriverInfo subbdi; BlockDriverInfo subbdi;
int ret; int ret;
ret = bdrv_get_info(bs->file->bs, &subbdi); ret = bdrv_co_get_info(bs->file->bs, &subbdi);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
@ -953,9 +953,9 @@ static BlockDriver bdrv_crypto_luks = {
.bdrv_refresh_limits = block_crypto_refresh_limits, .bdrv_refresh_limits = block_crypto_refresh_limits,
.bdrv_co_preadv = block_crypto_co_preadv, .bdrv_co_preadv = block_crypto_co_preadv,
.bdrv_co_pwritev = block_crypto_co_pwritev, .bdrv_co_pwritev = block_crypto_co_pwritev,
.bdrv_getlength = block_crypto_getlength, .bdrv_co_getlength = block_crypto_co_getlength,
.bdrv_measure = block_crypto_measure, .bdrv_measure = block_crypto_measure,
.bdrv_get_info = block_crypto_get_info_luks, .bdrv_co_get_info = block_crypto_co_get_info_luks,
.bdrv_get_specific_info = block_crypto_get_specific_info_luks, .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
.bdrv_amend_options = block_crypto_amend_options_luks, .bdrv_amend_options = block_crypto_amend_options_luks,
.bdrv_co_amend = block_crypto_co_amend_luks, .bdrv_co_amend = block_crypto_co_amend_luks,

View File

@ -958,7 +958,7 @@ static void curl_close(BlockDriverState *bs)
g_free(s->proxypassword); g_free(s->proxypassword);
} }
static int64_t curl_getlength(BlockDriverState *bs) static int64_t coroutine_fn curl_co_getlength(BlockDriverState *bs)
{ {
BDRVCURLState *s = bs->opaque; BDRVCURLState *s = bs->opaque;
return s->len; return s->len;
@ -1002,7 +1002,7 @@ static BlockDriver bdrv_http = {
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_file_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_getlength = curl_getlength, .bdrv_co_getlength = curl_co_getlength,
.bdrv_co_preadv = curl_co_preadv, .bdrv_co_preadv = curl_co_preadv,
@ -1021,7 +1021,7 @@ static BlockDriver bdrv_https = {
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_file_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_getlength = curl_getlength, .bdrv_co_getlength = curl_co_getlength,
.bdrv_co_preadv = curl_co_preadv, .bdrv_co_preadv = curl_co_preadv,
@ -1040,7 +1040,7 @@ static BlockDriver bdrv_ftp = {
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_file_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_getlength = curl_getlength, .bdrv_co_getlength = curl_co_getlength,
.bdrv_co_preadv = curl_co_preadv, .bdrv_co_preadv = curl_co_preadv,
@ -1059,7 +1059,7 @@ static BlockDriver bdrv_ftps = {
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_file_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_getlength = curl_getlength, .bdrv_co_getlength = curl_co_getlength,
.bdrv_co_preadv = curl_co_preadv, .bdrv_co_preadv = curl_co_preadv,

View File

@ -189,7 +189,7 @@ static int fd_open(BlockDriverState *bs)
return -EIO; return -EIO;
} }
static int64_t raw_getlength(BlockDriverState *bs); static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs);
typedef struct RawPosixAIOData { typedef struct RawPosixAIOData {
BlockDriverState *bs; BlockDriverState *bs;
@ -2132,7 +2132,7 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE); return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE);
} }
static void raw_aio_plug(BlockDriverState *bs) static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
{ {
BDRVRawState __attribute__((unused)) *s = bs->opaque; BDRVRawState __attribute__((unused)) *s = bs->opaque;
#ifdef CONFIG_LINUX_AIO #ifdef CONFIG_LINUX_AIO
@ -2149,7 +2149,7 @@ static void raw_aio_plug(BlockDriverState *bs)
#endif #endif
} }
static void raw_aio_unplug(BlockDriverState *bs) static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
{ {
BDRVRawState __attribute__((unused)) *s = bs->opaque; BDRVRawState __attribute__((unused)) *s = bs->opaque;
#ifdef CONFIG_LINUX_AIO #ifdef CONFIG_LINUX_AIO
@ -2280,7 +2280,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
} }
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
int64_t cur_length = raw_getlength(bs); int64_t cur_length = raw_co_getlength(bs);
if (offset != cur_length && exact) { if (offset != cur_length && exact) {
error_setg(errp, "Cannot resize device files"); error_setg(errp, "Cannot resize device files");
@ -2298,7 +2298,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
} }
#ifdef __OpenBSD__ #ifdef __OpenBSD__
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int fd = s->fd; int fd = s->fd;
@ -2317,7 +2317,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
return st.st_size; return st.st_size;
} }
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int fd = s->fd; int fd = s->fd;
@ -2342,7 +2342,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
return st.st_size; return st.st_size;
} }
#elif defined(__sun__) #elif defined(__sun__)
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
struct dk_minfo minfo; struct dk_minfo minfo;
@ -2373,7 +2373,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
return size; return size;
} }
#elif defined(CONFIG_BSD) #elif defined(CONFIG_BSD)
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int fd = s->fd; int fd = s->fd;
@ -2445,7 +2445,7 @@ again:
return size; return size;
} }
#else #else
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int ret; int ret;
@ -2464,7 +2464,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
} }
#endif #endif
static int64_t raw_get_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
{ {
struct stat st; struct stat st;
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -2830,7 +2830,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
* round up if necessary. * round up if necessary.
*/ */
if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
int64_t file_length = raw_getlength(bs); int64_t file_length = raw_co_getlength(bs);
if (file_length > 0) { if (file_length > 0) {
/* Ignore errors, this is just a safeguard */ /* Ignore errors, this is just a safeguard */
assert(hole == file_length); assert(hole == file_length);
@ -2852,7 +2852,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
#if defined(__linux__) #if defined(__linux__)
/* Verify that the file is not in the page cache */ /* Verify that the file is not in the page cache */
static void check_cache_dropped(BlockDriverState *bs, Error **errp) static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
{ {
const size_t window_size = 128 * 1024 * 1024; const size_t window_size = 128 * 1024 * 1024;
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -2867,7 +2867,7 @@ static void check_cache_dropped(BlockDriverState *bs, Error **errp)
page_size = sysconf(_SC_PAGESIZE); page_size = sysconf(_SC_PAGESIZE);
vec = g_malloc(DIV_ROUND_UP(window_size, page_size)); vec = g_malloc(DIV_ROUND_UP(window_size, page_size));
end = raw_getlength(bs); end = raw_co_getlength(bs);
for (offset = 0; offset < end; offset += window_size) { for (offset = 0; offset < end; offset += window_size) {
void *new_window; void *new_window;
@ -3086,11 +3086,40 @@ static int coroutine_fn raw_co_pwrite_zeroes(
return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false); return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false);
} }
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
return 0; return 0;
} }
static ImageInfoSpecific *raw_get_specific_info(BlockDriverState *bs,
Error **errp)
{
ImageInfoSpecificFile *file_info = g_new0(ImageInfoSpecificFile, 1);
ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
*spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_FILE,
.u.file.data = file_info,
};
#ifdef FS_IOC_FSGETXATTR
{
BDRVRawState *s = bs->opaque;
struct fsxattr attr;
int ret;
ret = ioctl(s->fd, FS_IOC_FSGETXATTR, &attr);
if (!ret && attr.fsx_extsize != 0) {
file_info->has_extent_size_hint = true;
file_info->extent_size_hint = attr.fsx_extsize;
}
}
#endif
return spec_info;
}
static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs) static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -3317,15 +3346,15 @@ BlockDriver bdrv_file = {
.bdrv_co_copy_range_from = raw_co_copy_range_from, .bdrv_co_copy_range_from = raw_co_copy_range_from,
.bdrv_co_copy_range_to = raw_co_copy_range_to, .bdrv_co_copy_range_to = raw_co_copy_range_to,
.bdrv_refresh_limits = raw_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_io_unplug = raw_aio_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.bdrv_get_info = raw_get_info, .bdrv_co_get_info = raw_co_get_info,
.bdrv_get_allocated_file_size .bdrv_get_specific_info = raw_get_specific_info,
= raw_get_allocated_file_size, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
.bdrv_get_specific_stats = raw_get_specific_stats, .bdrv_get_specific_stats = raw_get_specific_stats,
.bdrv_check_perm = raw_check_perm, .bdrv_check_perm = raw_check_perm,
.bdrv_set_perm = raw_set_perm, .bdrv_set_perm = raw_set_perm,
@ -3689,15 +3718,15 @@ static BlockDriver bdrv_host_device = {
.bdrv_co_copy_range_from = raw_co_copy_range_from, .bdrv_co_copy_range_from = raw_co_copy_range_from,
.bdrv_co_copy_range_to = raw_co_copy_range_to, .bdrv_co_copy_range_to = raw_co_copy_range_to,
.bdrv_refresh_limits = raw_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_io_unplug = raw_aio_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.bdrv_get_info = raw_get_info, .bdrv_co_get_info = raw_co_get_info,
.bdrv_get_allocated_file_size .bdrv_get_specific_info = raw_get_specific_info,
= raw_get_allocated_file_size, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
.bdrv_get_specific_stats = hdev_get_specific_stats, .bdrv_get_specific_stats = hdev_get_specific_stats,
.bdrv_check_perm = raw_check_perm, .bdrv_check_perm = raw_check_perm,
.bdrv_set_perm = raw_set_perm, .bdrv_set_perm = raw_set_perm,
@ -3757,7 +3786,7 @@ out:
return prio; return prio;
} }
static bool cdrom_is_inserted(BlockDriverState *bs) static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int ret; int ret;
@ -3766,7 +3795,7 @@ static bool cdrom_is_inserted(BlockDriverState *bs)
return ret == CDS_DISC_OK; return ret == CDS_DISC_OK;
} }
static void cdrom_eject(BlockDriverState *bs, bool eject_flag) static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -3779,7 +3808,7 @@ static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
} }
} }
static void cdrom_lock_medium(BlockDriverState *bs, bool locked) static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -3813,20 +3842,19 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk, .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_refresh_limits = raw_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_io_unplug = raw_aio_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true, .has_variable_length = true,
.bdrv_get_allocated_file_size .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
= raw_get_allocated_file_size,
/* removable device support */ /* removable device support */
.bdrv_is_inserted = cdrom_is_inserted, .bdrv_co_is_inserted = cdrom_co_is_inserted,
.bdrv_eject = cdrom_eject, .bdrv_co_eject = cdrom_co_eject,
.bdrv_lock_medium = cdrom_lock_medium, .bdrv_co_lock_medium = cdrom_co_lock_medium,
/* generic scsi device */ /* generic scsi device */
.bdrv_co_ioctl = hdev_co_ioctl, .bdrv_co_ioctl = hdev_co_ioctl,
@ -3883,12 +3911,12 @@ static int cdrom_reopen(BlockDriverState *bs)
return 0; return 0;
} }
static bool cdrom_is_inserted(BlockDriverState *bs) static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
{ {
return raw_getlength(bs) > 0; return raw_co_getlength(bs) > 0;
} }
static void cdrom_eject(BlockDriverState *bs, bool eject_flag) static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -3908,7 +3936,7 @@ static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
cdrom_reopen(bs); cdrom_reopen(bs);
} }
static void cdrom_lock_medium(BlockDriverState *bs, bool locked) static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
@ -3943,20 +3971,19 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk, .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_refresh_limits = raw_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_io_unplug = raw_aio_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true, .has_variable_length = true,
.bdrv_get_allocated_file_size .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
= raw_get_allocated_file_size,
/* removable device support */ /* removable device support */
.bdrv_is_inserted = cdrom_is_inserted, .bdrv_co_is_inserted = cdrom_co_is_inserted,
.bdrv_eject = cdrom_eject, .bdrv_co_eject = cdrom_co_eject,
.bdrv_lock_medium = cdrom_lock_medium, .bdrv_co_lock_medium = cdrom_co_lock_medium,
}; };
#endif /* __FreeBSD__ */ #endif /* __FreeBSD__ */

View File

@ -526,7 +526,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
return 0; return 0;
} }
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
LARGE_INTEGER l; LARGE_INTEGER l;
@ -559,7 +559,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
return l.QuadPart; return l.QuadPart;
} }
static int64_t raw_get_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
{ {
typedef DWORD (WINAPI * get_compressed_t)(const char *filename, typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
DWORD * high); DWORD * high);
@ -764,9 +764,9 @@ BlockDriver bdrv_file = {
.bdrv_aio_flush = raw_aio_flush, .bdrv_aio_flush = raw_aio_flush,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.bdrv_get_allocated_file_size .bdrv_co_get_allocated_file_size
= raw_get_allocated_file_size, = raw_co_get_allocated_file_size,
.create_opts = &raw_create_opts, .create_opts = &raw_create_opts,
}; };
@ -933,11 +933,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_detach_aio_context = raw_detach_aio_context, .bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context, .bdrv_attach_aio_context = raw_attach_aio_context,
.bdrv_getlength = raw_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true, .has_variable_length = true,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
}; };
static void bdrv_file_init(void) static void bdrv_file_init(void)

View File

@ -55,9 +55,9 @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
} }
static int64_t compress_getlength(BlockDriverState *bs) static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
@ -117,15 +117,17 @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
} }
static void compress_eject(BlockDriverState *bs, bool eject_flag) static void coroutine_fn
compress_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
bdrv_eject(bs->file->bs, eject_flag); bdrv_co_eject(bs->file->bs, eject_flag);
} }
static void compress_lock_medium(BlockDriverState *bs, bool locked) static void coroutine_fn
compress_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
bdrv_lock_medium(bs->file->bs, locked); bdrv_co_lock_medium(bs->file->bs, locked);
} }
@ -135,7 +137,7 @@ static BlockDriver bdrv_compress = {
.bdrv_open = compress_open, .bdrv_open = compress_open,
.bdrv_child_perm = bdrv_default_perms, .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = compress_getlength, .bdrv_co_getlength = compress_co_getlength,
.bdrv_co_preadv_part = compress_co_preadv_part, .bdrv_co_preadv_part = compress_co_preadv_part,
.bdrv_co_pwritev_part = compress_co_pwritev_part, .bdrv_co_pwritev_part = compress_co_pwritev_part,
@ -143,8 +145,8 @@ static BlockDriver bdrv_compress = {
.bdrv_co_pdiscard = compress_co_pdiscard, .bdrv_co_pdiscard = compress_co_pdiscard,
.bdrv_refresh_limits = compress_refresh_limits, .bdrv_refresh_limits = compress_refresh_limits,
.bdrv_eject = compress_eject, .bdrv_co_eject = compress_co_eject,
.bdrv_lock_medium = compress_lock_medium, .bdrv_co_lock_medium = compress_co_lock_medium,
.has_variable_length = true, .has_variable_length = true,
.is_filter = true, .is_filter = true,

View File

@ -1318,7 +1318,7 @@ static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
} }
#endif #endif
static int64_t qemu_gluster_getlength(BlockDriverState *bs) static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
{ {
BDRVGlusterState *s = bs->opaque; BDRVGlusterState *s = bs->opaque;
int64_t ret; int64_t ret;
@ -1331,7 +1331,8 @@ static int64_t qemu_gluster_getlength(BlockDriverState *bs)
} }
} }
static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn
qemu_gluster_co_get_allocated_file_size(BlockDriverState *bs)
{ {
BDRVGlusterState *s = bs->opaque; BDRVGlusterState *s = bs->opaque;
struct stat st; struct stat st;
@ -1510,7 +1511,7 @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
* round up if necessary. * round up if necessary.
*/ */
if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
int64_t file_length = qemu_gluster_getlength(bs); int64_t file_length = qemu_gluster_co_getlength(bs);
if (file_length > 0) { if (file_length > 0) {
/* Ignore errors, this is just a safeguard */ /* Ignore errors, this is just a safeguard */
assert(hole == file_length); assert(hole == file_length);
@ -1559,8 +1560,8 @@ static BlockDriver bdrv_gluster = {
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_co_create = qemu_gluster_co_create, .bdrv_co_create = qemu_gluster_co_create,
.bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_co_create_opts = qemu_gluster_co_create_opts,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_co_getlength = qemu_gluster_co_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
.bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_truncate = qemu_gluster_co_truncate,
.bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_readv = qemu_gluster_co_readv,
.bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_writev = qemu_gluster_co_writev,
@ -1588,8 +1589,8 @@ static BlockDriver bdrv_gluster_tcp = {
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_co_create = qemu_gluster_co_create, .bdrv_co_create = qemu_gluster_co_create,
.bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_co_create_opts = qemu_gluster_co_create_opts,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_co_getlength = qemu_gluster_co_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
.bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_truncate = qemu_gluster_co_truncate,
.bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_readv = qemu_gluster_co_readv,
.bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_writev = qemu_gluster_co_writev,
@ -1617,8 +1618,8 @@ static BlockDriver bdrv_gluster_unix = {
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_co_create = qemu_gluster_co_create, .bdrv_co_create = qemu_gluster_co_create,
.bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_co_create_opts = qemu_gluster_co_create_opts,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_co_getlength = qemu_gluster_co_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
.bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_truncate = qemu_gluster_co_truncate,
.bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_readv = qemu_gluster_co_readv,
.bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_writev = qemu_gluster_co_writev,
@ -1652,8 +1653,8 @@ static BlockDriver bdrv_gluster_rdma = {
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_co_create = qemu_gluster_co_create, .bdrv_co_create = qemu_gluster_co_create,
.bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_co_create_opts = qemu_gluster_co_create_opts,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_co_getlength = qemu_gluster_co_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
.bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_truncate = qemu_gluster_co_truncate,
.bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_readv = qemu_gluster_co_readv,
.bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_writev = qemu_gluster_co_writev,

View File

@ -722,14 +722,14 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
/** /**
* Round a region to cluster boundaries * Round a region to cluster boundaries
*/ */
void bdrv_round_to_clusters(BlockDriverState *bs, void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *cluster_offset, int64_t *cluster_offset,
int64_t *cluster_bytes) int64_t *cluster_bytes)
{ {
BlockDriverInfo bdi; BlockDriverInfo bdi;
IO_CODE(); IO_CODE();
if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) { if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
*cluster_offset = offset; *cluster_offset = offset;
*cluster_bytes = bytes; *cluster_bytes = bytes;
} else { } else {
@ -739,12 +739,12 @@ void bdrv_round_to_clusters(BlockDriverState *bs,
} }
} }
static int bdrv_get_cluster_size(BlockDriverState *bs) static coroutine_fn int bdrv_get_cluster_size(BlockDriverState *bs)
{ {
BlockDriverInfo bdi; BlockDriverInfo bdi;
int ret; int ret;
ret = bdrv_get_info(bs, &bdi); ret = bdrv_co_get_info(bs, &bdi);
if (ret < 0 || bdi.cluster_size == 0) { if (ret < 0 || bdi.cluster_size == 0) {
return bs->bl.request_alignment; return bs->bl.request_alignment;
} else { } else {
@ -1251,7 +1251,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
goto err; goto err;
} }
bdrv_debug_event(bs, BLKDBG_COR_WRITE); bdrv_co_debug_event(bs, BLKDBG_COR_WRITE);
if (drv->bdrv_co_pwrite_zeroes && if (drv->bdrv_co_pwrite_zeroes &&
buffer_is_zero(bounce_buffer, pnum)) { buffer_is_zero(bounce_buffer, pnum)) {
/* FIXME: Should we (perhaps conditionally) be setting /* FIXME: Should we (perhaps conditionally) be setting
@ -1496,10 +1496,10 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
if (pad->head) { if (pad->head) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
} }
if (pad->merge_reads && pad->tail) { if (pad->merge_reads && pad->tail) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
} }
ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
align, &local_qiov, 0, 0); align, &local_qiov, 0, 0);
@ -1507,10 +1507,10 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
return ret; return ret;
} }
if (pad->head) { if (pad->head) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
} }
if (pad->merge_reads && pad->tail) { if (pad->merge_reads && pad->tail) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
} }
if (pad->merge_reads) { if (pad->merge_reads) {
@ -1521,7 +1521,7 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
if (pad->tail) { if (pad->tail) {
qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align); qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
ret = bdrv_aligned_preadv( ret = bdrv_aligned_preadv(
child, req, child, req,
req->overlap_offset + req->overlap_bytes - align, req->overlap_offset + req->overlap_bytes - align,
@ -1529,7 +1529,7 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
} }
zero_mem: zero_mem:
@ -1622,7 +1622,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
trace_bdrv_co_preadv_part(bs, offset, bytes, flags); trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
if (!bdrv_is_inserted(bs)) { if (!bdrv_co_is_inserted(bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@ -1931,16 +1931,16 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
if (ret < 0) { if (ret < 0) {
/* Do nothing, write notifier decided to fail this request */ /* Do nothing, write notifier decided to fail this request */
} else if (flags & BDRV_REQ_ZERO_WRITE) { } else if (flags & BDRV_REQ_ZERO_WRITE) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_ZERO);
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) { } else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
qiov, qiov_offset); qiov, qiov_offset);
} else if (bytes <= max_transfer) { } else if (bytes <= max_transfer) {
bdrv_debug_event(bs, BLKDBG_PWRITEV); bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags); ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags);
} else { } else {
bdrv_debug_event(bs, BLKDBG_PWRITEV); bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
while (bytes_remaining) { while (bytes_remaining) {
int num = MIN(bytes_remaining, max_transfer); int num = MIN(bytes_remaining, max_transfer);
int local_flags = flags; int local_flags = flags;
@ -1963,7 +1963,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
bytes_remaining -= num; bytes_remaining -= num;
} }
} }
bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE); bdrv_co_debug_event(bs, BLKDBG_PWRITEV_DONE);
if (ret >= 0) { if (ret >= 0) {
ret = 0; ret = 0;
@ -2067,7 +2067,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags); trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
if (!bdrv_is_inserted(bs)) { if (!bdrv_co_is_inserted(bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@ -2720,8 +2720,8 @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
if (drv->bdrv_load_vmstate) { if (drv->bdrv_co_load_vmstate) {
ret = drv->bdrv_load_vmstate(bs, qiov, pos); ret = drv->bdrv_co_load_vmstate(bs, qiov, pos);
} else if (child_bs) { } else if (child_bs) {
ret = bdrv_co_readv_vmstate(child_bs, qiov, pos); ret = bdrv_co_readv_vmstate(child_bs, qiov, pos);
} else { } else {
@ -2753,8 +2753,8 @@ bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
if (drv->bdrv_save_vmstate) { if (drv->bdrv_co_save_vmstate) {
ret = drv->bdrv_save_vmstate(bs, qiov, pos); ret = drv->bdrv_co_save_vmstate(bs, qiov, pos);
} else if (child_bs) { } else if (child_bs) {
ret = bdrv_co_writev_vmstate(child_bs, qiov, pos); ret = bdrv_co_writev_vmstate(child_bs, qiov, pos);
} else { } else {
@ -2835,7 +2835,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs) || if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
bdrv_is_sg(bs)) { bdrv_is_sg(bs)) {
goto early_exit; goto early_exit;
} }
@ -2959,7 +2959,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
IO_CODE(); IO_CODE();
if (!bs || !bs->drv || !bdrv_is_inserted(bs)) { if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@ -3137,24 +3137,24 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
return mem; return mem;
} }
void bdrv_io_plug(BlockDriverState *bs) void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
{ {
BdrvChild *child; BdrvChild *child;
IO_CODE(); IO_CODE();
QLIST_FOREACH(child, &bs->children, next) { QLIST_FOREACH(child, &bs->children, next) {
bdrv_io_plug(child->bs); bdrv_co_io_plug(child->bs);
} }
if (qatomic_fetch_inc(&bs->io_plugged) == 0) { if (qatomic_fetch_inc(&bs->io_plugged) == 0) {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
if (drv && drv->bdrv_io_plug) { if (drv && drv->bdrv_co_io_plug) {
drv->bdrv_io_plug(bs); drv->bdrv_co_io_plug(bs);
} }
} }
} }
void bdrv_io_unplug(BlockDriverState *bs) void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
{ {
BdrvChild *child; BdrvChild *child;
IO_CODE(); IO_CODE();
@ -3162,13 +3162,13 @@ void bdrv_io_unplug(BlockDriverState *bs)
assert(bs->io_plugged); assert(bs->io_plugged);
if (qatomic_fetch_dec(&bs->io_plugged) == 1) { if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
if (drv && drv->bdrv_io_unplug) { if (drv && drv->bdrv_co_io_unplug) {
drv->bdrv_io_unplug(bs); drv->bdrv_co_io_unplug(bs);
} }
} }
QLIST_FOREACH(child, &bs->children, next) { QLIST_FOREACH(child, &bs->children, next) {
bdrv_io_unplug(child->bs); bdrv_co_io_unplug(child->bs);
} }
} }
@ -3241,7 +3241,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
assert(!(read_flags & BDRV_REQ_NO_WAIT)); assert(!(read_flags & BDRV_REQ_NO_WAIT));
assert(!(write_flags & BDRV_REQ_NO_WAIT)); assert(!(write_flags & BDRV_REQ_NO_WAIT));
if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) { if (!dst || !dst->bs || !bdrv_co_is_inserted(dst->bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
ret = bdrv_check_request32(dst_offset, bytes, NULL, 0); ret = bdrv_check_request32(dst_offset, bytes, NULL, 0);
@ -3252,7 +3252,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags); return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags);
} }
if (!src || !src->bs || !bdrv_is_inserted(src->bs)) { if (!src || !src->bs || !bdrv_co_is_inserted(src->bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
ret = bdrv_check_request32(src_offset, bytes, NULL, 0); ret = bdrv_check_request32(src_offset, bytes, NULL, 0);
@ -3444,7 +3444,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
if (new_bytes && backing) { if (new_bytes && backing) {
int64_t backing_len; int64_t backing_len;
backing_len = bdrv_getlength(backing->bs); backing_len = bdrv_co_getlength(backing->bs);
if (backing_len < 0) { if (backing_len < 0) {
ret = backing_len; ret = backing_len;
error_setg_errno(errp, -ret, "Could not get backing file size"); error_setg_errno(errp, -ret, "Could not get backing file size");
@ -3474,15 +3474,17 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
goto out; goto out;
} }
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); ret = bdrv_co_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count"); error_setg_errno(errp, -ret, "Could not refresh total sector count");
} else { } else {
offset = bs->total_sectors * BDRV_SECTOR_SIZE; offset = bs->total_sectors * BDRV_SECTOR_SIZE;
} }
/* It's possible that truncation succeeded but refresh_total_sectors /*
* It's possible that truncation succeeded but bdrv_refresh_total_sectors
* failed, but the latter doesn't affect how we should finish the request. * failed, but the latter doesn't affect how we should finish the request.
* Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */ * Pass 0 as the last parameter so that dirty bitmaps etc. are handled.
*/
bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0); bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0);
out: out:

View File

@ -1127,8 +1127,8 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
#endif #endif
static int64_t static int64_t coroutine_fn
iscsi_getlength(BlockDriverState *bs) iscsi_co_getlength(BlockDriverState *bs)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
int64_t len; int64_t len;
@ -2155,7 +2155,7 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
return -EIO; return -EIO;
} }
cur_length = iscsi_getlength(bs); cur_length = iscsi_co_getlength(bs);
if (offset != cur_length && exact) { if (offset != cur_length && exact) {
error_setg(errp, "Cannot resize iSCSI devices"); error_setg(errp, "Cannot resize iSCSI devices");
return -ENOTSUP; return -ENOTSUP;
@ -2171,7 +2171,8 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
return 0; return 0;
} }
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
iscsi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
bdi->cluster_size = iscsilun->cluster_size; bdi->cluster_size = iscsilun->cluster_size;
@ -2434,8 +2435,8 @@ static BlockDriver bdrv_iscsi = {
.bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_reopen_commit = iscsi_reopen_commit,
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
.bdrv_getlength = iscsi_getlength, .bdrv_co_getlength = iscsi_co_getlength,
.bdrv_get_info = iscsi_get_info, .bdrv_co_get_info = iscsi_co_get_info,
.bdrv_co_truncate = iscsi_co_truncate, .bdrv_co_truncate = iscsi_co_truncate,
.bdrv_refresh_limits = iscsi_refresh_limits, .bdrv_refresh_limits = iscsi_refresh_limits,
@ -2473,8 +2474,8 @@ static BlockDriver bdrv_iser = {
.bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_reopen_commit = iscsi_reopen_commit,
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
.bdrv_getlength = iscsi_getlength, .bdrv_co_getlength = iscsi_co_getlength,
.bdrv_get_info = iscsi_get_info, .bdrv_co_get_info = iscsi_co_get_info,
.bdrv_co_truncate = iscsi_co_truncate, .bdrv_co_truncate = iscsi_co_truncate,
.bdrv_refresh_limits = iscsi_refresh_limits, .bdrv_refresh_limits = iscsi_refresh_limits,

View File

@ -139,6 +139,7 @@ block_gen_c = custom_target('block-gen.c',
input: files( input: files(
'../include/block/block-io.h', '../include/block/block-io.h',
'../include/block/dirty-bitmap.h', '../include/block/dirty-bitmap.h',
'../include/block/block_int-io.h',
'../include/block/block-global-state.h', '../include/block/block-global-state.h',
'../include/sysemu/block-backend-io.h', '../include/sysemu/block-backend-io.h',
'coroutines.h' 'coroutines.h'

View File

@ -910,13 +910,13 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
goto immediate_exit; goto immediate_exit;
} }
s->bdev_length = bdrv_getlength(bs); s->bdev_length = bdrv_co_getlength(bs);
if (s->bdev_length < 0) { if (s->bdev_length < 0) {
ret = s->bdev_length; ret = s->bdev_length;
goto immediate_exit; goto immediate_exit;
} }
target_length = blk_getlength(s->target); target_length = blk_co_getlength(s->target);
if (target_length < 0) { if (target_length < 0) {
ret = target_length; ret = target_length;
goto immediate_exit; goto immediate_exit;
@ -957,7 +957,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
*/ */
bdrv_get_backing_filename(target_bs, backing_filename, bdrv_get_backing_filename(target_bs, backing_filename,
sizeof(backing_filename)); sizeof(backing_filename));
if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) { if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) {
s->target_cluster_size = bdi.cluster_size; s->target_cluster_size = bdi.cluster_size;
} else { } else {
s->target_cluster_size = BDRV_SECTOR_SIZE; s->target_cluster_size = BDRV_SECTOR_SIZE;

View File

@ -725,7 +725,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
monitor_printf(mon, "\nImages:\n"); monitor_printf(mon, "\nImages:\n");
image_info = inserted->image; image_info = inserted->image;
while (1) { while (1) {
bdrv_image_info_dump(image_info); bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0, false);
if (image_info->backing_image) { if (image_info->backing_image) {
image_info = image_info->backing_image; image_info = image_info->backing_image;
} else { } else {

View File

@ -1992,7 +1992,7 @@ static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset,
return 0; return 0;
} }
static int64_t nbd_getlength(BlockDriverState *bs) static int64_t coroutine_fn nbd_co_getlength(BlockDriverState *bs)
{ {
BDRVNBDState *s = bs->opaque; BDRVNBDState *s = bs->opaque;
@ -2124,7 +2124,7 @@ static BlockDriver bdrv_nbd = {
.bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_co_pdiscard = nbd_client_co_pdiscard,
.bdrv_refresh_limits = nbd_refresh_limits, .bdrv_refresh_limits = nbd_refresh_limits,
.bdrv_co_truncate = nbd_co_truncate, .bdrv_co_truncate = nbd_co_truncate,
.bdrv_getlength = nbd_getlength, .bdrv_co_getlength = nbd_co_getlength,
.bdrv_refresh_filename = nbd_refresh_filename, .bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status, .bdrv_co_block_status = nbd_client_co_block_status,
.bdrv_dirname = nbd_dirname, .bdrv_dirname = nbd_dirname,
@ -2152,7 +2152,7 @@ static BlockDriver bdrv_nbd_tcp = {
.bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_co_pdiscard = nbd_client_co_pdiscard,
.bdrv_refresh_limits = nbd_refresh_limits, .bdrv_refresh_limits = nbd_refresh_limits,
.bdrv_co_truncate = nbd_co_truncate, .bdrv_co_truncate = nbd_co_truncate,
.bdrv_getlength = nbd_getlength, .bdrv_co_getlength = nbd_co_getlength,
.bdrv_refresh_filename = nbd_refresh_filename, .bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status, .bdrv_co_block_status = nbd_client_co_block_status,
.bdrv_dirname = nbd_dirname, .bdrv_dirname = nbd_dirname,
@ -2180,7 +2180,7 @@ static BlockDriver bdrv_nbd_unix = {
.bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_co_pdiscard = nbd_client_co_pdiscard,
.bdrv_refresh_limits = nbd_refresh_limits, .bdrv_refresh_limits = nbd_refresh_limits,
.bdrv_co_truncate = nbd_co_truncate, .bdrv_co_truncate = nbd_co_truncate,
.bdrv_getlength = nbd_getlength, .bdrv_co_getlength = nbd_co_getlength,
.bdrv_refresh_filename = nbd_refresh_filename, .bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status, .bdrv_co_block_status = nbd_client_co_block_status,
.bdrv_dirname = nbd_dirname, .bdrv_dirname = nbd_dirname,

View File

@ -732,7 +732,7 @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data,
bdrv_wakeup(task->bs); bdrv_wakeup(task->bs);
} }
static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn nfs_co_get_allocated_file_size(BlockDriverState *bs)
{ {
NFSClient *client = bs->opaque; NFSClient *client = bs->opaque;
NFSRPC task = {0}; NFSRPC task = {0};
@ -885,7 +885,7 @@ static BlockDriver bdrv_nfs = {
.bdrv_has_zero_init = nfs_has_zero_init, .bdrv_has_zero_init = nfs_has_zero_init,
/* libnfs does not provide the allocated filesize of a file on win32. */ /* libnfs does not provide the allocated filesize of a file on win32. */
#if !defined(_WIN32) #if !defined(_WIN32)
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size, .bdrv_co_get_allocated_file_size = nfs_co_get_allocated_file_size,
#endif #endif
.bdrv_co_truncate = nfs_file_co_truncate, .bdrv_co_truncate = nfs_file_co_truncate,

View File

@ -100,7 +100,7 @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
return ret; return ret;
} }
static int64_t null_getlength(BlockDriverState *bs) static int64_t coroutine_fn null_co_getlength(BlockDriverState *bs)
{ {
BDRVNullState *s = bs->opaque; BDRVNullState *s = bs->opaque;
return s->length; return s->length;
@ -265,7 +265,8 @@ static void null_refresh_filename(BlockDriverState *bs)
bs->drv->format_name); bs->drv->format_name);
} }
static int64_t null_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn
null_co_get_allocated_file_size(BlockDriverState *bs)
{ {
return 0; return 0;
} }
@ -284,8 +285,8 @@ static BlockDriver bdrv_null_co = {
.bdrv_file_open = null_file_open, .bdrv_file_open = null_file_open,
.bdrv_parse_filename = null_co_parse_filename, .bdrv_parse_filename = null_co_parse_filename,
.bdrv_getlength = null_getlength, .bdrv_co_getlength = null_co_getlength,
.bdrv_get_allocated_file_size = null_allocated_file_size, .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
.bdrv_co_preadv = null_co_preadv, .bdrv_co_preadv = null_co_preadv,
.bdrv_co_pwritev = null_co_pwritev, .bdrv_co_pwritev = null_co_pwritev,
@ -305,8 +306,8 @@ static BlockDriver bdrv_null_aio = {
.bdrv_file_open = null_file_open, .bdrv_file_open = null_file_open,
.bdrv_parse_filename = null_aio_parse_filename, .bdrv_parse_filename = null_aio_parse_filename,
.bdrv_getlength = null_getlength, .bdrv_co_getlength = null_co_getlength,
.bdrv_get_allocated_file_size = null_allocated_file_size, .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
.bdrv_aio_preadv = null_aio_preadv, .bdrv_aio_preadv = null_aio_preadv,
.bdrv_aio_pwritev = null_aio_pwritev, .bdrv_aio_pwritev = null_aio_pwritev,

View File

@ -1002,7 +1002,7 @@ fail:
return ret; return ret;
} }
static int64_t nvme_getlength(BlockDriverState *bs) static int64_t coroutine_fn nvme_co_getlength(BlockDriverState *bs)
{ {
BDRVNVMeState *s = bs->opaque; BDRVNVMeState *s = bs->opaque;
return s->nsze << s->blkshift; return s->nsze << s->blkshift;
@ -1486,7 +1486,7 @@ static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset,
return -ENOTSUP; return -ENOTSUP;
} }
cur_length = nvme_getlength(bs); cur_length = nvme_co_getlength(bs);
if (offset != cur_length && exact) { if (offset != cur_length && exact) {
error_setg(errp, "Cannot resize NVMe devices"); error_setg(errp, "Cannot resize NVMe devices");
return -ENOTSUP; return -ENOTSUP;
@ -1567,14 +1567,14 @@ static void nvme_attach_aio_context(BlockDriverState *bs,
} }
} }
static void nvme_aio_plug(BlockDriverState *bs) static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
{ {
BDRVNVMeState *s = bs->opaque; BDRVNVMeState *s = bs->opaque;
assert(!s->plugged); assert(!s->plugged);
s->plugged = true; s->plugged = true;
} }
static void nvme_aio_unplug(BlockDriverState *bs) static void coroutine_fn nvme_co_io_unplug(BlockDriverState *bs)
{ {
BDRVNVMeState *s = bs->opaque; BDRVNVMeState *s = bs->opaque;
assert(s->plugged); assert(s->plugged);
@ -1643,7 +1643,7 @@ static BlockDriver bdrv_nvme = {
.bdrv_parse_filename = nvme_parse_filename, .bdrv_parse_filename = nvme_parse_filename,
.bdrv_file_open = nvme_file_open, .bdrv_file_open = nvme_file_open,
.bdrv_close = nvme_close, .bdrv_close = nvme_close,
.bdrv_getlength = nvme_getlength, .bdrv_co_getlength = nvme_co_getlength,
.bdrv_probe_blocksizes = nvme_probe_blocksizes, .bdrv_probe_blocksizes = nvme_probe_blocksizes,
.bdrv_co_truncate = nvme_co_truncate, .bdrv_co_truncate = nvme_co_truncate,
@ -1664,8 +1664,8 @@ static BlockDriver bdrv_nvme = {
.bdrv_detach_aio_context = nvme_detach_aio_context, .bdrv_detach_aio_context = nvme_detach_aio_context,
.bdrv_attach_aio_context = nvme_attach_aio_context, .bdrv_attach_aio_context = nvme_attach_aio_context,
.bdrv_io_plug = nvme_aio_plug, .bdrv_co_io_plug = nvme_co_io_plug,
.bdrv_io_unplug = nvme_aio_unplug, .bdrv_co_io_unplug = nvme_co_io_unplug,
.bdrv_register_buf = nvme_register_buf, .bdrv_register_buf = nvme_register_buf,
.bdrv_unregister_buf = nvme_unregister_buf, .bdrv_unregister_buf = nvme_unregister_buf,

View File

@ -287,7 +287,7 @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
} }
if (s->data_end < 0) { if (s->data_end < 0) {
s->data_end = bdrv_getlength(bs->file->bs); s->data_end = bdrv_co_getlength(bs->file->bs);
if (s->data_end < 0) { if (s->data_end < 0) {
return false; return false;
} }
@ -309,7 +309,7 @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
} }
if (s->file_end < 0) { if (s->file_end < 0) {
s->file_end = bdrv_getlength(bs->file->bs); s->file_end = bdrv_co_getlength(bs->file->bs);
if (s->file_end < 0) { if (s->file_end < 0) {
return false; return false;
} }
@ -381,7 +381,7 @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
if (s->data_end >= 0 && offset > s->data_end) { if (s->data_end >= 0 && offset > s->data_end) {
if (s->file_end < 0) { if (s->file_end < 0) {
s->file_end = bdrv_getlength(bs->file->bs); s->file_end = bdrv_co_getlength(bs->file->bs);
if (s->file_end < 0) { if (s->file_end < 0) {
error_setg(errp, "failed to get file length"); error_setg(errp, "failed to get file length");
return s->file_end; return s->file_end;
@ -442,7 +442,7 @@ static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
return bdrv_co_flush(bs->file->bs); return bdrv_co_flush(bs->file->bs);
} }
static int64_t preallocate_getlength(BlockDriverState *bs) static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
{ {
int64_t ret; int64_t ret;
BDRVPreallocateState *s = bs->opaque; BDRVPreallocateState *s = bs->opaque;
@ -451,7 +451,7 @@ static int64_t preallocate_getlength(BlockDriverState *bs)
return s->data_end; return s->data_end;
} }
ret = bdrv_getlength(bs->file->bs); ret = bdrv_co_getlength(bs->file->bs);
if (has_prealloc_perms(bs)) { if (has_prealloc_perms(bs)) {
s->file_end = s->zero_start = s->data_end = ret; s->file_end = s->zero_start = s->data_end = ret;
@ -537,7 +537,7 @@ BlockDriver bdrv_preallocate_filter = {
.format_name = "preallocate", .format_name = "preallocate",
.instance_size = sizeof(BDRVPreallocateState), .instance_size = sizeof(BDRVPreallocateState),
.bdrv_getlength = preallocate_getlength, .bdrv_co_getlength = preallocate_co_getlength,
.bdrv_open = preallocate_open, .bdrv_open = preallocate_open,
.bdrv_close = preallocate_close, .bdrv_close = preallocate_close,

View File

@ -48,8 +48,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
Error **errp) Error **errp)
{ {
ImageInfo **p_image_info; ImageInfo **p_image_info;
ImageInfo *backing_info;
BlockDriverState *bs0, *backing; BlockDriverState *bs0, *backing;
BlockDeviceInfo *info; BlockDeviceInfo *info;
ERRP_GUARD();
if (!bs->drv) { if (!bs->drv) {
error_setg(errp, "Block device %s is ejected", bs->node_name); error_setg(errp, "Block device %s is ejected", bs->node_name);
@ -147,37 +149,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
bs0 = bs; bs0 = bs;
p_image_info = &info->image; p_image_info = &info->image;
info->backing_file_depth = 0; info->backing_file_depth = 0;
while (1) {
Error *local_err = NULL; /*
bdrv_query_image_info(bs0, p_image_info, &local_err); * Skip automatically inserted nodes that the user isn't aware of for
if (local_err) { * query-block (blk != NULL), but not for query-named-block-nodes
error_propagate(errp, local_err); */
bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
if (*errp) {
qapi_free_BlockDeviceInfo(info); qapi_free_BlockDeviceInfo(info);
return NULL; return NULL;
} }
/* stop gathering data for flat output */ backing_info = info->image->backing_image;
if (flat) { while (backing_info) {
break;
}
if (bs0->drv && bdrv_filter_or_cow_child(bs0)) {
/*
* Put any filtered child here (for backwards compatibility to when
* we put bs0->backing here, which might be any filtered child).
*/
info->backing_file_depth++; info->backing_file_depth++;
bs0 = bdrv_filter_or_cow_bs(bs0); backing_info = backing_info->backing_image;
p_image_info = &((*p_image_info)->backing_image);
} else {
break;
}
/* Skip automatically inserted nodes that the user isn't aware of for
* query-block (blk != NULL), but not for query-named-block-nodes */
if (blk) {
bs0 = bdrv_skip_implicit_filters(bs0);
}
} }
return info; return info;
@ -238,22 +224,11 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
} }
/** /**
* bdrv_query_image_info: * Helper function for other query info functions. Store information about @bs
* @bs: block device to examine * in @info, setting @errp on error.
* @p_info: location to store image information
* @errp: location to store error information
*
* Store "flat" image information in @p_info.
*
* "Flat" means it does *not* query backing image information,
* i.e. (*pinfo)->has_backing_image will be set to false and
* (*pinfo)->backing_image to NULL even when the image does in fact have
* a backing image.
*
* @p_info will be set only on success. On error, store error in @errp.
*/ */
void bdrv_query_image_info(BlockDriverState *bs, static void bdrv_do_query_node_info(BlockDriverState *bs,
ImageInfo **p_info, BlockNodeInfo *info,
Error **errp) Error **errp)
{ {
int64_t size; int64_t size;
@ -261,7 +236,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
BlockDriverInfo bdi; BlockDriverInfo bdi;
int ret; int ret;
Error *err = NULL; Error *err = NULL;
ImageInfo *info;
aio_context_acquire(bdrv_get_aio_context(bs)); aio_context_acquire(bdrv_get_aio_context(bs));
@ -274,7 +248,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
bdrv_refresh_filename(bs); bdrv_refresh_filename(bs);
info = g_new0(ImageInfo, 1);
info->filename = g_strdup(bs->filename); info->filename = g_strdup(bs->filename);
info->format = g_strdup(bdrv_get_format_name(bs)); info->format = g_strdup(bdrv_get_format_name(bs));
info->virtual_size = size; info->virtual_size = size;
@ -295,7 +268,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
info->format_specific = bdrv_get_specific_info(bs, &err); info->format_specific = bdrv_get_specific_info(bs, &err);
if (err) { if (err) {
error_propagate(errp, err); error_propagate(errp, err);
qapi_free_ImageInfo(info);
goto out; goto out;
} }
backing_filename = bs->backing_file; backing_filename = bs->backing_file;
@ -331,16 +303,154 @@ void bdrv_query_image_info(BlockDriverState *bs,
break; break;
default: default:
error_propagate(errp, err); error_propagate(errp, err);
qapi_free_ImageInfo(info);
goto out; goto out;
} }
*p_info = info;
out: out:
aio_context_release(bdrv_get_aio_context(bs)); aio_context_release(bdrv_get_aio_context(bs));
} }
/**
* bdrv_query_block_node_info:
* @bs: block node to examine
* @p_info: location to store node information
* @errp: location to store error information
*
* Store image information about @bs in @p_info.
*
* @p_info will be set only on success. On error, store error in @errp.
*/
void bdrv_query_block_node_info(BlockDriverState *bs,
BlockNodeInfo **p_info,
Error **errp)
{
BlockNodeInfo *info;
ERRP_GUARD();
info = g_new0(BlockNodeInfo, 1);
bdrv_do_query_node_info(bs, info, errp);
if (*errp) {
qapi_free_BlockNodeInfo(info);
return;
}
*p_info = info;
}
/**
* bdrv_query_image_info:
* @bs: block node to examine
* @p_info: location to store image information
* @flat: skip backing node information
* @skip_implicit_filters: skip implicit filters in the backing chain
* @errp: location to store error information
*
* Store image information in @p_info, potentially recursively covering the
* backing chain.
*
* If @flat is true, do not query backing image information, i.e.
* (*p_info)->has_backing_image will be set to false and
* (*p_info)->backing_image to NULL even when the image does in fact have a
* backing image.
*
* If @skip_implicit_filters is true, implicit filter nodes in the backing chain
* will be skipped when querying backing image information.
* (@skip_implicit_filters is ignored when @flat is true.)
*
* @p_info will be set only on success. On error, store error in @errp.
*/
void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info,
bool flat,
bool skip_implicit_filters,
Error **errp)
{
ImageInfo *info;
ERRP_GUARD();
info = g_new0(ImageInfo, 1);
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
if (*errp) {
goto fail;
}
if (!flat) {
BlockDriverState *backing;
/*
* Use any filtered child here (for backwards compatibility to when
* we always took bs->backing, which might be any filtered child).
*/
backing = bdrv_filter_or_cow_bs(bs);
if (skip_implicit_filters) {
backing = bdrv_skip_implicit_filters(backing);
}
if (backing) {
bdrv_query_image_info(backing, &info->backing_image, false,
skip_implicit_filters, errp);
if (*errp) {
goto fail;
}
}
}
*p_info = info;
return;
fail:
assert(*errp);
qapi_free_ImageInfo(info);
}
/**
* bdrv_query_block_graph_info:
* @bs: root node to start from
* @p_info: location to store image information
* @errp: location to store error information
*
* Store image information about the graph starting from @bs in @p_info.
*
* @p_info will be set only on success. On error, store error in @errp.
*/
void bdrv_query_block_graph_info(BlockDriverState *bs,
BlockGraphInfo **p_info,
Error **errp)
{
BlockGraphInfo *info;
BlockChildInfoList **children_list_tail;
BdrvChild *c;
ERRP_GUARD();
info = g_new0(BlockGraphInfo, 1);
bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
if (*errp) {
goto fail;
}
children_list_tail = &info->children;
QLIST_FOREACH(c, &bs->children, next) {
BlockChildInfo *c_info;
c_info = g_new0(BlockChildInfo, 1);
QAPI_LIST_APPEND(children_list_tail, c_info);
c_info->name = g_strdup(c->name);
bdrv_query_block_graph_info(c->bs, &c_info->info, errp);
if (*errp) {
goto fail;
}
}
*p_info = info;
return;
fail:
assert(*errp != NULL);
qapi_free_BlockGraphInfo(info);
}
/* @p_info will be set only on success. */ /* @p_info will be set only on success. */
static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
Error **errp) Error **errp)
@ -760,7 +870,36 @@ static void dump_qdict(int indentation, QDict *dict)
} }
} }
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec) /*
* Return whether dumping the given QObject with dump_qobject() would
* yield an empty dump, i.e. not print anything.
*/
static bool qobject_is_empty_dump(const QObject *obj)
{
switch (qobject_type(obj)) {
case QTYPE_QNUM:
case QTYPE_QSTRING:
case QTYPE_QBOOL:
return false;
case QTYPE_QDICT:
return qdict_size(qobject_to(QDict, obj)) == 0;
case QTYPE_QLIST:
return qlist_empty(qobject_to(QList, obj));
default:
abort();
}
}
/**
* Dumps the given ImageInfoSpecific object in a human-readable form,
* prepending an optional prefix if the dump is not empty.
*/
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
const char *prefix,
int indentation)
{ {
QObject *obj, *data; QObject *obj, *data;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
@ -768,45 +907,78 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec)
visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort); visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
data = qdict_get(qobject_to(QDict, obj), "data"); data = qdict_get(qobject_to(QDict, obj), "data");
dump_qobject(1, data); if (!qobject_is_empty_dump(data)) {
if (prefix) {
qemu_printf("%*s%s", indentation * 4, "", prefix);
}
dump_qobject(indentation + 1, data);
}
qobject_unref(obj); qobject_unref(obj);
visit_free(v); visit_free(v);
} }
void bdrv_image_info_dump(ImageInfo *info) /**
* Print the given @info object in human-readable form. Every field is indented
* using the given @indentation (four spaces per indentation level).
*
* When using this to print a whole block graph, @protocol can be set to true to
* signify that the given information is associated with a protocol node, i.e.
* just data storage for an image, such that the data it presents is not really
* a full VM disk. If so, several fields change name: For example, "virtual
* size" is printed as "file length".
* (Consider a qcow2 image, which is represented by a qcow2 node and a file
* node. Printing a "virtual size" for the file node does not make sense,
* because without the qcow2 node, it is not really a guest disk, so it does not
* have a "virtual size". Therefore, we call it "file length" instead.)
*
* @protocol is ignored when @indentation is 0, because we take that to mean
* that the associated node is the root node in the queried block graph, and
* thus is always to be interpreted as a standalone guest disk.
*/
void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol)
{ {
char *size_buf, *dsize_buf; char *size_buf, *dsize_buf;
g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, "");
if (indentation == 0) {
/* Top level, consider this a normal image */
protocol = false;
}
if (!info->has_actual_size) { if (!info->has_actual_size) {
dsize_buf = g_strdup("unavailable"); dsize_buf = g_strdup("unavailable");
} else { } else {
dsize_buf = size_to_str(info->actual_size); dsize_buf = size_to_str(info->actual_size);
} }
size_buf = size_to_str(info->virtual_size); size_buf = size_to_str(info->virtual_size);
qemu_printf("image: %s\n" qemu_printf("%s%s: %s\n"
"file format: %s\n" "%s%s: %s\n"
"virtual size: %s (%" PRId64 " bytes)\n" "%s%s: %s (%" PRId64 " bytes)\n"
"disk size: %s\n", "%sdisk size: %s\n",
info->filename, info->format, size_buf, ind_s, protocol ? "filename" : "image", info->filename,
info->virtual_size, ind_s, protocol ? "protocol type" : "file format",
dsize_buf); info->format,
ind_s, protocol ? "file length" : "virtual size",
size_buf, info->virtual_size,
ind_s, dsize_buf);
g_free(size_buf); g_free(size_buf);
g_free(dsize_buf); g_free(dsize_buf);
if (info->has_encrypted && info->encrypted) { if (info->has_encrypted && info->encrypted) {
qemu_printf("encrypted: yes\n"); qemu_printf("%sencrypted: yes\n", ind_s);
} }
if (info->has_cluster_size) { if (info->has_cluster_size) {
qemu_printf("cluster_size: %" PRId64 "\n", qemu_printf("%scluster_size: %" PRId64 "\n",
info->cluster_size); ind_s, info->cluster_size);
} }
if (info->has_dirty_flag && info->dirty_flag) { if (info->has_dirty_flag && info->dirty_flag) {
qemu_printf("cleanly shut down: no\n"); qemu_printf("%scleanly shut down: no\n", ind_s);
} }
if (info->backing_filename) { if (info->backing_filename) {
qemu_printf("backing file: %s", info->backing_filename); qemu_printf("%sbacking file: %s", ind_s, info->backing_filename);
if (!info->full_backing_filename) { if (!info->full_backing_filename) {
qemu_printf(" (cannot determine actual path)"); qemu_printf(" (cannot determine actual path)");
} else if (strcmp(info->backing_filename, } else if (strcmp(info->backing_filename,
@ -815,15 +987,16 @@ void bdrv_image_info_dump(ImageInfo *info)
} }
qemu_printf("\n"); qemu_printf("\n");
if (info->backing_filename_format) { if (info->backing_filename_format) {
qemu_printf("backing file format: %s\n", qemu_printf("%sbacking file format: %s\n",
info->backing_filename_format); ind_s, info->backing_filename_format);
} }
} }
if (info->has_snapshots) { if (info->has_snapshots) {
SnapshotInfoList *elem; SnapshotInfoList *elem;
qemu_printf("Snapshot list:\n"); qemu_printf("%sSnapshot list:\n", ind_s);
qemu_printf("%s", ind_s);
bdrv_snapshot_dump(NULL); bdrv_snapshot_dump(NULL);
qemu_printf("\n"); qemu_printf("\n");
@ -843,13 +1016,15 @@ void bdrv_image_info_dump(ImageInfo *info)
pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
pstrcpy(sn.name, sizeof(sn.name), elem->value->name); pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
qemu_printf("%s", ind_s);
bdrv_snapshot_dump(&sn); bdrv_snapshot_dump(&sn);
qemu_printf("\n"); qemu_printf("\n");
} }
} }
if (info->format_specific) { if (info->format_specific) {
qemu_printf("Format specific information:\n"); bdrv_image_info_specific_dump(info->format_specific,
bdrv_image_info_specific_dump(info->format_specific); "Format specific information:\n",
indentation);
} }
} }

View File

@ -1129,7 +1129,8 @@ fail:
return ret; return ret;
} }
static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
qcow_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
bdi->cluster_size = s->cluster_size; bdi->cluster_size = s->cluster_size;
@ -1198,7 +1199,7 @@ static BlockDriver bdrv_qcow = {
.bdrv_make_empty = qcow_make_empty, .bdrv_make_empty = qcow_make_empty,
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed, .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
.bdrv_get_info = qcow_get_info, .bdrv_co_get_info = qcow_co_get_info,
.create_opts = &qcow_create_opts, .create_opts = &qcow_create_opts,
.strong_runtime_opts = qcow_strong_runtime_opts, .strong_runtime_opts = qcow_strong_runtime_opts,

View File

@ -117,7 +117,7 @@ static int update_header_sync(BlockDriverState *bs)
return bdrv_flush(bs->file->bs); return bdrv_flush(bs->file->bs);
} }
static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size) static inline void bitmap_table_bswap_be(uint64_t *bitmap_table, size_t size)
{ {
size_t i; size_t i;
@ -1403,9 +1403,10 @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
goto fail; goto fail;
} }
bitmap_table_to_be(tb, tb_size); bitmap_table_bswap_be(tb, tb_size);
ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0); ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
if (ret < 0) { if (ret < 0) {
bitmap_table_bswap_be(tb, tb_size);
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file", error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
bm_name); bm_name);
goto fail; goto fail;

View File

@ -3720,7 +3720,7 @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
return file_length; return file_length;
} }
real_allocation = bdrv_get_allocated_file_size(bs->file->bs); real_allocation = bdrv_co_get_allocated_file_size(bs->file->bs);
if (real_allocation < 0) { if (real_allocation < 0) {
return real_allocation; return real_allocation;
} }

View File

@ -5143,7 +5143,8 @@ err:
return NULL; return NULL;
} }
static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
bdi->cluster_size = s->cluster_size; bdi->cluster_size = s->cluster_size;
@ -5286,7 +5287,7 @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
return pos; return pos;
} }
static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs, static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
QEMUIOVector *qiov, int64_t pos) QEMUIOVector *qiov, int64_t pos)
{ {
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
@ -5298,7 +5299,7 @@ static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0); return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
} }
static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs, static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
QEMUIOVector *qiov, int64_t pos) QEMUIOVector *qiov, int64_t pos)
{ {
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
@ -6077,11 +6078,11 @@ BlockDriver bdrv_qcow2 = {
.bdrv_snapshot_list = qcow2_snapshot_list, .bdrv_snapshot_list = qcow2_snapshot_list,
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
.bdrv_measure = qcow2_measure, .bdrv_measure = qcow2_measure,
.bdrv_get_info = qcow2_get_info, .bdrv_co_get_info = qcow2_co_get_info,
.bdrv_get_specific_info = qcow2_get_specific_info, .bdrv_get_specific_info = qcow2_get_specific_info,
.bdrv_save_vmstate = qcow2_save_vmstate, .bdrv_co_save_vmstate = qcow2_co_save_vmstate,
.bdrv_load_vmstate = qcow2_load_vmstate, .bdrv_co_load_vmstate = qcow2_co_load_vmstate,
.is_format = true, .is_format = true,
.supports_backing = true, .supports_backing = true,

View File

@ -424,7 +424,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
} }
/* Round down file size to the last cluster */ /* Round down file size to the last cluster */
file_size = bdrv_getlength(bs->file->bs); file_size = bdrv_co_getlength(bs->file->bs);
if (file_size < 0) { if (file_size < 0) {
error_setg(errp, "Failed to get file length"); error_setg(errp, "Failed to get file length");
return file_size; return file_size;
@ -1480,13 +1480,14 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
return ret; return ret;
} }
static int64_t bdrv_qed_getlength(BlockDriverState *bs) static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
{ {
BDRVQEDState *s = bs->opaque; BDRVQEDState *s = bs->opaque;
return s->header.image_size; return s->header.image_size;
} }
static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVQEDState *s = bs->opaque; BDRVQEDState *s = bs->opaque;
@ -1653,8 +1654,8 @@ static BlockDriver bdrv_qed = {
.bdrv_co_writev = bdrv_qed_co_writev, .bdrv_co_writev = bdrv_qed_co_writev,
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes, .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
.bdrv_co_truncate = bdrv_qed_co_truncate, .bdrv_co_truncate = bdrv_qed_co_truncate,
.bdrv_getlength = bdrv_qed_getlength, .bdrv_co_getlength = bdrv_qed_co_getlength,
.bdrv_get_info = bdrv_qed_get_info, .bdrv_co_get_info = bdrv_qed_co_get_info,
.bdrv_refresh_limits = bdrv_qed_refresh_limits, .bdrv_refresh_limits = bdrv_qed_refresh_limits,
.bdrv_change_backing_file = bdrv_qed_change_backing_file, .bdrv_change_backing_file = bdrv_qed_change_backing_file,
.bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache, .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,

View File

@ -754,19 +754,19 @@ static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
flags | BDRV_REQ_ZERO_WRITE); flags | BDRV_REQ_ZERO_WRITE);
} }
static int64_t quorum_getlength(BlockDriverState *bs) static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
{ {
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
int64_t result; int64_t result;
int i; int i;
/* check that all file have the same length */ /* check that all file have the same length */
result = bdrv_getlength(s->children[0]->bs); result = bdrv_co_getlength(s->children[0]->bs);
if (result < 0) { if (result < 0) {
return result; return result;
} }
for (i = 1; i < s->num_children; i++) { for (i = 1; i < s->num_children; i++) {
int64_t value = bdrv_getlength(s->children[i]->bs); int64_t value = bdrv_co_getlength(s->children[i]->bs);
if (value < 0) { if (value < 0) {
return value; return value;
} }
@ -1283,7 +1283,7 @@ static BlockDriver bdrv_quorum = {
.bdrv_co_flush = quorum_co_flush, .bdrv_co_flush = quorum_co_flush,
.bdrv_getlength = quorum_getlength, .bdrv_co_getlength = quorum_co_getlength,
.bdrv_co_preadv = quorum_co_preadv, .bdrv_co_preadv = quorum_co_preadv,
.bdrv_co_pwritev = quorum_co_pwritev, .bdrv_co_pwritev = quorum_co_pwritev,

View File

@ -317,14 +317,14 @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
return bdrv_co_pdiscard(bs->file, offset, bytes); return bdrv_co_pdiscard(bs->file, offset, bytes);
} }
static int64_t raw_getlength(BlockDriverState *bs) static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
{ {
int64_t len; int64_t len;
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
/* Update size. It should not change unless the file was externally /* Update size. It should not change unless the file was externally
* modified. */ * modified. */
len = bdrv_getlength(bs->file->bs); len = bdrv_co_getlength(bs->file->bs);
if (len < 0) { if (len < 0) {
return len; return len;
} }
@ -368,9 +368,10 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
return info; return info;
} }
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
return bdrv_get_info(bs->file->bs, bdi); return bdrv_co_get_info(bs->file->bs, bdi);
} }
static void raw_refresh_limits(BlockDriverState *bs, Error **errp) static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
@ -404,14 +405,14 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
} }
static void raw_eject(BlockDriverState *bs, bool eject_flag) static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
bdrv_eject(bs->file->bs, eject_flag); bdrv_co_eject(bs->file->bs, eject_flag);
} }
static void raw_lock_medium(BlockDriverState *bs, bool locked) static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
bdrv_lock_medium(bs->file->bs, locked); bdrv_co_lock_medium(bs->file->bs, locked);
} }
static int coroutine_fn raw_co_ioctl(BlockDriverState *bs, static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
@ -622,16 +623,16 @@ BlockDriver bdrv_raw = {
.bdrv_co_copy_range_from = &raw_co_copy_range_from, .bdrv_co_copy_range_from = &raw_co_copy_range_from,
.bdrv_co_copy_range_to = &raw_co_copy_range_to, .bdrv_co_copy_range_to = &raw_co_copy_range_to,
.bdrv_co_truncate = &raw_co_truncate, .bdrv_co_truncate = &raw_co_truncate,
.bdrv_getlength = &raw_getlength, .bdrv_co_getlength = &raw_co_getlength,
.is_format = true, .is_format = true,
.has_variable_length = true, .has_variable_length = true,
.bdrv_measure = &raw_measure, .bdrv_measure = &raw_measure,
.bdrv_get_info = &raw_get_info, .bdrv_co_get_info = &raw_co_get_info,
.bdrv_refresh_limits = &raw_refresh_limits, .bdrv_refresh_limits = &raw_refresh_limits,
.bdrv_probe_blocksizes = &raw_probe_blocksizes, .bdrv_probe_blocksizes = &raw_probe_blocksizes,
.bdrv_probe_geometry = &raw_probe_geometry, .bdrv_probe_geometry = &raw_probe_geometry,
.bdrv_eject = &raw_eject, .bdrv_co_eject = &raw_co_eject,
.bdrv_lock_medium = &raw_lock_medium, .bdrv_co_lock_medium = &raw_co_lock_medium,
.bdrv_co_ioctl = &raw_co_ioctl, .bdrv_co_ioctl = &raw_co_ioctl,
.create_opts = &raw_create_opts, .create_opts = &raw_create_opts,
.bdrv_has_zero_init = &raw_has_zero_init, .bdrv_has_zero_init = &raw_has_zero_init,

View File

@ -1240,7 +1240,8 @@ coroutine_fn qemu_rbd_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
} }
#endif #endif
static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
qemu_rbd_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVRBDState *s = bs->opaque; BDRVRBDState *s = bs->opaque;
bdi->cluster_size = s->object_size; bdi->cluster_size = s->object_size;
@ -1430,7 +1431,7 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
return status; return status;
} }
static int64_t qemu_rbd_getlength(BlockDriverState *bs) static int64_t coroutine_fn qemu_rbd_co_getlength(BlockDriverState *bs)
{ {
BDRVRBDState *s = bs->opaque; BDRVRBDState *s = bs->opaque;
int r; int r;
@ -1651,10 +1652,10 @@ static BlockDriver bdrv_rbd = {
.bdrv_co_create = qemu_rbd_co_create, .bdrv_co_create = qemu_rbd_co_create,
.bdrv_co_create_opts = qemu_rbd_co_create_opts, .bdrv_co_create_opts = qemu_rbd_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_get_info = qemu_rbd_getinfo, .bdrv_co_get_info = qemu_rbd_co_get_info,
.bdrv_get_specific_info = qemu_rbd_get_specific_info, .bdrv_get_specific_info = qemu_rbd_get_specific_info,
.create_opts = &qemu_rbd_create_opts, .create_opts = &qemu_rbd_create_opts,
.bdrv_getlength = qemu_rbd_getlength, .bdrv_co_getlength = qemu_rbd_co_getlength,
.bdrv_co_truncate = qemu_rbd_co_truncate, .bdrv_co_truncate = qemu_rbd_co_truncate,
.protocol_name = "rbd", .protocol_name = "rbd",

View File

@ -179,9 +179,9 @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
return; return;
} }
static int64_t replication_getlength(BlockDriverState *bs) static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static int replication_get_io_status(BDRVReplicationState *s) static int replication_get_io_status(BDRVReplicationState *s)
@ -758,7 +758,7 @@ static BlockDriver bdrv_replication = {
.bdrv_close = replication_close, .bdrv_close = replication_close,
.bdrv_child_perm = replication_child_perm, .bdrv_child_perm = replication_child_perm,
.bdrv_getlength = replication_getlength, .bdrv_co_getlength = replication_co_getlength,
.bdrv_co_readv = replication_co_readv, .bdrv_co_readv = replication_co_readv,
.bdrv_co_writev = replication_co_writev, .bdrv_co_writev = replication_co_writev,

View File

@ -1253,7 +1253,7 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
return ret; return ret;
} }
static int64_t ssh_getlength(BlockDriverState *bs) static int64_t coroutine_fn ssh_co_getlength(BlockDriverState *bs)
{ {
BDRVSSHState *s = bs->opaque; BDRVSSHState *s = bs->opaque;
int64_t length; int64_t length;
@ -1364,7 +1364,7 @@ static BlockDriver bdrv_ssh = {
.bdrv_has_zero_init = ssh_has_zero_init, .bdrv_has_zero_init = ssh_has_zero_init,
.bdrv_co_readv = ssh_co_readv, .bdrv_co_readv = ssh_co_readv,
.bdrv_co_writev = ssh_co_writev, .bdrv_co_writev = ssh_co_writev,
.bdrv_getlength = ssh_getlength, .bdrv_co_getlength = ssh_co_getlength,
.bdrv_co_truncate = ssh_co_truncate, .bdrv_co_truncate = ssh_co_truncate,
.bdrv_co_flush_to_disk = ssh_co_flush, .bdrv_co_flush_to_disk = ssh_co_flush,
.bdrv_refresh_filename = ssh_refresh_filename, .bdrv_refresh_filename = ssh_refresh_filename,

View File

@ -106,9 +106,9 @@ static void throttle_close(BlockDriverState *bs)
} }
static int64_t throttle_getlength(BlockDriverState *bs) static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
{ {
return bdrv_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static int coroutine_fn throttle_co_preadv(BlockDriverState *bs, static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
@ -247,7 +247,7 @@ static BlockDriver bdrv_throttle = {
.bdrv_child_perm = bdrv_default_perms, .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = throttle_getlength, .bdrv_co_getlength = throttle_co_getlength,
.bdrv_co_preadv = throttle_co_preadv, .bdrv_co_preadv = throttle_co_preadv,
.bdrv_co_pwritev = throttle_co_pwritev, .bdrv_co_pwritev = throttle_co_pwritev,

View File

@ -327,9 +327,10 @@ static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
return 0; return 0;
} }
static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
vdi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
/* TODO: vdi_get_info would be needed for machine snapshots. /* TODO: vdi_co_get_info would be needed for machine snapshots.
vm_state_offset is still missing. */ vm_state_offset is still missing. */
BDRVVdiState *s = (BDRVVdiState *)bs->opaque; BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
logout("\n"); logout("\n");
@ -1049,7 +1050,7 @@ static BlockDriver bdrv_vdi = {
.bdrv_co_pwritev = vdi_co_pwritev, .bdrv_co_pwritev = vdi_co_pwritev,
#endif #endif
.bdrv_get_info = vdi_get_info, .bdrv_co_get_info = vdi_co_get_info,
.is_format = true, .is_format = true,
.create_opts = &vdi_create_opts, .create_opts = &vdi_create_opts,

View File

@ -1161,7 +1161,8 @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
} }
static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVVHDXState *s = bs->opaque; BDRVVHDXState *s = bs->opaque;
@ -2245,7 +2246,7 @@ static BlockDriver bdrv_vhdx = {
.bdrv_co_writev = vhdx_co_writev, .bdrv_co_writev = vhdx_co_writev,
.bdrv_co_create = vhdx_co_create, .bdrv_co_create = vhdx_co_create,
.bdrv_co_create_opts = vhdx_co_create_opts, .bdrv_co_create_opts = vhdx_co_create_opts,
.bdrv_get_info = vhdx_get_info, .bdrv_co_get_info = vhdx_co_get_info,
.bdrv_co_check = vhdx_co_check, .bdrv_co_check = vhdx_co_check,
.bdrv_has_zero_init = vhdx_has_zero_init, .bdrv_has_zero_init = vhdx_has_zero_init,

View File

@ -2856,14 +2856,15 @@ static void vmdk_close(BlockDriverState *bs)
error_free(s->migration_blocker); error_free(s->migration_blocker);
} }
static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) static int64_t coroutine_fn
vmdk_co_get_allocated_file_size(BlockDriverState *bs)
{ {
int i; int i;
int64_t ret = 0; int64_t ret = 0;
int64_t r; int64_t r;
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
ret = bdrv_get_allocated_file_size(bs->file->bs); ret = bdrv_co_get_allocated_file_size(bs->file->bs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -2871,7 +2872,7 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
if (s->extents[i].file == bs->file) { if (s->extents[i].file == bs->file) {
continue; continue;
} }
r = bdrv_get_allocated_file_size(s->extents[i].file->bs); r = bdrv_co_get_allocated_file_size(s->extents[i].file->bs);
if (r < 0) { if (r < 0) {
return r; return r;
} }
@ -2897,12 +2898,12 @@ static int vmdk_has_zero_init(BlockDriverState *bs)
return 1; return 1;
} }
static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
{ {
ImageInfo *info = g_new0(ImageInfo, 1); VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);
bdrv_refresh_filename(extent->file->bs); bdrv_refresh_filename(extent->file->bs);
*info = (ImageInfo){ *info = (VmdkExtentInfo){
.filename = g_strdup(extent->file->bs->filename), .filename = g_strdup(extent->file->bs->filename),
.format = g_strdup(extent->type), .format = g_strdup(extent->type),
.virtual_size = extent->sectors * BDRV_SECTOR_SIZE, .virtual_size = extent->sectors * BDRV_SECTOR_SIZE,
@ -2981,7 +2982,7 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
int i; int i;
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1); ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
ImageInfoList **tail; VmdkExtentInfoList **tail;
*spec_info = (ImageInfoSpecific){ *spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK, .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
@ -3011,7 +3012,8 @@ static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b)
(a->flat || a->cluster_sectors == b->cluster_sectors); (a->flat || a->cluster_sectors == b->cluster_sectors);
} }
static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
vmdk_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
int i; int i;
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
@ -3124,11 +3126,11 @@ static BlockDriver bdrv_vmdk = {
.bdrv_co_create_opts = vmdk_co_create_opts, .bdrv_co_create_opts = vmdk_co_create_opts,
.bdrv_co_create = vmdk_co_create, .bdrv_co_create = vmdk_co_create,
.bdrv_co_block_status = vmdk_co_block_status, .bdrv_co_block_status = vmdk_co_block_status,
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, .bdrv_co_get_allocated_file_size = vmdk_co_get_allocated_file_size,
.bdrv_has_zero_init = vmdk_has_zero_init, .bdrv_has_zero_init = vmdk_has_zero_init,
.bdrv_get_specific_info = vmdk_get_specific_info, .bdrv_get_specific_info = vmdk_get_specific_info,
.bdrv_refresh_limits = vmdk_refresh_limits, .bdrv_refresh_limits = vmdk_refresh_limits,
.bdrv_get_info = vmdk_get_info, .bdrv_co_get_info = vmdk_co_get_info,
.bdrv_gather_child_options = vmdk_gather_child_options, .bdrv_gather_child_options = vmdk_gather_child_options,
.is_format = true, .is_format = true,

View File

@ -598,7 +598,8 @@ fail:
return ret; return ret;
} }
static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static int coroutine_fn
vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{ {
BDRVVPCState *s = (BDRVVPCState *)bs->opaque; BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
@ -1240,7 +1241,7 @@ static BlockDriver bdrv_vpc = {
.bdrv_co_pwritev = vpc_co_pwritev, .bdrv_co_pwritev = vpc_co_pwritev,
.bdrv_co_block_status = vpc_co_block_status, .bdrv_co_block_status = vpc_co_block_status,
.bdrv_get_info = vpc_get_info, .bdrv_co_get_info = vpc_co_get_info,
.is_format = true, .is_format = true,
.create_opts = &vpc_create_opts, .create_opts = &vpc_create_opts,

View File

@ -1024,6 +1024,7 @@ fail:
static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp) static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
{ {
BlockDriverState *bs; BlockDriverState *bs;
AioContext *aio_context;
bs = bdrv_lookup_bs(name, name, errp); bs = bdrv_lookup_bs(name, name, errp);
if (bs == NULL) { if (bs == NULL) {
@ -1035,11 +1036,16 @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
return NULL; return NULL;
} }
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (!bdrv_is_inserted(bs)) { if (!bdrv_is_inserted(bs)) {
error_setg(errp, "Device has no medium"); error_setg(errp, "Device has no medium");
return NULL; bs = NULL;
} }
aio_context_release(aio_context);
return bs; return bs;
} }

View File

@ -15,6 +15,40 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qapi-types-block.h" #include "qapi/qapi-types-block.h"
/*
* Read the non-zeroes parts of @blk into @buf
* Reading all of the @blk is expensive if the zeroes parts of @blk
* is large enough. Therefore check the block status and only write
* the non-zeroes block into @buf.
*
* Return 0 on success, non-zero on error.
*/
static int blk_pread_nonzeroes(BlockBackend *blk, hwaddr size, void *buf)
{
int ret;
int64_t bytes, offset = 0;
BlockDriverState *bs = blk_bs(blk);
for (;;) {
bytes = MIN(size - offset, BDRV_REQUEST_MAX_SECTORS);
if (bytes <= 0) {
return 0;
}
ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
if (ret < 0) {
return ret;
}
if (!(ret & BDRV_BLOCK_ZERO)) {
ret = bdrv_pread(bs->file, offset, bytes,
(uint8_t *) buf + offset, 0);
if (ret < 0) {
return ret;
}
}
offset += bytes;
}
}
/* /*
* Read the entire contents of @blk into @buf. * Read the entire contents of @blk into @buf.
* @blk's contents must be @size bytes, and @size must be at most * @blk's contents must be @size bytes, and @size must be at most
@ -54,7 +88,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
* block device and read only on demand. * block device and read only on demand.
*/ */
assert(size <= BDRV_REQUEST_MAX_BYTES); assert(size <= BDRV_REQUEST_MAX_BYTES);
ret = blk_pread(blk, 0, size, buf, 0); ret = blk_pread_nonzeroes(blk, size, buf);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "can't read block backend"); error_setg_errno(errp, -ret, "can't read block backend");
return false; return false;

View File

@ -2332,10 +2332,15 @@ static void scsi_disk_reset(DeviceState *dev)
{ {
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
uint64_t nb_sectors; uint64_t nb_sectors;
AioContext *ctx;
scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET)); scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
ctx = blk_get_aio_context(s->qdev.conf.blk);
aio_context_acquire(ctx);
blk_get_geometry(s->qdev.conf.blk, &nb_sectors); blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
aio_context_release(ctx);
nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE;
if (nb_sectors) { if (nb_sectors) {
nb_sectors--; nb_sectors--;

View File

@ -45,11 +45,14 @@
* - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but * - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but
* automatically take and release the graph rdlock when creating a new * automatically take and release the graph rdlock when creating a new
* coroutine. * coroutine.
*
* These functions should not be called from a coroutine_fn; instead,
* call the wrapped function directly.
*/ */
#define co_wrapper #define co_wrapper no_coroutine_fn
#define co_wrapper_mixed #define co_wrapper_mixed no_coroutine_fn coroutine_mixed_fn
#define co_wrapper_bdrv_rdlock #define co_wrapper_bdrv_rdlock no_coroutine_fn
#define co_wrapper_mixed_bdrv_rdlock #define co_wrapper_mixed_bdrv_rdlock no_coroutine_fn coroutine_mixed_fn
#include "block/blockjob.h" #include "block/blockjob.h"

View File

@ -76,9 +76,15 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
PreallocMode prealloc, BdrvRequestFlags flags, PreallocMode prealloc, BdrvRequestFlags flags,
Error **errp); Error **errp);
int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
int64_t bdrv_getlength(BlockDriverState *bs); int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
BlockDriverState *in_bs, Error **errp); BlockDriverState *in_bs, Error **errp);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
@ -136,16 +142,23 @@ bool bdrv_is_read_only(BlockDriverState *bs);
bool bdrv_is_writable(BlockDriverState *bs); bool bdrv_is_writable(BlockDriverState *bs);
bool bdrv_is_sg(BlockDriverState *bs); bool bdrv_is_sg(BlockDriverState *bs);
int bdrv_get_flags(BlockDriverState *bs); int bdrv_get_flags(BlockDriverState *bs);
bool bdrv_is_inserted(BlockDriverState *bs);
void bdrv_lock_medium(BlockDriverState *bs, bool locked); bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
void bdrv_eject(BlockDriverState *bs, bool eject_flag); bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
const char *bdrv_get_format_name(BlockDriverState *bs); const char *bdrv_get_format_name(BlockDriverState *bs);
bool bdrv_supports_compressed_writes(BlockDriverState *bs); bool bdrv_supports_compressed_writes(BlockDriverState *bs);
const char *bdrv_get_node_name(const BlockDriverState *bs); const char *bdrv_get_node_name(const BlockDriverState *bs);
const char *bdrv_get_device_name(const BlockDriverState *bs); const char *bdrv_get_device_name(const BlockDriverState *bs);
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs); const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
int co_wrapper_mixed bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs, ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
Error **errp); Error **errp);
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs); BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
@ -178,7 +191,10 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
void bdrv_enable_copy_on_read(BlockDriverState *bs); void bdrv_enable_copy_on_read(BlockDriverState *bs);
void bdrv_disable_copy_on_read(BlockDriverState *bs); void bdrv_disable_copy_on_read(BlockDriverState *bs);
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event); void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs,
BlkdebugEvent event);
void co_wrapper_mixed bdrv_debug_event(BlockDriverState *bs,
BlkdebugEvent event);
#define BLKDBG_EVENT(child, evt) \ #define BLKDBG_EVENT(child, evt) \
do { \ do { \
@ -213,15 +229,10 @@ AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs);
*/ */
void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
/**
* Transfer control to @co in the aio context of @bs
*/
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co);
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
void bdrv_io_plug(BlockDriverState *bs); void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
void bdrv_io_unplug(BlockDriverState *bs); void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
const char *name, const char *name,

View File

@ -680,8 +680,10 @@ struct BlockDriver {
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset, int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc, bool exact, PreallocMode prealloc,
BdrvRequestFlags flags, Error **errp); BdrvRequestFlags flags, Error **errp);
int64_t (*bdrv_getlength)(BlockDriverState *bs); int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
BlockDriverState *bs);
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs, BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
Error **errp); Error **errp);
@ -691,22 +693,23 @@ struct BlockDriver {
int64_t offset, int64_t bytes, QEMUIOVector *qiov, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
size_t qiov_offset); size_t qiov_offset);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
BlockDriverInfo *bdi);
ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs, ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
Error **errp); Error **errp);
BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs); BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_save_vmstate)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)(
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_load_vmstate)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_load_vmstate)(
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
/* removable device specific */ /* removable device specific */
bool (*bdrv_is_inserted)(BlockDriverState *bs); bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
/* to control generic scsi devices */ /* to control generic scsi devices */
BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
@ -722,11 +725,12 @@ struct BlockDriver {
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)(
BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix); BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix);
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event); void coroutine_fn (*bdrv_co_debug_event)(BlockDriverState *bs,
BlkdebugEvent event);
/* io queue for linux-aio */ /* io queue for linux-aio */
void (*bdrv_io_plug)(BlockDriverState *bs); void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
void (*bdrv_io_unplug)(BlockDriverState *bs); void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
/** /**
* bdrv_drain_begin is called if implemented in the beginning of a * bdrv_drain_begin is called if implemented in the beginning of a

View File

@ -122,7 +122,10 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
BdrvRequestFlags read_flags, BdrvRequestFlags read_flags,
BdrvRequestFlags write_flags); BdrvRequestFlags write_flags);
int refresh_total_sectors(BlockDriverState *bs, int64_t hint); int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
int64_t hint);
int co_wrapper_mixed
bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
BdrvChild *bdrv_cow_child(BlockDriverState *bs); BdrvChild *bdrv_cow_child(BlockDriverState *bs);
BdrvChild *bdrv_filter_child(BlockDriverState *bs); BdrvChild *bdrv_filter_child(BlockDriverState *bs);

View File

@ -24,6 +24,7 @@
#include "io/channel-socket.h" #include "io/channel-socket.h"
#include "crypto/tlscreds.h" #include "crypto/tlscreds.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/bswap.h"
extern const BlockExportDriver blk_exp_nbd; extern const BlockExportDriver blk_exp_nbd;

View File

@ -35,11 +35,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
int bdrv_query_snapshot_info_list(BlockDriverState *bs, int bdrv_query_snapshot_info_list(BlockDriverState *bs,
SnapshotInfoList **p_list, SnapshotInfoList **p_list,
Error **errp); Error **errp);
void bdrv_query_block_node_info(BlockDriverState *bs,
BlockNodeInfo **p_info,
Error **errp);
void bdrv_query_image_info(BlockDriverState *bs, void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info, ImageInfo **p_info,
bool flat,
bool skip_implicit_filters,
Error **errp);
void bdrv_query_block_graph_info(BlockDriverState *bs,
BlockGraphInfo **p_info,
Error **errp); Error **errp);
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn); void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec); void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
void bdrv_image_info_dump(ImageInfo *info); const char *prefix,
int indentation);
void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol);
#endif #endif

View File

@ -171,7 +171,51 @@ extern "C" {
* .... * ....
* } * }
*/ */
#ifdef __clang__
#define coroutine_fn __attribute__((__annotate__("coroutine_fn")))
#else
#define coroutine_fn #define coroutine_fn
#endif
/**
* Mark a function that can suspend when executed in coroutine context,
* but can handle running in non-coroutine context too.
*/
#ifdef __clang__
#define coroutine_mixed_fn __attribute__((__annotate__("coroutine_mixed_fn")))
#else
#define coroutine_mixed_fn
#endif
/**
* Mark a function that should not be called from a coroutine context.
* Usually there will be an analogous, coroutine_fn function that should
* be used instead.
*
* When the function is also marked as coroutine_mixed_fn, the function should
* only be called if the caller does not know whether it is in coroutine
* context.
*
* Functions that are only no_coroutine_fn, on the other hand, should not
* be called from within coroutines at all. This for example includes
* functions that block.
*
* In the future it would be nice to enable compiler or static checker
* support for catching such errors. This annotation is the first step
* towards this, and in the meantime it serves as documentation.
*
* For example:
*
* static void no_coroutine_fn foo(void) {
* ....
* }
*/
#ifdef __clang__
#define no_coroutine_fn __attribute__((__annotate__("no_coroutine_fn")))
#else
#define no_coroutine_fn
#endif
/* /*
* For mingw, as of v6.0.0, the function implementing the assert macro is * For mingw, as of v6.0.0, the function implementing the assert macro is

View File

@ -54,13 +54,26 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
void blk_inc_in_flight(BlockBackend *blk); void blk_inc_in_flight(BlockBackend *blk);
void blk_dec_in_flight(BlockBackend *blk); void blk_dec_in_flight(BlockBackend *blk);
bool blk_is_inserted(BlockBackend *blk);
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
bool blk_is_available(BlockBackend *blk); bool blk_is_available(BlockBackend *blk);
void blk_lock_medium(BlockBackend *blk, bool locked);
void blk_eject(BlockBackend *blk, bool eject_flag); void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
int64_t blk_getlength(BlockBackend *blk); void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag);
void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag);
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk);
int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk);
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr); void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr);
int64_t blk_nb_sectors(BlockBackend *blk);
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk);
int64_t co_wrapper_mixed blk_nb_sectors(BlockBackend *blk);
void *blk_try_blockalign(BlockBackend *blk, size_t size); void *blk_try_blockalign(BlockBackend *blk, size_t size);
void *blk_blockalign(BlockBackend *blk, size_t size); void *blk_blockalign(BlockBackend *blk, size_t size);
bool blk_is_writable(BlockBackend *blk); bool blk_is_writable(BlockBackend *blk);
@ -74,8 +87,12 @@ void blk_iostatus_set_err(BlockBackend *blk, int error);
int blk_get_max_iov(BlockBackend *blk); int blk_get_max_iov(BlockBackend *blk);
int blk_get_max_hw_iov(BlockBackend *blk); int blk_get_max_hw_iov(BlockBackend *blk);
void blk_io_plug(BlockBackend *blk); void coroutine_fn blk_co_io_plug(BlockBackend *blk);
void blk_io_unplug(BlockBackend *blk); void co_wrapper blk_io_plug(BlockBackend *blk);
void coroutine_fn blk_co_io_unplug(BlockBackend *blk);
void co_wrapper blk_io_unplug(BlockBackend *blk);
AioContext *blk_get_aio_context(BlockBackend *blk); AioContext *blk_get_aio_context(BlockBackend *blk);
BlockAcctStats *blk_get_stats(BlockBackend *blk); BlockAcctStats *blk_get_stats(BlockBackend *blk);
void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,

View File

@ -124,7 +124,33 @@
'create-type': 'str', 'create-type': 'str',
'cid': 'int', 'cid': 'int',
'parent-cid': 'int', 'parent-cid': 'int',
'extents': ['ImageInfo'] 'extents': ['VmdkExtentInfo']
} }
##
# @VmdkExtentInfo:
#
# Information about a VMDK extent file
#
# @filename: Name of the extent file
#
# @format: Extent type (e.g. FLAT or SPARSE)
#
# @virtual-size: Number of bytes covered by this extent
#
# @cluster-size: Cluster size in bytes (for non-flat extents)
#
# @compressed: Whether this extent contains compressed data
#
# Since: 8.0
##
{ 'struct': 'VmdkExtentInfo',
'data': {
'filename': 'str',
'format': 'str',
'virtual-size': 'int',
'*cluster-size': 'int',
'*compressed': 'bool'
} } } }
## ##
@ -139,16 +165,29 @@
'*encryption-format': 'RbdImageEncryptionFormat' '*encryption-format': 'RbdImageEncryptionFormat'
} } } }
##
# @ImageInfoSpecificFile:
#
# @extent-size-hint: Extent size hint (if available)
#
# Since: 8.0
##
{ 'struct': 'ImageInfoSpecificFile',
'data': {
'*extent-size-hint': 'size'
} }
## ##
# @ImageInfoSpecificKind: # @ImageInfoSpecificKind:
# #
# @luks: Since 2.7 # @luks: Since 2.7
# @rbd: Since 6.1 # @rbd: Since 6.1
# @file: Since 8.0
# #
# Since: 1.7 # Since: 1.7
## ##
{ 'enum': 'ImageInfoSpecificKind', { 'enum': 'ImageInfoSpecificKind',
'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] } 'data': [ 'qcow2', 'vmdk', 'luks', 'rbd', 'file' ] }
## ##
# @ImageInfoSpecificQCow2Wrapper: # @ImageInfoSpecificQCow2Wrapper:
@ -185,6 +224,14 @@
{ 'struct': 'ImageInfoSpecificRbdWrapper', { 'struct': 'ImageInfoSpecificRbdWrapper',
'data': { 'data': 'ImageInfoSpecificRbd' } } 'data': { 'data': 'ImageInfoSpecificRbd' } }
##
# @ImageInfoSpecificFileWrapper:
#
# Since: 8.0
##
{ 'struct': 'ImageInfoSpecificFileWrapper',
'data': { 'data': 'ImageInfoSpecificFile' } }
## ##
# @ImageInfoSpecific: # @ImageInfoSpecific:
# #
@ -199,11 +246,12 @@
'qcow2': 'ImageInfoSpecificQCow2Wrapper', 'qcow2': 'ImageInfoSpecificQCow2Wrapper',
'vmdk': 'ImageInfoSpecificVmdkWrapper', 'vmdk': 'ImageInfoSpecificVmdkWrapper',
'luks': 'ImageInfoSpecificLUKSWrapper', 'luks': 'ImageInfoSpecificLUKSWrapper',
'rbd': 'ImageInfoSpecificRbdWrapper' 'rbd': 'ImageInfoSpecificRbdWrapper',
'file': 'ImageInfoSpecificFileWrapper'
} } } }
## ##
# @ImageInfo: # @BlockNodeInfo:
# #
# Information about a QEMU image file # Information about a QEMU image file
# #
@ -231,22 +279,69 @@
# #
# @snapshots: list of VM snapshots # @snapshots: list of VM snapshots
# #
# @backing-image: info of the backing image (since 1.6)
#
# @format-specific: structure supplying additional format-specific # @format-specific: structure supplying additional format-specific
# information (since 1.7) # information (since 1.7)
# #
# Since: 1.3 # Since: 8.0
## ##
{ 'struct': 'ImageInfo', { 'struct': 'BlockNodeInfo',
'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
'*actual-size': 'int', 'virtual-size': 'int', '*actual-size': 'int', 'virtual-size': 'int',
'*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool', '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
'*backing-filename': 'str', '*full-backing-filename': 'str', '*backing-filename': 'str', '*full-backing-filename': 'str',
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
'*backing-image': 'ImageInfo',
'*format-specific': 'ImageInfoSpecific' } } '*format-specific': 'ImageInfoSpecific' } }
##
# @ImageInfo:
#
# Information about a QEMU image file, and potentially its backing image
#
# @backing-image: info of the backing image
#
# Since: 1.3
##
{ 'struct': 'ImageInfo',
'base': 'BlockNodeInfo',
'data': {
'*backing-image': 'ImageInfo'
} }
##
# @BlockChildInfo:
#
# Information about all nodes in the block graph starting at some node,
# annotated with information about that node in relation to its parent.
#
# @name: Child name of the root node in the BlockGraphInfo struct, in its role
# as the child of some undescribed parent node
#
# @info: Block graph information starting at this node
#
# Since: 8.0
##
{ 'struct': 'BlockChildInfo',
'data': {
'name': 'str',
'info': 'BlockGraphInfo'
} }
##
# @BlockGraphInfo:
#
# Information about all nodes in a block (sub)graph in the form of BlockNodeInfo
# data.
# The base BlockNodeInfo struct contains the information for the (sub)graph's
# root node.
#
# @children: Array of links to this node's child nodes' information
#
# Since: 8.0
##
{ 'struct': 'BlockGraphInfo',
'base': 'BlockNodeInfo',
'data': { 'children': ['BlockChildInfo'] } }
## ##
# @ImageCheck: # @ImageCheck:
# #
@ -5732,3 +5827,13 @@
'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, 'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
'returns': 'SnapshotInfo', 'returns': 'SnapshotInfo',
'allow-preconfig': true } 'allow-preconfig': true }
##
# @DummyBlockCoreForceArrays:
#
# Not used by QMP; hack to let us use BlockGraphInfoList internally
#
# Since: 8.0
##
{ 'struct': 'DummyBlockCoreForceArrays',
'data': { 'unused-block-graph-info': ['BlockGraphInfo'] } }

View File

@ -450,6 +450,11 @@ static BlockBackend *img_open(bool image_opts,
blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet, blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
force_share); force_share);
} }
if (blk) {
blk_set_force_allow_inactivate(blk);
}
return blk; return blk;
} }
@ -1120,6 +1125,14 @@ unref_backing:
done: done:
qemu_progress_end(); qemu_progress_end();
/*
* Manually inactivate the image first because this way we can know whether
* an error occurred. blk_unref() doesn't tell us about failures.
*/
ret = bdrv_inactivate_all();
if (ret < 0 && !local_err) {
error_setg_errno(&local_err, -ret, "Error while closing the image");
}
blk_unref(blk); blk_unref(blk);
if (local_err) { if (local_err) {
@ -2804,13 +2817,13 @@ static void dump_snapshots(BlockDriverState *bs)
g_free(sn_tab); g_free(sn_tab);
} }
static void dump_json_image_info_list(ImageInfoList *list) static void dump_json_block_graph_info_list(BlockGraphInfoList *list)
{ {
GString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfoList(v, NULL, &list, &error_abort); visit_type_BlockGraphInfoList(v, NULL, &list, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj, true); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
@ -2820,13 +2833,13 @@ static void dump_json_image_info_list(ImageInfoList *list)
g_string_free(str, true); g_string_free(str, true);
} }
static void dump_json_image_info(ImageInfo *info) static void dump_json_block_graph_info(BlockGraphInfo *info)
{ {
GString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfo(v, NULL, &info, &error_abort); visit_type_BlockGraphInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj, true); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
@ -2836,9 +2849,30 @@ static void dump_json_image_info(ImageInfo *info)
g_string_free(str, true); g_string_free(str, true);
} }
static void dump_human_image_info_list(ImageInfoList *list) static void dump_human_image_info(BlockGraphInfo *info, int indentation,
const char *path)
{ {
ImageInfoList *elem; BlockChildInfoList *children_list;
bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation,
info->children == NULL);
for (children_list = info->children; children_list;
children_list = children_list->next)
{
BlockChildInfo *child = children_list->value;
g_autofree char *child_path = NULL;
printf("%*sChild node '%s%s':\n",
indentation * 4, "", path, child->name);
child_path = g_strdup_printf("%s%s/", path, child->name);
dump_human_image_info(child->info, indentation + 1, child_path);
}
}
static void dump_human_image_info_list(BlockGraphInfoList *list)
{
BlockGraphInfoList *elem;
bool delim = false; bool delim = false;
for (elem = list; elem; elem = elem->next) { for (elem = list; elem; elem = elem->next) {
@ -2847,7 +2881,7 @@ static void dump_human_image_info_list(ImageInfoList *list)
} }
delim = true; delim = true;
bdrv_image_info_dump(elem->value); dump_human_image_info(elem->value, 0, "/");
} }
} }
@ -2857,24 +2891,24 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
} }
/** /**
* Open an image file chain and return an ImageInfoList * Open an image file chain and return an BlockGraphInfoList
* *
* @filename: topmost image filename * @filename: topmost image filename
* @fmt: topmost image format (may be NULL to autodetect) * @fmt: topmost image format (may be NULL to autodetect)
* @chain: true - enumerate entire backing file chain * @chain: true - enumerate entire backing file chain
* false - only topmost image file * false - only topmost image file
* *
* Returns a list of ImageInfo objects or NULL if there was an error opening an * Returns a list of BlockNodeInfo objects or NULL if there was an error
* image file. If there was an error a message will have been printed to * opening an image file. If there was an error a message will have been
* stderr. * printed to stderr.
*/ */
static ImageInfoList *collect_image_info_list(bool image_opts, static BlockGraphInfoList *collect_image_info_list(bool image_opts,
const char *filename, const char *filename,
const char *fmt, const char *fmt,
bool chain, bool force_share) bool chain, bool force_share)
{ {
ImageInfoList *head = NULL; BlockGraphInfoList *head = NULL;
ImageInfoList **tail = &head; BlockGraphInfoList **tail = &head;
GHashTable *filenames; GHashTable *filenames;
Error *err = NULL; Error *err = NULL;
@ -2883,7 +2917,7 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
while (filename) { while (filename) {
BlockBackend *blk; BlockBackend *blk;
BlockDriverState *bs; BlockDriverState *bs;
ImageInfo *info; BlockGraphInfo *info;
if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) { if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
error_report("Backing file '%s' creates an infinite loop.", error_report("Backing file '%s' creates an infinite loop.",
@ -2900,7 +2934,14 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
} }
bs = blk_bs(blk); bs = blk_bs(blk);
bdrv_query_image_info(bs, &info, &err); /*
* Note that the returned BlockGraphInfo object will not have
* information about this image's backing node, because we have opened
* it with BDRV_O_NO_BACKING. Printing this object will therefore not
* duplicate the backing chain information that we obtain by walking
* the chain manually here.
*/
bdrv_query_block_graph_info(bs, &info, &err);
if (err) { if (err) {
error_report_err(err); error_report_err(err);
blk_unref(blk); blk_unref(blk);
@ -2933,7 +2974,7 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
return head; return head;
err: err:
qapi_free_ImageInfoList(head); qapi_free_BlockGraphInfoList(head);
g_hash_table_destroy(filenames); g_hash_table_destroy(filenames);
return NULL; return NULL;
} }
@ -2944,7 +2985,7 @@ static int img_info(int argc, char **argv)
OutputFormat output_format = OFORMAT_HUMAN; OutputFormat output_format = OFORMAT_HUMAN;
bool chain = false; bool chain = false;
const char *filename, *fmt, *output; const char *filename, *fmt, *output;
ImageInfoList *list; BlockGraphInfoList *list;
bool image_opts = false; bool image_opts = false;
bool force_share = false; bool force_share = false;
@ -3023,14 +3064,14 @@ static int img_info(int argc, char **argv)
break; break;
case OFORMAT_JSON: case OFORMAT_JSON:
if (chain) { if (chain) {
dump_json_image_info_list(list); dump_json_block_graph_info_list(list);
} else { } else {
dump_json_image_info(list->value); dump_json_block_graph_info(list->value);
} }
break; break;
} }
qapi_free_ImageInfoList(list); qapi_free_BlockGraphInfoList(list);
return 0; return 0;
} }
@ -4633,6 +4674,7 @@ static int img_bitmap(int argc, char **argv)
QSIMPLEQ_HEAD(, ImgBitmapAction) actions; QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
ImgBitmapAction *act, *act_next; ImgBitmapAction *act, *act_next;
const char *op; const char *op;
int inactivate_ret;
QSIMPLEQ_INIT(&actions); QSIMPLEQ_INIT(&actions);
@ -4817,6 +4859,16 @@ static int img_bitmap(int argc, char **argv)
ret = 0; ret = 0;
out: out:
/*
* Manually inactivate the images first because this way we can know whether
* an error occurred. blk_unref() doesn't tell us about failures.
*/
inactivate_ret = bdrv_inactivate_all();
if (inactivate_ret < 0) {
error_report("Error while closing the image: %s", strerror(-inactivate_ret));
ret = 1;
}
blk_unref(src); blk_unref(src);
blk_unref(blk); blk_unref(blk);
qemu_opts_del(opts); qemu_opts_del(opts);

View File

@ -572,54 +572,17 @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
return 1; return 1;
} }
typedef struct { static int do_pwrite_zeroes(BlockBackend *blk, int64_t offset,
BlockBackend *blk;
int64_t offset;
int64_t bytes;
int64_t *total;
int flags;
int ret;
bool done;
} CoWriteZeroes;
static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
{
CoWriteZeroes *data = opaque;
data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
data->flags);
data->done = true;
if (data->ret < 0) {
*data->total = data->ret;
return;
}
*data->total = data->bytes;
}
static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
int64_t bytes, int flags, int64_t *total) int64_t bytes, int flags, int64_t *total)
{ {
Coroutine *co; int ret = blk_pwrite_zeroes(blk, offset, bytes,
CoWriteZeroes data = { flags | BDRV_REQ_ZERO_WRITE);
.blk = blk,
.offset = offset,
.bytes = bytes,
.total = total,
.flags = flags,
.done = false,
};
co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data); if (ret < 0) {
bdrv_coroutine_enter(blk_bs(blk), co); return ret;
while (!data.done) {
aio_poll(blk_get_aio_context(blk), true);
} }
if (data.ret < 0) { *total = bytes;
return data.ret;
} else {
return 1; return 1;
}
} }
static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset, static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
@ -1042,7 +1005,7 @@ static void write_help(void)
" -C, -- report statistics in a machine parsable format\n" " -C, -- report statistics in a machine parsable format\n"
" -q, -- quiet mode, do not show I/O statistics\n" " -q, -- quiet mode, do not show I/O statistics\n"
" -u, -- with -z, allow unmapping\n" " -u, -- with -z, allow unmapping\n"
" -z, -- write zeroes using blk_co_pwrite_zeroes\n" " -z, -- write zeroes using blk_pwrite_zeroes\n"
"\n"); "\n");
} }
@ -1199,7 +1162,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
if (bflag) { if (bflag) {
ret = do_save_vmstate(blk, buf, offset, count, &total); ret = do_save_vmstate(blk, buf, offset, count, &total);
} else if (zflag) { } else if (zflag) {
ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total); ret = do_pwrite_zeroes(blk, offset, count, flags, &total);
} else if (cflag) { } else if (cflag) {
ret = do_write_compressed(blk, buf, offset, count, &total); ret = do_write_compressed(blk, buf, offset, count, &total);
} else { } else {
@ -1825,8 +1788,9 @@ static int info_f(BlockBackend *blk, int argc, char **argv)
return -EIO; return -EIO;
} }
if (spec_info) { if (spec_info) {
printf("Format specific information:\n"); bdrv_image_info_specific_dump(spec_info,
bdrv_image_info_specific_dump(spec_info); "Format specific information:\n",
0);
qapi_free_ImageInfoSpecific(spec_info); qapi_free_ImageInfoSpecific(spec_info);
} }

View File

@ -86,6 +86,16 @@ class FuncDecl:
ctx = 'qemu_get_aio_context()' ctx = 'qemu_get_aio_context()'
self.ctx = ctx self.ctx = ctx
self.get_result = 's->ret = '
self.ret = 'return s.ret;'
self.co_ret = 'return '
self.return_field = self.return_type + " ret;"
if self.return_type == 'void':
self.get_result = ''
self.ret = ''
self.co_ret = ''
self.return_field = ''
def gen_list(self, format: str) -> str: def gen_list(self, format: str) -> str:
return ', '.join(format.format_map(arg.__dict__) for arg in self.args) return ', '.join(format.format_map(arg.__dict__) for arg in self.args)
@ -132,7 +142,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
{{ {{
if (qemu_in_coroutine()) {{ if (qemu_in_coroutine()) {{
{graph_assume_lock} {graph_assume_lock}
return {name}({ func.gen_list('{name}') }); {func.co_ret}{name}({ func.gen_list('{name}') });
}} else {{ }} else {{
{struct_name} s = {{ {struct_name} s = {{
.poll_state.ctx = {func.ctx}, .poll_state.ctx = {func.ctx},
@ -144,7 +154,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
s.poll_state.co = qemu_coroutine_create({name}_entry, &s); s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
bdrv_poll_co(&s.poll_state); bdrv_poll_co(&s.poll_state);
return s.ret; {func.ret}
}} }}
}}""" }}"""
@ -169,7 +179,7 @@ def create_co_wrapper(func: FuncDecl) -> str:
s.poll_state.co = qemu_coroutine_create({name}_entry, &s); s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
bdrv_poll_co(&s.poll_state); bdrv_poll_co(&s.poll_state);
return s.ret; {func.ret}
}}""" }}"""
@ -196,7 +206,7 @@ def gen_wrapper(func: FuncDecl) -> str:
typedef struct {struct_name} {{ typedef struct {struct_name} {{
BdrvPollCo poll_state; BdrvPollCo poll_state;
{func.return_type} ret; {func.return_field}
{ func.gen_block(' {decl};') } { func.gen_block(' {decl};') }
}} {struct_name}; }} {struct_name};
@ -205,7 +215,7 @@ static void coroutine_fn {name}_entry(void *opaque)
{struct_name} *s = opaque; {struct_name} *s = opaque;
{graph_lock} {graph_lock}
s->ret = {name}({ func.gen_list('s->{name}') }); {func.get_result}{name}({ func.gen_list('s->{name}') });
{graph_unlock} {graph_unlock}
s->poll_state.in_progress = false; s->poll_state.in_progress = false;

View File

@ -56,7 +56,7 @@ class TestQemuImgInfo(TestImageInfoSpecific):
def test_human(self): def test_human(self):
data = qemu_img('info', '--output=human', test_img).stdout.split('\n') data = qemu_img('info', '--output=human', test_img).stdout.split('\n')
data = data[(data.index('Format specific information:') + 1) data = data[(data.index('Format specific information:') + 1)
:data.index('')] :data.index("Child node '/file':")]
for field in data: for field in data:
self.assertTrue(re.match('^ {4}[^ ]', field) is not None) self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
data = [line.strip() for line in data] data = [line.strip() for line in data]

View File

@ -66,7 +66,7 @@ for create_mode in off falloc full; do
expected_size=$((expected_size + $GROWTH_SIZE)) expected_size=$((expected_size + $GROWTH_SIZE))
fi fi
actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
# The actual size may exceed the expected size, depending on the file # The actual size may exceed the expected size, depending on the file
@ -105,7 +105,7 @@ for growth_mode in falloc full; do
_make_test_img -o "extent_size_hint=0" 2G _make_test_img -o "extent_size_hint=0" 2G
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
if [ $actual_size -lt $GROWTH_SIZE ]; then if [ $actual_size -lt $GROWTH_SIZE ]; then

View File

@ -102,7 +102,8 @@ let data_size="8 * $cluster_size"
$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \ $QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
2>&1 | _filter_qemu_io | _filter_testdir 2>&1 | _filter_qemu_io | _filter_testdir
sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" | sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
sed -n '/"actual-size":/ s/[^0-9]//gp') sed -n '/"actual-size":/ s/[^0-9]//gp' |
head -n 1)
_make_test_img 2M -o cluster_size=$cluster_size _make_test_img 2M -o cluster_size=$cluster_size
echo "Write compressed data:" echo "Write compressed data:"
@ -124,7 +125,8 @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
_filter_qemu_io | _filter_testdir _filter_qemu_io | _filter_testdir
sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" | sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
sed -n '/"actual-size":/ s/[^0-9]//gp') sed -n '/"actual-size":/ s/[^0-9]//gp' |
head -n 1)
if [ $sizeA -lt $sizeB ] if [ $sizeA -lt $sizeB ]
then then

View File

@ -25,7 +25,8 @@ import iotests
import os import os
iotests.script_initialize(supported_fmts=['qcow2'], iotests.script_initialize(supported_fmts=['qcow2'],
supported_platforms=['linux']) supported_platforms=['linux'],
required_fmts=['blkverify'])
with iotests.FilePath('img') as img_path, \ with iotests.FilePath('img') as img_path, \
iotests.FilePath('mig_fifo') as fifo, \ iotests.FilePath('mig_fifo') as fifo, \

View File

@ -4,6 +4,11 @@ image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
file format: raw file format: raw
virtual size: 448 KiB (458752 bytes) virtual size: 448 KiB (458752 bytes)
disk size: unavailable disk size: unavailable
Child node '/file':
filename: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
protocol type: nbd
file length: 448 KiB (458752 bytes)
disk size: unavailable
=== Converted image info === === Converted image info ===
image: TEST_IMG image: TEST_IMG

View File

@ -217,12 +217,12 @@ echo
echo '=== Remove export ===' echo '=== Remove export ==='
# Double-check that $EXT_MP appears as a non-empty file (the raw image) # Double-check that $EXT_MP appears as a non-empty file (the raw image)
$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' $QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
fuse_export_del 'export-mp' fuse_export_del 'export-mp'
# See that the file appears empty again # See that the file appears empty again
$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' $QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
echo echo
echo '=== Writable export ===' echo '=== Writable export ==='

View File

@ -52,6 +52,7 @@ _supported_fmt qcow2
_supported_proto file _supported_proto file
_supported_os Linux _supported_os Linux
_unsupported_imgopts cluster_size data_file _unsupported_imgopts cluster_size data_file
_require_drivers quorum
echo echo
echo '### Create all images' # three source (quorum), one destination echo '### Create all images' # three source (quorum), one destination

View File

@ -223,6 +223,7 @@ _filter_img_info()
discard=0 discard=0
regex_json_spec_start='^ *"format-specific": \{' regex_json_spec_start='^ *"format-specific": \{'
regex_json_child_start='^ *"children": \['
gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \
@ -251,20 +252,25 @@ _filter_img_info()
-e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \ -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \
-e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \ -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \
while IFS='' read -r line; do while IFS='' read -r line; do
if [[ $format_specific == 1 ]]; then if [[ $discard == 0 ]]; then
discard=0 if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
elif [[ $line == "Format specific information:" ]]; then discard=1
elif [[ $line =~ "Child node '/" ]]; then
discard=1 discard=1
elif [[ $line =~ $regex_json_spec_start ]]; then elif [[ $line =~ $regex_json_spec_start ]]; then
discard=2 discard=2
regex_json_spec_end="^${line%%[^ ]*}\\},? *$" regex_json_end="^${line%%[^ ]*}\\},? *$"
elif [[ $line =~ $regex_json_child_start ]]; then
discard=2
regex_json_end="^${line%%[^ ]*}\\],? *$"
fi
fi fi
if [[ $discard == 0 ]]; then if [[ $discard == 0 ]]; then
echo "$line" echo "$line"
elif [[ $discard == 1 && ! $line ]]; then elif [[ $discard == 1 && ! $line ]]; then
echo echo
discard=0 discard=0
elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
discard=0 discard=0
fi fi
done done

View File

@ -711,6 +711,7 @@ _img_info()
discard=0 discard=0
regex_json_spec_start='^ *"format-specific": \{' regex_json_spec_start='^ *"format-specific": \{'
regex_json_child_start='^ *"children": \['
$QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
@ -721,20 +722,25 @@ _img_info()
-e "/^disk size:/ D" \ -e "/^disk size:/ D" \
-e "/actual-size/ D" | \ -e "/actual-size/ D" | \
while IFS='' read -r line; do while IFS='' read -r line; do
if [[ $format_specific == 1 ]]; then if [[ $discard == 0 ]]; then
discard=0 if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
elif [[ $line == "Format specific information:" ]]; then
discard=1 discard=1
elif [[ $line =~ $regex_json_spec_start ]]; then elif [[ $line =~ "Child node '/" ]]; then
discard=1
elif [[ $format_specific == 0 && $line =~ $regex_json_spec_start ]]; then
discard=2 discard=2
regex_json_spec_end="^${line%%[^ ]*}\\},? *$" regex_json_end="^${line%%[^ ]*}\\},? *$"
elif [[ $line =~ $regex_json_child_start ]]; then
discard=2
regex_json_end="^${line%%[^ ]*}\\],? *$"
fi
fi fi
if [[ $discard == 0 ]]; then if [[ $discard == 0 ]]; then
echo "$line" echo "$line"
elif [[ $discard == 1 && ! $line ]]; then elif [[ $discard == 1 && ! $line ]]; then
echo echo
discard=0 discard=0
elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
discard=0 discard=0
fi fi
done done

View File

@ -329,7 +329,7 @@ def qemu_img_log(*args: str, check: bool = True
def img_info_log(filename: str, filter_path: Optional[str] = None, def img_info_log(filename: str, filter_path: Optional[str] = None,
use_image_opts: bool = False, extra_args: Sequence[str] = (), use_image_opts: bool = False, extra_args: Sequence[str] = (),
check: bool = True, check: bool = True, drop_child_info: bool = True,
) -> None: ) -> None:
args = ['info'] args = ['info']
if use_image_opts: if use_image_opts:
@ -342,7 +342,7 @@ def img_info_log(filename: str, filter_path: Optional[str] = None,
output = qemu_img(*args, check=check).stdout output = qemu_img(*args, check=check).stdout
if not filter_path: if not filter_path:
filter_path = filename filter_path = filename
log(filter_img_info(output, filter_path)) log(filter_img_info(output, filter_path, drop_child_info))
def qemu_io_wrap_args(args: Sequence[str]) -> List[str]: def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
if '-f' in args or '--image-opts' in args: if '-f' in args or '--image-opts' in args:
@ -642,11 +642,23 @@ def filter_qmp_virtio_scsi(qmsg):
def filter_generated_node_ids(msg): def filter_generated_node_ids(msg):
return re.sub("#block[0-9]+", "NODE_NAME", msg) return re.sub("#block[0-9]+", "NODE_NAME", msg)
def filter_img_info(output, filename): def filter_img_info(output: str, filename: str,
drop_child_info: bool = True) -> str:
lines = [] lines = []
drop_indented = False
for line in output.split('\n'): for line in output.split('\n'):
if 'disk size' in line or 'actual-size' in line: if 'disk size' in line or 'actual-size' in line:
continue continue
# Drop child node info
if drop_indented:
if line.startswith(' '):
continue
drop_indented = False
if drop_child_info and "Child node '/" in line:
drop_indented = True
continue
line = line.replace(filename, 'TEST_IMG') line = line.replace(filename, 'TEST_IMG')
line = filter_testfiles(line) line = filter_testfiles(line)
line = line.replace(imgfmt, 'IMGFMT') line = line.replace(imgfmt, 'IMGFMT')

View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
# group: rw auto quick
#
# Check that errors while closing the image, in particular writing back dirty
# bitmaps, is correctly reported with a failing qemu-img exit code.
#
# Copyright (C) 2023 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# creator
owner=kwolf@redhat.com
seq="$(basename $0)"
echo "QA output created by $seq"
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
cd ..
. ./common.rc
. ./common.filter
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
size=1G
# The error we are going to use is ENOSPC. Depending on how many bitmaps we
# create in the backing file (and therefore increase the used up space), we get
# failures in different places. With a low number, only merging the bitmap
# fails, whereas with a higher number, already 'qemu-img commit' fails.
for max_bitmap in 6 7; do
echo
echo "=== Test with $max_bitmap bitmaps ==="
TEST_IMG="$TEST_IMG.base" _make_test_img -q $size
for i in $(seq 1 $max_bitmap); do
$QEMU_IMG bitmap --add "$TEST_IMG.base" "stale-bitmap-$i"
done
# Simulate a block device of 128 MB by resizing the image file accordingly
# and then enforcing the size with the raw driver
$QEMU_IO -f raw -c "truncate 128M" "$TEST_IMG.base"
BASE_JSON='json:{
"driver": "qcow2",
"file": {
"driver": "raw",
"size": 134217728,
"file": {
"driver": "file",
"filename":"'"$TEST_IMG.base"'"
}
}
}'
_make_test_img -q -b "$BASE_JSON" -F $IMGFMT
$QEMU_IMG bitmap --add "$TEST_IMG" "good-bitmap"
$QEMU_IO -c 'write 0 126m' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG commit -d "$TEST_IMG" 2>&1 | _filter_generated_node_ids
echo "qemu-img commit exit code: ${PIPESTATUS[0]}"
$QEMU_IMG bitmap --add "$BASE_JSON" "good-bitmap"
echo "qemu-img bitmap --add exit code: $?"
$QEMU_IMG bitmap --merge "good-bitmap" -b "$TEST_IMG" "$BASE_JSON" \
"good-bitmap" 2>&1 | _filter_generated_node_ids
echo "qemu-img bitmap --merge exit code: ${PIPESTATUS[0]}"
done
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View File

@ -0,0 +1,23 @@
QA output created by qemu-img-close-errors
=== Test with 6 bitmaps ===
wrote 132120576/132120576 bytes at offset 0
126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image committed.
qemu-img commit exit code: 0
qemu-img bitmap --add exit code: 0
qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
qemu-img: Error while closing the image: Invalid argument
qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
qemu-img bitmap --merge exit code: 1
=== Test with 7 bitmaps ===
wrote 132120576/132120576 bytes at offset 0
126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
qemu-img: Error while closing the image: Invalid argument
qemu-img commit exit code: 1
qemu-img bitmap --add exit code: 0
qemu-img bitmap --merge exit code: 0
*** done

View File

@ -832,7 +832,10 @@ static void test_attach_second_node(void)
qdict_put_str(options, "driver", "raw"); qdict_put_str(options, "driver", "raw");
qdict_put_str(options, "file", "base"); qdict_put_str(options, "file", "base");
aio_context_acquire(ctx);
filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
aio_context_release(ctx);
g_assert(blk_get_aio_context(blk) == ctx); g_assert(blk_get_aio_context(blk) == ctx);
g_assert(bdrv_get_aio_context(bs) == ctx); g_assert(bdrv_get_aio_context(bs) == ctx);
g_assert(bdrv_get_aio_context(filter) == ctx); g_assert(bdrv_get_aio_context(filter) == ctx);