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