Block layer patches:
- Remove deprecated -drive options for geometry/serial/addr - luks: Allow shared writers if the parents allow them (share-rw=on) - qemu-img: Fix error when trying to convert to encrypted target image - mirror: Fail gracefully for source == target - I/O throttling: Fix behaviour during drain (always ignore the limits) - bdrv_reopen() related fixes for bs->options/explicit_options content - Documentation improvements -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbdApvAAoJEH8JsnLIjy/WJB8P/3JX843sJCKXG2GijuEvgblB QEJrMowaxWea7LSwc4DoU3Bduj/xri05w3dFvkKzrW+dk7wJB5hb8rfTcROVGP9X IByZW/Bqom41kvKCshbaGa7WsaOEu24/nW/pzn69iBpEQdZv5xrM1CAVHwlBgKtf Rc/angKQRE4Lm12Jb40R/r/Fnr1JTRDzb6rwk4w3zOeeKVPYxWT1F6Jk8XJC+R0W n6fGl6FRiv6kue7UkWrjpASOdKhsZSla0M8nyE/ABuHFXFIcwusPuWkm+qXMWlbH uXRTLfnzc3brzn4IYR1VVbHCZUBLpyfeuE5S5a8kHFTjLYnNzZH0Crdh7ofpYTnV AsyL1xnAI238XhExV37c7vnIn9UsYBRm8KrFmFYuGQ2PYFNTUrVRmKAUhh4m89jw vXhmQckhefyyLRwL/4OQqzbBuDhCewXyBFkj9kq9FonFLmWUo5VzpMUbTYw47QAB Y/hDYz854UCxoPU/tqevAcpKBgK3rFIXfHcsxqcnsQrqQwgEjhJnNzNwEl+VQWER nYxad9L91BDjYZiW0MKjqF9d6jKKFVO9HYFY62pYSM5lwkHCirs2j39kfEaWK46T 6WZWSoLNB0uUt9WUn1uM3uo6UWlUWEyEoV9XsKQCzx/XRuLoxMhfTUkMAgMcjqaD hXcLbldpvtpXj8YAdn8/ =aYYo -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - Remove deprecated -drive options for geometry/serial/addr - luks: Allow shared writers if the parents allow them (share-rw=on) - qemu-img: Fix error when trying to convert to encrypted target image - mirror: Fail gracefully for source == target - I/O throttling: Fix behaviour during drain (always ignore the limits) - bdrv_reopen() related fixes for bs->options/explicit_options content - Documentation improvements # gpg: Signature made Wed 15 Aug 2018 12:11:43 BST # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (21 commits) qapi: block: Remove mentions of error types which were removed block: Simplify append_open_options() block: Update bs->options if bdrv_reopen() succeeds block: Simplify bdrv_reopen_abort() block: Remove children options from bs->{options,explicit_options} qdict: Make qdict_extract_subqdict() accept dst = NULL block: drop empty .bdrv_close handlers block: make .bdrv_close optional qemu-img: fix regression copying secrets during convert mirror: Fail gracefully for source == target qapi/block: Document restrictions for node names block: Remove dead deprecation warning code block: Remove deprecated -drive option serial block: Remove deprecated -drive option addr block: Remove deprecated -drive geometry options luks: Allow share-rw=on throttle-groups: Don't allow timers without throttled requests qemu-iotests: Update 093 to improve the draining test throttle-groups: Skip the round-robin if a member is being drained qemu-iotests: Test removing a throttle group member with a pending timer ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d3bd57d9f6
46
block.c
46
block.c
|
@ -2584,6 +2584,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||||
BlockBackend *file = NULL;
|
BlockBackend *file = NULL;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriver *drv = NULL;
|
BlockDriver *drv = NULL;
|
||||||
|
BdrvChild *child;
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
const char *backing;
|
const char *backing;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
@ -2767,6 +2768,15 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove all children options from bs->options and bs->explicit_options */
|
||||||
|
QLIST_FOREACH(child, &bs->children, next) {
|
||||||
|
char *child_key_dot;
|
||||||
|
child_key_dot = g_strdup_printf("%s.", child->name);
|
||||||
|
qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
|
||||||
|
qdict_extract_subqdict(bs->options, NULL, child_key_dot);
|
||||||
|
g_free(child_key_dot);
|
||||||
|
}
|
||||||
|
|
||||||
bdrv_refresh_filename(bs);
|
bdrv_refresh_filename(bs);
|
||||||
|
|
||||||
/* Check if any unknown options were used */
|
/* Check if any unknown options were used */
|
||||||
|
@ -2976,6 +2986,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
child_key_dot = g_strdup_printf("%s.", child->name);
|
child_key_dot = g_strdup_printf("%s.", child->name);
|
||||||
|
qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
|
||||||
qdict_extract_subqdict(options, &new_child_options, child_key_dot);
|
qdict_extract_subqdict(options, &new_child_options, child_key_dot);
|
||||||
g_free(child_key_dot);
|
g_free(child_key_dot);
|
||||||
|
|
||||||
|
@ -3039,12 +3050,13 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||||
if (ret && bs_entry->prepared) {
|
if (ret) {
|
||||||
bdrv_reopen_abort(&bs_entry->state);
|
if (bs_entry->prepared) {
|
||||||
} else if (ret) {
|
bdrv_reopen_abort(&bs_entry->state);
|
||||||
|
}
|
||||||
qobject_unref(bs_entry->state.explicit_options);
|
qobject_unref(bs_entry->state.explicit_options);
|
||||||
|
qobject_unref(bs_entry->state.options);
|
||||||
}
|
}
|
||||||
qobject_unref(bs_entry->state.options);
|
|
||||||
g_free(bs_entry);
|
g_free(bs_entry);
|
||||||
}
|
}
|
||||||
g_free(bs_queue);
|
g_free(bs_queue);
|
||||||
|
@ -3144,6 +3156,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
QDict *orig_reopen_opts;
|
||||||
const char *value;
|
const char *value;
|
||||||
bool read_only;
|
bool read_only;
|
||||||
|
|
||||||
|
@ -3151,6 +3164,11 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||||
assert(reopen_state->bs->drv != NULL);
|
assert(reopen_state->bs->drv != NULL);
|
||||||
drv = reopen_state->bs->drv;
|
drv = reopen_state->bs->drv;
|
||||||
|
|
||||||
|
/* This function and each driver's bdrv_reopen_prepare() remove
|
||||||
|
* entries from reopen_state->options as they are processed, so
|
||||||
|
* we need to make a copy of the original QDict. */
|
||||||
|
orig_reopen_opts = qdict_clone_shallow(reopen_state->options);
|
||||||
|
|
||||||
/* Process generic block layer options */
|
/* Process generic block layer options */
|
||||||
opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
|
opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
|
||||||
qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err);
|
qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err);
|
||||||
|
@ -3257,8 +3275,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
/* Restore the original reopen_state->options QDict */
|
||||||
|
qobject_unref(reopen_state->options);
|
||||||
|
reopen_state->options = qobject_ref(orig_reopen_opts);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
|
qobject_unref(orig_reopen_opts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3288,8 +3311,10 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
||||||
|
|
||||||
/* set BDS specific flags now */
|
/* set BDS specific flags now */
|
||||||
qobject_unref(bs->explicit_options);
|
qobject_unref(bs->explicit_options);
|
||||||
|
qobject_unref(bs->options);
|
||||||
|
|
||||||
bs->explicit_options = reopen_state->explicit_options;
|
bs->explicit_options = reopen_state->explicit_options;
|
||||||
|
bs->options = reopen_state->options;
|
||||||
bs->open_flags = reopen_state->flags;
|
bs->open_flags = reopen_state->flags;
|
||||||
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
|
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
|
||||||
|
|
||||||
|
@ -3330,8 +3355,6 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
|
||||||
drv->bdrv_reopen_abort(reopen_state);
|
drv->bdrv_reopen_abort(reopen_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
qobject_unref(reopen_state->explicit_options);
|
|
||||||
|
|
||||||
bdrv_abort_perm_update(reopen_state->bs);
|
bdrv_abort_perm_update(reopen_state->bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3349,7 +3372,9 @@ static void bdrv_close(BlockDriverState *bs)
|
||||||
bdrv_drain(bs); /* in case flush left pending I/O */
|
bdrv_drain(bs); /* in case flush left pending I/O */
|
||||||
|
|
||||||
if (bs->drv) {
|
if (bs->drv) {
|
||||||
bs->drv->bdrv_close(bs);
|
if (bs->drv->bdrv_close) {
|
||||||
|
bs->drv->bdrv_close(bs);
|
||||||
|
}
|
||||||
bs->drv = NULL;
|
bs->drv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5125,16 +5150,13 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
|
||||||
QemuOptDesc *desc;
|
QemuOptDesc *desc;
|
||||||
BdrvChild *child;
|
BdrvChild *child;
|
||||||
bool found_any = false;
|
bool found_any = false;
|
||||||
const char *p;
|
|
||||||
|
|
||||||
for (entry = qdict_first(bs->options); entry;
|
for (entry = qdict_first(bs->options); entry;
|
||||||
entry = qdict_next(bs->options, entry))
|
entry = qdict_next(bs->options, entry))
|
||||||
{
|
{
|
||||||
/* Exclude options for children */
|
/* Exclude node-name references to children */
|
||||||
QLIST_FOREACH(child, &bs->children, next) {
|
QLIST_FOREACH(child, &bs->children, next) {
|
||||||
if (strstart(qdict_entry_key(entry), child->name, &p)
|
if (!strcmp(entry->key, child->name)) {
|
||||||
&& (!*p || *p == '.'))
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,6 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blkreplay_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t blkreplay_getlength(BlockDriverState *bs)
|
static int64_t blkreplay_getlength(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
return bdrv_getlength(bs->file->bs);
|
return bdrv_getlength(bs->file->bs);
|
||||||
|
@ -135,7 +131,6 @@ static BlockDriver bdrv_blkreplay = {
|
||||||
.instance_size = 0,
|
.instance_size = 0,
|
||||||
|
|
||||||
.bdrv_open = blkreplay_open,
|
.bdrv_open = blkreplay_open,
|
||||||
.bdrv_close = blkreplay_close,
|
|
||||||
.bdrv_child_perm = bdrv_filter_default_perms,
|
.bdrv_child_perm = bdrv_filter_default_perms,
|
||||||
.bdrv_getlength = blkreplay_getlength,
|
.bdrv_getlength = blkreplay_getlength,
|
||||||
|
|
||||||
|
|
|
@ -419,7 +419,6 @@ static void drive_info_del(DriveInfo *dinfo)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qemu_opts_del(dinfo->opts);
|
qemu_opts_del(dinfo->opts);
|
||||||
g_free(dinfo->serial);
|
|
||||||
g_free(dinfo);
|
g_free(dinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,10 +239,6 @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
|
||||||
bs->backing->bs->filename);
|
bs->backing->bs->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdrv_commit_top_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||||
const BdrvChildRole *role,
|
const BdrvChildRole *role,
|
||||||
BlockReopenQueue *reopen_queue,
|
BlockReopenQueue *reopen_queue,
|
||||||
|
@ -260,7 +256,6 @@ static BlockDriver bdrv_commit_top = {
|
||||||
.bdrv_co_preadv = bdrv_commit_top_preadv,
|
.bdrv_co_preadv = bdrv_commit_top_preadv,
|
||||||
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
||||||
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
|
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
|
||||||
.bdrv_close = bdrv_commit_top_close,
|
|
||||||
.bdrv_child_perm = bdrv_commit_top_child_perm,
|
.bdrv_child_perm = bdrv_commit_top_child_perm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,6 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cor_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define PERM_PASSTHROUGH (BLK_PERM_CONSISTENT_READ \
|
#define PERM_PASSTHROUGH (BLK_PERM_CONSISTENT_READ \
|
||||||
| BLK_PERM_WRITE \
|
| BLK_PERM_WRITE \
|
||||||
| BLK_PERM_RESIZE)
|
| BLK_PERM_RESIZE)
|
||||||
|
@ -143,7 +138,6 @@ BlockDriver bdrv_copy_on_read = {
|
||||||
.format_name = "copy-on-read",
|
.format_name = "copy-on-read",
|
||||||
|
|
||||||
.bdrv_open = cor_open,
|
.bdrv_open = cor_open,
|
||||||
.bdrv_close = cor_close,
|
|
||||||
.bdrv_child_perm = cor_child_perm,
|
.bdrv_child_perm = cor_child_perm,
|
||||||
|
|
||||||
.bdrv_getlength = cor_getlength,
|
.bdrv_getlength = cor_getlength,
|
||||||
|
|
|
@ -627,7 +627,9 @@ BlockDriver bdrv_crypto_luks = {
|
||||||
.bdrv_probe = block_crypto_probe_luks,
|
.bdrv_probe = block_crypto_probe_luks,
|
||||||
.bdrv_open = block_crypto_open_luks,
|
.bdrv_open = block_crypto_open_luks,
|
||||||
.bdrv_close = block_crypto_close,
|
.bdrv_close = block_crypto_close,
|
||||||
.bdrv_child_perm = bdrv_format_default_perms,
|
/* This driver doesn't modify LUKS metadata except when creating image.
|
||||||
|
* Allow share-rw=on as a special case. */
|
||||||
|
.bdrv_child_perm = bdrv_filter_default_perms,
|
||||||
.bdrv_co_create = block_crypto_co_create_luks,
|
.bdrv_co_create = block_crypto_co_create_luks,
|
||||||
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
|
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
|
||||||
.bdrv_co_truncate = block_crypto_co_truncate,
|
.bdrv_co_truncate = block_crypto_co_truncate,
|
||||||
|
|
|
@ -1426,10 +1426,6 @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
|
||||||
bs->backing->bs->filename);
|
bs->backing->bs->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdrv_mirror_top_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||||
const BdrvChildRole *role,
|
const BdrvChildRole *role,
|
||||||
BlockReopenQueue *reopen_queue,
|
BlockReopenQueue *reopen_queue,
|
||||||
|
@ -1456,7 +1452,6 @@ static BlockDriver bdrv_mirror_top = {
|
||||||
.bdrv_co_flush = bdrv_mirror_top_flush,
|
.bdrv_co_flush = bdrv_mirror_top_flush,
|
||||||
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
||||||
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
|
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
|
||||||
.bdrv_close = bdrv_mirror_top_close,
|
|
||||||
.bdrv_child_perm = bdrv_mirror_top_child_perm,
|
.bdrv_child_perm = bdrv_mirror_top_child_perm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1499,6 +1494,11 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||||
buf_size = DEFAULT_MIRROR_BUF_SIZE;
|
buf_size = DEFAULT_MIRROR_BUF_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs == target) {
|
||||||
|
error_setg(errp, "Can't mirror node into itself");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* In the case of active commit, add dummy driver to provide consistent
|
/* In the case of active commit, add dummy driver to provide consistent
|
||||||
* reads on the top, while disabling it in the intermediate nodes, and make
|
* reads on the top, while disabling it in the intermediate nodes, and make
|
||||||
* the backing chain writable. */
|
* the backing chain writable. */
|
||||||
|
|
|
@ -97,10 +97,6 @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void null_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t null_getlength(BlockDriverState *bs)
|
static int64_t null_getlength(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BDRVNullState *s = bs->opaque;
|
BDRVNullState *s = bs->opaque;
|
||||||
|
@ -263,7 +259,6 @@ 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_close = null_close,
|
|
||||||
.bdrv_getlength = null_getlength,
|
.bdrv_getlength = null_getlength,
|
||||||
|
|
||||||
.bdrv_co_preadv = null_co_preadv,
|
.bdrv_co_preadv = null_co_preadv,
|
||||||
|
@ -283,7 +278,6 @@ 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_close = null_close,
|
|
||||||
.bdrv_getlength = null_getlength,
|
.bdrv_getlength = null_getlength,
|
||||||
|
|
||||||
.bdrv_aio_preadv = null_aio_preadv,
|
.bdrv_aio_preadv = null_aio_preadv,
|
||||||
|
|
|
@ -594,7 +594,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
|
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
|
||||||
BlockStatsList *info = g_malloc0(sizeof(*info));
|
BlockStatsList *info;
|
||||||
AioContext *ctx = blk_get_aio_context(blk);
|
AioContext *ctx = blk_get_aio_context(blk);
|
||||||
BlockStats *s;
|
BlockStats *s;
|
||||||
char *qdev;
|
char *qdev;
|
||||||
|
@ -619,6 +619,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
|
||||||
bdrv_query_blk_stats(s->stats, blk);
|
bdrv_query_blk_stats(s->stats, blk);
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
|
|
||||||
|
info = g_malloc0(sizeof(*info));
|
||||||
info->value = s;
|
info->value = s;
|
||||||
*p_next = info;
|
*p_next = info;
|
||||||
p_next = &info->next;
|
p_next = &info->next;
|
||||||
|
|
|
@ -459,10 +459,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raw_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
|
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||||
{
|
{
|
||||||
/* smallest possible positive score so that raw is used if and only if no
|
/* smallest possible positive score so that raw is used if and only if no
|
||||||
|
@ -543,7 +539,6 @@ BlockDriver bdrv_raw = {
|
||||||
.bdrv_reopen_commit = &raw_reopen_commit,
|
.bdrv_reopen_commit = &raw_reopen_commit,
|
||||||
.bdrv_reopen_abort = &raw_reopen_abort,
|
.bdrv_reopen_abort = &raw_reopen_abort,
|
||||||
.bdrv_open = &raw_open,
|
.bdrv_open = &raw_open,
|
||||||
.bdrv_close = &raw_close,
|
|
||||||
.bdrv_child_perm = bdrv_filter_default_perms,
|
.bdrv_child_perm = bdrv_filter_default_perms,
|
||||||
.bdrv_co_create_opts = &raw_co_create_opts,
|
.bdrv_co_create_opts = &raw_co_create_opts,
|
||||||
.bdrv_co_preadv = &raw_co_preadv,
|
.bdrv_co_preadv = &raw_co_preadv,
|
||||||
|
|
|
@ -218,7 +218,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||||
qobject_unref(file_options);
|
qobject_unref(file_options);
|
||||||
qdict_put_str(options, "file", bdrv_get_node_name(file));
|
qdict_put_str(options, "file", bdrv_get_node_name(file));
|
||||||
|
|
||||||
drv->bdrv_close(bs);
|
if (drv->bdrv_close) {
|
||||||
|
drv->bdrv_close(bs);
|
||||||
|
}
|
||||||
bdrv_unref_child(bs, bs->file);
|
bdrv_unref_child(bs, bs->file);
|
||||||
bs->file = NULL;
|
bs->file = NULL;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
static void throttle_group_obj_init(Object *obj);
|
static void throttle_group_obj_init(Object *obj);
|
||||||
static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
|
static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
|
||||||
|
static void timer_cb(ThrottleGroupMember *tgm, bool is_write);
|
||||||
|
|
||||||
/* The ThrottleGroup structure (with its ThrottleState) is shared
|
/* The ThrottleGroup structure (with its ThrottleState) is shared
|
||||||
* among different ThrottleGroupMembers and it's independent from
|
* among different ThrottleGroupMembers and it's independent from
|
||||||
|
@ -221,6 +222,15 @@ static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm,
|
||||||
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
|
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
|
||||||
ThrottleGroupMember *token, *start;
|
ThrottleGroupMember *token, *start;
|
||||||
|
|
||||||
|
/* If this member has its I/O limits disabled then it means that
|
||||||
|
* it's being drained. Skip the round-robin search and return tgm
|
||||||
|
* immediately if it has pending requests. Otherwise we could be
|
||||||
|
* forcing it to wait for other member's throttled requests. */
|
||||||
|
if (tgm_has_pending_reqs(tgm, is_write) &&
|
||||||
|
atomic_read(&tgm->io_limits_disabled)) {
|
||||||
|
return tgm;
|
||||||
|
}
|
||||||
|
|
||||||
start = token = tg->tokens[is_write];
|
start = token = tg->tokens[is_write];
|
||||||
|
|
||||||
/* get next bs round in round robin style */
|
/* get next bs round in round robin style */
|
||||||
|
@ -415,15 +425,31 @@ static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write
|
||||||
rd->tgm = tgm;
|
rd->tgm = tgm;
|
||||||
rd->is_write = is_write;
|
rd->is_write = is_write;
|
||||||
|
|
||||||
|
/* This function is called when a timer is fired or when
|
||||||
|
* throttle_group_restart_tgm() is called. Either way, there can
|
||||||
|
* be no timer pending on this tgm at this point */
|
||||||
|
assert(!timer_pending(tgm->throttle_timers.timers[is_write]));
|
||||||
|
|
||||||
co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd);
|
co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd);
|
||||||
aio_co_enter(tgm->aio_context, co);
|
aio_co_enter(tgm->aio_context, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
|
void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (tgm->throttle_state) {
|
if (tgm->throttle_state) {
|
||||||
throttle_group_restart_queue(tgm, 0);
|
for (i = 0; i < 2; i++) {
|
||||||
throttle_group_restart_queue(tgm, 1);
|
QEMUTimer *t = tgm->throttle_timers.timers[i];
|
||||||
|
if (timer_pending(t)) {
|
||||||
|
/* If there's a pending timer on this tgm, fire it now */
|
||||||
|
timer_del(t);
|
||||||
|
timer_cb(tgm, i);
|
||||||
|
} else {
|
||||||
|
/* Else run the next request from the queue manually */
|
||||||
|
throttle_group_restart_queue(tgm, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,16 +584,11 @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
|
|
||||||
assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
|
|
||||||
assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
|
|
||||||
|
|
||||||
qemu_mutex_lock(&tg->lock);
|
qemu_mutex_lock(&tg->lock);
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (timer_pending(tgm->throttle_timers.timers[i])) {
|
assert(tgm->pending_reqs[i] == 0);
|
||||||
tg->any_timer_armed[i] = false;
|
assert(qemu_co_queue_empty(&tgm->throttled_reqs[i]));
|
||||||
schedule_next_request(tgm, i);
|
assert(!timer_pending(tgm->throttle_timers.timers[i]));
|
||||||
}
|
|
||||||
if (tg->tokens[i] == tgm) {
|
if (tg->tokens[i] == tgm) {
|
||||||
token = throttle_group_next_tgm(tgm);
|
token = throttle_group_next_tgm(tgm);
|
||||||
/* Take care of the case where this is the last tgm in the group */
|
/* Take care of the case where this is the last tgm in the group */
|
||||||
|
|
110
blockdev.c
110
blockdev.c
|
@ -730,30 +730,6 @@ QemuOptsList qemu_legacy_drive_opts = {
|
||||||
.name = "if",
|
.name = "if",
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
|
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
|
||||||
},{
|
|
||||||
.name = "cyls",
|
|
||||||
.type = QEMU_OPT_NUMBER,
|
|
||||||
.help = "number of cylinders (ide disk geometry)",
|
|
||||||
},{
|
|
||||||
.name = "heads",
|
|
||||||
.type = QEMU_OPT_NUMBER,
|
|
||||||
.help = "number of heads (ide disk geometry)",
|
|
||||||
},{
|
|
||||||
.name = "secs",
|
|
||||||
.type = QEMU_OPT_NUMBER,
|
|
||||||
.help = "number of sectors (ide disk geometry)",
|
|
||||||
},{
|
|
||||||
.name = "trans",
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "chs translation (auto, lba, none)",
|
|
||||||
},{
|
|
||||||
.name = "addr",
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "pci address (virtio only)",
|
|
||||||
},{
|
|
||||||
.name = "serial",
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "disk serial number",
|
|
||||||
},{
|
},{
|
||||||
.name = "file",
|
.name = "file",
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
|
@ -792,19 +768,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
QemuOpts *legacy_opts;
|
QemuOpts *legacy_opts;
|
||||||
DriveMediaType media = MEDIA_DISK;
|
DriveMediaType media = MEDIA_DISK;
|
||||||
BlockInterfaceType type;
|
BlockInterfaceType type;
|
||||||
int cyls, heads, secs, translation;
|
|
||||||
int max_devs, bus_id, unit_id, index;
|
int max_devs, bus_id, unit_id, index;
|
||||||
const char *devaddr;
|
|
||||||
const char *werror, *rerror;
|
const char *werror, *rerror;
|
||||||
bool read_only = false;
|
bool read_only = false;
|
||||||
bool copy_on_read;
|
bool copy_on_read;
|
||||||
const char *serial;
|
|
||||||
const char *filename;
|
const char *filename;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int i;
|
int i;
|
||||||
const char *deprecated[] = {
|
|
||||||
"serial", "trans", "secs", "heads", "cyls", "addr"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Change legacy command line options into QMP ones */
|
/* Change legacy command line options into QMP ones */
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -881,16 +851,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Other deprecated options */
|
|
||||||
if (!qtest_enabled()) {
|
|
||||||
for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
|
|
||||||
if (qemu_opt_get(legacy_opts, deprecated[i]) != NULL) {
|
|
||||||
error_report("'%s' is deprecated, please use the corresponding "
|
|
||||||
"option of '-device' instead", deprecated[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Media type */
|
/* Media type */
|
||||||
value = qemu_opt_get(legacy_opts, "media");
|
value = qemu_opt_get(legacy_opts, "media");
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -932,57 +892,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
type = block_default_type;
|
type = block_default_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Geometry */
|
|
||||||
cyls = qemu_opt_get_number(legacy_opts, "cyls", 0);
|
|
||||||
heads = qemu_opt_get_number(legacy_opts, "heads", 0);
|
|
||||||
secs = qemu_opt_get_number(legacy_opts, "secs", 0);
|
|
||||||
|
|
||||||
if (cyls || heads || secs) {
|
|
||||||
if (cyls < 1) {
|
|
||||||
error_report("invalid physical cyls number");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (heads < 1) {
|
|
||||||
error_report("invalid physical heads number");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (secs < 1) {
|
|
||||||
error_report("invalid physical secs number");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
|
||||||
value = qemu_opt_get(legacy_opts, "trans");
|
|
||||||
if (value != NULL) {
|
|
||||||
if (!cyls) {
|
|
||||||
error_report("'%s' trans must be used with cyls, heads and secs",
|
|
||||||
value);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!strcmp(value, "none")) {
|
|
||||||
translation = BIOS_ATA_TRANSLATION_NONE;
|
|
||||||
} else if (!strcmp(value, "lba")) {
|
|
||||||
translation = BIOS_ATA_TRANSLATION_LBA;
|
|
||||||
} else if (!strcmp(value, "large")) {
|
|
||||||
translation = BIOS_ATA_TRANSLATION_LARGE;
|
|
||||||
} else if (!strcmp(value, "rechs")) {
|
|
||||||
translation = BIOS_ATA_TRANSLATION_RECHS;
|
|
||||||
} else if (!strcmp(value, "auto")) {
|
|
||||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
|
||||||
} else {
|
|
||||||
error_report("'%s' invalid translation type", value);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (media == MEDIA_CDROM) {
|
|
||||||
if (cyls || secs || heads) {
|
|
||||||
error_report("CHS can't be set with media=cdrom");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Device address specified by bus/unit or index.
|
/* Device address specified by bus/unit or index.
|
||||||
* If none was specified, try to find the first free one. */
|
* If none was specified, try to find the first free one. */
|
||||||
bus_id = qemu_opt_get_number(legacy_opts, "bus", 0);
|
bus_id = qemu_opt_get_number(legacy_opts, "bus", 0);
|
||||||
|
@ -1022,9 +931,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Serial number */
|
|
||||||
serial = qemu_opt_get(legacy_opts, "serial");
|
|
||||||
|
|
||||||
/* no id supplied -> create one */
|
/* no id supplied -> create one */
|
||||||
if (qemu_opts_id(all_opts) == NULL) {
|
if (qemu_opts_id(all_opts) == NULL) {
|
||||||
char *new_id;
|
char *new_id;
|
||||||
|
@ -1044,12 +950,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add virtio block device */
|
/* Add virtio block device */
|
||||||
devaddr = qemu_opt_get(legacy_opts, "addr");
|
|
||||||
if (devaddr && type != IF_VIRTIO) {
|
|
||||||
error_report("addr is not supported by this bus type");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == IF_VIRTIO) {
|
if (type == IF_VIRTIO) {
|
||||||
QemuOpts *devopts;
|
QemuOpts *devopts;
|
||||||
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
|
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
|
||||||
|
@ -1061,9 +961,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
}
|
}
|
||||||
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
|
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
|
||||||
&error_abort);
|
&error_abort);
|
||||||
if (devaddr) {
|
|
||||||
qemu_opt_set(devopts, "addr", devaddr, &error_abort);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filename = qemu_opt_get(legacy_opts, "file");
|
filename = qemu_opt_get(legacy_opts, "file");
|
||||||
|
@ -1105,16 +1002,9 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||||
dinfo = g_malloc0(sizeof(*dinfo));
|
dinfo = g_malloc0(sizeof(*dinfo));
|
||||||
dinfo->opts = all_opts;
|
dinfo->opts = all_opts;
|
||||||
|
|
||||||
dinfo->cyls = cyls;
|
|
||||||
dinfo->heads = heads;
|
|
||||||
dinfo->secs = secs;
|
|
||||||
dinfo->trans = translation;
|
|
||||||
|
|
||||||
dinfo->type = type;
|
dinfo->type = type;
|
||||||
dinfo->bus = bus_id;
|
dinfo->bus = bus_id;
|
||||||
dinfo->unit = unit_id;
|
dinfo->unit = unit_id;
|
||||||
dinfo->devaddr = devaddr;
|
|
||||||
dinfo->serial = g_strdup(serial);
|
|
||||||
|
|
||||||
blk_set_legacy_dinfo(blk, dinfo);
|
blk_set_legacy_dinfo(blk, dinfo);
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,6 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
|
||||||
if (!dinfo) {
|
if (!dinfo) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (dinfo->devaddr) {
|
|
||||||
monitor_printf(mon, "Parameter addr not supported\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (dinfo->type) {
|
switch (dinfo->type) {
|
||||||
case IF_NONE:
|
case IF_NONE:
|
||||||
|
|
|
@ -1306,7 +1306,6 @@ ETEXI
|
||||||
.params = "[-n] [[<domain>:]<bus>:]<slot>\n"
|
.params = "[-n] [[<domain>:]<bus>:]<slot>\n"
|
||||||
"[file=file][,if=type][,bus=n]\n"
|
"[file=file][,if=type][,bus=n]\n"
|
||||||
"[,unit=m][,media=d][,index=i]\n"
|
"[,unit=m][,media=d][,index=i]\n"
|
||||||
"[,cyls=c,heads=h,secs=s[,trans=t]]\n"
|
|
||||||
"[,snapshot=on|off][,cache=on|off]\n"
|
"[,snapshot=on|off][,cache=on|off]\n"
|
||||||
"[,readonly=on|off][,copy-on-read=on|off]",
|
"[,readonly=on|off][,copy-on-read=on|off]",
|
||||||
.help = "add drive to PCI storage controller",
|
.help = "add drive to PCI storage controller",
|
||||||
|
|
|
@ -15,19 +15,6 @@
|
||||||
#include "qapi/qapi-types-block.h"
|
#include "qapi/qapi-types-block.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
void blkconf_serial(BlockConf *conf, char **serial)
|
|
||||||
{
|
|
||||||
DriveInfo *dinfo;
|
|
||||||
|
|
||||||
if (!*serial) {
|
|
||||||
/* try to fall back to value set with legacy -drive serial=... */
|
|
||||||
dinfo = blk_legacy_dinfo(conf->blk);
|
|
||||||
if (dinfo) {
|
|
||||||
*serial = g_strdup(dinfo->serial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void blkconf_blocksizes(BlockConf *conf)
|
void blkconf_blocksizes(BlockConf *conf)
|
||||||
{
|
{
|
||||||
BlockBackend *blk = conf->blk;
|
BlockBackend *blk = conf->blk;
|
||||||
|
@ -108,20 +95,6 @@ bool blkconf_geometry(BlockConf *conf, int *ptrans,
|
||||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
|
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
DriveInfo *dinfo;
|
|
||||||
|
|
||||||
if (!conf->cyls && !conf->heads && !conf->secs) {
|
|
||||||
/* try to fall back to value set with legacy -drive cyls=... */
|
|
||||||
dinfo = blk_legacy_dinfo(conf->blk);
|
|
||||||
if (dinfo) {
|
|
||||||
conf->cyls = dinfo->cyls;
|
|
||||||
conf->heads = dinfo->heads;
|
|
||||||
conf->secs = dinfo->secs;
|
|
||||||
if (ptrans) {
|
|
||||||
*ptrans = dinfo->trans;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!conf->cyls && !conf->heads && !conf->secs) {
|
if (!conf->cyls && !conf->heads && !conf->secs) {
|
||||||
hd_geometry_guess(conf->blk,
|
hd_geometry_guess(conf->blk,
|
||||||
&conf->cyls, &conf->heads, &conf->secs,
|
&conf->cyls, &conf->heads, &conf->secs,
|
||||||
|
|
|
@ -1217,7 +1217,6 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkconf_serial(&n->conf, &n->serial);
|
|
||||||
if (!n->serial) {
|
if (!n->serial) {
|
||||||
error_setg(errp, "serial property not set");
|
error_setg(errp, "serial property not set");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -935,7 +935,6 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkconf_serial(&conf->conf, &conf->serial);
|
|
||||||
if (!blkconf_apply_backend_options(&conf->conf,
|
if (!blkconf_apply_backend_options(&conf->conf,
|
||||||
blk_is_read_only(conf->conf.blk), true,
|
blk_is_read_only(conf->conf.blk), true,
|
||||||
errp)) {
|
errp)) {
|
||||||
|
|
|
@ -188,7 +188,6 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkconf_serial(&dev->conf, &dev->serial);
|
|
||||||
if (kind != IDE_CD) {
|
if (kind != IDE_CD) {
|
||||||
if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
|
if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
|
||||||
errp)) {
|
errp)) {
|
||||||
|
|
|
@ -2379,7 +2379,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkconf_serial(&s->qdev.conf, &s->serial);
|
|
||||||
blkconf_blocksizes(&s->qdev.conf);
|
blkconf_blocksizes(&s->qdev.conf);
|
||||||
|
|
||||||
if (s->qdev.conf.logical_block_size >
|
if (s->qdev.conf.logical_block_size >
|
||||||
|
|
|
@ -599,7 +599,6 @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkconf_serial(&s->conf, &dev->serial);
|
|
||||||
blkconf_blocksizes(&s->conf);
|
blkconf_blocksizes(&s->conf);
|
||||||
if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
|
if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
|
||||||
errp)) {
|
errp)) {
|
||||||
|
|
|
@ -72,7 +72,6 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
||||||
|
|
||||||
/* Configuration helpers */
|
/* Configuration helpers */
|
||||||
|
|
||||||
void blkconf_serial(BlockConf *conf, char **serial);
|
|
||||||
bool blkconf_geometry(BlockConf *conf, int *trans,
|
bool blkconf_geometry(BlockConf *conf, int *trans,
|
||||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
|
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
|
@ -28,16 +28,13 @@ typedef enum {
|
||||||
} BlockInterfaceType;
|
} BlockInterfaceType;
|
||||||
|
|
||||||
struct DriveInfo {
|
struct DriveInfo {
|
||||||
const char *devaddr;
|
|
||||||
BlockInterfaceType type;
|
BlockInterfaceType type;
|
||||||
int bus;
|
int bus;
|
||||||
int unit;
|
int unit;
|
||||||
int auto_del; /* see blockdev_mark_auto_del() */
|
int auto_del; /* see blockdev_mark_auto_del() */
|
||||||
bool is_default; /* Added by default_drive() ? */
|
bool is_default; /* Added by default_drive() ? */
|
||||||
int media_cd;
|
int media_cd;
|
||||||
int cyls, heads, secs, trans;
|
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
char *serial;
|
|
||||||
QTAILQ_ENTRY(DriveInfo) next;
|
QTAILQ_ENTRY(DriveInfo) next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1499,11 +1499,8 @@
|
||||||
# autogenerated. (Since: 2.9)
|
# autogenerated. (Since: 2.9)
|
||||||
#
|
#
|
||||||
# Returns: Nothing on success
|
# Returns: Nothing on success
|
||||||
# If commit or stream is already active on this device, DeviceInUse
|
|
||||||
# If @device does not exist, DeviceNotFound
|
# If @device does not exist, DeviceNotFound
|
||||||
# If image commit is not supported by this device, NotSupported
|
# Any other error returns a GenericError.
|
||||||
# If @base or @top is invalid, a generic error is returned
|
|
||||||
# If @speed is invalid, InvalidParameter
|
|
||||||
#
|
#
|
||||||
# Since: 1.3
|
# Since: 1.3
|
||||||
#
|
#
|
||||||
|
@ -3572,6 +3569,9 @@
|
||||||
# @driver: block driver name
|
# @driver: block driver name
|
||||||
# @node-name: the node name of the new node (Since 2.0).
|
# @node-name: the node name of the new node (Since 2.0).
|
||||||
# This option is required on the top level of blockdev-add.
|
# This option is required on the top level of blockdev-add.
|
||||||
|
# Valid node names start with an alphabetic character and may
|
||||||
|
# contain only alphanumeric characters, '-', '.' and '_'. Their
|
||||||
|
# maximum length is 31 characters.
|
||||||
# @discard: discard-related options (default: ignore)
|
# @discard: discard-related options (default: ignore)
|
||||||
# @cache: cache-related options
|
# @cache: cache-related options
|
||||||
# @read-only: whether the block device should be read-only (default: false).
|
# @read-only: whether the block device should be read-only (default: false).
|
||||||
|
|
|
@ -94,21 +94,6 @@ with ``-device ...,netdev=x''), or ``-nic user,smb=/some/dir''
|
||||||
(for embedded NICs). The new syntax allows different settings to be
|
(for embedded NICs). The new syntax allows different settings to be
|
||||||
provided per NIC.
|
provided per NIC.
|
||||||
|
|
||||||
@subsection -drive cyls=...,heads=...,secs=...,trans=... (since 2.10.0)
|
|
||||||
|
|
||||||
The drive geometry arguments are replaced by the the geometry arguments
|
|
||||||
that can be specified with the ``-device'' parameter.
|
|
||||||
|
|
||||||
@subsection -drive serial=... (since 2.10.0)
|
|
||||||
|
|
||||||
The drive serial argument is replaced by the the serial argument
|
|
||||||
that can be specified with the ``-device'' parameter.
|
|
||||||
|
|
||||||
@subsection -drive addr=... (since 2.10.0)
|
|
||||||
|
|
||||||
The drive addr argument is replaced by the the addr argument
|
|
||||||
that can be specified with the ``-device'' parameter.
|
|
||||||
|
|
||||||
@subsection -usbdevice (since 2.10.0)
|
@subsection -usbdevice (since 2.10.0)
|
||||||
|
|
||||||
The ``-usbdevice DEV'' argument is now a synonym for setting
|
The ``-usbdevice DEV'' argument is now a synonym for setting
|
||||||
|
|
32
qemu-img.c
32
qemu-img.c
|
@ -345,21 +345,6 @@ static int img_add_key_secrets(void *opaque,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockBackend *img_open_new_file(const char *filename,
|
|
||||||
QemuOpts *create_opts,
|
|
||||||
const char *fmt, int flags,
|
|
||||||
bool writethrough, bool quiet,
|
|
||||||
bool force_share)
|
|
||||||
{
|
|
||||||
QDict *options = NULL;
|
|
||||||
|
|
||||||
options = qdict_new();
|
|
||||||
qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort);
|
|
||||||
|
|
||||||
return img_open_file(filename, options, fmt, flags, writethrough, quiet,
|
|
||||||
force_share);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static BlockBackend *img_open(bool image_opts,
|
static BlockBackend *img_open(bool image_opts,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
@ -2018,6 +2003,7 @@ static int img_convert(int argc, char **argv)
|
||||||
BlockDriverState *out_bs;
|
BlockDriverState *out_bs;
|
||||||
QemuOpts *opts = NULL, *sn_opts = NULL;
|
QemuOpts *opts = NULL, *sn_opts = NULL;
|
||||||
QemuOptsList *create_opts = NULL;
|
QemuOptsList *create_opts = NULL;
|
||||||
|
QDict *open_opts = NULL;
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
bool writethrough, src_writethrough, quiet = false, image_opts = false,
|
bool writethrough, src_writethrough, quiet = false, image_opts = false,
|
||||||
|
@ -2362,6 +2348,16 @@ static int img_convert(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The later open call will need any decryption secrets, and
|
||||||
|
* bdrv_create() will purge "opts", so extract them now before
|
||||||
|
* they are lost.
|
||||||
|
*/
|
||||||
|
if (!skip_create) {
|
||||||
|
open_opts = qdict_new();
|
||||||
|
qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort);
|
||||||
|
}
|
||||||
|
|
||||||
if (!skip_create) {
|
if (!skip_create) {
|
||||||
/* Create the new image */
|
/* Create the new image */
|
||||||
ret = bdrv_create(drv, out_filename, opts, &local_err);
|
ret = bdrv_create(drv, out_filename, opts, &local_err);
|
||||||
|
@ -2388,8 +2384,9 @@ static int img_convert(int argc, char **argv)
|
||||||
* That has to wait for bdrv_create to be improved
|
* That has to wait for bdrv_create to be improved
|
||||||
* to allow filenames in option syntax
|
* to allow filenames in option syntax
|
||||||
*/
|
*/
|
||||||
s.target = img_open_new_file(out_filename, opts, out_fmt,
|
s.target = img_open_file(out_filename, open_opts, out_fmt,
|
||||||
flags, writethrough, quiet, false);
|
flags, writethrough, quiet, false);
|
||||||
|
open_opts = NULL; /* blk_new_open will have freed it */
|
||||||
}
|
}
|
||||||
if (!s.target) {
|
if (!s.target) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -2464,6 +2461,7 @@ out:
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
qemu_opts_free(create_opts);
|
qemu_opts_free(create_opts);
|
||||||
qemu_opts_del(sn_opts);
|
qemu_opts_del(sn_opts);
|
||||||
|
qobject_unref(open_opts);
|
||||||
blk_unref(s.target);
|
blk_unref(s.target);
|
||||||
if (s.src) {
|
if (s.src) {
|
||||||
for (bs_i = 0; bs_i < s.src_num; bs_i++) {
|
for (bs_i = 0; bs_i < s.src_num; bs_i++) {
|
||||||
|
|
|
@ -804,9 +804,8 @@ ETEXI
|
||||||
|
|
||||||
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
|
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
|
||||||
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
|
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
|
||||||
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
|
|
||||||
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
|
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
|
||||||
" [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
|
" [,snapshot=on|off][,rerror=ignore|stop|report]\n"
|
||||||
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
|
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
|
||||||
" [,readonly=on|off][,copy-on-read=on|off]\n"
|
" [,readonly=on|off][,copy-on-read=on|off]\n"
|
||||||
" [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
|
" [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
|
||||||
|
@ -847,10 +846,6 @@ This option defines where is connected the drive by using an index in the list
|
||||||
of available connectors of a given interface type.
|
of available connectors of a given interface type.
|
||||||
@item media=@var{media}
|
@item media=@var{media}
|
||||||
This option defines the type of the media: disk or cdrom.
|
This option defines the type of the media: disk or cdrom.
|
||||||
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
|
|
||||||
Force disk physical geometry and the optional BIOS translation (trans=none or
|
|
||||||
lba). These parameters are deprecated, use the corresponding parameters
|
|
||||||
of @code{-device} instead.
|
|
||||||
@item snapshot=@var{snapshot}
|
@item snapshot=@var{snapshot}
|
||||||
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
|
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
|
||||||
(see @option{-snapshot}).
|
(see @option{-snapshot}).
|
||||||
|
@ -884,13 +879,6 @@ The default mode is @option{cache=writeback}.
|
||||||
Specify which disk @var{format} will be used rather than detecting
|
Specify which disk @var{format} will be used rather than detecting
|
||||||
the format. Can be used to specify format=raw to avoid interpreting
|
the format. Can be used to specify format=raw to avoid interpreting
|
||||||
an untrusted format header.
|
an untrusted format header.
|
||||||
@item serial=@var{serial}
|
|
||||||
This option specifies the serial number to assign to the device. This
|
|
||||||
parameter is deprecated, use the corresponding parameter of @code{-device}
|
|
||||||
instead.
|
|
||||||
@item addr=@var{addr}
|
|
||||||
Specify the controller's PCI address (if=virtio only). This parameter is
|
|
||||||
deprecated, use the corresponding parameter of @code{-device} instead.
|
|
||||||
@item werror=@var{action},rerror=@var{action}
|
@item werror=@var{action},rerror=@var{action}
|
||||||
Specify which @var{action} to take on write and read errors. Valid actions are:
|
Specify which @var{action} to take on write and read errors. Valid actions are:
|
||||||
"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
|
"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
|
||||||
|
|
|
@ -158,20 +158,25 @@ void qdict_flatten(QDict *qdict)
|
||||||
qdict_flatten_qdict(qdict, qdict, NULL);
|
qdict_flatten_qdict(qdict, qdict, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract all the src QDict entries starting by start into dst */
|
/* extract all the src QDict entries starting by start into dst.
|
||||||
|
* If dst is NULL then the entries are simply removed from src. */
|
||||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
|
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
|
||||||
|
|
||||||
{
|
{
|
||||||
const QDictEntry *entry, *next;
|
const QDictEntry *entry, *next;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
*dst = qdict_new();
|
if (dst) {
|
||||||
|
*dst = qdict_new();
|
||||||
|
}
|
||||||
entry = qdict_first(src);
|
entry = qdict_first(src);
|
||||||
|
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
next = qdict_next(src, entry);
|
next = qdict_next(src, entry);
|
||||||
if (strstart(entry->key, start, &p)) {
|
if (strstart(entry->key, start, &p)) {
|
||||||
qdict_put_obj(*dst, p, qobject_ref(entry->value));
|
if (dst) {
|
||||||
|
qdict_put_obj(*dst, p, qobject_ref(entry->value));
|
||||||
|
}
|
||||||
qdict_del(src, entry->key);
|
qdict_del(src, entry->key);
|
||||||
}
|
}
|
||||||
entry = next;
|
entry = next;
|
||||||
|
|
|
@ -180,12 +180,12 @@ static AHCIQState *ahci_boot(const char *cli, ...)
|
||||||
s = ahci_vboot(cli, ap);
|
s = ahci_vboot(cli, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
} else {
|
} else {
|
||||||
cli = "-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s"
|
cli = "-drive if=none,id=drive0,file=%s,cache=writeback,format=%s"
|
||||||
",format=%s"
|
|
||||||
" -M q35 "
|
" -M q35 "
|
||||||
"-device ide-hd,drive=drive0 "
|
"-device ide-hd,drive=drive0 "
|
||||||
|
"-global ide-hd.serial=%s "
|
||||||
"-global ide-hd.ver=%s";
|
"-global ide-hd.ver=%s";
|
||||||
s = ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version");
|
s = ahci_boot(cli, tmp_path, imgfmt, "testdisk", "version");
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -201,7 +201,7 @@ static void setup_mbr(int img_idx, MBRcontents mbr)
|
||||||
|
|
||||||
static int setup_ide(int argc, char *argv[], int argv_sz,
|
static int setup_ide(int argc, char *argv[], int argv_sz,
|
||||||
int ide_idx, const char *dev, int img_idx,
|
int ide_idx, const char *dev, int img_idx,
|
||||||
MBRcontents mbr, const char *opts)
|
MBRcontents mbr)
|
||||||
{
|
{
|
||||||
char *s1, *s2, *s3;
|
char *s1, *s2, *s3;
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ static int setup_ide(int argc, char *argv[], int argv_sz,
|
||||||
s3 = g_strdup(",media=cdrom");
|
s3 = g_strdup(",media=cdrom");
|
||||||
}
|
}
|
||||||
argc = append_arg(argc, argv, argv_sz,
|
argc = append_arg(argc, argv, argv_sz,
|
||||||
g_strdup_printf("%s%s%s%s", s1, s2, s3, opts));
|
g_strdup_printf("%s%s%s", s1, s2, s3));
|
||||||
g_free(s1);
|
g_free(s1);
|
||||||
g_free(s2);
|
g_free(s2);
|
||||||
g_free(s3);
|
g_free(s3);
|
||||||
|
@ -260,7 +260,7 @@ static void test_ide_mbr(bool use_device, MBRcontents mbr)
|
||||||
for (i = 0; i < backend_last; i++) {
|
for (i = 0; i < backend_last; i++) {
|
||||||
cur_ide[i] = &hd_chst[i][mbr];
|
cur_ide[i] = &hd_chst[i][mbr];
|
||||||
dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
|
dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
|
||||||
argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr, "");
|
argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr);
|
||||||
}
|
}
|
||||||
args = g_strjoinv(" ", argv);
|
args = g_strjoinv(" ", argv);
|
||||||
qtest_start(args);
|
qtest_start(args);
|
||||||
|
@ -327,16 +327,12 @@ static void test_ide_drive_user(const char *dev, bool trans)
|
||||||
const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
|
const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
|
||||||
|
|
||||||
argc = setup_common(argv, ARGV_SIZE);
|
argc = setup_common(argv, ARGV_SIZE);
|
||||||
opts = g_strdup_printf("%s,%s%scyls=%d,heads=%d,secs=%d",
|
opts = g_strdup_printf("%s,%scyls=%d,heads=%d,secs=%d",
|
||||||
dev ?: "",
|
dev, trans ? "bios-chs-trans=lba," : "",
|
||||||
trans && dev ? "bios-chs-" : "",
|
|
||||||
trans ? "trans=lba," : "",
|
|
||||||
expected_chst.cyls, expected_chst.heads,
|
expected_chst.cyls, expected_chst.heads,
|
||||||
expected_chst.secs);
|
expected_chst.secs);
|
||||||
cur_ide[0] = &expected_chst;
|
cur_ide[0] = &expected_chst;
|
||||||
argc = setup_ide(argc, argv, ARGV_SIZE,
|
argc = setup_ide(argc, argv, ARGV_SIZE, 0, opts, backend_small, mbr_chs);
|
||||||
0, dev ? opts : NULL, backend_small, mbr_chs,
|
|
||||||
dev ? "" : opts);
|
|
||||||
g_free(opts);
|
g_free(opts);
|
||||||
args = g_strjoinv(" ", argv);
|
args = g_strjoinv(" ", argv);
|
||||||
qtest_start(args);
|
qtest_start(args);
|
||||||
|
@ -346,22 +342,6 @@ static void test_ide_drive_user(const char *dev, bool trans)
|
||||||
qtest_end();
|
qtest_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Test case: IDE device (if=ide) with explicit CHS
|
|
||||||
*/
|
|
||||||
static void test_ide_drive_user_chs(void)
|
|
||||||
{
|
|
||||||
test_ide_drive_user(NULL, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test case: IDE device (if=ide) with explicit CHS and translation
|
|
||||||
*/
|
|
||||||
static void test_ide_drive_user_chst(void)
|
|
||||||
{
|
|
||||||
test_ide_drive_user(NULL, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test case: IDE device (if=none) with explicit CHS
|
* Test case: IDE device (if=none) with explicit CHS
|
||||||
*/
|
*/
|
||||||
|
@ -392,8 +372,7 @@ static void test_ide_drive_cd_0(void)
|
||||||
for (i = 0; i <= backend_empty; i++) {
|
for (i = 0; i <= backend_empty; i++) {
|
||||||
ide_idx = backend_empty - i;
|
ide_idx = backend_empty - i;
|
||||||
cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
|
cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
|
||||||
argc = setup_ide(argc, argv, ARGV_SIZE,
|
argc = setup_ide(argc, argv, ARGV_SIZE, ide_idx, NULL, i, mbr_blank);
|
||||||
ide_idx, NULL, i, mbr_blank, "");
|
|
||||||
}
|
}
|
||||||
args = g_strjoinv(" ", argv);
|
args = g_strjoinv(" ", argv);
|
||||||
qtest_start(args);
|
qtest_start(args);
|
||||||
|
@ -422,8 +401,6 @@ int main(int argc, char **argv)
|
||||||
qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
|
qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
|
||||||
qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
|
qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
|
||||||
qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
|
qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
|
||||||
qtest_add_func("hd-geo/ide/drive/user/chs", test_ide_drive_user_chs);
|
|
||||||
qtest_add_func("hd-geo/ide/drive/user/chst", test_ide_drive_user_chst);
|
|
||||||
qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
|
qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
|
||||||
qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
|
qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
|
||||||
qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
|
qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
|
||||||
|
|
|
@ -529,8 +529,8 @@ static void test_bmdma_no_busmaster(void)
|
||||||
static void test_bmdma_setup(void)
|
static void test_bmdma_setup(void)
|
||||||
{
|
{
|
||||||
ide_test_start(
|
ide_test_start(
|
||||||
"-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw "
|
"-drive file=%s,if=ide,cache=writeback,format=raw "
|
||||||
"-global ide-hd.ver=%s",
|
"-global ide-hd.serial=%s -global ide-hd.ver=%s",
|
||||||
tmp_path, "testdisk", "version");
|
tmp_path, "testdisk", "version");
|
||||||
qtest_irq_intercept_in(global_qtest, "ioapic");
|
qtest_irq_intercept_in(global_qtest, "ioapic");
|
||||||
}
|
}
|
||||||
|
@ -561,8 +561,8 @@ static void test_identify(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ide_test_start(
|
ide_test_start(
|
||||||
"-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw "
|
"-drive file=%s,if=ide,cache=writeback,format=raw "
|
||||||
"-global ide-hd.ver=%s",
|
"-global ide-hd.serial=%s -global ide-hd.ver=%s",
|
||||||
tmp_path, "testdisk", "version");
|
tmp_path, "testdisk", "version");
|
||||||
|
|
||||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||||
|
|
|
@ -234,6 +234,12 @@ class TestSingleBlockdev(TestSingleDrive):
|
||||||
result = self.vm.qmp("blockdev-add", **args)
|
result = self.vm.qmp("blockdev-add", **args)
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
def test_mirror_to_self(self):
|
||||||
|
result = self.vm.qmp(self.qmp_cmd, job_id='job0',
|
||||||
|
device=self.qmp_target, sync='full',
|
||||||
|
target=self.qmp_target)
|
||||||
|
self.assert_qmp(result, 'error/class', 'GenericError')
|
||||||
|
|
||||||
test_large_cluster = None
|
test_large_cluster = None
|
||||||
test_image_not_found = None
|
test_image_not_found = None
|
||||||
test_small_buffer2 = None
|
test_small_buffer2 = None
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.....................................................................................
|
........................................................................................
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Ran 85 tests
|
Ran 88 tests
|
||||||
|
|
||||||
OK
|
OK
|
||||||
|
|
|
@ -208,6 +208,61 @@ class ThrottleTestCase(iotests.QMPTestCase):
|
||||||
limits[tk] = rate
|
limits[tk] = rate
|
||||||
self.do_test_throttle(ndrives, 5, limits)
|
self.do_test_throttle(ndrives, 5, limits)
|
||||||
|
|
||||||
|
# Test that removing a drive from a throttle group should not
|
||||||
|
# affect the remaining members of the group.
|
||||||
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1535914
|
||||||
|
def test_remove_group_member(self):
|
||||||
|
# Create a throttle group with two drives
|
||||||
|
# and set a 4 KB/s read limit.
|
||||||
|
params = {"bps": 0,
|
||||||
|
"bps_rd": 4096,
|
||||||
|
"bps_wr": 0,
|
||||||
|
"iops": 0,
|
||||||
|
"iops_rd": 0,
|
||||||
|
"iops_wr": 0 }
|
||||||
|
self.configure_throttle(2, params)
|
||||||
|
|
||||||
|
# Read 4KB from drive0. This is performed immediately.
|
||||||
|
self.vm.hmp_qemu_io("drive0", "aio_read 0 4096")
|
||||||
|
|
||||||
|
# Read 2KB. The I/O limit has been exceeded so this
|
||||||
|
# request is throttled and a timer is set to wake it up.
|
||||||
|
self.vm.hmp_qemu_io("drive0", "aio_read 0 2048")
|
||||||
|
|
||||||
|
# Read 2KB again. We're still over the I/O limit so this is
|
||||||
|
# request is also throttled, but no new timer is set since
|
||||||
|
# there's already one.
|
||||||
|
self.vm.hmp_qemu_io("drive0", "aio_read 0 2048")
|
||||||
|
|
||||||
|
# Read from drive1. This request is also throttled, and no
|
||||||
|
# timer is set in drive1 because there's already one in
|
||||||
|
# drive0.
|
||||||
|
self.vm.hmp_qemu_io("drive1", "aio_read 0 4096")
|
||||||
|
|
||||||
|
# At this point only the first 4KB have been read from drive0.
|
||||||
|
# The other requests are throttled.
|
||||||
|
self.assertEqual(self.blockstats('drive0')[0], 4096)
|
||||||
|
self.assertEqual(self.blockstats('drive1')[0], 0)
|
||||||
|
|
||||||
|
# Remove drive0 from the throttle group and disable its I/O limits.
|
||||||
|
# drive1 remains in the group with a throttled request.
|
||||||
|
params['bps_rd'] = 0
|
||||||
|
params['device'] = 'drive0'
|
||||||
|
result = self.vm.qmp("block_set_io_throttle", conv_keys=False, **params)
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
# Removing the I/O limits from drive0 drains its two pending requests.
|
||||||
|
# The read request in drive1 is still throttled.
|
||||||
|
self.assertEqual(self.blockstats('drive0')[0], 8192)
|
||||||
|
self.assertEqual(self.blockstats('drive1')[0], 0)
|
||||||
|
|
||||||
|
# Advance the clock 5 seconds. This completes the request in drive1
|
||||||
|
self.vm.qtest("clock_step %d" % (5 * nsec_per_sec))
|
||||||
|
|
||||||
|
# Now all requests have been processed.
|
||||||
|
self.assertEqual(self.blockstats('drive0')[0], 8192)
|
||||||
|
self.assertEqual(self.blockstats('drive1')[0], 4096)
|
||||||
|
|
||||||
class ThrottleTestCoroutine(ThrottleTestCase):
|
class ThrottleTestCoroutine(ThrottleTestCase):
|
||||||
test_img = "null-co://"
|
test_img = "null-co://"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
........
|
..........
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Ran 8 tests
|
Ran 10 tests
|
||||||
|
|
||||||
OK
|
OK
|
||||||
|
|
Loading…
Reference in New Issue