qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

283 (5163B)


      1 #!/usr/bin/env python3
      2 # group: auto quick
      3 #
      4 # Test for copy-before-write filter permission conflict
      5 #
      6 # Copyright (c) 2019 Virtuozzo International GmbH.
      7 #
      8 # This program is free software; you can redistribute it and/or modify
      9 # it under the terms of the GNU General Public License as published by
     10 # the Free Software Foundation; either version 2 of the License, or
     11 # (at your option) any later version.
     12 #
     13 # This program is distributed in the hope that it will be useful,
     14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 # GNU General Public License for more details.
     17 #
     18 # You should have received a copy of the GNU General Public License
     19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     20 #
     21 
     22 import iotests
     23 
     24 # The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
     25 iotests.script_initialize(
     26     supported_fmts=['qcow2'],
     27 )
     28 
     29 size = 1024 * 1024
     30 
     31 """ Test description
     32 
     33 When performing a backup, all writes on the source subtree must go through the
     34 copy-before-write filter so it can copy all data to the target before it is
     35 changed.  copy-before-write filter is appended above source node, to achieve
     36 this thing, so all parents of source node are handled. A configuration with
     37 side parents of source sub-tree with write permission is unsupported (we'd have
     38 append several copy-before-write filter like nodes to handle such parents). The
     39 test create an example of such configuration and checks that a backup is then
     40 not allowed (blockdev-backup command should fail).
     41 
     42 The configuration:
     43 
     44     ┌────────┐  target  ┌─────────────┐
     45     │ target │ ◀─────── │ backup_top  │
     46     └────────┘          └─────────────┘
     47     48                             │ backing
     49     50                         ┌─────────────┐
     51                         │   source    │
     52                         └─────────────┘
     53     54                             │ file
     55     56                         ┌─────────────┐  write perm   ┌───────┐
     57                         │    base     │ ◀──────────── │ other │
     58                         └─────────────┘               └───────┘
     59 
     60 copy-before-write filter wants to unshare write permission on its source child.
     61 Write unsharing will be propagated to the "source->base" link and will conflict
     62 with other node write permission. So permission update will fail and backup job
     63 will not be started.
     64 
     65 Note, that the only thing which prevents backup of running on such
     66 configuration is default permission propagation scheme. It may be altered by
     67 different block drivers, so backup will run in invalid configuration. But
     68 something is better than nothing. Also, before the previous commit (commit
     69 preceding this test creation), starting backup on such configuration led to
     70 crash, so current "something" is a lot better, and this test actual goal is
     71 to check that crash is fixed :)
     72 """
     73 
     74 vm = iotests.VM()
     75 vm.launch()
     76 
     77 vm.qmp_log('blockdev-add', **{
     78     'node-name': 'target',
     79     'driver': 'null-co',
     80     'size': size,
     81 })
     82 
     83 vm.qmp_log('blockdev-add', **{
     84     'node-name': 'source',
     85     'driver': 'blkdebug',
     86     'image': {'node-name': 'base', 'driver': 'null-co', 'size': size}
     87 })
     88 
     89 vm.qmp_log('blockdev-add', **{
     90     'node-name': 'other',
     91     'driver': 'blkdebug',
     92     'image': 'base',
     93     'take-child-perms': ['write']
     94 })
     95 
     96 vm.qmp_log('blockdev-backup', sync='full', device='source', target='target',
     97            job_id="backup0")
     98 
     99 vm.shutdown()
    100 
    101 
    102 print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
    103 
    104 # Check that the copy-before-write node is gone after job-finalize.
    105 
    106 vm = iotests.VM()
    107 vm.launch()
    108 
    109 vm.qmp_log('blockdev-add', **{
    110     'node-name': 'source',
    111     'driver': 'null-co',
    112 })
    113 
    114 vm.qmp_log('blockdev-add', **{
    115     'node-name': 'target',
    116     'driver': 'null-co',
    117 })
    118 
    119 vm.qmp_log('blockdev-backup',
    120            job_id='backup',
    121            device='source',
    122            target='target',
    123            sync='full',
    124            filter_node_name='backup-filter',
    125            auto_finalize=False,
    126            auto_dismiss=False)
    127 
    128 vm.event_wait('BLOCK_JOB_PENDING', 5.0)
    129 
    130 # The copy-before-write filter should still be present prior to finalization
    131 assert vm.node_info('backup-filter') is not None
    132 
    133 vm.qmp_log('job-finalize', id='backup')
    134 vm.event_wait('BLOCK_JOB_COMPLETED', 5.0)
    135 
    136 # The filter should be gone now.  Check that by trying to access it
    137 # with qemu-io (which will most likely crash qemu if it is still
    138 # there.).
    139 vm.qmp_log('human-monitor-command',
    140            command_line='qemu-io backup-filter "write 0 1M"')
    141 
    142 # (Also, do an explicit check.)
    143 assert vm.node_info('backup-filter') is None
    144 
    145 vm.qmp_log('job-dismiss', id='backup')
    146 vm.event_wait('JOB_STATUS_CHANGE', 5.0, {'data': {'status': 'null'}})
    147 
    148 vm.shutdown()