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