17c477526SPhilippe Mathieu-Daudé#!/usr/bin/env python3 214da540fSJohn Snow# 314da540fSJohn Snow# Test bitmap merges. 414da540fSJohn Snow# 514da540fSJohn Snow# Copyright (c) 2018 John Snow for Red Hat, Inc. 614da540fSJohn Snow# 714da540fSJohn Snow# This program is free software; you can redistribute it and/or modify 814da540fSJohn Snow# it under the terms of the GNU General Public License as published by 914da540fSJohn Snow# the Free Software Foundation; either version 2 of the License, or 1014da540fSJohn Snow# (at your option) any later version. 1114da540fSJohn Snow# 1214da540fSJohn Snow# This program is distributed in the hope that it will be useful, 1314da540fSJohn Snow# but WITHOUT ANY WARRANTY; without even the implied warranty of 1414da540fSJohn Snow# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1514da540fSJohn Snow# GNU General Public License for more details. 1614da540fSJohn Snow# 1714da540fSJohn Snow# You should have received a copy of the GNU General Public License 1814da540fSJohn Snow# along with this program. If not, see <http://www.gnu.org/licenses/>. 1914da540fSJohn Snow# 2014da540fSJohn Snow# owner=jsnow@redhat.com 2114da540fSJohn Snow 2214da540fSJohn Snowimport iotests 2314da540fSJohn Snowfrom iotests import log 2414da540fSJohn Snow 25*7d814059SJohn Snowiotests.script_initialize(supported_fmts=['generic']) 2614da540fSJohn Snowsize = 64 * 1024 * 1024 2714da540fSJohn Snowgranularity = 64 * 1024 2814da540fSJohn Snow 2914da540fSJohn Snowpatterns = [("0x5d", "0", "64k"), 3014da540fSJohn Snow ("0xd5", "1M", "64k"), 3114da540fSJohn Snow ("0xdc", "32M", "64k"), 3214da540fSJohn Snow ("0xcd", "0x3ff0000", "64k")] # 64M - 64K 3314da540fSJohn Snow 3414da540fSJohn Snowoverwrite = [("0xab", "0", "64k"), # Full overwrite 3514da540fSJohn Snow ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K) 3614da540fSJohn Snow ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K) 3714da540fSJohn Snow ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K) 3814da540fSJohn Snow 3914da540fSJohn Snowdef query_bitmaps(vm): 4014da540fSJohn Snow res = vm.qmp("query-block") 4114da540fSJohn Snow return { "bitmaps": { device['device']: device.get('dirty-bitmaps', []) for 4214da540fSJohn Snow device in res['return'] } } 4314da540fSJohn Snow 4414da540fSJohn Snowwith iotests.FilePath('img') as img_path, \ 4514da540fSJohn Snow iotests.VM() as vm: 4614da540fSJohn Snow 4714da540fSJohn Snow log('--- Preparing image & VM ---\n') 4814da540fSJohn Snow iotests.qemu_img_create('-f', iotests.imgfmt, img_path, str(size)) 4914da540fSJohn Snow vm.add_drive(img_path) 5014da540fSJohn Snow vm.launch() 5114da540fSJohn Snow 5214da540fSJohn Snow log('\n--- Adding preliminary bitmaps A & B ---\n') 5314da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-add", node="drive0", 5414da540fSJohn Snow name="bitmapA", granularity=granularity) 5514da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-add", node="drive0", 5614da540fSJohn Snow name="bitmapB", granularity=granularity) 5714da540fSJohn Snow 5814da540fSJohn Snow # Dirties 4 clusters. count=262144 5914da540fSJohn Snow log('\n--- Emulating writes ---\n') 6014da540fSJohn Snow for p in patterns: 6114da540fSJohn Snow cmd = "write -P%s %s %s" % p 6214da540fSJohn Snow log(cmd) 6314da540fSJohn Snow log(vm.hmp_qemu_io("drive0", cmd)) 6414da540fSJohn Snow 6514da540fSJohn Snow log(query_bitmaps(vm), indent=2) 6614da540fSJohn Snow 6714da540fSJohn Snow log('\n--- Submitting & Aborting Transaction ---\n') 6814da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 6914da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 7014da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapB" }}, 7114da540fSJohn Snow { "type": "block-dirty-bitmap-add", 7214da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC", 7314da540fSJohn Snow "granularity": granularity }}, 7414da540fSJohn Snow { "type": "block-dirty-bitmap-clear", 7514da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapA" }}, 7614da540fSJohn Snow { "type": "abort", "data": {}} 7714da540fSJohn Snow ]) 7814da540fSJohn Snow log(query_bitmaps(vm), indent=2) 7914da540fSJohn Snow 8014da540fSJohn Snow log('\n--- Disabling B & Adding C ---\n') 8114da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 8214da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 8314da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapB" }}, 8414da540fSJohn Snow { "type": "block-dirty-bitmap-add", 8514da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC", 8614da540fSJohn Snow "granularity": granularity }}, 8714da540fSJohn Snow # Purely extraneous, but test that it works: 8814da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 8914da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }}, 9014da540fSJohn Snow { "type": "block-dirty-bitmap-enable", 9114da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }}, 9214da540fSJohn Snow ]) 9314da540fSJohn Snow 9414da540fSJohn Snow log('\n--- Emulating further writes ---\n') 9514da540fSJohn Snow # Dirties 6 clusters, 3 of which are new in contrast to "A". 9614da540fSJohn Snow # A = 64 * 1024 * (4 + 3) = 458752 9714da540fSJohn Snow # C = 64 * 1024 * 6 = 393216 9814da540fSJohn Snow for p in overwrite: 9914da540fSJohn Snow cmd = "write -P%s %s %s" % p 10014da540fSJohn Snow log(cmd) 10114da540fSJohn Snow log(vm.hmp_qemu_io("drive0", cmd)) 10214da540fSJohn Snow 10314da540fSJohn Snow log('\n--- Disabling A & C ---\n') 10414da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 10514da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 10614da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapA" }}, 10714da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 10814da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }} 10914da540fSJohn Snow ]) 11014da540fSJohn Snow 11114da540fSJohn Snow # A: 7 clusters 11214da540fSJohn Snow # B: 4 clusters 11314da540fSJohn Snow # C: 6 clusters 11414da540fSJohn Snow log(query_bitmaps(vm), indent=2) 11514da540fSJohn Snow 11614da540fSJohn Snow log('\n--- Submitting & Aborting Merge Transaction ---\n') 11714da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 11814da540fSJohn Snow { "type": "block-dirty-bitmap-add", 11914da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapD", 12014da540fSJohn Snow "disabled": True, "granularity": granularity }}, 12114da540fSJohn Snow { "type": "block-dirty-bitmap-merge", 12214da540fSJohn Snow "data": { "node": "drive0", "target": "bitmapD", 12314da540fSJohn Snow "bitmaps": ["bitmapB", "bitmapC"] }}, 12414da540fSJohn Snow { "type": "abort", "data": {}} 12514da540fSJohn Snow ]) 12614da540fSJohn Snow log(query_bitmaps(vm), indent=2) 12714da540fSJohn Snow 12814da540fSJohn Snow log('\n--- Creating D as a merge of B & C ---\n') 12914da540fSJohn Snow # Good hygiene: create a disabled bitmap as a merge target. 13014da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 13114da540fSJohn Snow { "type": "block-dirty-bitmap-add", 13214da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapD", 13314da540fSJohn Snow "disabled": True, "granularity": granularity }}, 13414da540fSJohn Snow { "type": "block-dirty-bitmap-merge", 13514da540fSJohn Snow "data": { "node": "drive0", "target": "bitmapD", 13614da540fSJohn Snow "bitmaps": ["bitmapB", "bitmapC"] }} 13714da540fSJohn Snow ]) 13814da540fSJohn Snow 13914da540fSJohn Snow # A and D should now both have 7 clusters apiece. 14014da540fSJohn Snow # B and C remain unchanged with 4 and 6 respectively. 14114da540fSJohn Snow log(query_bitmaps(vm), indent=2) 14214da540fSJohn Snow 14314da540fSJohn Snow # A and D should be equivalent. 14414da540fSJohn Snow # Some formats round the size of the disk, so don't print the checksums. 14514da540fSJohn Snow check_a = vm.qmp('x-debug-block-dirty-bitmap-sha256', 14614da540fSJohn Snow node="drive0", name="bitmapA")['return']['sha256'] 14714da540fSJohn Snow check_d = vm.qmp('x-debug-block-dirty-bitmap-sha256', 14814da540fSJohn Snow node="drive0", name="bitmapD")['return']['sha256'] 14914da540fSJohn Snow assert(check_a == check_d) 15014da540fSJohn Snow 15114da540fSJohn Snow log('\n--- Removing bitmaps A, B, C, and D ---\n') 15214da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapA") 15314da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapB") 15414da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapC") 15514da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapD") 15614da540fSJohn Snow 15714da540fSJohn Snow log('\n--- Final Query ---\n') 15814da540fSJohn Snow log(query_bitmaps(vm), indent=2) 15914da540fSJohn Snow 16014da540fSJohn Snow log('\n--- Done ---\n') 16114da540fSJohn Snow vm.shutdown() 162