1#!/usr/bin/env python 2# 3# Test for qcow2 bitmap printed information 4# 5# Copyright (c) 2019 Virtuozzo International GmbH 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20 21import iotests 22import json 23from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \ 24 file_path, img_info_log, log, filter_qemu_io 25 26iotests.verify_image_format(supported_fmts=['qcow2']) 27 28disk = file_path('disk') 29chunk = 256 * 1024 30bitmap_flag_unknown = 1 << 2 31# flag_offset = 5*cluster_size + flag_offset_in_bitmap_directory_entry 32flag_offset = 0x5000f 33 34 35def print_bitmap(extra_args): 36 log('qemu-img info dump:\n') 37 img_info_log(disk, extra_args=extra_args) 38 result = json.loads(qemu_img_pipe('info', '--force-share', 39 '--output=json', disk)) 40 if 'bitmaps' in result['format-specific']['data']: 41 bitmaps = result['format-specific']['data']['bitmaps'] 42 log('The same bitmaps in JSON format:') 43 log(bitmaps, indent=2) 44 else: 45 log('No bitmap in JSON format output') 46 47 48def add_bitmap(bitmap_number, persistent, disabled): 49 granularity = 1 << (13 + bitmap_number) 50 bitmap_name = 'bitmap-' + str(bitmap_number-1) 51 vm = iotests.VM().add_drive(disk) 52 vm.launch() 53 vm.qmp_log('block-dirty-bitmap-add', node='drive0', name=bitmap_name, 54 granularity=granularity, persistent=persistent, 55 disabled=disabled) 56 vm.shutdown() 57 58 59def write_to_disk(offset, size): 60 write = 'write {} {}'.format(offset, size) 61 log(qemu_io('-c', write, disk), filters=[filter_qemu_io]) 62 63 64def toggle_flag(offset): 65 with open(disk, "r+b") as f: 66 f.seek(offset, 0) 67 c = f.read(1) 68 toggled = chr(ord(c) ^ bitmap_flag_unknown) 69 f.seek(-1, 1) 70 f.write(toggled) 71 72 73qemu_img_create('-f', iotests.imgfmt, disk, '1M') 74 75for num in range(1, 4): 76 disabled = False 77 if num == 2: 78 disabled = True 79 log('Test {}'.format(num)) 80 add_bitmap(num, num > 1, disabled) 81 write_to_disk((num-1) * chunk, chunk) 82 print_bitmap([]) 83 log('') 84 85vm = iotests.VM().add_drive(disk) 86vm.launch() 87num += 1 88log('Test {}\nChecking "in-use" flag...'.format(num)) 89print_bitmap(['--force-share']) 90vm.shutdown() 91 92num += 1 93log('\nTest {}'.format(num)) 94qemu_img_create('-f', iotests.imgfmt, disk, '1M') 95add_bitmap(1, True, False) 96log('Write an unknown bitmap flag \'{}\' into a new QCOW2 image at offset {}' 97 .format(hex(bitmap_flag_unknown), flag_offset)) 98toggle_flag(flag_offset) 99img_info_log(disk) 100toggle_flag(flag_offset) 101log('Unset the unknown bitmap flag \'{}\' in the bitmap directory entry:\n' 102 .format(hex(bitmap_flag_unknown))) 103img_info_log(disk) 104log('Test complete') 105