1#!/usr/bin/env python3 2# group: rw quick 3# 4# Tests for persistent dirty bitmaps. 5# 6# Copyright: Vladimir Sementsov-Ogievskiy 2015-2017 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 22import os 23import re 24import iotests 25from iotests import qemu_img 26 27disk = os.path.join(iotests.test_dir, 'disk') 28disk_size = 0x40000000 # 1G 29 30# regions for qemu_io: (start, count) in bytes 31regions1 = ((0x0fff00, 0x10000), 32 (0x200000, 0x100000)) 33 34regions2 = ((0x10000000, 0x20000), 35 (0x3fff0000, 0x10000)) 36 37class TestPersistentDirtyBitmap(iotests.QMPTestCase): 38 39 def setUp(self): 40 qemu_img('create', '-f', iotests.imgfmt, disk, str(disk_size)) 41 42 def tearDown(self): 43 os.remove(disk) 44 45 def mkVm(self): 46 return iotests.VM().add_drive(disk, opts='node-name=node0') 47 48 def mkVmRo(self): 49 return iotests.VM().add_drive(disk, opts='readonly=on,node-name=node0') 50 51 def getSha256(self): 52 result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256', 53 node='drive0', name='bitmap0') 54 return result['return']['sha256'] 55 56 def checkBitmap(self, sha256): 57 result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256', 58 node='drive0', name='bitmap0') 59 self.assert_qmp(result, 'return/sha256', sha256); 60 61 def writeRegions(self, regions): 62 for r in regions: 63 self.vm.hmp_qemu_io('drive0', 64 'write %d %d' % r) 65 66 def qmpAddBitmap(self): 67 self.vm.qmp('block-dirty-bitmap-add', node='drive0', 68 name='bitmap0', persistent=True) 69 70 def test_persistent(self): 71 self.vm = self.mkVm() 72 self.vm.launch() 73 self.qmpAddBitmap() 74 75 self.writeRegions(regions1) 76 sha256 = self.getSha256() 77 78 self.vm.shutdown() 79 80 self.vm = self.mkVmRo() 81 self.vm.launch() 82 self.vm.shutdown() 83 84 #catch 'Persistent bitmaps are lost' possible error 85 log = self.vm.get_log() 86 log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log) 87 log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log) 88 if log: 89 print(log) 90 91 self.vm = self.mkVm() 92 self.vm.launch() 93 94 self.checkBitmap(sha256) 95 self.writeRegions(regions2) 96 sha256 = self.getSha256() 97 98 self.vm.shutdown() 99 self.vm.launch() 100 101 self.checkBitmap(sha256) 102 103 self.vm.shutdown() 104 105 def test_reopen_rw(self): 106 self.vm = self.mkVm() 107 self.vm.launch() 108 self.qmpAddBitmap() 109 110 # Calculate hashes 111 112 self.writeRegions(regions1) 113 sha256_1 = self.getSha256() 114 115 self.writeRegions(regions2) 116 sha256_2 = self.getSha256() 117 assert sha256_1 != sha256_2 # Otherwise, it's not very interesting. 118 119 result = self.vm.qmp('block-dirty-bitmap-clear', node='drive0', 120 name='bitmap0') 121 self.assert_qmp(result, 'return', {}) 122 123 # Start with regions1 124 125 self.writeRegions(regions1) 126 assert sha256_1 == self.getSha256() 127 128 self.vm.shutdown() 129 130 self.vm = self.mkVmRo() 131 self.vm.launch() 132 133 assert sha256_1 == self.getSha256() 134 135 # Check that we are in RO mode and can't modify bitmap. 136 self.writeRegions(regions2) 137 assert sha256_1 == self.getSha256() 138 139 # Reopen to RW 140 result = self.vm.qmp('blockdev-reopen', options=[{ 141 'node-name': 'node0', 142 'driver': iotests.imgfmt, 143 'file': { 144 'driver': 'file', 145 'filename': disk 146 }, 147 'read-only': False 148 }]) 149 self.assert_qmp(result, 'return', {}) 150 151 # Check that bitmap is reopened to RW and we can write to it. 152 self.writeRegions(regions2) 153 assert sha256_2 == self.getSha256() 154 155 self.vm.shutdown() 156 157 158if __name__ == '__main__': 159 iotests.main(supported_fmts=['qcow2'], 160 supported_protocols=['file'], 161 unsupported_imgopts=['compat']) 162