242 (3422B)
1 #!/usr/bin/env python3 2 # group: rw quick 3 # 4 # Test for qcow2 bitmap printed information 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 import json 24 import struct 25 from iotests import qemu_img_create, qemu_io_log, qemu_img_info, \ 26 file_path, img_info_log, log 27 28 iotests.script_initialize(supported_fmts=['qcow2'], 29 supported_protocols=['file'], 30 unsupported_imgopts=['refcount_bits', 'compat']) 31 32 disk = file_path('disk') 33 chunk = 256 * 1024 34 bitmap_flag_unknown = 1 << 2 35 # flag_offset = 5*cluster_size + flag_offset_in_bitmap_directory_entry 36 flag_offset = 0x5000f 37 38 39 def print_bitmap(extra_args): 40 log('qemu-img info dump:\n') 41 img_info_log(disk, extra_args=extra_args) 42 result = qemu_img_info('--force-share', disk) 43 if 'bitmaps' in result['format-specific']['data']: 44 bitmaps = result['format-specific']['data']['bitmaps'] 45 log('The same bitmaps in JSON format:') 46 log(bitmaps, indent=2) 47 else: 48 log('No bitmap in JSON format output') 49 50 51 def add_bitmap(bitmap_number, persistent, disabled): 52 granularity = 1 << (13 + bitmap_number) 53 bitmap_name = 'bitmap-' + str(bitmap_number-1) 54 vm = iotests.VM().add_drive(disk) 55 vm.launch() 56 vm.qmp_log('block-dirty-bitmap-add', node='drive0', name=bitmap_name, 57 granularity=granularity, persistent=persistent, 58 disabled=disabled) 59 vm.shutdown() 60 61 62 def write_to_disk(offset, size): 63 write = 'write {} {}'.format(offset, size) 64 qemu_io_log('-c', write, disk) 65 66 67 def toggle_flag(offset): 68 with open(disk, "r+b") as f: 69 f.seek(offset, 0) 70 # Read one byte in a way compatible with Python 2 71 flags = struct.unpack("B", f.read(1)) 72 toggled = flags[0] ^ bitmap_flag_unknown 73 f.seek(-1, 1) 74 f.write(struct.pack("B", toggled)) 75 76 77 qemu_img_create('-f', iotests.imgfmt, disk, '1M') 78 79 for num in range(1, 4): 80 disabled = False 81 if num == 2: 82 disabled = True 83 log('Test {}'.format(num)) 84 add_bitmap(num, num > 1, disabled) 85 write_to_disk((num-1) * chunk, chunk) 86 print_bitmap([]) 87 log('') 88 89 vm = iotests.VM().add_drive(disk) 90 vm.launch() 91 num += 1 92 log('Test {}\nChecking "in-use" flag...'.format(num)) 93 print_bitmap(['--force-share']) 94 vm.shutdown() 95 96 num += 1 97 log('\nTest {}'.format(num)) 98 qemu_img_create('-f', iotests.imgfmt, disk, '1M') 99 add_bitmap(1, True, False) 100 log('Write an unknown bitmap flag \'{}\' into a new QCOW2 image at offset {}' 101 .format(hex(bitmap_flag_unknown), flag_offset)) 102 toggle_flag(flag_offset) 103 img_info_log(disk, check=False) 104 toggle_flag(flag_offset) 105 log('Unset the unknown bitmap flag \'{}\' in the bitmap directory entry:\n' 106 .format(hex(bitmap_flag_unknown))) 107 img_info_log(disk) 108 log('Test complete')