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 29d2ef210cSKevin Wolf 30d2ef210cSKevin Wolftest_img = os.path.join(iotests.test_dir, 'test.img') 31d2ef210cSKevin Wolf 32d2ef210cSKevin Wolfclass TestRefcountTableGrowth(iotests.QMPTestCase): 33d2ef210cSKevin Wolf '''Abstract base class for image mirroring test cases''' 34d2ef210cSKevin Wolf 35d2ef210cSKevin Wolf def preallocate(self, name): 36d2ef210cSKevin Wolf fd = open(name, "r+b") 37d2ef210cSKevin Wolf try: 38d2ef210cSKevin Wolf off_reftable = 512 39d2ef210cSKevin Wolf off_refblock = off_reftable + (512 * 512) 40d2ef210cSKevin Wolf off_l1 = off_refblock + (512 * 512 * 64) 41d2ef210cSKevin Wolf off_l2 = off_l1 + (512 * 512 * 4 * 8) 42d2ef210cSKevin Wolf off_data = off_l2 + (512 * 512 * 4 * 512) 43d2ef210cSKevin Wolf 44d2ef210cSKevin Wolf # Write a new header 45d2ef210cSKevin Wolf h = QcowHeader(fd) 46d2ef210cSKevin Wolf h.refcount_table_offset = off_reftable 47d2ef210cSKevin Wolf h.refcount_table_clusters = 512 48d2ef210cSKevin Wolf h.l1_table_offset = off_l1 49d2ef210cSKevin Wolf h.l1_size = 512 * 512 * 4 50d2ef210cSKevin Wolf h.update(fd) 51d2ef210cSKevin Wolf 52d2ef210cSKevin Wolf # Write a refcount table 53d2ef210cSKevin Wolf fd.seek(off_reftable) 54d2ef210cSKevin Wolf 55d2ef210cSKevin Wolf for i in xrange(0, h.refcount_table_clusters): 56*8eb5e674SMax Reitz sector = b''.join(struct.pack('>Q', 57d2ef210cSKevin Wolf off_refblock + i * 64 * 512 + j * 512) 58d2ef210cSKevin Wolf for j in xrange(0, 64)) 59d2ef210cSKevin Wolf fd.write(sector) 60d2ef210cSKevin Wolf 61d2ef210cSKevin Wolf # Write the refcount blocks 62d2ef210cSKevin Wolf assert(fd.tell() == off_refblock) 63*8eb5e674SMax Reitz sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256)) 64d2ef210cSKevin Wolf for block in xrange(0, h.refcount_table_clusters): 65d2ef210cSKevin Wolf fd.write(sector) 66d2ef210cSKevin Wolf 67d2ef210cSKevin Wolf # Write the L1 table 68d2ef210cSKevin Wolf assert(fd.tell() == off_l1) 69d2ef210cSKevin Wolf assert(off_l2 + 512 * h.l1_size == off_data) 70*8eb5e674SMax Reitz table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) 71d2ef210cSKevin Wolf for j in xrange(0, h.l1_size)) 72d2ef210cSKevin Wolf fd.write(table) 73d2ef210cSKevin Wolf 74d2ef210cSKevin Wolf # Write the L2 tables 75d2ef210cSKevin Wolf assert(fd.tell() == off_l2) 76d2ef210cSKevin Wolf img_file_size = h.refcount_table_clusters * 64 * 256 * 512 77d2ef210cSKevin Wolf remaining = img_file_size - off_data 78d2ef210cSKevin Wolf 79d2ef210cSKevin Wolf off = off_data 80d2ef210cSKevin Wolf while remaining > 1024 * 512: 81d2ef210cSKevin Wolf pytable = list((1 << 63) | off + 512 * j 82d2ef210cSKevin Wolf for j in xrange(0, 1024)) 83d2ef210cSKevin Wolf table = struct.pack('>1024Q', *pytable) 84d2ef210cSKevin Wolf fd.write(table) 85d2ef210cSKevin Wolf remaining = remaining - 1024 * 512 86d2ef210cSKevin Wolf off = off + 1024 * 512 87d2ef210cSKevin Wolf 88*8eb5e674SMax Reitz table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) 89d2ef210cSKevin Wolf for j in xrange(0, remaining / 512)) 90d2ef210cSKevin Wolf fd.write(table) 91d2ef210cSKevin Wolf 92d2ef210cSKevin Wolf 93d2ef210cSKevin Wolf # Data 94d2ef210cSKevin Wolf fd.truncate(img_file_size) 95d2ef210cSKevin Wolf 96d2ef210cSKevin Wolf 97d2ef210cSKevin Wolf finally: 98d2ef210cSKevin Wolf fd.close() 99d2ef210cSKevin Wolf 100d2ef210cSKevin Wolf 101d2ef210cSKevin Wolf def setUp(self): 102d2ef210cSKevin Wolf qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G') 103d2ef210cSKevin Wolf self.preallocate(test_img) 104d2ef210cSKevin Wolf pass 105d2ef210cSKevin Wolf 106d2ef210cSKevin Wolf 107d2ef210cSKevin Wolf def tearDown(self): 108d2ef210cSKevin Wolf os.remove(test_img) 109d2ef210cSKevin Wolf pass 110d2ef210cSKevin Wolf 111d2ef210cSKevin Wolf def test_grow_refcount_table(self): 112d2ef210cSKevin Wolf qemu_io('-c', 'write 3800M 1M', test_img) 113d2ef210cSKevin Wolf qemu_img_verbose('check' , test_img) 114d2ef210cSKevin Wolf pass 115d2ef210cSKevin Wolf 116d2ef210cSKevin Wolfif __name__ == '__main__': 117d2ef210cSKevin Wolf iotests.main(supported_fmts=['qcow2']) 118