qemu/tests/qemu-iotests/283
Vladimir Sementsov-Ogievskiy 985cac8f20 blockjob: drop BlockJob.blk field
It's unused now (except for permission handling)[*]. The only reasonable
user of it was block-stream job, recently updated to use own blk. And
other block jobs prefer to use own source node related objects.

So, the arguments of dropping the field are:

 - block jobs prefer not to use it
 - block jobs usually has more then one node to operate on, and better
   to operate symmetrically (for example has both source and target
   blk's in specific block-job state structure)

*: BlockJob.blk is used to keep some permissions. We simply move
permissions to block-job child created in block_job_create() together
with blk.

In mirror, we just should not care anymore about restoring state of
blk. Most probably this code could be dropped long ago, after dropping
bs->job pointer. Now it finally goes away together with BlockJob.blk
itself.

iotest 141 output is updated, as "bdrv_has_blk(bs)" check in
qmp_blockdev_del() doesn't fail (we don't have blk now). Still, new
error message looks even better.

In iotest 283 we need to add a job id, otherwise "Invalid job ID"
happens now earlier than permission check (as permissions moved from
blk to block-job node).

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
2021-12-28 15:18:59 +01:00

149 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
# group: auto quick
#
# Test for copy-before-write filter permission conflict
#
# Copyright (c) 2019 Virtuozzo International GmbH.
#
# 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/>.
#
import iotests
# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
iotests.script_initialize(
supported_fmts=['qcow2'],
)
size = 1024 * 1024
""" Test description
When performing a backup, all writes on the source subtree must go through the
copy-before-write filter so it can copy all data to the target before it is
changed. copy-before-write filter is appended above source node, to achieve
this thing, so all parents of source node are handled. A configuration with
side parents of source sub-tree with write permission is unsupported (we'd have
append several copy-before-write filter like nodes to handle such parents). The
test create an example of such configuration and checks that a backup is then
not allowed (blockdev-backup command should fail).
The configuration:
┌────────┐ target ┌─────────────┐
│ target │ ◀─────── │ backup_top │
└────────┘ └─────────────┘
│ backing
┌─────────────┐
│ source │
└─────────────┘
│ file
┌─────────────┐ write perm ┌───────┐
│ base │ ◀──────────── │ other │
└─────────────┘ └───────┘
copy-before-write filter wants to unshare write permission on its source child.
Write unsharing will be propagated to the "source->base" link and will conflict
with other node write permission. So permission update will fail and backup job
will not be started.
Note, that the only thing which prevents backup of running on such
configuration is default permission propagation scheme. It may be altered by
different block drivers, so backup will run in invalid configuration. But
something is better than nothing. Also, before the previous commit (commit
preceding this test creation), starting backup on such configuration led to
crash, so current "something" is a lot better, and this test actual goal is
to check that crash is fixed :)
"""
vm = iotests.VM()
vm.launch()
vm.qmp_log('blockdev-add', **{
'node-name': 'target',
'driver': 'null-co',
'size': size,
})
vm.qmp_log('blockdev-add', **{
'node-name': 'source',
'driver': 'blkdebug',
'image': {'node-name': 'base', 'driver': 'null-co', 'size': size}
})
vm.qmp_log('blockdev-add', **{
'node-name': 'other',
'driver': 'blkdebug',
'image': 'base',
'take-child-perms': ['write']
})
vm.qmp_log('blockdev-backup', sync='full', device='source', target='target',
job_id="backup0")
vm.shutdown()
print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
# Check that the copy-before-write node is gone after job-finalize.
vm = iotests.VM()
vm.launch()
vm.qmp_log('blockdev-add', **{
'node-name': 'source',
'driver': 'null-co',
})
vm.qmp_log('blockdev-add', **{
'node-name': 'target',
'driver': 'null-co',
})
vm.qmp_log('blockdev-backup',
job_id='backup',
device='source',
target='target',
sync='full',
filter_node_name='backup-filter',
auto_finalize=False,
auto_dismiss=False)
vm.event_wait('BLOCK_JOB_PENDING', 5.0)
# The copy-before-write filter should still be present prior to finalization
assert vm.node_info('backup-filter') is not None
vm.qmp_log('job-finalize', id='backup')
vm.event_wait('BLOCK_JOB_COMPLETED', 5.0)
# The filter should be gone now. Check that by trying to access it
# with qemu-io (which will most likely crash qemu if it is still
# there.).
vm.qmp_log('human-monitor-command',
command_line='qemu-io backup-filter "write 0 1M"')
# (Also, do an explicit check.)
assert vm.node_info('backup-filter') is None
vm.qmp_log('job-dismiss', id='backup')
vm.event_wait('JOB_STATUS_CHANGE', 5.0, {'data': {'status': 'null'}})
vm.shutdown()