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