118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #!/usr/bin/env python | ||
|  | # | ||
|  | # Tests growing a large refcount table. | ||
|  | # | ||
|  | # Copyright (C) 2012 Red Hat, Inc. | ||
|  | # | ||
|  | # This program is free software; you can redistribute it and/or modify | ||
|  | # it under the terms of the GNU General Public License as published by | ||
|  | # the Free Software Foundation; either version 2 of the License, or | ||
|  | # (at your option) any later version. | ||
|  | # | ||
|  | # This program is distributed in the hope that it will be useful, | ||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  | # GNU General Public License for more details. | ||
|  | # | ||
|  | # You should have received a copy of the GNU General Public License | ||
|  | # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||
|  | # | ||
|  | 
 | ||
|  | import time | ||
|  | import os | ||
|  | import qcow2 | ||
|  | from qcow2 import QcowHeader | ||
|  | import iotests | ||
|  | from iotests import qemu_img, qemu_img_verbose, qemu_io | ||
|  | import struct | ||
|  | import subprocess | ||
|  | 
 | ||
|  | test_img = os.path.join(iotests.test_dir, 'test.img') | ||
|  | 
 | ||
|  | class TestRefcountTableGrowth(iotests.QMPTestCase): | ||
|  |     '''Abstract base class for image mirroring test cases''' | ||
|  | 
 | ||
|  |     def preallocate(self, name): | ||
|  |         fd = open(name, "r+b") | ||
|  |         try: | ||
|  |             off_reftable = 512 | ||
|  |             off_refblock = off_reftable + (512 * 512) | ||
|  |             off_l1       = off_refblock + (512 * 512 * 64) | ||
|  |             off_l2       = off_l1 + (512 * 512 * 4 * 8) | ||
|  |             off_data     = off_l2 + (512 * 512 * 4 * 512) | ||
|  | 
 | ||
|  |             # Write a new header | ||
|  |             h = QcowHeader(fd) | ||
|  |             h.refcount_table_offset = off_reftable | ||
|  |             h.refcount_table_clusters = 512 | ||
|  |             h.l1_table_offset = off_l1 | ||
|  |             h.l1_size = 512 * 512 * 4 | ||
|  |             h.update(fd) | ||
|  | 
 | ||
|  |             # Write a refcount table | ||
|  |             fd.seek(off_reftable) | ||
|  | 
 | ||
|  |             for i in xrange(0, h.refcount_table_clusters): | ||
|  |                 sector = ''.join(struct.pack('>Q', | ||
|  |                     off_refblock + i * 64 * 512 + j * 512) | ||
|  |                     for j in xrange(0, 64)) | ||
|  |                 fd.write(sector) | ||
|  | 
 | ||
|  |             # Write the refcount blocks | ||
|  |             assert(fd.tell() == off_refblock) | ||
|  |             sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256)) | ||
|  |             for block in xrange(0, h.refcount_table_clusters): | ||
|  |                 fd.write(sector) | ||
|  | 
 | ||
|  |             # Write the L1 table | ||
|  |             assert(fd.tell() == off_l1) | ||
|  |             assert(off_l2 + 512 * h.l1_size == off_data) | ||
|  |             table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) | ||
|  |                 for j in xrange(0, h.l1_size)) | ||
|  |             fd.write(table) | ||
|  | 
 | ||
|  |             # Write the L2 tables | ||
|  |             assert(fd.tell() == off_l2) | ||
|  |             img_file_size = h.refcount_table_clusters * 64 * 256 * 512 | ||
|  |             remaining = img_file_size - off_data | ||
|  | 
 | ||
|  |             off = off_data | ||
|  |             while remaining > 1024 * 512: | ||
|  |                 pytable = list((1 << 63) | off + 512 * j | ||
|  |                     for j in xrange(0, 1024)) | ||
|  |                 table = struct.pack('>1024Q', *pytable) | ||
|  |                 fd.write(table) | ||
|  |                 remaining = remaining - 1024 * 512 | ||
|  |                 off = off + 1024 * 512 | ||
|  | 
 | ||
|  |             table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) | ||
|  |                 for j in xrange(0, remaining / 512)) | ||
|  |             fd.write(table) | ||
|  | 
 | ||
|  | 
 | ||
|  |             # Data | ||
|  |             fd.truncate(img_file_size) | ||
|  | 
 | ||
|  | 
 | ||
|  |         finally: | ||
|  |             fd.close() | ||
|  | 
 | ||
|  | 
 | ||
|  |     def setUp(self): | ||
|  |         qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G') | ||
|  |         self.preallocate(test_img) | ||
|  |         pass | ||
|  | 
 | ||
|  | 
 | ||
|  |     def tearDown(self): | ||
|  |         os.remove(test_img) | ||
|  |         pass | ||
|  | 
 | ||
|  |     def test_grow_refcount_table(self): | ||
|  |         qemu_io('-c', 'write 3800M 1M', test_img) | ||
|  |         qemu_img_verbose('check' , test_img) | ||
|  |         pass | ||
|  | 
 | ||
|  | if __name__ == '__main__': | ||
|  |     iotests.main(supported_fmts=['qcow2']) |