xref: /openbmc/qemu/tests/qemu-iotests/236 (revision 14da540f2a68b3f730b1a7c31de783f3d68f6fc7)
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