Block layer patches
- Expose block limits in monitor and qemu-img info - Resize: Refresh filter node size when its child was resized - Support configuring stats-intervals in -device (instead of only -drive) - luks: Fix QMP x-blockdev-amend crash and image creation with detached-header - iotests: Several test case fixes - Code cleanups -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmkCAkIRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9a3bA/+MMS9ocOyEiE4u66XbhQ4KgqxECtD/uzg 3lYQJbfVpphizq0QQn1pAno9rpjdWnkwPv9TasAEM/9R/wz/ygjmXM9GyQDvNLoB t6dTyWKpsi4lVB7FNPBNQvyz7mHqWQULrhI/mNGLsbiss32SMiE08amjOzSrFSZJ zn8TsEzDB218Bv8OBH/eI1mMvZ2gG6+yzPf7znA5nSOtJkG1kGLPInZuRgeN7e7W DUl5EeiP3sGZh4pF/IyRc8BNMsvPR7Lk31PrPEXAz+7g0y8dfPukrcR0nY6nwekT omPhbIBfDOEKpYdBxheOdh9TkT40Fo2Oc7DIhzY4at3O02BKy60kJSZaqoWj+80L A3yJ1K7wgiwqzOw0VaHU56Y5awnD5cculciwHxrfc6OHnG9cotvCSxsU2qr/UMd2 N/cPhUDKfWcilVoRNy+yYiubQsp2s4amF2uGDn/QjjZx0c3dgfXc9BCNmu9nbAMr UsmzZBH9GCpaTajVIsX8RdnaovMTxGr4UFyuSQ2jWYWp3k2BR89jkBpXReGGOYr6 SuEOOnx/E1duTZUPq1gdSkQm9uGxxq5FSGIWR+rWMdFkZS09HStmq5hcY+Zx0pSg JzDaLgPATV65y0VswFVUj6NemmNU983DwKPACwVCpemeBETtVuoU/CydzEPPwiL6 Kl5ISmjZz3I= =v2BI -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging Block layer patches - Expose block limits in monitor and qemu-img info - Resize: Refresh filter node size when its child was resized - Support configuring stats-intervals in -device (instead of only -drive) - luks: Fix QMP x-blockdev-amend crash and image creation with detached-header - iotests: Several test case fixes - Code cleanups # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCgAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmkCAkIRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9a3bA/+MMS9ocOyEiE4u66XbhQ4KgqxECtD/uzg # 3lYQJbfVpphizq0QQn1pAno9rpjdWnkwPv9TasAEM/9R/wz/ygjmXM9GyQDvNLoB # t6dTyWKpsi4lVB7FNPBNQvyz7mHqWQULrhI/mNGLsbiss32SMiE08amjOzSrFSZJ # zn8TsEzDB218Bv8OBH/eI1mMvZ2gG6+yzPf7znA5nSOtJkG1kGLPInZuRgeN7e7W # DUl5EeiP3sGZh4pF/IyRc8BNMsvPR7Lk31PrPEXAz+7g0y8dfPukrcR0nY6nwekT # omPhbIBfDOEKpYdBxheOdh9TkT40Fo2Oc7DIhzY4at3O02BKy60kJSZaqoWj+80L # A3yJ1K7wgiwqzOw0VaHU56Y5awnD5cculciwHxrfc6OHnG9cotvCSxsU2qr/UMd2 # N/cPhUDKfWcilVoRNy+yYiubQsp2s4amF2uGDn/QjjZx0c3dgfXc9BCNmu9nbAMr # UsmzZBH9GCpaTajVIsX8RdnaovMTxGr4UFyuSQ2jWYWp3k2BR89jkBpXReGGOYr6 # SuEOOnx/E1duTZUPq1gdSkQm9uGxxq5FSGIWR+rWMdFkZS09HStmq5hcY+Zx0pSg # JzDaLgPATV65y0VswFVUj6NemmNU983DwKPACwVCpemeBETtVuoU/CydzEPPwiL6 # Kl5ISmjZz3I= # =v2BI # -----END PGP SIGNATURE----- # gpg: Signature made Wed 29 Oct 2025 01:02:10 PM CET # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [unknown] # gpg: WARNING: The key's User ID is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: qemu-img info: Add cache mode option qemu-img info: Optionally show block limits block: Expose block limits for images in QMP block: Improve comments in BlockLimits iotests: add test for resizing a 'file' node below a 'raw' node iotests: add test for resizing a node below filters block: implement 'resize' callback for child_of_bds class block: make bdrv_co_parent_cb_resize() a proper IO API function include/block/block_int-common: document when resize callback is used MAINTAINERS: Mark VHDX block driver as "Odd Fixes" block: enable stats-intervals for storage devices iotests: Adjust fuse-allow-other expected output iotests: Adjust nbd expected outputs to match current behavior block/curl.c: Fix CURLOPT_VERBOSE parameter type block/monitor: Use hmp_handle_error to report error block: fix luks 'amend' when run in coroutine block: remove 'detached-header' option from opts after use tests/qemu-iotests: Mark the 'inactive-node-nbd' as unsupported with -luks Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
0979667049
32 changed files with 479 additions and 96 deletions
|
|
@ -4081,7 +4081,7 @@ F: block/rbd.c
|
|||
VHDX
|
||||
M: Jeff Cody <codyprime@gmail.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: block/vhdx*
|
||||
|
||||
VDI
|
||||
|
|
|
|||
12
block.c
12
block.c
|
|
@ -1497,6 +1497,17 @@ static void GRAPH_WRLOCK bdrv_child_cb_detach(BdrvChild *child)
|
|||
}
|
||||
}
|
||||
|
||||
static void coroutine_fn GRAPH_RDLOCK bdrv_child_cb_resize(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
|
||||
if (child->role & BDRV_CHILD_FILTERED) {
|
||||
/* Best effort, ignore errors. */
|
||||
bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
|
||||
bdrv_co_parent_cb_resize(bs);
|
||||
}
|
||||
}
|
||||
|
||||
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
|
||||
const char *filename,
|
||||
bool backing_mask_protocol,
|
||||
|
|
@ -1529,6 +1540,7 @@ const BdrvChildClass child_of_bds = {
|
|||
.detach = bdrv_child_cb_detach,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
.change_aio_ctx = bdrv_child_cb_change_aio_ctx,
|
||||
.resize = bdrv_child_cb_resize,
|
||||
.update_filename = bdrv_child_cb_update_filename,
|
||||
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "block/block_int.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "system/qtest.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static QEMUClockType clock_type = QEMU_CLOCK_REALTIME;
|
||||
static const int qtest_latency_ns = NANOSECONDS_PER_SECOND / 1000;
|
||||
|
|
@ -56,13 +57,25 @@ static bool bool_from_onoffauto(OnOffAuto val, bool def)
|
|||
}
|
||||
}
|
||||
|
||||
void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
|
||||
enum OnOffAuto account_failed)
|
||||
bool block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
|
||||
enum OnOffAuto account_failed, uint32_t *stats_intervals,
|
||||
uint32_t num_stats_intervals, Error **errp)
|
||||
{
|
||||
stats->account_invalid = bool_from_onoffauto(account_invalid,
|
||||
stats->account_invalid);
|
||||
stats->account_failed = bool_from_onoffauto(account_failed,
|
||||
stats->account_failed);
|
||||
if (stats_intervals) {
|
||||
for (int i = 0; i < num_stats_intervals; i++) {
|
||||
if (stats_intervals[i] <= 0) {
|
||||
error_setg(errp, "Invalid interval length: %u", stats_intervals[i]);
|
||||
return false;
|
||||
}
|
||||
block_acct_add_interval(stats, stats_intervals[i]);
|
||||
}
|
||||
g_free(stats_intervals);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void block_acct_cleanup(BlockAcctStats *stats)
|
||||
|
|
|
|||
|
|
@ -67,11 +67,18 @@ static int block_crypto_read_func(QCryptoBlock *block,
|
|||
BlockCrypto *crypto = bs->opaque;
|
||||
ssize_t ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
if (qemu_in_coroutine()) {
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
ret = bdrv_pread(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
ret = bdrv_co_pread(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
} else {
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
ret = bdrv_pread(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read encryption header");
|
||||
return ret;
|
||||
|
|
@ -90,11 +97,18 @@ static int block_crypto_write_func(QCryptoBlock *block,
|
|||
BlockCrypto *crypto = bs->opaque;
|
||||
ssize_t ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
if (qemu_in_coroutine()) {
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
ret = bdrv_pwrite(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
ret = bdrv_co_pwrite(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
} else {
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
ret = bdrv_pwrite(crypto->header ? crypto->header : bs->file,
|
||||
offset, buflen, buf, 0);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not write encryption header");
|
||||
return ret;
|
||||
|
|
@ -792,7 +806,7 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
|
|||
char *buf = NULL;
|
||||
int64_t size;
|
||||
bool detached_hdr =
|
||||
qemu_opt_get_bool(opts, "detached-header", false);
|
||||
qemu_opt_get_bool_del(opts, "detached-header", false);
|
||||
unsigned int cflags = 0;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
|
|||
#endif
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
if (curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1)) {
|
||||
if (curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1L)) {
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -46,9 +46,6 @@
|
|||
/* Maximum read size for checking if data reads as zero, in bytes */
|
||||
#define MAX_ZERO_CHECK_BUFFER (128 * KiB)
|
||||
|
||||
static void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_parent_cb_resize(BlockDriverState *bs);
|
||||
|
||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
|
||||
|
||||
|
|
@ -2038,7 +2035,7 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
|
|||
end_sector > bs->total_sectors) &&
|
||||
req->type != BDRV_TRACKED_DISCARD) {
|
||||
bs->total_sectors = end_sector;
|
||||
bdrv_parent_cb_resize(bs);
|
||||
bdrv_co_parent_cb_resize(bs);
|
||||
bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS);
|
||||
}
|
||||
if (req->bytes) {
|
||||
|
|
@ -3570,11 +3567,11 @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
|
|||
bytes, read_flags, write_flags);
|
||||
}
|
||||
|
||||
static void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_parent_cb_resize(BlockDriverState *bs)
|
||||
void coroutine_fn bdrv_co_parent_cb_resize(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *c;
|
||||
|
||||
IO_CODE();
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
QLIST_FOREACH(c, &bs->parents, next_parent) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static void hmp_drive_add_node(Monitor *mon, const char *optstr)
|
|||
{
|
||||
QemuOpts *opts;
|
||||
QDict *qdict;
|
||||
Error *local_err = NULL;
|
||||
Error *err = NULL;
|
||||
|
||||
opts = qemu_opts_parse_noisily(&qemu_drive_opts, optstr, false);
|
||||
if (!opts) {
|
||||
|
|
@ -73,19 +73,19 @@ static void hmp_drive_add_node(Monitor *mon, const char *optstr)
|
|||
|
||||
if (!qdict_get_try_str(qdict, "node-name")) {
|
||||
qobject_unref(qdict);
|
||||
error_report("'node-name' needs to be specified");
|
||||
error_setg(&err, "'node-name' needs to be specified");
|
||||
goto out;
|
||||
}
|
||||
|
||||
BlockDriverState *bs = bds_tree_init(qdict, &local_err);
|
||||
BlockDriverState *bs = bds_tree_init(qdict, &err);
|
||||
if (!bs) {
|
||||
error_report_err(local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_set_monitor_owned(bs);
|
||||
out:
|
||||
qemu_opts_del(opts);
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_drive_add(Monitor *mon, const QDict *qdict)
|
||||
|
|
@ -109,7 +109,6 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
|
|||
mc = MACHINE_GET_CLASS(current_machine);
|
||||
dinfo = drive_new(opts, mc->block_default_type, &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
qemu_opts_del(opts);
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -123,7 +122,7 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
|
|||
monitor_printf(mon, "OK\n");
|
||||
break;
|
||||
default:
|
||||
monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
|
||||
error_setg(&err, "Can't hot-add drive to type %d", dinfo->type);
|
||||
goto err;
|
||||
}
|
||||
return;
|
||||
|
|
@ -134,6 +133,7 @@ err:
|
|||
monitor_remove_blk(blk);
|
||||
blk_unref(blk);
|
||||
}
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||
|
|
@ -141,36 +141,32 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
|||
const char *id = qdict_get_str(qdict, "id");
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
Error *local_err = NULL;
|
||||
Error *err = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
bs = bdrv_find_node(id);
|
||||
if (bs) {
|
||||
qmp_blockdev_del(id, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
qmp_blockdev_del(id, &err);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
blk = blk_by_name(id);
|
||||
if (!blk) {
|
||||
error_report("Device '%s' not found", id);
|
||||
error_setg(&err, "Device '%s' not found", id);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!blk_legacy_dinfo(blk)) {
|
||||
error_report("Deleting device added with blockdev-add"
|
||||
" is not supported");
|
||||
error_setg(&err, "Deleting device added with blockdev-add"
|
||||
" is not supported");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
bs = blk_bs(blk);
|
||||
if (bs) {
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &err)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +192,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
|||
|
||||
unlock:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||
|
|
@ -203,6 +200,7 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
|||
const char *device = qdict_get_str(qdict, "device");
|
||||
BlockBackend *blk;
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
|
@ -214,22 +212,25 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
|||
|
||||
blk = blk_by_name(device);
|
||||
if (!blk) {
|
||||
error_report("Device '%s' not found", device);
|
||||
return;
|
||||
error_setg(&err, "Device '%s' not found", device);
|
||||
goto end;
|
||||
}
|
||||
|
||||
bs = bdrv_skip_implicit_filters(blk_bs(blk));
|
||||
|
||||
if (!blk_is_available(blk)) {
|
||||
error_report("Device '%s' has no medium", device);
|
||||
return;
|
||||
error_setg(&err, "Device '%s' has no medium", device);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = bdrv_commit(bs);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_report("'commit' error for '%s': %s", device, strerror(-ret));
|
||||
error_setg(&err, "'commit' error for '%s': %s", device, strerror(-ret));
|
||||
}
|
||||
|
||||
end:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
|
||||
|
|
@ -890,7 +891,7 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
|||
|
||||
bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, &err);
|
||||
if (!bs) {
|
||||
error_report_err(err);
|
||||
hmp_handle_error(mon, err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
66
block/qapi.c
66
block/qapi.c
|
|
@ -235,7 +235,8 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
|
|||
* in @info, setting @errp on error.
|
||||
*/
|
||||
static void GRAPH_RDLOCK
|
||||
bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
|
||||
bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, bool limits,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t size;
|
||||
const char *backing_filename;
|
||||
|
|
@ -269,6 +270,33 @@ bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
|
|||
info->dirty_flag = bdi.is_dirty;
|
||||
info->has_dirty_flag = true;
|
||||
}
|
||||
|
||||
if (limits) {
|
||||
info->limits = g_new(BlockLimitsInfo, 1);
|
||||
*info->limits = (BlockLimitsInfo) {
|
||||
.request_alignment = bs->bl.request_alignment,
|
||||
.has_max_discard = bs->bl.max_pdiscard != 0,
|
||||
.max_discard = bs->bl.max_pdiscard,
|
||||
.has_discard_alignment = bs->bl.pdiscard_alignment != 0,
|
||||
.discard_alignment = bs->bl.pdiscard_alignment,
|
||||
.has_max_write_zeroes = bs->bl.max_pwrite_zeroes != 0,
|
||||
.max_write_zeroes = bs->bl.max_pwrite_zeroes,
|
||||
.has_write_zeroes_alignment = bs->bl.pwrite_zeroes_alignment != 0,
|
||||
.write_zeroes_alignment = bs->bl.pwrite_zeroes_alignment,
|
||||
.has_opt_transfer = bs->bl.opt_transfer != 0,
|
||||
.opt_transfer = bs->bl.opt_transfer,
|
||||
.has_max_transfer = bs->bl.max_transfer != 0,
|
||||
.max_transfer = bs->bl.max_transfer,
|
||||
.has_max_hw_transfer = bs->bl.max_hw_transfer != 0,
|
||||
.max_hw_transfer = bs->bl.max_hw_transfer,
|
||||
.max_iov = bs->bl.max_iov,
|
||||
.has_max_hw_iov = bs->bl.max_hw_iov != 0,
|
||||
.max_hw_iov = bs->bl.max_hw_iov,
|
||||
.min_mem_alignment = bs->bl.min_mem_alignment,
|
||||
.opt_mem_alignment = bs->bl.opt_mem_alignment,
|
||||
};
|
||||
}
|
||||
|
||||
info->format_specific = bdrv_get_specific_info(bs, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
|
|
@ -343,7 +371,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
|||
ImageInfo *info;
|
||||
|
||||
info = g_new0(ImageInfo, 1);
|
||||
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
|
||||
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), true, errp);
|
||||
if (*errp) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -389,6 +417,7 @@ fail:
|
|||
*/
|
||||
void bdrv_query_block_graph_info(BlockDriverState *bs,
|
||||
BlockGraphInfo **p_info,
|
||||
bool limits,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
|
|
@ -397,7 +426,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
|
|||
BdrvChild *c;
|
||||
|
||||
info = g_new0(BlockGraphInfo, 1);
|
||||
bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
|
||||
bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), limits, errp);
|
||||
if (*errp) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -411,7 +440,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
|
|||
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);
|
||||
bdrv_query_block_graph_info(c->bs, &c_info->info, limits, errp);
|
||||
if (*errp) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -908,6 +937,29 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
|
|||
visit_free(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the given BlockLimitsInfo object in a human-readable form,
|
||||
* prepending an optional prefix if the dump is not empty.
|
||||
*/
|
||||
static void bdrv_image_info_limits_dump(BlockLimitsInfo *limits,
|
||||
const char *prefix,
|
||||
int indentation)
|
||||
{
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_BlockLimitsInfo(v, NULL, &limits, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
if (!qobject_is_empty_dump(obj)) {
|
||||
if (prefix) {
|
||||
qemu_printf("%*s%s", indentation * 4, "", prefix);
|
||||
}
|
||||
dump_qobject(indentation + 1, obj);
|
||||
}
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the given @info object in human-readable form. Every field is indented
|
||||
* using the given @indentation (four spaces per indentation level).
|
||||
|
|
@ -983,6 +1035,12 @@ void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol)
|
|||
}
|
||||
}
|
||||
|
||||
if (info->limits) {
|
||||
bdrv_image_info_limits_dump(info->limits,
|
||||
"Block limits:\n",
|
||||
indentation);
|
||||
}
|
||||
|
||||
if (info->has_snapshots) {
|
||||
SnapshotInfoList *elem;
|
||||
|
||||
|
|
|
|||
|
|
@ -617,7 +617,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
|||
|
||||
bs->detect_zeroes = detect_zeroes;
|
||||
|
||||
block_acct_setup(blk_get_stats(blk), account_invalid, account_failed);
|
||||
block_acct_setup(blk_get_stats(blk), account_invalid, account_failed,
|
||||
NULL, 0, NULL);
|
||||
|
||||
if (!parse_stats_intervals(blk_get_stats(blk), interval_list, errp)) {
|
||||
blk_unref(blk);
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ Command description:
|
|||
|
||||
The size syntax is similar to :manpage:`dd(1)`'s size syntax.
|
||||
|
||||
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [-U] FILENAME
|
||||
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-t CACHE] [-U] FILENAME
|
||||
|
||||
Give information about the disk image *FILENAME*. Use it in
|
||||
particular to know the size reserved on disk which can be different
|
||||
|
|
@ -571,6 +571,10 @@ Command description:
|
|||
``ImageInfoSpecific*`` QAPI object (e.g. ``ImageInfoSpecificQCow2``
|
||||
for qcow2 images).
|
||||
|
||||
*Block limits*
|
||||
The block limits for I/O that QEMU detected for the image.
|
||||
This information is only shown if the ``--limits`` option was specified.
|
||||
|
||||
.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME
|
||||
|
||||
Dump the metadata of image *FILENAME* and its backing file chain.
|
||||
|
|
|
|||
|
|
@ -249,8 +249,11 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
|
|||
blk_set_enable_write_cache(blk, wce);
|
||||
blk_set_on_error(blk, rerror, werror);
|
||||
|
||||
block_acct_setup(blk_get_stats(blk), conf->account_invalid,
|
||||
conf->account_failed);
|
||||
if (!block_acct_setup(blk_get_stats(blk), conf->account_invalid,
|
||||
conf->account_failed, conf->stats_intervals,
|
||||
conf->num_stats_intervals, errp)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,8 +101,9 @@ typedef struct BlockAcctCookie {
|
|||
} BlockAcctCookie;
|
||||
|
||||
void block_acct_init(BlockAcctStats *stats);
|
||||
void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
|
||||
enum OnOffAuto account_failed);
|
||||
bool block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
|
||||
enum OnOffAuto account_failed, uint32_t *stats_intervals,
|
||||
uint32_t num_stats_intervals, Error **errp);
|
||||
void block_acct_cleanup(BlockAcctStats *stats);
|
||||
void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length);
|
||||
BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats,
|
||||
|
|
|
|||
|
|
@ -817,10 +817,10 @@ typedef struct BlockLimits {
|
|||
int64_t max_pdiscard;
|
||||
|
||||
/*
|
||||
* Optimal alignment for discard requests in bytes. A power of 2
|
||||
* is best but not mandatory. Must be a multiple of
|
||||
* bl.request_alignment, and must be less than max_pdiscard if
|
||||
* that is set. May be 0 if bl.request_alignment is good enough
|
||||
* Optimal alignment for discard requests in bytes. Note that this doesn't
|
||||
* have to be a power of two. Must be a multiple of bl.request_alignment,
|
||||
* and must be less than max_pdiscard if that is set. May be 0 if
|
||||
* bl.request_alignment is good enough.
|
||||
*/
|
||||
uint32_t pdiscard_alignment;
|
||||
|
||||
|
|
@ -831,11 +831,10 @@ typedef struct BlockLimits {
|
|||
int64_t max_pwrite_zeroes;
|
||||
|
||||
/*
|
||||
* Optimal alignment for write zeroes requests in bytes. A power
|
||||
* of 2 is best but not mandatory. Must be a multiple of
|
||||
* bl.request_alignment, and must be less than max_pwrite_zeroes
|
||||
* if that is set. May be 0 if bl.request_alignment is good
|
||||
* enough
|
||||
* Optimal alignment for write zeroes requests in bytes. Note that this
|
||||
* doesn't have to be a power of two. Must be a multiple of
|
||||
* bl.request_alignment, and must be less than max_pwrite_zeroes if that is
|
||||
* set. May be 0 if bl.request_alignment is good enough.
|
||||
*/
|
||||
uint32_t pwrite_zeroes_alignment;
|
||||
|
||||
|
|
@ -863,18 +862,23 @@ typedef struct BlockLimits {
|
|||
uint64_t max_hw_transfer;
|
||||
|
||||
/*
|
||||
* Maximal number of scatter/gather elements allowed by the hardware.
|
||||
* Maximum number of scatter/gather elements allowed by the hardware.
|
||||
* Applies whenever transfers to the device bypass the kernel I/O
|
||||
* scheduler, for example with SG_IO. If larger than max_iov
|
||||
* or if zero, blk_get_max_hw_iov will fall back to max_iov.
|
||||
*/
|
||||
int max_hw_iov;
|
||||
|
||||
|
||||
/* memory alignment, in bytes so that no bounce buffer is needed */
|
||||
/*
|
||||
* Minimal required memory alignment in bytes for zero-copy I/O to succeed.
|
||||
* For unaligned requests, a bounce buffer will be used.
|
||||
*/
|
||||
size_t min_mem_alignment;
|
||||
|
||||
/* memory alignment, in bytes, for bounce buffer */
|
||||
/*
|
||||
* Optimal memory alignment in bytes. This is the alignment used for any
|
||||
* buffer allocations QEMU performs internally.
|
||||
*/
|
||||
size_t opt_mem_alignment;
|
||||
|
||||
/* maximum number of iovec elements */
|
||||
|
|
@ -1020,7 +1024,10 @@ struct BdrvChildClass {
|
|||
* the I/O API.
|
||||
*/
|
||||
|
||||
void (*resize)(BdrvChild *child);
|
||||
/*
|
||||
* Notifies the parent that the child was resized.
|
||||
*/
|
||||
void GRAPH_RDLOCK_PTR (*resize)(BdrvChild *child);
|
||||
|
||||
/*
|
||||
* Returns a name that is supposedly more useful for human users than the
|
||||
|
|
|
|||
|
|
@ -191,4 +191,10 @@ void bdrv_bsc_invalidate_range(BlockDriverState *bs,
|
|||
*/
|
||||
void bdrv_bsc_fill(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
||||
|
||||
/*
|
||||
* Notify all parents that the size of the child changed.
|
||||
*/
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_parent_cb_resize(BlockDriverState *bs);
|
||||
|
||||
#endif /* BLOCK_INT_IO_H */
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
|
|||
bool skip_implicit_filters, Error **errp);
|
||||
void GRAPH_RDLOCK
|
||||
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
|
||||
Error **errp);
|
||||
bool limits, Error **errp);
|
||||
|
||||
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
|
||||
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ typedef struct BlockConf {
|
|||
OnOffAuto account_invalid, account_failed;
|
||||
BlockdevOnError rerror;
|
||||
BlockdevOnError werror;
|
||||
uint32_t num_stats_intervals;
|
||||
uint32_t *stats_intervals;
|
||||
} BlockConf;
|
||||
|
||||
static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
||||
|
|
@ -66,7 +68,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|||
DEFINE_PROP_ON_OFF_AUTO("account-invalid", _state, \
|
||||
_conf.account_invalid, ON_OFF_AUTO_AUTO), \
|
||||
DEFINE_PROP_ON_OFF_AUTO("account-failed", _state, \
|
||||
_conf.account_failed, ON_OFF_AUTO_AUTO)
|
||||
_conf.account_failed, ON_OFF_AUTO_AUTO), \
|
||||
DEFINE_PROP_ARRAY("stats-intervals", _state, \
|
||||
_conf.num_stats_intervals, _conf.stats_intervals, \
|
||||
qdev_prop_uint32, uint32_t)
|
||||
|
||||
#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
|
||||
|
|
|
|||
|
|
@ -275,6 +275,69 @@
|
|||
'file': 'ImageInfoSpecificFileWrapper'
|
||||
} }
|
||||
|
||||
##
|
||||
# @BlockLimitsInfo:
|
||||
#
|
||||
# @request-alignment: Alignment requirement, in bytes, for
|
||||
# offset/length of I/O requests.
|
||||
#
|
||||
# @max-discard: Maximum number of bytes that can be discarded at once.
|
||||
# If not present, there is no specific maximum.
|
||||
#
|
||||
# @discard-alignment: Optimal alignment for discard requests in bytes.
|
||||
# Note that this doesn't have to be a power of two. If not
|
||||
# present, discards don't have a alignment requirement different
|
||||
# from @request-alignment.
|
||||
#
|
||||
# @max-write-zeroes: Maximum number of bytes that can be zeroed out at
|
||||
# once. If not present, there is no specific maximum.
|
||||
#
|
||||
# @write-zeroes-alignment: Optimal alignment for write zeroes requests
|
||||
# in bytes. Note that this doesn't have to be a power of two. If
|
||||
# not present, write_zeroes doesn't have a alignment requirement
|
||||
# different from @request-alignment.
|
||||
#
|
||||
# @opt-transfer: Optimal transfer length in bytes. If not present,
|
||||
# there is no preferred size.
|
||||
#
|
||||
# @max-transfer: Maximal transfer length in bytes. If not present,
|
||||
# there is no specific maximum.
|
||||
#
|
||||
# @max-hw-transfer: Maximal hardware transfer length in bytes.
|
||||
# Applies whenever transfers to the device bypass the kernel I/O
|
||||
# scheduler, for example with SG_IO. If not present, there is no
|
||||
# specific maximum.
|
||||
#
|
||||
# @max-iov: Maximum number of scatter/gather elements
|
||||
#
|
||||
# @max-hw-iov: Maximum number of scatter/gather elements allowed by
|
||||
# the hardware. Applies whenever transfers to the device bypass
|
||||
# the kernel I/O scheduler, for example with SG_IO. If not
|
||||
# present, the hardware limits is unknown and @max-iov is always
|
||||
# used.
|
||||
#
|
||||
# @min-mem-alignment: Minimal required memory alignment in bytes for
|
||||
# zero-copy I/O to succeed. For unaligned requests, a bounce
|
||||
# buffer will be used.
|
||||
#
|
||||
# @opt-mem-alignment: Optimal memory alignment in bytes. This is the
|
||||
# alignment used for any buffer allocations QEMU performs
|
||||
# internally.
|
||||
##
|
||||
{ 'struct': 'BlockLimitsInfo',
|
||||
'data': { 'request-alignment': 'uint32',
|
||||
'*max-discard': 'uint64',
|
||||
'*discard-alignment': 'uint32',
|
||||
'*max-write-zeroes': 'uint64',
|
||||
'*write-zeroes-alignment': 'uint32',
|
||||
'*opt-transfer': 'uint32',
|
||||
'*max-transfer': 'uint32',
|
||||
'*max-hw-transfer': 'uint32',
|
||||
'max-iov': 'int',
|
||||
'*max-hw-iov': 'int',
|
||||
'min-mem-alignment': 'size',
|
||||
'opt-mem-alignment': 'size' } }
|
||||
|
||||
##
|
||||
# @BlockNodeInfo:
|
||||
#
|
||||
|
|
@ -304,6 +367,8 @@
|
|||
#
|
||||
# @snapshots: list of VM snapshots
|
||||
#
|
||||
# @limits: block limits that are used for I/O on the node (Since 10.2)
|
||||
#
|
||||
# @format-specific: structure supplying additional format-specific
|
||||
# information (since 1.7)
|
||||
#
|
||||
|
|
@ -315,6 +380,7 @@
|
|||
'*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
|
||||
'*backing-filename': 'str', '*full-backing-filename': 'str',
|
||||
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
|
||||
'*limits': 'BlockLimitsInfo',
|
||||
'*format-specific': 'ImageInfoSpecific' } }
|
||||
|
||||
##
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ SRST
|
|||
ERST
|
||||
|
||||
DEF("info", img_info,
|
||||
"info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [-U] filename")
|
||||
"info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [--limits] [-t CACHE] [-U] filename")
|
||||
SRST
|
||||
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [-U] FILENAME
|
||||
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-t CACHE] [-U] FILENAME
|
||||
ERST
|
||||
|
||||
DEF("map", img_map,
|
||||
|
|
|
|||
40
qemu-img.c
40
qemu-img.c
|
|
@ -86,6 +86,7 @@ enum {
|
|||
OPTION_BITMAPS = 275,
|
||||
OPTION_FORCE = 276,
|
||||
OPTION_SKIP_BROKEN = 277,
|
||||
OPTION_LIMITS = 278,
|
||||
};
|
||||
|
||||
typedef enum OutputFormat {
|
||||
|
|
@ -3002,12 +3003,23 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
|
|||
static BlockGraphInfoList *collect_image_info_list(bool image_opts,
|
||||
const char *filename,
|
||||
const char *fmt,
|
||||
bool chain, bool force_share)
|
||||
const char *cache,
|
||||
bool chain, bool limits,
|
||||
bool force_share)
|
||||
{
|
||||
BlockGraphInfoList *head = NULL;
|
||||
BlockGraphInfoList **tail = &head;
|
||||
GHashTable *filenames;
|
||||
Error *err = NULL;
|
||||
int cache_flags = 0;
|
||||
bool writethrough = false;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_parse_cache_mode(cache, &cache_flags, &writethrough);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid cache option: %s", cache);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
|
||||
|
||||
|
|
@ -3024,8 +3036,8 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
|
|||
g_hash_table_insert(filenames, (gpointer)filename, NULL);
|
||||
|
||||
blk = img_open(image_opts, filename, fmt,
|
||||
BDRV_O_NO_BACKING | BDRV_O_NO_IO, false, false,
|
||||
force_share);
|
||||
BDRV_O_NO_BACKING | BDRV_O_NO_IO | cache_flags,
|
||||
writethrough, false, force_share);
|
||||
if (!blk) {
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -3039,7 +3051,7 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
|
|||
* the chain manually here.
|
||||
*/
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
bdrv_query_block_graph_info(bs, &info, &err);
|
||||
bdrv_query_block_graph_info(bs, &info, limits, &err);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
if (err) {
|
||||
|
|
@ -3085,9 +3097,11 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
|
|||
OutputFormat output_format = OFORMAT_HUMAN;
|
||||
bool chain = false;
|
||||
const char *filename, *fmt;
|
||||
const char *cache = BDRV_DEFAULT_CACHE;
|
||||
BlockGraphInfoList *list;
|
||||
bool image_opts = false;
|
||||
bool force_share = false;
|
||||
bool limits = false;
|
||||
|
||||
fmt = NULL;
|
||||
for(;;) {
|
||||
|
|
@ -3096,12 +3110,14 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
|
|||
{"format", required_argument, 0, 'f'},
|
||||
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
|
||||
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
|
||||
{"cache", required_argument, 0, 't'},
|
||||
{"force-share", no_argument, 0, 'U'},
|
||||
{"limits", no_argument, 0, OPTION_LIMITS},
|
||||
{"output", required_argument, 0, OPTION_OUTPUT},
|
||||
{"object", required_argument, 0, OPTION_OBJECT},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, "hf:U", long_options, NULL);
|
||||
c = getopt_long(argc, argv, "hf:t:U", long_options, NULL);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -3117,8 +3133,12 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
|
|||
" (incompatible with -f|--format)\n"
|
||||
" --backing-chain\n"
|
||||
" display information about the backing chain for copy-on-write overlays\n"
|
||||
" -t, --cache CACHE\n"
|
||||
" cache mode for FILE (default: " BDRV_DEFAULT_CACHE ")\n"
|
||||
" -U, --force-share\n"
|
||||
" open image in shared mode for concurrent access\n"
|
||||
" --limits\n"
|
||||
" show detected block limits (may depend on options, e.g. cache mode)\n"
|
||||
" --output human|json\n"
|
||||
" specify output format (default: human)\n"
|
||||
" --object OBJDEF\n"
|
||||
|
|
@ -3137,9 +3157,15 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
|
|||
case OPTION_BACKING_CHAIN:
|
||||
chain = true;
|
||||
break;
|
||||
case 't':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'U':
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_LIMITS:
|
||||
limits = true;
|
||||
break;
|
||||
case OPTION_OUTPUT:
|
||||
output_format = parse_output_format(argv[0], optarg);
|
||||
break;
|
||||
|
|
@ -3155,8 +3181,8 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
|
|||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
list = collect_image_info_list(image_opts, filename, fmt, chain,
|
||||
force_share);
|
||||
list = collect_image_info_list(image_opts, filename, fmt, cache, chain,
|
||||
limits, force_share);
|
||||
if (!list) {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,6 @@ Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
|
|||
{'execute': 'quit'}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ QMP_VERSION
|
|||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
*** done
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ Testing:
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ Testing: -fda TEST_DIR/t.qcow2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -95,6 +97,7 @@ Testing: -fdb TEST_DIR/t.qcow2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -109,6 +112,7 @@ Testing: -fdb TEST_DIR/t.qcow2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -149,6 +153,7 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -163,6 +168,7 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -204,6 +210,7 @@ Testing: -fdb
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -218,6 +225,7 @@ Testing: -fdb
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
|
||||
|
||||
|
|
@ -247,6 +255,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -283,6 +292,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -297,6 +307,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -337,6 +348,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -351,6 +363,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -395,6 +408,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -431,6 +445,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -467,6 +482,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -481,6 +497,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -531,6 +548,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -545,6 +563,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -586,6 +605,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -600,6 +620,7 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -641,6 +662,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 1 (0x1)
|
||||
|
|
@ -655,6 +677,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -696,6 +719,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 1 (0x1)
|
||||
|
|
@ -710,6 +734,7 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -760,6 +785,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -774,6 +800,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -815,6 +842,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
dev: floppy, id ""
|
||||
unit = 0 (0x0)
|
||||
|
|
@ -829,6 +857,7 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/unattached/device[N]
|
||||
|
|
@ -876,6 +905,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -942,6 +972,7 @@ Testing: -device floppy
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
|
||||
Testing: -device floppy,drive-type=120
|
||||
|
|
@ -968,6 +999,7 @@ Testing: -device floppy,drive-type=120
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "120"
|
||||
|
||||
Testing: -device floppy,drive-type=144
|
||||
|
|
@ -994,6 +1026,7 @@ Testing: -device floppy,drive-type=144
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
|
||||
Testing: -device floppy,drive-type=288
|
||||
|
|
@ -1020,6 +1053,7 @@ Testing: -device floppy,drive-type=288
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
|
||||
|
||||
|
|
@ -1049,6 +1083,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "120"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -1085,6 +1120,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "288"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -1124,6 +1160,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
@ -1160,6 +1197,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
|
|||
share-rw = false
|
||||
account-invalid = "auto"
|
||||
account-failed = "auto"
|
||||
stats-intervals = <null>
|
||||
drive-type = "144"
|
||||
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
|
||||
Attached to: /machine/peripheral-anon/device[N]
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ do_run_qemu()
|
|||
|
||||
run_qemu()
|
||||
{
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
|
||||
| _filter_qemu_io | _filter_generated_node_ids
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp \
|
||||
| _filter_qemu_io | _filter_generated_node_ids \
|
||||
| _filter_img_info
|
||||
}
|
||||
|
||||
test_throttle=$($QEMU_IMG --help|grep throttle)
|
||||
|
|
|
|||
|
|
@ -41,12 +41,6 @@ Testing:
|
|||
},
|
||||
"iops_wr": 0,
|
||||
"ro": false,
|
||||
"children": [
|
||||
{
|
||||
"node-name": "disk0",
|
||||
"child": "file"
|
||||
}
|
||||
],
|
||||
"node-name": "throttle0",
|
||||
"backing_file_depth": 1,
|
||||
"drv": "throttle",
|
||||
|
|
@ -75,8 +69,6 @@ Testing:
|
|||
},
|
||||
"iops_wr": 0,
|
||||
"ro": false,
|
||||
"children": [
|
||||
],
|
||||
"node-name": "disk0",
|
||||
"backing_file_depth": 0,
|
||||
"drv": "null-co",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
(qemu) savevm snap0
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) info snapshots
|
||||
no block device can store vmstate for snapshot
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) loadvm snap0
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) quit
|
||||
|
|
@ -22,7 +22,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
(qemu) savevm snap0
|
||||
Error: Device 'none0' is writable but does not support snapshots
|
||||
(qemu) info snapshots
|
||||
no block device can store vmstate for snapshot
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) loadvm snap0
|
||||
Error: Device 'none0' is writable but does not support snapshots
|
||||
(qemu) quit
|
||||
|
|
@ -58,7 +58,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
(qemu) savevm snap0
|
||||
Error: Device 'virtio0' is writable but does not support snapshots
|
||||
(qemu) info snapshots
|
||||
no block device can store vmstate for snapshot
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) loadvm snap0
|
||||
Error: Device 'virtio0' is writable but does not support snapshots
|
||||
(qemu) quit
|
||||
|
|
@ -83,7 +83,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
(qemu) savevm snap0
|
||||
Error: Device 'file' is writable but does not support snapshots
|
||||
(qemu) info snapshots
|
||||
no block device can store vmstate for snapshot
|
||||
Error: no block device can store vmstate for snapshot
|
||||
(qemu) loadvm snap0
|
||||
Error: Device 'file' is writable but does not support snapshots
|
||||
(qemu) quit
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ _filter_img_info()
|
|||
discard=0
|
||||
regex_json_spec_start='^ *"format-specific": \{'
|
||||
regex_json_child_start='^ *"children": \['
|
||||
regex_json_limit_start='^ *"limits": \{'
|
||||
gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$TEST_DIR#TEST_DIR#g" \
|
||||
|
|
@ -261,7 +262,7 @@ _filter_img_info()
|
|||
discard=1
|
||||
elif [[ $line =~ "Child node '/" ]]; then
|
||||
discard=1
|
||||
elif [[ $line =~ $regex_json_spec_start ]]; then
|
||||
elif [[ $line =~ $regex_json_spec_start || $line =~ $regex_json_limit_start ]]; then
|
||||
discard=2
|
||||
regex_json_end="^${line%%[^ ]*}\\},? *$"
|
||||
elif [[ $line =~ $regex_json_child_start ]]; then
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ stat: cannot statx 'fuse-export': Permission denied
|
|||
cat: fuse-export: Permission denied
|
||||
stat: cannot statx 'fuse-export': Permission denied
|
||||
{'execute': 'quit'}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}}
|
||||
{"return": {}}
|
||||
|
||||
--- allow-other=on ---
|
||||
{'execute': 'qmp_capabilities'}
|
||||
|
|
@ -55,9 +55,9 @@ Permissions seen by nobody: 444
|
|||
cat: fuse-export: Permission denied
|
||||
Permissions seen by nobody: 440
|
||||
{'execute': 'quit'}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}}
|
||||
{"return": {}}
|
||||
|
||||
--- allow-other=auto ---
|
||||
{'execute': 'qmp_capabilities'}
|
||||
|
|
@ -82,7 +82,7 @@ Permissions seen by nobody: 444
|
|||
cat: fuse-export: Permission denied
|
||||
Permissions seen by nobody: 440
|
||||
{'execute': 'quit'}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from iotests import QemuIoInteractive
|
|||
from iotests import filter_qemu_io, filter_qtest, filter_qmp_testfiles
|
||||
|
||||
iotests.script_initialize(supported_fmts=['generic'],
|
||||
unsupported_fmts=['luks'],
|
||||
supported_protocols=['file'],
|
||||
supported_platforms=['linux'])
|
||||
|
||||
|
|
|
|||
73
tests/qemu-iotests/tests/resize-below-filter
Executable file
73
tests/qemu-iotests/tests/resize-below-filter
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env python3
|
||||
# group: rw quick
|
||||
#
|
||||
# Test what happens when a node below filter nodes is resized.
|
||||
#
|
||||
# Copyright (C) Proxmox Server Solutions GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import iotests
|
||||
from iotests import imgfmt, qemu_img_create, QMPTestCase
|
||||
|
||||
image_size = 1 * 1024 * 1024
|
||||
image = os.path.join(iotests.test_dir, 'test.img')
|
||||
|
||||
class TestResizeBelowFilter(QMPTestCase):
|
||||
def setUp(self) -> None:
|
||||
qemu_img_create('-f', imgfmt, image, str(image_size))
|
||||
|
||||
self.vm = iotests.VM()
|
||||
self.vm.add_blockdev(self.vm.qmp_to_opts({
|
||||
'driver': imgfmt,
|
||||
'node-name': 'node0',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': image,
|
||||
}
|
||||
}))
|
||||
self.vm.add_blockdev(self.vm.qmp_to_opts({
|
||||
'driver': 'compress',
|
||||
'node-name': 'comp0',
|
||||
'file': 'node0',
|
||||
}))
|
||||
self.vm.add_object('throttle-group,id=thrgr0')
|
||||
self.vm.add_blockdev(self.vm.qmp_to_opts({
|
||||
'driver': 'throttle',
|
||||
'node-name': 'thr0',
|
||||
'throttle-group': 'thrgr0',
|
||||
'file': 'comp0',
|
||||
}))
|
||||
self.vm.add_object('throttle-group,id=thrgr1')
|
||||
self.vm.add_blockdev(self.vm.qmp_to_opts({
|
||||
'driver': 'throttle',
|
||||
'node-name': 'thr1',
|
||||
'throttle-group': 'thrgr1',
|
||||
'file': 'node0',
|
||||
}))
|
||||
self.vm.launch()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.vm.shutdown()
|
||||
os.remove(image)
|
||||
|
||||
def assert_size(self, size: int) -> None:
|
||||
nodes = self.vm.qmp('query-named-block-nodes', flat=True)['return']
|
||||
self.assertEqual(len(nodes), 5)
|
||||
for node in nodes:
|
||||
if node['drv'] == 'file':
|
||||
continue
|
||||
self.assertEqual(node['image']['virtual-size'], size)
|
||||
|
||||
def test_resize_below_filter(self) -> None:
|
||||
self.assert_size(image_size)
|
||||
self.vm.qmp('block_resize', node_name='thr0', size=2*image_size)
|
||||
self.assert_size(2*image_size)
|
||||
self.vm.qmp('block_resize', node_name='comp0', size=3*image_size)
|
||||
self.assert_size(3*image_size)
|
||||
self.vm.qmp('block_resize', node_name='node0', size=4*image_size)
|
||||
self.assert_size(4*image_size)
|
||||
|
||||
if __name__ == '__main__':
|
||||
iotests.main(supported_fmts=['qcow2'], supported_protocols=['file'])
|
||||
5
tests/qemu-iotests/tests/resize-below-filter.out
Normal file
5
tests/qemu-iotests/tests/resize-below-filter.out
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 tests
|
||||
|
||||
OK
|
||||
53
tests/qemu-iotests/tests/resize-below-raw
Executable file
53
tests/qemu-iotests/tests/resize-below-raw
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python3
|
||||
# group: rw quick
|
||||
#
|
||||
# Test what happens when a 'file' node below a 'raw' node is resized.
|
||||
#
|
||||
# Copyright (C) Proxmox Server Solutions GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import iotests
|
||||
from iotests import imgfmt, qemu_img_create, QMPTestCase
|
||||
|
||||
image_size = 1 * 1024 * 1024
|
||||
image = os.path.join(iotests.test_dir, 'test.img')
|
||||
|
||||
class TestResizeBelowRaw(QMPTestCase):
|
||||
def setUp(self) -> None:
|
||||
qemu_img_create('-f', imgfmt, image, str(image_size))
|
||||
|
||||
self.vm = iotests.VM()
|
||||
self.vm.add_blockdev(self.vm.qmp_to_opts({
|
||||
'driver': imgfmt,
|
||||
'node-name': 'node0',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': image,
|
||||
'node-name': 'file0',
|
||||
}
|
||||
}))
|
||||
self.vm.launch()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.vm.shutdown()
|
||||
os.remove(image)
|
||||
|
||||
def assert_size(self, size: int) -> None:
|
||||
nodes = self.vm.qmp('query-named-block-nodes', flat=True)['return']
|
||||
self.assertEqual(len(nodes), 2)
|
||||
for node in nodes:
|
||||
if node['drv'] == 'file':
|
||||
continue
|
||||
self.assertEqual(node['image']['virtual-size'], size)
|
||||
|
||||
def test_resize_below_raw(self) -> None:
|
||||
self.assert_size(image_size)
|
||||
self.vm.qmp('block_resize', node_name='file0', size=2*image_size)
|
||||
self.assert_size(2*image_size)
|
||||
self.vm.qmp('block_resize', node_name='node0', size=3*image_size)
|
||||
self.assert_size(3*image_size)
|
||||
|
||||
if __name__ == '__main__':
|
||||
iotests.main(supported_fmts=['raw'], supported_protocols=['file'])
|
||||
5
tests/qemu-iotests/tests/resize-below-raw.out
Normal file
5
tests/qemu-iotests/tests/resize-below-raw.out
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 tests
|
||||
|
||||
OK
|
||||
Loading…
Add table
Add a link
Reference in a new issue