Block layer patches:
- mirror: Fix early return from drain (could cause deadlocks) - vmdk: Fixed probing for version 3 images - vl: Fix to create migration object before block backends again (fixes segfault for block drivers that set migration blockers) - Several minor fixes, documentation and test case improvements -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJckQPFAAoJEH8JsnLIjy/WI98P/2alH9DhtHwg1ufIrWonv8C6 zagmZoaABD8bI6x/YNGF+by7TJpYb2+aHv7ilu99n9ZgbVuVu0H1AlpnBYWBp/a/ Kqjq7eYpS5HNnpwnJHwLH3wFko3sU+7OxQieHcdd/v9ollXaA+w/MLq9Jwgb58jJ BUwq80D2SHsZchZnTdvF2njWSEf+vYOQ389Uh0pwAL6mTeNontjtjwsIQEKqYJIs 4EI27tmf1kB6IGDw6Ad+K4TbsziblUKIxvM8u+J20BrqV/5zL3TwrAV9sB31Xn6t ZuBEmNm/dFp1tl5qkJ4feXEaRL9/XFPgLKgaaBwgLDWzdf2MvPcEnkfX2mDTRUB9 5+fDE5i8K8wFN+ITCEApwHUrzuebRm/8Dy+k4IR4k0y85D7EZZWrGC7biw61aZ1z 2MnCIx9a6m3Ht9JrXSiaR3G2XbZkp0dh8o8AQkUk2Ax55P5WVSwR6TIl5aO/xXBz vdZPCP71KbB3ioii48yvBr8ZVz+Q6NAVPJH19PfwWksIXn/lnKUtoF0T6nV5xmEG pHGh11I08Pc4FQ6wpV8eLqEcKuOd3Dt9k9hBepKU6AVjfCUbI8Rtd/yO1vWpZw+l 4Q7LO1iC8dr8U9DUBj6AkZChWIJ41X++ArnH5MhSieh4OSmoF4rQ0vg0hYlNaNE/ G/XYHHXJyTz1h7Ty11Cw =GcJ/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - mirror: Fix early return from drain (could cause deadlocks) - vmdk: Fixed probing for version 3 images - vl: Fix to create migration object before block backends again (fixes segfault for block drivers that set migration blockers) - Several minor fixes, documentation and test case improvements # gpg: Signature made Tue 19 Mar 2019 14:59:17 GMT # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: qemu-iotests: Treat custom TEST_DIR in 051 blockdev: Check @replaces in blockdev_mirror_common block: Make bdrv_{copy_on_read,crypto_luks,replication} static blockjob: fix user pause in block_job_error_action qemu-iotests: Fix 232 for non-qcow2 vl: Fix to create migration object before block backends again iotests: 153: Wait for an answer to QMP commands block: Silence Coverity in bdrv_drop_intermediate() vmdk: Support version=3 in VMDK descriptor files qapi: fix block-latency-histogram-set description and examples qcow2: Fix data file error condition in qcow2_co_create() mirror: Confirm we're quiesced only if the job is paused or cancelled Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e0991e2616
7
block.c
7
block.c
@ -4350,11 +4350,10 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
|||||||
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
|
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
|
||||||
/* Check whether we are allowed to switch c from top to base */
|
/* Check whether we are allowed to switch c from top to base */
|
||||||
GSList *ignore_children = g_slist_prepend(NULL, c);
|
GSList *ignore_children = g_slist_prepend(NULL, c);
|
||||||
bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
|
ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
|
||||||
ignore_children, &local_err);
|
ignore_children, &local_err);
|
||||||
g_slist_free(ignore_children);
|
g_slist_free(ignore_children);
|
||||||
if (local_err) {
|
if (ret < 0) {
|
||||||
ret = -EPERM;
|
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ static bool cor_recurse_is_first_non_filter(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlockDriver bdrv_copy_on_read = {
|
static BlockDriver bdrv_copy_on_read = {
|
||||||
.format_name = "copy-on-read",
|
.format_name = "copy-on-read",
|
||||||
|
|
||||||
.bdrv_open = cor_open,
|
.bdrv_open = cor_open,
|
||||||
|
@ -625,7 +625,7 @@ static const char *const block_crypto_strong_runtime_opts[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockDriver bdrv_crypto_luks = {
|
static BlockDriver bdrv_crypto_luks = {
|
||||||
.format_name = "luks",
|
.format_name = "luks",
|
||||||
.instance_size = sizeof(BlockCrypto),
|
.instance_size = sizeof(BlockCrypto),
|
||||||
.bdrv_probe = block_crypto_probe_luks,
|
.bdrv_probe = block_crypto_probe_luks,
|
||||||
|
@ -80,6 +80,7 @@ typedef struct MirrorBlockJob {
|
|||||||
bool initial_zeroing_ongoing;
|
bool initial_zeroing_ongoing;
|
||||||
int in_active_write_counter;
|
int in_active_write_counter;
|
||||||
bool prepared;
|
bool prepared;
|
||||||
|
bool in_drain;
|
||||||
} MirrorBlockJob;
|
} MirrorBlockJob;
|
||||||
|
|
||||||
typedef struct MirrorBDSOpaque {
|
typedef struct MirrorBDSOpaque {
|
||||||
@ -683,6 +684,7 @@ static int mirror_exit_common(Job *job)
|
|||||||
|
|
||||||
/* The mirror job has no requests in flight any more, but we need to
|
/* The mirror job has no requests in flight any more, but we need to
|
||||||
* drain potential other users of the BDS before changing the graph. */
|
* drain potential other users of the BDS before changing the graph. */
|
||||||
|
assert(s->in_drain);
|
||||||
bdrv_drained_begin(target_bs);
|
bdrv_drained_begin(target_bs);
|
||||||
bdrv_replace_node(to_replace, target_bs, &local_err);
|
bdrv_replace_node(to_replace, target_bs, &local_err);
|
||||||
bdrv_drained_end(target_bs);
|
bdrv_drained_end(target_bs);
|
||||||
@ -721,6 +723,7 @@ static int mirror_exit_common(Job *job)
|
|||||||
bs_opaque->job = NULL;
|
bs_opaque->job = NULL;
|
||||||
|
|
||||||
bdrv_drained_end(src);
|
bdrv_drained_end(src);
|
||||||
|
s->in_drain = false;
|
||||||
bdrv_unref(mirror_top_bs);
|
bdrv_unref(mirror_top_bs);
|
||||||
bdrv_unref(src);
|
bdrv_unref(src);
|
||||||
|
|
||||||
@ -1004,10 +1007,12 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
|||||||
*/
|
*/
|
||||||
trace_mirror_before_drain(s, cnt);
|
trace_mirror_before_drain(s, cnt);
|
||||||
|
|
||||||
|
s->in_drain = true;
|
||||||
bdrv_drained_begin(bs);
|
bdrv_drained_begin(bs);
|
||||||
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
|
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
|
||||||
if (cnt > 0 || mirror_flush(s) < 0) {
|
if (cnt > 0 || mirror_flush(s) < 0) {
|
||||||
bdrv_drained_end(bs);
|
bdrv_drained_end(bs);
|
||||||
|
s->in_drain = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,6 +1060,7 @@ immediate_exit:
|
|||||||
bdrv_dirty_iter_free(s->dbi);
|
bdrv_dirty_iter_free(s->dbi);
|
||||||
|
|
||||||
if (need_drain) {
|
if (need_drain) {
|
||||||
|
s->in_drain = true;
|
||||||
bdrv_drained_begin(bs);
|
bdrv_drained_begin(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,6 +1129,16 @@ static void coroutine_fn mirror_pause(Job *job)
|
|||||||
static bool mirror_drained_poll(BlockJob *job)
|
static bool mirror_drained_poll(BlockJob *job)
|
||||||
{
|
{
|
||||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
||||||
|
|
||||||
|
/* If the job isn't paused nor cancelled, we can't be sure that it won't
|
||||||
|
* issue more requests. We make an exception if we've reached this point
|
||||||
|
* from one of our own drain sections, to avoid a deadlock waiting for
|
||||||
|
* ourselves.
|
||||||
|
*/
|
||||||
|
if (!s->common.job.paused && !s->common.job.cancelled && !s->in_drain) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return !!s->in_flight;
|
return !!s->in_flight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3073,7 +3073,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp);
|
data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp);
|
||||||
if (bs == NULL) {
|
if (data_bs == NULL) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -682,7 +682,7 @@ static const char *const replication_strong_runtime_opts[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockDriver bdrv_replication = {
|
static BlockDriver bdrv_replication = {
|
||||||
.format_name = "replication",
|
.format_name = "replication",
|
||||||
.instance_size = sizeof(BDRVReplicationState),
|
.instance_size = sizeof(BDRVReplicationState),
|
||||||
|
|
||||||
|
@ -195,13 +195,15 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
|
|||||||
}
|
}
|
||||||
if (end - p >= strlen("version=X\n")) {
|
if (end - p >= strlen("version=X\n")) {
|
||||||
if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
|
if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
|
||||||
strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
|
strncmp("version=2\n", p, strlen("version=2\n")) == 0 ||
|
||||||
|
strncmp("version=3\n", p, strlen("version=3\n")) == 0) {
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end - p >= strlen("version=X\r\n")) {
|
if (end - p >= strlen("version=X\r\n")) {
|
||||||
if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
|
if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
|
||||||
strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
|
strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0 ||
|
||||||
|
strncmp("version=3\r\n", p, strlen("version=3\r\n")) == 0) {
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
blockdev.c
55
blockdev.c
@ -3756,6 +3756,39 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
|||||||
sync = MIRROR_SYNC_MODE_FULL;
|
sync = MIRROR_SYNC_MODE_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_replaces) {
|
||||||
|
BlockDriverState *to_replace_bs;
|
||||||
|
AioContext *replace_aio_context;
|
||||||
|
int64_t bs_size, replace_size;
|
||||||
|
|
||||||
|
bs_size = bdrv_getlength(bs);
|
||||||
|
if (bs_size < 0) {
|
||||||
|
error_setg_errno(errp, -bs_size, "Failed to query device's size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
to_replace_bs = check_to_replace_node(bs, replaces, errp);
|
||||||
|
if (!to_replace_bs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_aio_context = bdrv_get_aio_context(to_replace_bs);
|
||||||
|
aio_context_acquire(replace_aio_context);
|
||||||
|
replace_size = bdrv_getlength(to_replace_bs);
|
||||||
|
aio_context_release(replace_aio_context);
|
||||||
|
|
||||||
|
if (replace_size < 0) {
|
||||||
|
error_setg_errno(errp, -replace_size,
|
||||||
|
"Failed to query the replacement node's size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bs_size != replace_size) {
|
||||||
|
error_setg(errp, "cannot replace image with a mirror image of "
|
||||||
|
"different size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* pass the node name to replace to mirror start since it's loose coupling
|
/* pass the node name to replace to mirror start since it's loose coupling
|
||||||
* and will allow to check whether the node still exist at mirror completion
|
* and will allow to check whether the node still exist at mirror completion
|
||||||
*/
|
*/
|
||||||
@ -3816,33 +3849,11 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg->has_replaces) {
|
if (arg->has_replaces) {
|
||||||
BlockDriverState *to_replace_bs;
|
|
||||||
AioContext *replace_aio_context;
|
|
||||||
int64_t replace_size;
|
|
||||||
|
|
||||||
if (!arg->has_node_name) {
|
if (!arg->has_node_name) {
|
||||||
error_setg(errp, "a node-name must be provided when replacing a"
|
error_setg(errp, "a node-name must be provided when replacing a"
|
||||||
" named node of the graph");
|
" named node of the graph");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err);
|
|
||||||
|
|
||||||
if (!to_replace_bs) {
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
replace_aio_context = bdrv_get_aio_context(to_replace_bs);
|
|
||||||
aio_context_acquire(replace_aio_context);
|
|
||||||
replace_size = bdrv_getlength(to_replace_bs);
|
|
||||||
aio_context_release(replace_aio_context);
|
|
||||||
|
|
||||||
if (size != replace_size) {
|
|
||||||
error_setg(errp, "cannot replace image with a mirror image of "
|
|
||||||
"different size");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
|
if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
|
||||||
|
@ -501,9 +501,11 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
|
|||||||
action);
|
action);
|
||||||
}
|
}
|
||||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||||
job_pause(&job->job);
|
if (!job->job.user_paused) {
|
||||||
/* make the pause user visible, which will be resumed from QMP. */
|
job_pause(&job->job);
|
||||||
job->job.user_paused = true;
|
/* make the pause user visible, which will be resumed from QMP. */
|
||||||
|
job->job.user_paused = true;
|
||||||
|
}
|
||||||
block_job_iostatus_set_err(job, error);
|
block_job_iostatus_set_err(job, error);
|
||||||
}
|
}
|
||||||
return action;
|
return action;
|
||||||
|
@ -565,7 +565,7 @@
|
|||||||
#
|
#
|
||||||
# Manage read, write and flush latency histograms for the device.
|
# Manage read, write and flush latency histograms for the device.
|
||||||
#
|
#
|
||||||
# If only @device parameter is specified, remove all present latency histograms
|
# If only @id parameter is specified, remove all present latency histograms
|
||||||
# for the device. Otherwise, add/reset some of (or all) latency histograms.
|
# for the device. Otherwise, add/reset some of (or all) latency histograms.
|
||||||
#
|
#
|
||||||
# @id: The name or QOM path of the guest device.
|
# @id: The name or QOM path of the guest device.
|
||||||
@ -597,7 +597,7 @@
|
|||||||
# [0, 10), [10, 50), [50, 100), [100, +inf):
|
# [0, 10), [10, 50), [50, 100), [100, +inf):
|
||||||
#
|
#
|
||||||
# -> { "execute": "block-latency-histogram-set",
|
# -> { "execute": "block-latency-histogram-set",
|
||||||
# "arguments": { "device": "drive0",
|
# "arguments": { "id": "drive0",
|
||||||
# "boundaries": [10, 50, 100] } }
|
# "boundaries": [10, 50, 100] } }
|
||||||
# <- { "return": {} }
|
# <- { "return": {} }
|
||||||
#
|
#
|
||||||
@ -605,7 +605,7 @@
|
|||||||
# not changed (or not created):
|
# not changed (or not created):
|
||||||
#
|
#
|
||||||
# -> { "execute": "block-latency-histogram-set",
|
# -> { "execute": "block-latency-histogram-set",
|
||||||
# "arguments": { "device": "drive0",
|
# "arguments": { "id": "drive0",
|
||||||
# "boundaries-write": [10, 50, 100] } }
|
# "boundaries-write": [10, 50, 100] } }
|
||||||
# <- { "return": {} }
|
# <- { "return": {} }
|
||||||
#
|
#
|
||||||
@ -614,7 +614,7 @@
|
|||||||
# write: [0, 1000), [1000, 5000), [5000, +inf)
|
# write: [0, 1000), [1000, 5000), [5000, +inf)
|
||||||
#
|
#
|
||||||
# -> { "execute": "block-latency-histogram-set",
|
# -> { "execute": "block-latency-histogram-set",
|
||||||
# "arguments": { "device": "drive0",
|
# "arguments": { "id": "drive0",
|
||||||
# "boundaries": [10, 50, 100],
|
# "boundaries": [10, 50, 100],
|
||||||
# "boundaries-write": [1000, 5000] } }
|
# "boundaries-write": [1000, 5000] } }
|
||||||
# <- { "return": {} }
|
# <- { "return": {} }
|
||||||
@ -622,7 +622,7 @@
|
|||||||
# Example: remove all latency histograms:
|
# Example: remove all latency histograms:
|
||||||
#
|
#
|
||||||
# -> { "execute": "block-latency-histogram-set",
|
# -> { "execute": "block-latency-histogram-set",
|
||||||
# "arguments": { "device": "drive0" } }
|
# "arguments": { "id": "drive0" } }
|
||||||
# <- { "return": {} }
|
# <- { "return": {} }
|
||||||
##
|
##
|
||||||
{ 'command': 'block-latency-histogram-set',
|
{ 'command': 'block-latency-histogram-set',
|
||||||
|
@ -360,7 +360,7 @@ TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
|
|||||||
echo "info block" |
|
echo "info block" |
|
||||||
run_qemu -drive file="$TEST_IMG",snapshot=on,read-only=on,if=none,id=$device_id |
|
run_qemu -drive file="$TEST_IMG",snapshot=on,read-only=on,if=none,id=$device_id |
|
||||||
_filter_qemu_io |
|
_filter_qemu_io |
|
||||||
sed -e 's#"/[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g'
|
sed -e 's#"[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g'
|
||||||
|
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
|
@ -155,7 +155,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
|
|||||||
_img_info -U | grep 'file format'
|
_img_info -U | grep 'file format'
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
_send_qemu_cmd $h "{ 'execute': 'quit', }" ""
|
_send_qemu_cmd $h "{ 'execute': 'quit' }" ''
|
||||||
echo
|
echo
|
||||||
echo "Round done"
|
echo "Round done"
|
||||||
_cleanup_qemu
|
_cleanup_qemu
|
||||||
@ -219,7 +219,7 @@ echo "Adding drive"
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{ 'execute': 'human-monitor-command',
|
"{ 'execute': 'human-monitor-command',
|
||||||
'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=${TEST_IMG}' } }" \
|
'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=${TEST_IMG}' } }" \
|
||||||
""
|
'return'
|
||||||
|
|
||||||
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ echo "== Closing an image should unlock it =="
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{ 'execute': 'human-monitor-command',
|
"{ 'execute': 'human-monitor-command',
|
||||||
'arguments': { 'command-line': 'drive_del d0' } }" \
|
'arguments': { 'command-line': 'drive_del d0' } }" \
|
||||||
""
|
'return'
|
||||||
|
|
||||||
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ for d in d0 d1; do
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{ 'execute': 'human-monitor-command',
|
"{ 'execute': 'human-monitor-command',
|
||||||
'arguments': { 'command-line': 'drive_add 0 if=none,id=$d,file=${TEST_IMG},readonly=on' } }" \
|
'arguments': { 'command-line': 'drive_add 0 if=none,id=$d,file=${TEST_IMG},readonly=on' } }" \
|
||||||
""
|
'return'
|
||||||
done
|
done
|
||||||
|
|
||||||
_run_cmd $QEMU_IMG info "${TEST_IMG}"
|
_run_cmd $QEMU_IMG info "${TEST_IMG}"
|
||||||
@ -247,7 +247,7 @@ _run_cmd $QEMU_IMG info "${TEST_IMG}"
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{ 'execute': 'human-monitor-command',
|
"{ 'execute': 'human-monitor-command',
|
||||||
'arguments': { 'command-line': 'drive_del d0' } }" \
|
'arguments': { 'command-line': 'drive_del d0' } }" \
|
||||||
""
|
'return'
|
||||||
|
|
||||||
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ echo "Closing the other"
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{ 'execute': 'human-monitor-command',
|
"{ 'execute': 'human-monitor-command',
|
||||||
'arguments': { 'command-line': 'drive_del d1' } }" \
|
'arguments': { 'command-line': 'drive_del d1' } }" \
|
||||||
""
|
'return'
|
||||||
|
|
||||||
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
|
||||||
|
|
||||||
|
@ -417,6 +417,7 @@ Is another process using the image [TEST_DIR/t.qcow2]?
|
|||||||
_qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
|
_qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
Adding drive
|
Adding drive
|
||||||
|
{"return": "OKrn"}
|
||||||
|
|
||||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||||
@ -425,16 +426,21 @@ Creating overlay with qemu-img when the guest is running should be allowed
|
|||||||
|
|
||||||
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
|
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
|
||||||
== Closing an image should unlock it ==
|
== Closing an image should unlock it ==
|
||||||
|
{"return": ""}
|
||||||
|
|
||||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||||
Adding two and closing one
|
Adding two and closing one
|
||||||
|
{"return": "OKrn"}
|
||||||
|
{"return": "OKrn"}
|
||||||
|
|
||||||
_qemu_img_wrapper info TEST_DIR/t.qcow2
|
_qemu_img_wrapper info TEST_DIR/t.qcow2
|
||||||
|
{"return": ""}
|
||||||
|
|
||||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||||
Closing the other
|
Closing the other
|
||||||
|
{"return": ""}
|
||||||
|
|
||||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||||
|
|
||||||
|
@ -144,36 +144,6 @@ run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,a
|
|||||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
|
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
|
||||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
|
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
|
||||||
|
|
||||||
echo
|
|
||||||
echo "=== Try commit to backing file with auto-read-only ==="
|
|
||||||
echo
|
|
||||||
|
|
||||||
TEST_IMG="$TEST_IMG.0" _make_test_img $size
|
|
||||||
TEST_IMG="$TEST_IMG.1" _make_test_img $size
|
|
||||||
TEST_IMG="$TEST_IMG.2" _make_test_img $size
|
|
||||||
TEST_IMG="$TEST_IMG.3" _make_test_img $size
|
|
||||||
TEST_IMG="$TEST_IMG.4" _make_test_img $size
|
|
||||||
|
|
||||||
(cat <<EOF
|
|
||||||
{"execute":"qmp_capabilities"}
|
|
||||||
{"execute":"block-commit",
|
|
||||||
"arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}}
|
|
||||||
EOF
|
|
||||||
sleep 1
|
|
||||||
echo '{"execute":"quit"}'
|
|
||||||
) | $QEMU -qmp stdio -nographic -nodefaults \
|
|
||||||
-blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \
|
|
||||||
-blockdev qcow2,node-name=format-0,file=file-0,read-only=on \
|
|
||||||
-blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \
|
|
||||||
-blockdev qcow2,node-name=format-1,file=file-1,read-only=on,backing=format-0 \
|
|
||||||
-blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \
|
|
||||||
-blockdev qcow2,node-name=format-2,file=file-2,read-only=on,backing=format-1 \
|
|
||||||
-blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \
|
|
||||||
-blockdev qcow2,node-name=format-3,file=file-3,read-only=on,backing=format-2 \
|
|
||||||
-blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \
|
|
||||||
-blockdev qcow2,node-name=format-4,file=file-4,read-only=on,backing=format-3 |
|
|
||||||
_filter_qmp
|
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
rm -f $seq.full
|
rm -f $seq.full
|
||||||
|
@ -56,24 +56,4 @@ QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read
|
|||||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||||
node0: TEST_DIR/t.IMGFMT (file)
|
node0: TEST_DIR/t.IMGFMT (file)
|
||||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||||
|
|
||||||
=== Try commit to backing file with auto-read-only ===
|
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728
|
|
||||||
QMP_VERSION
|
|
||||||
{"return": {}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
|
||||||
{"return": {}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
|
||||||
{"return": {}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
|
||||||
*** done
|
*** done
|
||||||
|
79
tests/qemu-iotests/247
Executable file
79
tests/qemu-iotests/247
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Test for auto-read-only with commit block job
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# creator
|
||||||
|
owner=kwolf@redhat.com
|
||||||
|
|
||||||
|
seq=`basename $0`
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
status=1 # failure is the default!
|
||||||
|
|
||||||
|
_cleanup()
|
||||||
|
{
|
||||||
|
_cleanup_test_img
|
||||||
|
rm -f $TEST_IMG.[01234]
|
||||||
|
}
|
||||||
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
|
# get standard environment, filters and checks
|
||||||
|
. ./common.rc
|
||||||
|
. ./common.filter
|
||||||
|
|
||||||
|
# Requires backing files and .bdrv_change_backing_file support
|
||||||
|
_supported_fmt qcow2 qed
|
||||||
|
_supported_proto file
|
||||||
|
_supported_os Linux
|
||||||
|
|
||||||
|
size=128M
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Try commit to backing file with auto-read-only ==="
|
||||||
|
echo
|
||||||
|
TEST_IMG="$TEST_IMG.0" _make_test_img $size
|
||||||
|
TEST_IMG="$TEST_IMG.1" _make_test_img $size
|
||||||
|
TEST_IMG="$TEST_IMG.2" _make_test_img $size
|
||||||
|
TEST_IMG="$TEST_IMG.3" _make_test_img $size
|
||||||
|
TEST_IMG="$TEST_IMG.4" _make_test_img $size
|
||||||
|
|
||||||
|
(cat <<EOF
|
||||||
|
{"execute":"qmp_capabilities"}
|
||||||
|
{"execute":"block-commit",
|
||||||
|
"arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}}
|
||||||
|
EOF
|
||||||
|
sleep 1
|
||||||
|
echo '{"execute":"quit"}'
|
||||||
|
) | $QEMU -qmp stdio -nographic -nodefaults \
|
||||||
|
-blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \
|
||||||
|
-blockdev $IMGFMT,node-name=format-0,file=file-0,read-only=on \
|
||||||
|
-blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \
|
||||||
|
-blockdev $IMGFMT,node-name=format-1,file=file-1,read-only=on,backing=format-0 \
|
||||||
|
-blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \
|
||||||
|
-blockdev $IMGFMT,node-name=format-2,file=file-2,read-only=on,backing=format-1 \
|
||||||
|
-blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \
|
||||||
|
-blockdev $IMGFMT,node-name=format-3,file=file-3,read-only=on,backing=format-2 \
|
||||||
|
-blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \
|
||||||
|
-blockdev $IMGFMT,node-name=format-4,file=file-4,read-only=on,backing=format-3 |
|
||||||
|
_filter_qmp
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo "*** done"
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
22
tests/qemu-iotests/247.out
Normal file
22
tests/qemu-iotests/247.out
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
QA output created by 247
|
||||||
|
|
||||||
|
=== Try commit to backing file with auto-read-only ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728
|
||||||
|
QMP_VERSION
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||||
|
*** done
|
@ -245,3 +245,4 @@
|
|||||||
244 rw auto quick
|
244 rw auto quick
|
||||||
245 rw auto
|
245 rw auto
|
||||||
246 rw auto quick
|
246 rw auto quick
|
||||||
|
247 rw auto quick
|
||||||
|
15
vl.c
15
vl.c
@ -4276,10 +4276,17 @@ int main(int argc, char **argv, char **envp)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Migration object can only be created after global properties
|
||||||
|
* are applied correctly.
|
||||||
|
*/
|
||||||
|
migration_object_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: we need to create block backends before
|
* Note: we need to create block backends before
|
||||||
* machine_set_property(), so machine properties can refer to
|
* machine_set_property(), so machine properties can refer to
|
||||||
* them.
|
* them, and after migration_object_init(), so we can create
|
||||||
|
* migration blockers.
|
||||||
*/
|
*/
|
||||||
configure_blockdev(&bdo_queue, machine_class, snapshot);
|
configure_blockdev(&bdo_queue, machine_class, snapshot);
|
||||||
|
|
||||||
@ -4297,12 +4304,6 @@ int main(int argc, char **argv, char **envp)
|
|||||||
machine_class->name, machine_class->deprecation_reason);
|
machine_class->name, machine_class->deprecation_reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Migration object can only be created after global properties
|
|
||||||
* are applied correctly.
|
|
||||||
*/
|
|
||||||
migration_object_init();
|
|
||||||
|
|
||||||
if (qtest_chrdev) {
|
if (qtest_chrdev) {
|
||||||
qtest_init(qtest_chrdev, qtest_log, &error_fatal);
|
qtest_init(qtest_chrdev, qtest_log, &error_fatal);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user