1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 29dd003a9SVladimir Sementsov-Ogievskiy# group: rw 3d2ef210cSKevin Wolf# 4d2ef210cSKevin Wolf# Tests growing a large refcount table. 5d2ef210cSKevin Wolf# 6d2ef210cSKevin Wolf# Copyright (C) 2012 Red Hat, Inc. 7d2ef210cSKevin Wolf# 8d2ef210cSKevin Wolf# This program is free software; you can redistribute it and/or modify 9d2ef210cSKevin Wolf# it under the terms of the GNU General Public License as published by 10d2ef210cSKevin Wolf# the Free Software Foundation; either version 2 of the License, or 11d2ef210cSKevin Wolf# (at your option) any later version. 12d2ef210cSKevin Wolf# 13d2ef210cSKevin Wolf# This program is distributed in the hope that it will be useful, 14d2ef210cSKevin Wolf# but WITHOUT ANY WARRANTY; without even the implied warranty of 15d2ef210cSKevin Wolf# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16d2ef210cSKevin Wolf# GNU General Public License for more details. 17d2ef210cSKevin Wolf# 18d2ef210cSKevin Wolf# You should have received a copy of the GNU General Public License 19d2ef210cSKevin Wolf# along with this program. If not, see <http://www.gnu.org/licenses/>. 20d2ef210cSKevin Wolf# 21d2ef210cSKevin Wolf 22d2ef210cSKevin Wolfimport time 23d2ef210cSKevin Wolfimport os 24d2ef210cSKevin Wolfimport qcow2 25d2ef210cSKevin Wolffrom qcow2 import QcowHeader 26d2ef210cSKevin Wolfimport iotests 27*8f9e54ccSVladimir Sementsov-Ogievskiyfrom iotests import qemu_img, qemu_img_log, qemu_io 28d2ef210cSKevin Wolfimport struct 29d2ef210cSKevin Wolfimport subprocess 3068474776SMax Reitzimport sys 3168474776SMax Reitz 32d2ef210cSKevin Wolftest_img = os.path.join(iotests.test_dir, 'test.img') 33d2ef210cSKevin Wolf 34d2ef210cSKevin Wolfclass TestRefcountTableGrowth(iotests.QMPTestCase): 35d2ef210cSKevin Wolf '''Abstract base class for image mirroring test cases''' 36d2ef210cSKevin Wolf 37d2ef210cSKevin Wolf def preallocate(self, name): 38d2ef210cSKevin Wolf fd = open(name, "r+b") 39d2ef210cSKevin Wolf try: 40d2ef210cSKevin Wolf off_reftable = 512 41d2ef210cSKevin Wolf off_refblock = off_reftable + (512 * 512) 42d2ef210cSKevin Wolf off_l1 = off_refblock + (512 * 512 * 64) 43d2ef210cSKevin Wolf off_l2 = off_l1 + (512 * 512 * 4 * 8) 44d2ef210cSKevin Wolf off_data = off_l2 + (512 * 512 * 4 * 512) 45d2ef210cSKevin Wolf 46d2ef210cSKevin Wolf # Write a new header 47d2ef210cSKevin Wolf h = QcowHeader(fd) 48d2ef210cSKevin Wolf h.refcount_table_offset = off_reftable 49d2ef210cSKevin Wolf h.refcount_table_clusters = 512 50d2ef210cSKevin Wolf h.l1_table_offset = off_l1 51d2ef210cSKevin Wolf h.l1_size = 512 * 512 * 4 52d2ef210cSKevin Wolf h.update(fd) 53d2ef210cSKevin Wolf 54d2ef210cSKevin Wolf # Write a refcount table 55d2ef210cSKevin Wolf fd.seek(off_reftable) 56d2ef210cSKevin Wolf 5768474776SMax Reitz for i in range(0, h.refcount_table_clusters): 588eb5e674SMax Reitz sector = b''.join(struct.pack('>Q', 59d2ef210cSKevin Wolf off_refblock + i * 64 * 512 + j * 512) 6068474776SMax Reitz for j in range(0, 64)) 61d2ef210cSKevin Wolf fd.write(sector) 62d2ef210cSKevin Wolf 63d2ef210cSKevin Wolf # Write the refcount blocks 64d2ef210cSKevin Wolf assert(fd.tell() == off_refblock) 658eb5e674SMax Reitz sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256)) 6668474776SMax Reitz for block in range(0, h.refcount_table_clusters): 67d2ef210cSKevin Wolf fd.write(sector) 68d2ef210cSKevin Wolf 69d2ef210cSKevin Wolf # Write the L1 table 70d2ef210cSKevin Wolf assert(fd.tell() == off_l1) 71d2ef210cSKevin Wolf assert(off_l2 + 512 * h.l1_size == off_data) 728eb5e674SMax Reitz table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) 7368474776SMax Reitz for j in range(0, h.l1_size)) 74d2ef210cSKevin Wolf fd.write(table) 75d2ef210cSKevin Wolf 76d2ef210cSKevin Wolf # Write the L2 tables 77d2ef210cSKevin Wolf assert(fd.tell() == off_l2) 78d2ef210cSKevin Wolf img_file_size = h.refcount_table_clusters * 64 * 256 * 512 79d2ef210cSKevin Wolf remaining = img_file_size - off_data 80d2ef210cSKevin Wolf 81d2ef210cSKevin Wolf off = off_data 82d2ef210cSKevin Wolf while remaining > 1024 * 512: 83d2ef210cSKevin Wolf pytable = list((1 << 63) | off + 512 * j 8468474776SMax Reitz for j in range(0, 1024)) 85d2ef210cSKevin Wolf table = struct.pack('>1024Q', *pytable) 86d2ef210cSKevin Wolf fd.write(table) 87d2ef210cSKevin Wolf remaining = remaining - 1024 * 512 88d2ef210cSKevin Wolf off = off + 1024 * 512 89d2ef210cSKevin Wolf 908eb5e674SMax Reitz table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) 9168474776SMax Reitz for j in range(0, remaining // 512)) 92d2ef210cSKevin Wolf fd.write(table) 93d2ef210cSKevin Wolf 94d2ef210cSKevin Wolf 95d2ef210cSKevin Wolf # Data 96d2ef210cSKevin Wolf fd.truncate(img_file_size) 97d2ef210cSKevin Wolf 98d2ef210cSKevin Wolf 99d2ef210cSKevin Wolf finally: 100d2ef210cSKevin Wolf fd.close() 101d2ef210cSKevin Wolf 102d2ef210cSKevin Wolf 103d2ef210cSKevin Wolf def setUp(self): 104d2ef210cSKevin Wolf qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G') 105d2ef210cSKevin Wolf self.preallocate(test_img) 106d2ef210cSKevin Wolf pass 107d2ef210cSKevin Wolf 108d2ef210cSKevin Wolf 109d2ef210cSKevin Wolf def tearDown(self): 110d2ef210cSKevin Wolf os.remove(test_img) 111d2ef210cSKevin Wolf pass 112d2ef210cSKevin Wolf 113d2ef210cSKevin Wolf def test_grow_refcount_table(self): 114d2ef210cSKevin Wolf qemu_io('-c', 'write 3800M 1M', test_img) 115*8f9e54ccSVladimir Sementsov-Ogievskiy qemu_img_log('check' , test_img) 116d2ef210cSKevin Wolf pass 117d2ef210cSKevin Wolf 118d2ef210cSKevin Wolfif __name__ == '__main__': 119*8f9e54ccSVladimir Sementsov-Ogievskiy iotests.activate_logging() 120103cbc77SMax Reitz iotests.main(supported_fmts=['qcow2'], 121b30b8077SVladimir Sementsov-Ogievskiy supported_protocols=['file'], 122b30b8077SVladimir Sementsov-Ogievskiy unsupported_imgopts=['refcount_bits']) 123