1#!/usr/bin/env python3 2# group: rw backing 3# 4# Copyright (C) 2019 Red Hat, Inc. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18# 19# Creator/Owner: Kevin Wolf <kwolf@redhat.com> 20# 21# Some tests for short backing files and short overlays 22 23import iotests 24 25iotests.script_initialize(supported_fmts=['qcow2'], 26 supported_platforms=['linux'], 27 unsupported_imgopts=['refcount_bits', 'compat']) 28 29size_short = 1 * 1024 * 1024 30size_long = 2 * 1024 * 1024 31size_diff = size_long - size_short 32 33def create_chain() -> None: 34 iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, 35 str(size_long)) 36 iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, 37 '-F', iotests.imgfmt, mid, str(size_short)) 38 iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, 39 '-F', iotests.imgfmt, top, str(size_long)) 40 41 iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base) 42 43def create_vm() -> iotests.VM: 44 vm = iotests.VM() 45 vm.add_blockdev('file,filename=%s,node-name=base-file' % base) 46 vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt) 47 vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid) 48 vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base' 49 % iotests.imgfmt) 50 vm.add_drive(top, 'backing=mid,node-name=top') 51 return vm 52 53with iotests.FilePath('base') as base, \ 54 iotests.FilePath('mid') as mid, \ 55 iotests.FilePath('top') as top: 56 57 iotests.log('== Commit tests ==') 58 59 create_chain() 60 61 iotests.log('=== Check visible data ===') 62 63 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top) 64 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top) 65 66 iotests.log('=== Checking allocation status ===') 67 68 iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, 69 '-c', 'alloc %d %d' % (size_short, size_diff), 70 base) 71 72 iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, 73 '-c', 'alloc %d %d' % (size_short, size_diff), 74 mid) 75 76 iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, 77 '-c', 'alloc %d %d' % (size_short, size_diff), 78 top) 79 80 iotests.log('=== Checking map ===') 81 82 iotests.qemu_img_log('map', '--output=json', base) 83 iotests.qemu_img_log('map', '--output=human', base) 84 iotests.qemu_img_log('map', '--output=json', mid) 85 iotests.qemu_img_log('map', '--output=human', mid) 86 iotests.qemu_img_log('map', '--output=json', top) 87 iotests.qemu_img_log('map', '--output=human', top) 88 89 iotests.log('=== Testing qemu-img commit (top -> mid) ===') 90 91 iotests.qemu_img_log('commit', top) 92 iotests.img_info_log(mid) 93 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) 94 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) 95 96 iotests.log('=== Testing HMP commit (top -> mid) ===') 97 98 create_chain() 99 with create_vm() as vm: 100 vm.launch() 101 vm.qmp_log('human-monitor-command', command_line='commit drive0') 102 103 iotests.img_info_log(mid) 104 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) 105 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) 106 107 iotests.log('=== Testing QMP active commit (top -> mid) ===') 108 109 create_chain() 110 with create_vm() as vm: 111 vm.launch() 112 vm.qmp_log('block-commit', device='top', base_node='mid', 113 job_id='job0', auto_dismiss=False) 114 vm.run_job('job0', wait=5) 115 116 iotests.img_info_log(mid) 117 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) 118 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) 119 120 iotests.log('=== Testing qemu-img commit (top -> base) ===') 121 122 create_chain() 123 iotests.qemu_img_log('commit', '-b', base, top) 124 iotests.img_info_log(base) 125 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, base) 126 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), base) 127 128 iotests.log('=== Testing QMP active commit (top -> base) ===') 129 130 create_chain() 131 with create_vm() as vm: 132 vm.launch() 133 vm.qmp_log('block-commit', device='top', base_node='base', 134 job_id='job0', auto_dismiss=False) 135 vm.run_job('job0', wait=5) 136 137 iotests.img_info_log(mid) 138 iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, base) 139 iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), base) 140 141 iotests.log('== Resize tests ==') 142 143 # Use different sizes for different allocation modes: 144 # 145 # We want to have at least one test where 32 bit truncation in the size of 146 # the overlapping area becomes visible. This is covered by the 147 # prealloc='off' case (1G to 6G is an overlap of 5G). 148 # 149 # However, we can only do this for modes that don't preallocate data 150 # because otherwise we might run out of space on the test host. 151 # 152 # We also want to test some unaligned combinations. 153 for (prealloc, base_size, top_size_old, top_size_new, off) in [ 154 ('off', '6G', '1G', '8G', '5G'), 155 ('metadata', '32G', '30G', '33G', '31G'), 156 ('falloc', '10M', '5M', '15M', '9M'), 157 ('full', '16M', '8M', '12M', '11M'), 158 ('off', '384k', '253k', '512k', '253k'), 159 ('off', '400k', '256k', '512k', '336k'), 160 ('off', '512k', '256k', '500k', '436k')]: 161 162 iotests.log('=== preallocation=%s ===' % prealloc) 163 iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size) 164 iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, 165 '-F', iotests.imgfmt, top, top_size_old) 166 iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base) 167 168 # After this, top_size_old to base_size should be allocated/zeroed. 169 # 170 # In theory, leaving base_size to top_size_new unallocated would be 171 # correct, but in practice, if we zero out anything, we zero out 172 # everything up to top_size_new. 173 iotests.qemu_img_log('resize', '-f', iotests.imgfmt, 174 '--preallocation', prealloc, top, top_size_new) 175 iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top) 176 iotests.qemu_io_log('-c', 'map', top) 177 iotests.qemu_img_log('map', '--output=json', top) 178