-----BEGIN PGP SIGNATURE-----

iQIcBAABAgAGBQJa8b++AAoJEL2+eyfA3jBXtLwP/imBRBHjruK9LWH56wQPUBjS
 DHqObGRuN3wthq2NxfhsInV0b7XbJ94V5n0n8/L0KR8u533JEd/vgONNHi+KBJdI
 we/Idv+UWpbr95aXmPgHYn0bWroKd6roke31h/MuPhAB4gxQRE2P8H7Mi5wu2DYj
 VJRHEKJabaE1wIYFI+4yL/vbxDqxIaDHAannx1MhM4VusnRoc5kOZTtxIYWPQXtj
 X6BiytL6d4SqCBFaeZu77vf3xLBd2cSCAvZeGpj7tRQ1MxEd4Am/V5YCtaQtYiu1
 5668g+8Im1PBDrjBUu2zspmDhDde9xjDwqJSiqLlU54zyK+04/0ivR0iWg73qrf1
 N0C00Q3XeBfPz6vHZiYWy8e7JRWGOZrjr6YNy6t///GuPJphr4uJyrnKmyjxv/TZ
 StSvmg2KYa12yvlHRr7Se4kfGFwZ+GBOc2+oj1Nh0qCZledKk6nf8nsZqvn5hetr
 Tn5rQPyf2zcDmKKKp5HOyGQOQEt+d2yREzHItLDamrCLGslo1pRXk8NX3jySVKEr
 hvzunyOo4X9oL8x6YYUemsppIOEcnWi7YaCKekaOXAII8MgmlvMQzkqvs0at7zGa
 a6XC0ZWlV2oAX8g+bgGJ+WKre6VkpSkFh7G57fwzUs0NxkaXKm1+nCLTkQ55+DbH
 8xRQq+03BjIKEMwy2+Qx
 =eOou
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging

# gpg: Signature made Tue 08 May 2018 16:18:22 BST
# gpg:                using RSA key BDBE7B27C0DE3057
# gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>"
# gpg:                 aka "Jeffrey Cody <jeff@codyprime.org>"
# gpg:                 aka "Jeffrey Cody <codyprime@gmail.com>"
# Primary key fingerprint: 9957 4B4D 3474 90E7 9D98  D624 BDBE 7B27 C0DE 3057

* remotes/cody/tags/block-pull-request:
  sheepdog: Fix sd_co_create_opts() memory leaks
  iotests: Add test for cancelling a mirror job
  block/mirror: Make cancel always cancel pre-READY
  block/mirror: honor ratelimit again

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2018-05-08 17:05:58 +01:00
commit e5cd695266
6 changed files with 182 additions and 7 deletions

View File

@ -868,12 +868,16 @@ static void coroutine_fn mirror_run(void *opaque)
}
ret = 0;
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
if (block_job_is_cancelled(&s->common) && s->common.force) {
break;
} else if (!should_complete) {
if (s->synced && !should_complete) {
delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
block_job_sleep_ns(&s->common, delay_ns);
}
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
block_job_sleep_ns(&s->common, delay_ns);
if (block_job_is_cancelled(&s->common) &&
(!s->synced || s->common.force))
{
break;
}
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
}

View File

@ -1987,6 +1987,7 @@ static SheepdogRedundancy *parse_redundancy_str(const char *opt)
} else {
ret = qemu_strtol(n2, NULL, 10, &parity);
if (ret < 0) {
g_free(redundancy);
return NULL;
}
@ -2183,7 +2184,7 @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
QDict *qdict, *location_qdict;
QObject *crumpled;
Visitor *v;
const char *redundancy;
char *redundancy;
Error *local_err = NULL;
int ret;
@ -2253,6 +2254,7 @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
fail:
qapi_free_BlockdevCreateOptions(create_options);
qobject_unref(qdict);
g_free(redundancy);
return ret;
}

View File

@ -36,9 +36,9 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q
{"return": {}}
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
=== Start backup job and exit qemu ===

138
tests/qemu-iotests/218 Normal file
View File

@ -0,0 +1,138 @@
#!/usr/bin/env python
#
# This test covers what happens when a mirror block job is cancelled
# in various phases of its existence.
#
# Note that this test only checks the emitted events (i.e.
# BLOCK_JOB_COMPLETED vs. BLOCK_JOB_CANCELLED), it does not compare
# whether the target is in sync with the source when the
# BLOCK_JOB_COMPLETED event occurs. This is covered by other tests
# (such as 041).
#
# Copyright (C) 2018 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: Max Reitz <mreitz@redhat.com>
import iotests
from iotests import log
iotests.verify_platform(['linux'])
# Launches the VM, adds two null-co nodes (source and target), and
# starts a blockdev-mirror job on them.
#
# Either both or none of speed and buf_size must be given.
def start_mirror(vm, speed=None, buf_size=None):
vm.launch()
ret = vm.qmp('blockdev-add',
node_name='source',
driver='null-co',
size=1048576)
assert ret['return'] == {}
ret = vm.qmp('blockdev-add',
node_name='target',
driver='null-co',
size=1048576)
assert ret['return'] == {}
if speed is not None:
ret = vm.qmp('blockdev-mirror',
job_id='mirror',
device='source',
target='target',
sync='full',
speed=speed,
buf_size=buf_size)
else:
ret = vm.qmp('blockdev-mirror',
job_id='mirror',
device='source',
target='target',
sync='full')
assert ret['return'] == {}
log('')
log('=== Cancel mirror job before convergence ===')
log('')
log('--- force=false ---')
log('')
with iotests.VM() as vm:
# Low speed so it does not converge
start_mirror(vm, 65536, 65536)
log('Cancelling job')
log(vm.qmp('block-job-cancel', device='mirror', force=False))
log(vm.event_wait('BLOCK_JOB_CANCELLED'),
filters=[iotests.filter_qmp_event])
log('')
log('--- force=true ---')
log('')
with iotests.VM() as vm:
# Low speed so it does not converge
start_mirror(vm, 65536, 65536)
log('Cancelling job')
log(vm.qmp('block-job-cancel', device='mirror', force=True))
log(vm.event_wait('BLOCK_JOB_CANCELLED'),
filters=[iotests.filter_qmp_event])
log('')
log('=== Cancel mirror job after convergence ===')
log('')
log('--- force=false ---')
log('')
with iotests.VM() as vm:
start_mirror(vm)
log(vm.event_wait('BLOCK_JOB_READY'),
filters=[iotests.filter_qmp_event])
log('Cancelling job')
log(vm.qmp('block-job-cancel', device='mirror', force=False))
log(vm.event_wait('BLOCK_JOB_COMPLETED'),
filters=[iotests.filter_qmp_event])
log('')
log('--- force=true ---')
log('')
with iotests.VM() as vm:
start_mirror(vm)
log(vm.event_wait('BLOCK_JOB_READY'),
filters=[iotests.filter_qmp_event])
log('Cancelling job')
log(vm.qmp('block-job-cancel', device='mirror', force=True))
log(vm.event_wait('BLOCK_JOB_CANCELLED'),
filters=[iotests.filter_qmp_event])

View File

@ -0,0 +1,30 @@
=== Cancel mirror job before convergence ===
--- force=false ---
Cancelling job
{u'return': {}}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'}
--- force=true ---
Cancelling job
{u'return': {}}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'}
=== Cancel mirror job after convergence ===
--- force=false ---
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'}
Cancelling job
{u'return': {}}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_COMPLETED'}
--- force=true ---
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'}
Cancelling job
{u'return': {}}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_CANCELLED'}

View File

@ -212,3 +212,4 @@
211 rw auto quick
212 rw auto quick
213 rw auto quick
218 rw auto quick