8eb5e6746f
Since byte strings are no longer the default in Python 3, we have to explicitly use them where we need to, which is mostly when working with structures. It also means that we need to open a file in binary mode when we want to use structures. On the other hand, we have to accomodate for the fact that some functions (still) work with byte strings but we want to use unicode strings (in Python 3 at least, and it does not matter in Python 2). This includes base64 encoding, but it is most notable when working with the subprocess module: Either we set universal_newlines to True so that the default streams are opened in text mode (hence this parameter is aliased as "text" as of 3.7), or, if that is not possible, we have to decode the output to a normal string. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Message-Id: <20181022135307.14398-4-mreitz@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
118 lines
3.7 KiB
Python
Executable File
118 lines
3.7 KiB
Python
Executable File
#!/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 = b''.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 = b''.join(struct.pack('>H', 1) for j in range(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 = b''.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 = b''.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'])
|