1*14da540fSJohn Snow#!/usr/bin/env python 2*14da540fSJohn Snow# 3*14da540fSJohn Snow# Test bitmap merges. 4*14da540fSJohn Snow# 5*14da540fSJohn Snow# Copyright (c) 2018 John Snow for Red Hat, Inc. 6*14da540fSJohn Snow# 7*14da540fSJohn Snow# This program is free software; you can redistribute it and/or modify 8*14da540fSJohn Snow# it under the terms of the GNU General Public License as published by 9*14da540fSJohn Snow# the Free Software Foundation; either version 2 of the License, or 10*14da540fSJohn Snow# (at your option) any later version. 11*14da540fSJohn Snow# 12*14da540fSJohn Snow# This program is distributed in the hope that it will be useful, 13*14da540fSJohn Snow# but WITHOUT ANY WARRANTY; without even the implied warranty of 14*14da540fSJohn Snow# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*14da540fSJohn Snow# GNU General Public License for more details. 16*14da540fSJohn Snow# 17*14da540fSJohn Snow# You should have received a copy of the GNU General Public License 18*14da540fSJohn Snow# along with this program. If not, see <http://www.gnu.org/licenses/>. 19*14da540fSJohn Snow# 20*14da540fSJohn Snow# owner=jsnow@redhat.com 21*14da540fSJohn Snow 22*14da540fSJohn Snowimport iotests 23*14da540fSJohn Snowfrom iotests import log 24*14da540fSJohn Snow 25*14da540fSJohn Snowiotests.verify_image_format(supported_fmts=['generic']) 26*14da540fSJohn Snowsize = 64 * 1024 * 1024 27*14da540fSJohn Snowgranularity = 64 * 1024 28*14da540fSJohn Snow 29*14da540fSJohn Snowpatterns = [("0x5d", "0", "64k"), 30*14da540fSJohn Snow ("0xd5", "1M", "64k"), 31*14da540fSJohn Snow ("0xdc", "32M", "64k"), 32*14da540fSJohn Snow ("0xcd", "0x3ff0000", "64k")] # 64M - 64K 33*14da540fSJohn Snow 34*14da540fSJohn Snowoverwrite = [("0xab", "0", "64k"), # Full overwrite 35*14da540fSJohn Snow ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K) 36*14da540fSJohn Snow ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K) 37*14da540fSJohn Snow ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K) 38*14da540fSJohn Snow 39*14da540fSJohn Snowdef query_bitmaps(vm): 40*14da540fSJohn Snow res = vm.qmp("query-block") 41*14da540fSJohn Snow return { "bitmaps": { device['device']: device.get('dirty-bitmaps', []) for 42*14da540fSJohn Snow device in res['return'] } } 43*14da540fSJohn Snow 44*14da540fSJohn Snowwith iotests.FilePath('img') as img_path, \ 45*14da540fSJohn Snow iotests.VM() as vm: 46*14da540fSJohn Snow 47*14da540fSJohn Snow log('--- Preparing image & VM ---\n') 48*14da540fSJohn Snow iotests.qemu_img_create('-f', iotests.imgfmt, img_path, str(size)) 49*14da540fSJohn Snow vm.add_drive(img_path) 50*14da540fSJohn Snow vm.launch() 51*14da540fSJohn Snow 52*14da540fSJohn Snow log('\n--- Adding preliminary bitmaps A & B ---\n') 53*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-add", node="drive0", 54*14da540fSJohn Snow name="bitmapA", granularity=granularity) 55*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-add", node="drive0", 56*14da540fSJohn Snow name="bitmapB", granularity=granularity) 57*14da540fSJohn Snow 58*14da540fSJohn Snow # Dirties 4 clusters. count=262144 59*14da540fSJohn Snow log('\n--- Emulating writes ---\n') 60*14da540fSJohn Snow for p in patterns: 61*14da540fSJohn Snow cmd = "write -P%s %s %s" % p 62*14da540fSJohn Snow log(cmd) 63*14da540fSJohn Snow log(vm.hmp_qemu_io("drive0", cmd)) 64*14da540fSJohn Snow 65*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 66*14da540fSJohn Snow 67*14da540fSJohn Snow log('\n--- Submitting & Aborting Transaction ---\n') 68*14da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 69*14da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 70*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapB" }}, 71*14da540fSJohn Snow { "type": "block-dirty-bitmap-add", 72*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC", 73*14da540fSJohn Snow "granularity": granularity }}, 74*14da540fSJohn Snow { "type": "block-dirty-bitmap-clear", 75*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapA" }}, 76*14da540fSJohn Snow { "type": "abort", "data": {}} 77*14da540fSJohn Snow ]) 78*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 79*14da540fSJohn Snow 80*14da540fSJohn Snow log('\n--- Disabling B & Adding C ---\n') 81*14da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 82*14da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 83*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapB" }}, 84*14da540fSJohn Snow { "type": "block-dirty-bitmap-add", 85*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC", 86*14da540fSJohn Snow "granularity": granularity }}, 87*14da540fSJohn Snow # Purely extraneous, but test that it works: 88*14da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 89*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }}, 90*14da540fSJohn Snow { "type": "block-dirty-bitmap-enable", 91*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }}, 92*14da540fSJohn Snow ]) 93*14da540fSJohn Snow 94*14da540fSJohn Snow log('\n--- Emulating further writes ---\n') 95*14da540fSJohn Snow # Dirties 6 clusters, 3 of which are new in contrast to "A". 96*14da540fSJohn Snow # A = 64 * 1024 * (4 + 3) = 458752 97*14da540fSJohn Snow # C = 64 * 1024 * 6 = 393216 98*14da540fSJohn Snow for p in overwrite: 99*14da540fSJohn Snow cmd = "write -P%s %s %s" % p 100*14da540fSJohn Snow log(cmd) 101*14da540fSJohn Snow log(vm.hmp_qemu_io("drive0", cmd)) 102*14da540fSJohn Snow 103*14da540fSJohn Snow log('\n--- Disabling A & C ---\n') 104*14da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 105*14da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 106*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapA" }}, 107*14da540fSJohn Snow { "type": "block-dirty-bitmap-disable", 108*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapC" }} 109*14da540fSJohn Snow ]) 110*14da540fSJohn Snow 111*14da540fSJohn Snow # A: 7 clusters 112*14da540fSJohn Snow # B: 4 clusters 113*14da540fSJohn Snow # C: 6 clusters 114*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 115*14da540fSJohn Snow 116*14da540fSJohn Snow log('\n--- Submitting & Aborting Merge Transaction ---\n') 117*14da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 118*14da540fSJohn Snow { "type": "block-dirty-bitmap-add", 119*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapD", 120*14da540fSJohn Snow "disabled": True, "granularity": granularity }}, 121*14da540fSJohn Snow { "type": "block-dirty-bitmap-merge", 122*14da540fSJohn Snow "data": { "node": "drive0", "target": "bitmapD", 123*14da540fSJohn Snow "bitmaps": ["bitmapB", "bitmapC"] }}, 124*14da540fSJohn Snow { "type": "abort", "data": {}} 125*14da540fSJohn Snow ]) 126*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 127*14da540fSJohn Snow 128*14da540fSJohn Snow log('\n--- Creating D as a merge of B & C ---\n') 129*14da540fSJohn Snow # Good hygiene: create a disabled bitmap as a merge target. 130*14da540fSJohn Snow vm.qmp_log("transaction", indent=2, actions=[ 131*14da540fSJohn Snow { "type": "block-dirty-bitmap-add", 132*14da540fSJohn Snow "data": { "node": "drive0", "name": "bitmapD", 133*14da540fSJohn Snow "disabled": True, "granularity": granularity }}, 134*14da540fSJohn Snow { "type": "block-dirty-bitmap-merge", 135*14da540fSJohn Snow "data": { "node": "drive0", "target": "bitmapD", 136*14da540fSJohn Snow "bitmaps": ["bitmapB", "bitmapC"] }} 137*14da540fSJohn Snow ]) 138*14da540fSJohn Snow 139*14da540fSJohn Snow # A and D should now both have 7 clusters apiece. 140*14da540fSJohn Snow # B and C remain unchanged with 4 and 6 respectively. 141*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 142*14da540fSJohn Snow 143*14da540fSJohn Snow # A and D should be equivalent. 144*14da540fSJohn Snow # Some formats round the size of the disk, so don't print the checksums. 145*14da540fSJohn Snow check_a = vm.qmp('x-debug-block-dirty-bitmap-sha256', 146*14da540fSJohn Snow node="drive0", name="bitmapA")['return']['sha256'] 147*14da540fSJohn Snow check_d = vm.qmp('x-debug-block-dirty-bitmap-sha256', 148*14da540fSJohn Snow node="drive0", name="bitmapD")['return']['sha256'] 149*14da540fSJohn Snow assert(check_a == check_d) 150*14da540fSJohn Snow 151*14da540fSJohn Snow log('\n--- Removing bitmaps A, B, C, and D ---\n') 152*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapA") 153*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapB") 154*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapC") 155*14da540fSJohn Snow vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapD") 156*14da540fSJohn Snow 157*14da540fSJohn Snow log('\n--- Final Query ---\n') 158*14da540fSJohn Snow log(query_bitmaps(vm), indent=2) 159*14da540fSJohn Snow 160*14da540fSJohn Snow log('\n--- Done ---\n') 161*14da540fSJohn Snow vm.shutdown() 162