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 = iotests.filter_qtest(self.vm.get_log()) 86 if log: 87 print(log) 88 89 self.vm = self.mkVm() 90 self.vm.launch() 91 92 self.checkBitmap(sha256) 93 self.writeRegions(regions2) 94 sha256 = self.getSha256() 95 96 self.vm.shutdown() 97 self.vm.launch() 98 99 self.checkBitmap(sha256) 100 101 self.vm.shutdown() 102 103 def test_reopen_rw(self): 104 self.vm = self.mkVm() 105 self.vm.launch() 106 self.qmpAddBitmap() 107 108 # Calculate hashes 109 110 self.writeRegions(regions1) 111 sha256_1 = self.getSha256() 112 113 self.writeRegions(regions2) 114 sha256_2 = self.getSha256() 115 assert sha256_1 != sha256_2 # Otherwise, it's not very interesting. 116 117 self.vm.cmd('block-dirty-bitmap-clear', node='drive0', 118 name='bitmap0') 119 120 # Start with regions1 121 122 self.writeRegions(regions1) 123 assert sha256_1 == self.getSha256() 124 125 self.vm.shutdown() 126 127 self.vm = self.mkVmRo() 128 self.vm.launch() 129 130 assert sha256_1 == self.getSha256() 131 132 # Check that we are in RO mode and can't modify bitmap. 133 self.writeRegions(regions2) 134 assert sha256_1 == self.getSha256() 135 136 # Reopen to RW 137 self.vm.cmd('blockdev-reopen', options=[{ 138 'node-name': 'node0', 139 'driver': iotests.imgfmt, 140 'file': { 141 'driver': 'file', 142 'filename': disk 143 }, 144 'read-only': False 145 }]) 146 147 # Check that bitmap is reopened to RW and we can write to it. 148 self.writeRegions(regions2) 149 assert sha256_2 == self.getSha256() 150 151 self.vm.shutdown() 152 153 154if __name__ == '__main__': 155 iotests.main(supported_fmts=['qcow2'], 156 supported_protocols=['file'], 157 unsupported_imgopts=['compat']) 158