Block patches:

- qcow2 subclusters (extended L2 entries)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl9GESASHG1yZWl0ekBy
 ZWRoYXQuY29tAAoJEPQH2wBh1c9AKNsH/1iG6YVi9c25BoE/3nnu1yJSQiVqpjzt
 hRsV0LzqqaUd3r/yLx5wyFpmcOC+iqJsNrrJCMR9GqMCXyOiH2S9xZs9rVnL44dr
 gt8bhbAfLTQr6ix9rzJUekRHWa0oeoECS6FLdkAnc6xB5Tf5YwOXdX8FYGiR6M9Q
 mibqBIRbQX10ptdZjRpQaDNiTAGMoXfXa1YxTfeFuvW/vwnP34mT+K1B6o1CxDdL
 G9mG9atF0Zu5qjovapw0a/lnEppyxIJXSpU0s6s7dGbuAzw8IRM5utJLSNu4hL/c
 fTxmAnhcB6bFPaMHHMP4izQFds1M1NBZFX/4ji+u0cE8CgTGSqmupRA=
 =j4jq
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-08-26' into staging

Block patches:
- qcow2 subclusters (extended L2 entries)

# gpg: Signature made Wed 26 Aug 2020 08:37:04 BST
# gpg:                using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40
# gpg:                issuer "mreitz@redhat.com"
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full]
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2020-08-26: (34 commits)
  iotests: Add tests for qcow2 images with extended L2 entries
  qcow2: Assert that expand_zero_clusters_in_l1() does not support subclusters
  qcow2: Allow preallocation and backing files if extended_l2 is set
  qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit
  qcow2: Add prealloc field to QCowL2Meta
  qcow2: Add subcluster support to qcow2_measure()
  qcow2: Add subcluster support to qcow2_co_pwrite_zeroes()
  qcow2: Add subcluster support to handle_alloc_space()
  qcow2: Clear the L2 bitmap when allocating a compressed cluster
  qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()
  qcow2: Add subcluster support to check_refcounts_l2()
  qcow2: Add subcluster support to discard_in_l2_slice()
  qcow2: Add subcluster support to zero_in_l2_slice()
  qcow2: Add subcluster support to qcow2_get_host_offset()
  qcow2: Add subcluster support to calculate_l2_meta()
  qcow2: Handle QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC
  qcow2: Replace QCOW2_CLUSTER_* with QCOW2_SUBCLUSTER_*
  qcow2: Add cluster type parameter to qcow2_get_host_offset()
  qcow2: Add qcow2_cluster_is_allocated()
  qcow2: Add qcow2_get_subcluster_range_type()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-08-26 10:28:36 +01:00
commit 25f6dc28a3
34 changed files with 2955 additions and 573 deletions

File diff suppressed because it is too large Load diff

View file

@ -1254,7 +1254,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
l2_slice = NULL;
l1_table = NULL;
l1_size2 = l1_size * sizeof(uint64_t);
slice_size2 = s->l2_slice_size * sizeof(uint64_t);
slice_size2 = s->l2_slice_size * l2_entry_size(s);
n_slices = s->cluster_size / slice_size2;
s->cache_discards = true;
@ -1310,7 +1310,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
uint64_t cluster_index;
uint64_t offset;
entry = be64_to_cpu(l2_slice[j]);
entry = get_l2_entry(s, l2_slice, j);
old_entry = entry;
entry &= ~QCOW_OFLAG_COPIED;
offset = entry & L2E_OFFSET_MASK;
@ -1384,7 +1384,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
qcow2_cache_set_dependency(bs, s->l2_table_cache,
s->refcount_block_cache);
}
l2_slice[j] = cpu_to_be64(entry);
set_l2_entry(s, l2_slice, j, entry);
qcow2_cache_entry_mark_dirty(s->l2_table_cache,
l2_slice);
}
@ -1605,7 +1605,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
int i, l2_size, nb_csectors, ret;
/* Read L2 table from disk */
l2_size = s->l2_size * sizeof(uint64_t);
l2_size = s->l2_size * l2_entry_size(s);
l2_table = g_malloc(l2_size);
ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size);
@ -1617,7 +1617,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
/* Do the actual checks */
for(i = 0; i < s->l2_size; i++) {
l2_entry = be64_to_cpu(l2_table[i]);
l2_entry = get_l2_entry(s, l2_table, i);
switch (qcow2_get_cluster_type(bs, l2_entry)) {
case QCOW2_CLUSTER_COMPRESSED:
@ -1669,26 +1669,33 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
/* Correct offsets are cluster aligned */
if (offset_into_cluster(s, offset)) {
bool contains_data;
res->corruptions++;
if (qcow2_get_cluster_type(bs, l2_entry) ==
QCOW2_CLUSTER_ZERO_ALLOC)
{
fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero "
if (has_subclusters(s)) {
uint64_t l2_bitmap = get_l2_bitmap(s, l2_table, i);
contains_data = (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC);
} else {
contains_data = !(l2_entry & QCOW_OFLAG_ZERO);
}
if (!contains_data) {
fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated "
"cluster is not properly aligned; L2 entry "
"corrupted.\n",
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
offset);
if (fix & BDRV_FIX_ERRORS) {
int idx = i * (l2_entry_size(s) / sizeof(uint64_t));
uint64_t l2e_offset =
l2_offset + (uint64_t)i * sizeof(uint64_t);
l2_offset + (uint64_t)i * l2_entry_size(s);
int ign = active ? QCOW2_OL_ACTIVE_L2 :
QCOW2_OL_INACTIVE_L2;
l2_entry = QCOW_OFLAG_ZERO;
l2_table[i] = cpu_to_be64(l2_entry);
l2_entry = has_subclusters(s) ? 0 : QCOW_OFLAG_ZERO;
set_l2_entry(s, l2_table, i, l2_entry);
ret = qcow2_pre_write_overlap_check(bs, ign,
l2e_offset, sizeof(uint64_t), false);
l2e_offset, l2_entry_size(s), false);
if (ret < 0) {
fprintf(stderr, "ERROR: Overlap check failed\n");
res->check_errors++;
@ -1698,7 +1705,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
}
ret = bdrv_pwrite_sync(bs->file, l2e_offset,
&l2_table[i], sizeof(uint64_t));
&l2_table[idx],
l2_entry_size(s));
if (ret < 0) {
fprintf(stderr, "ERROR: Failed to overwrite L2 "
"table entry: %s\n", strerror(-ret));
@ -1905,7 +1913,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
}
ret = bdrv_pread(bs->file, l2_offset, l2_table,
s->l2_size * sizeof(uint64_t));
s->l2_size * l2_entry_size(s));
if (ret < 0) {
fprintf(stderr, "ERROR: Could not read L2 table: %s\n",
strerror(-ret));
@ -1914,7 +1922,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
}
for (j = 0; j < s->l2_size; j++) {
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
uint64_t l2_entry = get_l2_entry(s, l2_table, j);
uint64_t data_offset = l2_entry & L2E_OFFSET_MASK;
QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry);
@ -1937,9 +1945,10 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
"l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
repair ? "Repairing" : "ERROR", l2_entry, refcount);
if (repair) {
l2_table[j] = cpu_to_be64(refcount == 1
? l2_entry | QCOW_OFLAG_COPIED
: l2_entry & ~QCOW_OFLAG_COPIED);
set_l2_entry(s, l2_table, j,
refcount == 1 ?
l2_entry | QCOW_OFLAG_COPIED :
l2_entry & ~QCOW_OFLAG_COPIED);
l2_dirty++;
}
}

View file

@ -74,7 +74,7 @@ typedef struct {
static int coroutine_fn
qcow2_co_preadv_compressed(BlockDriverState *bs,
uint64_t file_cluster_offset,
uint64_t cluster_descriptor,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@ -883,7 +883,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size);
/* An L2 table is always one cluster in size so the max cache size
* should be a multiple of the cluster size. */
uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t),
uint64_t max_l2_cache = ROUND_UP(max_l2_entries * l2_entry_size(s),
s->cluster_size);
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
@ -1042,7 +1042,7 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
}
}
r->l2_slice_size = l2_cache_entry_size / sizeof(uint64_t);
r->l2_slice_size = l2_cache_entry_size / l2_entry_size(s);
r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size,
l2_cache_entry_size);
r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size,
@ -1444,6 +1444,17 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
}
}
s->subclusters_per_cluster =
has_subclusters(s) ? QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER : 1;
s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
s->subcluster_bits = ctz32(s->subcluster_size);
if (s->subcluster_size < (1 << MIN_CLUSTER_BITS)) {
error_setg(errp, "Unsupported subcluster size: %d", s->subcluster_size);
ret = -EINVAL;
goto fail;
}
/* Check support for various header values */
if (header.refcount_order > 6) {
error_setg(errp, "Reference count entry width too large; may not "
@ -1484,7 +1495,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
bs->encrypted = true;
}
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
s->l2_bits = s->cluster_bits - ctz32(l2_entry_size(s));
s->l2_size = 1 << s->l2_bits;
/* 2^(s->refcount_order - 3) is the refcount width in bytes */
s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3);
@ -1908,7 +1919,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
/* Encryption works on a sector granularity */
bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
}
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
bs->bl.pwrite_zeroes_alignment = s->subcluster_size;
bs->bl.pdiscard_alignment = s->cluster_size;
}
@ -2036,8 +2047,9 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
BlockDriverState **file)
{
BDRVQcow2State *s = bs->opaque;
uint64_t cluster_offset;
uint64_t host_offset;
unsigned int bytes;
QCow2SubclusterType type;
int ret, status = 0;
qemu_co_mutex_lock(&s->lock);
@ -2049,7 +2061,7 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
}
bytes = MIN(INT_MAX, count);
ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset, &type);
qemu_co_mutex_unlock(&s->lock);
if (ret < 0) {
return ret;
@ -2057,15 +2069,18 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
*pnum = bytes;
if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) &&
!s->crypto) {
*map = cluster_offset | offset_into_cluster(s, offset);
if ((type == QCOW2_SUBCLUSTER_NORMAL ||
type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) && !s->crypto) {
*map = host_offset;
*file = s->data_file->bs;
status |= BDRV_BLOCK_OFFSET_VALID;
}
if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
type == QCOW2_SUBCLUSTER_ZERO_ALLOC) {
status |= BDRV_BLOCK_ZERO;
} else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
} else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) {
status |= BDRV_BLOCK_DATA;
}
if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
@ -2087,6 +2102,7 @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
QCowL2Meta *next;
if (link_l2) {
assert(!l2meta->prealloc);
ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
if (ret) {
goto out;
@ -2113,7 +2129,7 @@ out:
static coroutine_fn int
qcow2_co_preadv_encrypted(BlockDriverState *bs,
uint64_t file_cluster_offset,
uint64_t host_offset,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@ -2140,16 +2156,12 @@ qcow2_co_preadv_encrypted(BlockDriverState *bs,
}
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
ret = bdrv_co_pread(s->data_file,
file_cluster_offset + offset_into_cluster(s, offset),
bytes, buf, 0);
ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0);
if (ret < 0) {
goto fail;
}
if (qcow2_co_decrypt(bs,
file_cluster_offset + offset_into_cluster(s, offset),
offset, buf, bytes) < 0)
if (qcow2_co_decrypt(bs, host_offset, offset, buf, bytes) < 0)
{
ret = -EIO;
goto fail;
@ -2166,8 +2178,8 @@ typedef struct Qcow2AioTask {
AioTask task;
BlockDriverState *bs;
QCow2ClusterType cluster_type; /* only for read */
uint64_t file_cluster_offset;
QCow2SubclusterType subcluster_type; /* only for read */
uint64_t host_offset; /* or full descriptor in compressed clusters */
uint64_t offset;
uint64_t bytes;
QEMUIOVector *qiov;
@ -2179,8 +2191,8 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task);
static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
AioTaskPool *pool,
AioTaskFunc func,
QCow2ClusterType cluster_type,
uint64_t file_cluster_offset,
QCow2SubclusterType subcluster_type,
uint64_t host_offset,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@ -2193,9 +2205,9 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
*task = (Qcow2AioTask) {
.task.func = func,
.bs = bs,
.cluster_type = cluster_type,
.subcluster_type = subcluster_type,
.qiov = qiov,
.file_cluster_offset = file_cluster_offset,
.host_offset = host_offset,
.offset = offset,
.bytes = bytes,
.qiov_offset = qiov_offset,
@ -2204,7 +2216,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
func == qcow2_co_preadv_task_entry ? "read" : "write",
cluster_type, file_cluster_offset, offset, bytes,
subcluster_type, host_offset, offset, bytes,
qiov, qiov_offset);
if (!pool) {
@ -2217,42 +2229,40 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
}
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
QCow2ClusterType cluster_type,
uint64_t file_cluster_offset,
QCow2SubclusterType subc_type,
uint64_t host_offset,
uint64_t offset, uint64_t bytes,
QEMUIOVector *qiov,
size_t qiov_offset)
{
BDRVQcow2State *s = bs->opaque;
int offset_in_cluster = offset_into_cluster(s, offset);
switch (cluster_type) {
case QCOW2_CLUSTER_ZERO_PLAIN:
case QCOW2_CLUSTER_ZERO_ALLOC:
switch (subc_type) {
case QCOW2_SUBCLUSTER_ZERO_PLAIN:
case QCOW2_SUBCLUSTER_ZERO_ALLOC:
/* Both zero types are handled in qcow2_co_preadv_part */
g_assert_not_reached();
case QCOW2_CLUSTER_UNALLOCATED:
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
return bdrv_co_preadv_part(bs->backing, offset, bytes,
qiov, qiov_offset, 0);
case QCOW2_CLUSTER_COMPRESSED:
return qcow2_co_preadv_compressed(bs, file_cluster_offset,
case QCOW2_SUBCLUSTER_COMPRESSED:
return qcow2_co_preadv_compressed(bs, host_offset,
offset, bytes, qiov, qiov_offset);
case QCOW2_CLUSTER_NORMAL:
assert(offset_into_cluster(s, file_cluster_offset) == 0);
case QCOW2_SUBCLUSTER_NORMAL:
if (bs->encrypted) {
return qcow2_co_preadv_encrypted(bs, file_cluster_offset,
return qcow2_co_preadv_encrypted(bs, host_offset,
offset, bytes, qiov, qiov_offset);
}
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
return bdrv_co_preadv_part(s->data_file,
file_cluster_offset + offset_in_cluster,
return bdrv_co_preadv_part(s->data_file, host_offset,
bytes, qiov, qiov_offset, 0);
default:
@ -2268,8 +2278,9 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
assert(!t->l2meta);
return qcow2_co_preadv_task(t->bs, t->cluster_type, t->file_cluster_offset,
t->offset, t->bytes, t->qiov, t->qiov_offset);
return qcow2_co_preadv_task(t->bs, t->subcluster_type,
t->host_offset, t->offset, t->bytes,
t->qiov, t->qiov_offset);
}
static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
@ -2280,7 +2291,8 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
BDRVQcow2State *s = bs->opaque;
int ret = 0;
unsigned int cur_bytes; /* number of bytes in current iteration */
uint64_t cluster_offset = 0;
uint64_t host_offset = 0;
QCow2SubclusterType type;
AioTaskPool *aio = NULL;
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
@ -2292,23 +2304,25 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
}
qemu_co_mutex_lock(&s->lock);
ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset);
ret = qcow2_get_host_offset(bs, offset, &cur_bytes,
&host_offset, &type);
qemu_co_mutex_unlock(&s->lock);
if (ret < 0) {
goto out;
}
if (ret == QCOW2_CLUSTER_ZERO_PLAIN ||
ret == QCOW2_CLUSTER_ZERO_ALLOC ||
(ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
(type == QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && !bs->backing) ||
(type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC && !bs->backing))
{
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
} else {
if (!aio && cur_bytes != bytes) {
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
}
ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
cluster_offset, offset, cur_bytes,
ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, type,
host_offset, offset, cur_bytes,
qiov, qiov_offset, NULL);
if (ret < 0) {
goto out;
@ -2414,6 +2428,9 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
for (m = l2meta; m != NULL; m = m->next) {
int ret;
uint64_t start_offset = m->alloc_offset + m->cow_start.offset;
unsigned nb_bytes = m->cow_end.offset + m->cow_end.nb_bytes -
m->cow_start.offset;
if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) {
continue;
@ -2428,16 +2445,14 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
* efficiently zero out the whole clusters
*/
ret = qcow2_pre_write_overlap_check(bs, 0, m->alloc_offset,
m->nb_clusters * s->cluster_size,
ret = qcow2_pre_write_overlap_check(bs, 0, start_offset, nb_bytes,
true);
if (ret < 0) {
return ret;
}
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE);
ret = bdrv_co_pwrite_zeroes(s->data_file, m->alloc_offset,
m->nb_clusters * s->cluster_size,
ret = bdrv_co_pwrite_zeroes(s->data_file, start_offset, nb_bytes,
BDRV_REQ_NO_FALLBACK);
if (ret < 0) {
if (ret != -ENOTSUP && ret != -EAGAIN) {
@ -2459,7 +2474,7 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
* not use it somehow after qcow2_co_pwritev_task() call
*/
static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
uint64_t file_cluster_offset,
uint64_t host_offset,
uint64_t offset, uint64_t bytes,
QEMUIOVector *qiov,
uint64_t qiov_offset,
@ -2468,7 +2483,6 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
int ret;
BDRVQcow2State *s = bs->opaque;
void *crypt_buf = NULL;
int offset_in_cluster = offset_into_cluster(s, offset);
QEMUIOVector encrypted_qiov;
if (bs->encrypted) {
@ -2481,9 +2495,7 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
}
qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes);
if (qcow2_co_encrypt(bs, file_cluster_offset + offset_in_cluster,
offset, crypt_buf, bytes) < 0)
{
if (qcow2_co_encrypt(bs, host_offset, offset, crypt_buf, bytes) < 0) {
ret = -EIO;
goto out_unlocked;
}
@ -2507,10 +2519,8 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
*/
if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) {
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
trace_qcow2_writev_data(qemu_coroutine_self(),
file_cluster_offset + offset_in_cluster);
ret = bdrv_co_pwritev_part(s->data_file,
file_cluster_offset + offset_in_cluster,
trace_qcow2_writev_data(qemu_coroutine_self(), host_offset);
ret = bdrv_co_pwritev_part(s->data_file, host_offset,
bytes, qiov, qiov_offset, 0);
if (ret < 0) {
goto out_unlocked;
@ -2538,9 +2548,9 @@ static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
{
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
assert(!t->cluster_type);
assert(!t->subcluster_type);
return qcow2_co_pwritev_task(t->bs, t->file_cluster_offset,
return qcow2_co_pwritev_task(t->bs, t->host_offset,
t->offset, t->bytes, t->qiov, t->qiov_offset,
t->l2meta);
}
@ -2595,8 +2605,8 @@ static coroutine_fn int qcow2_co_pwritev_part(
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
}
ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
cluster_offset, offset, cur_bytes,
qiov, qiov_offset, l2meta);
cluster_offset + offset_in_cluster, offset,
cur_bytes, qiov, qiov_offset, l2meta);
l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
if (ret < 0) {
goto fail_nometa;
@ -2930,6 +2940,11 @@ int qcow2_update_header(BlockDriverState *bs)
.bit = QCOW2_INCOMPAT_COMPRESSION_BITNR,
.name = "compression type",
},
{
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
.bit = QCOW2_INCOMPAT_EXTL2_BITNR,
.name = "extended L2 entries",
},
{
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
@ -3127,6 +3142,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
while (meta) {
QCowL2Meta *next = meta->next;
meta->prealloc = true;
ret = qcow2_alloc_cluster_link_l2(bs, meta);
if (ret < 0) {
@ -3229,28 +3245,31 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size,
* @total_size: virtual disk size in bytes
* @cluster_size: cluster size in bytes
* @refcount_order: refcount bits power-of-2 exponent
* @extended_l2: true if the image has extended L2 entries
*
* Returns: Total number of bytes required for the fully allocated image
* (including metadata).
*/
static int64_t qcow2_calc_prealloc_size(int64_t total_size,
size_t cluster_size,
int refcount_order)
int refcount_order,
bool extended_l2)
{
int64_t meta_size = 0;
uint64_t nl1e, nl2e;
int64_t aligned_total_size = ROUND_UP(total_size, cluster_size);
size_t l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
/* header: 1 cluster */
meta_size += cluster_size;
/* total size of L2 tables */
nl2e = aligned_total_size / cluster_size;
nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t));
meta_size += nl2e * sizeof(uint64_t);
nl2e = ROUND_UP(nl2e, cluster_size / l2e_size);
meta_size += nl2e * l2e_size;
/* total size of L1 tables */
nl1e = nl2e * sizeof(uint64_t) / cluster_size;
nl1e = nl2e * l2e_size / cluster_size;
nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t));
meta_size += nl1e * sizeof(uint64_t);
@ -3262,7 +3281,8 @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
return meta_size + aligned_total_size;
}
static bool validate_cluster_size(size_t cluster_size, Error **errp)
static bool validate_cluster_size(size_t cluster_size, bool extended_l2,
Error **errp)
{
int cluster_bits = ctz32(cluster_size);
if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
@ -3272,16 +3292,28 @@ static bool validate_cluster_size(size_t cluster_size, Error **errp)
"%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
return false;
}
if (extended_l2) {
unsigned min_cluster_size =
(1 << MIN_CLUSTER_BITS) * QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER;
if (cluster_size < min_cluster_size) {
error_setg(errp, "Extended L2 entries are only supported with "
"cluster sizes of at least %u bytes", min_cluster_size);
return false;
}
}
return true;
}
static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp)
static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, bool extended_l2,
Error **errp)
{
size_t cluster_size;
cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
DEFAULT_CLUSTER_SIZE);
if (!validate_cluster_size(cluster_size, errp)) {
if (!validate_cluster_size(cluster_size, extended_l2, errp)) {
return 0;
}
return cluster_size;
@ -3395,7 +3427,20 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
cluster_size = DEFAULT_CLUSTER_SIZE;
}
if (!validate_cluster_size(cluster_size, errp)) {
if (!qcow2_opts->has_extended_l2) {
qcow2_opts->extended_l2 = false;
}
if (qcow2_opts->extended_l2) {
if (version < 3) {
error_setg(errp, "Extended L2 entries are only supported with "
"compatibility level 1.1 and above (use version=v3 or "
"greater)");
ret = -EINVAL;
goto out;
}
}
if (!validate_cluster_size(cluster_size, qcow2_opts->extended_l2, errp)) {
ret = -EINVAL;
goto out;
}
@ -3404,10 +3449,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
qcow2_opts->preallocation = PREALLOC_MODE_OFF;
}
if (qcow2_opts->has_backing_file &&
qcow2_opts->preallocation != PREALLOC_MODE_OFF)
qcow2_opts->preallocation != PREALLOC_MODE_OFF &&
!qcow2_opts->extended_l2)
{
error_setg(errp, "Backing file and preallocation cannot be used at "
"the same time");
error_setg(errp, "Backing file and preallocation can only be used at "
"the same time if extended_l2 is on");
ret = -EINVAL;
goto out;
}
@ -3546,6 +3592,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
cpu_to_be64(QCOW2_INCOMPAT_COMPRESSION);
}
if (qcow2_opts->extended_l2) {
header->incompatible_features |=
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
}
ret = blk_pwrite(blk, 0, header, cluster_size, 0);
g_free(header);
if (ret < 0) {
@ -3723,6 +3774,7 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
{ BLOCK_OPT_BACKING_FMT, "backing-fmt" },
{ BLOCK_OPT_CLUSTER_SIZE, "cluster-size" },
{ BLOCK_OPT_LAZY_REFCOUNTS, "lazy-refcounts" },
{ BLOCK_OPT_EXTL2, "extended-l2" },
{ BLOCK_OPT_REFCOUNT_BITS, "refcount-bits" },
{ BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT },
{ BLOCK_OPT_COMPAT_LEVEL, "version" },
@ -3830,8 +3882,9 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
int ret;
BDRVQcow2State *s = bs->opaque;
uint32_t head = offset % s->cluster_size;
uint32_t tail = (offset + bytes) % s->cluster_size;
uint32_t head = offset_into_subcluster(s, offset);
uint32_t tail = ROUND_UP(offset + bytes, s->subcluster_size) -
(offset + bytes);
trace_qcow2_pwrite_zeroes_start_req(qemu_coroutine_self(), offset, bytes);
if (offset + bytes == bs->total_sectors * BDRV_SECTOR_SIZE) {
@ -3841,25 +3894,27 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
if (head || tail) {
uint64_t off;
unsigned int nr;
QCow2SubclusterType type;
assert(head + bytes <= s->cluster_size);
assert(head + bytes + tail <= s->subcluster_size);
/* check whether remainder of cluster already reads as zero */
if (!(is_zero(bs, offset - head, head) &&
is_zero(bs, offset + bytes,
tail ? s->cluster_size - tail : 0))) {
is_zero(bs, offset + bytes, tail))) {
return -ENOTSUP;
}
qemu_co_mutex_lock(&s->lock);
/* We can have new write after previous check */
offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
bytes = s->cluster_size;
nr = s->cluster_size;
ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
if (ret != QCOW2_CLUSTER_UNALLOCATED &&
ret != QCOW2_CLUSTER_ZERO_PLAIN &&
ret != QCOW2_CLUSTER_ZERO_ALLOC) {
offset -= head;
bytes = s->subcluster_size;
nr = s->subcluster_size;
ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type);
if (ret < 0 ||
(type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC &&
type != QCOW2_SUBCLUSTER_ZERO_PLAIN &&
type != QCOW2_SUBCLUSTER_ZERO_ALLOC)) {
qemu_co_mutex_unlock(&s->lock);
return -ENOTSUP;
}
@ -3869,8 +3924,8 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
trace_qcow2_pwrite_zeroes(qemu_coroutine_self(), offset, bytes);
/* Whatever is left can use real zero clusters */
ret = qcow2_cluster_zeroize(bs, offset, bytes, flags);
/* Whatever is left can use real zero subclusters */
ret = qcow2_subcluster_zeroize(bs, offset, bytes, flags);
qemu_co_mutex_unlock(&s->lock);
return ret;
@ -3923,17 +3978,20 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
while (bytes != 0) {
uint64_t copy_offset = 0;
QCow2SubclusterType type;
/* prepare next request */
cur_bytes = MIN(bytes, INT_MAX);
cur_write_flags = write_flags;
ret = qcow2_get_cluster_offset(bs, src_offset, &cur_bytes, &copy_offset);
ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes,
&copy_offset, &type);
if (ret < 0) {
goto out;
}
switch (ret) {
case QCOW2_CLUSTER_UNALLOCATED:
switch (type) {
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
if (bs->backing && bs->backing->bs) {
int64_t backing_length = bdrv_getlength(bs->backing->bs);
if (src_offset >= backing_length) {
@ -3948,18 +4006,17 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
}
break;
case QCOW2_CLUSTER_ZERO_PLAIN:
case QCOW2_CLUSTER_ZERO_ALLOC:
case QCOW2_SUBCLUSTER_ZERO_PLAIN:
case QCOW2_SUBCLUSTER_ZERO_ALLOC:
cur_write_flags |= BDRV_REQ_ZERO_WRITE;
break;
case QCOW2_CLUSTER_COMPRESSED:
case QCOW2_SUBCLUSTER_COMPRESSED:
ret = -ENOTSUP;
goto out;
case QCOW2_CLUSTER_NORMAL:
case QCOW2_SUBCLUSTER_NORMAL:
child = s->data_file;
copy_offset += offset_into_cluster(s, src_offset);
break;
default:
@ -4206,6 +4263,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
int64_t clusters_allocated;
int64_t old_file_size, last_cluster, new_file_size;
uint64_t nb_new_data_clusters, nb_new_l2_tables;
bool subclusters_need_allocation = false;
/* With a data file, preallocation means just allocating the metadata
* and forwarding the truncate request to the data file */
@ -4246,7 +4304,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
* preallocation. All that matters is that we will not have to allocate
* new refcount structures for them.) */
nb_new_l2_tables = DIV_ROUND_UP(nb_new_data_clusters,
s->cluster_size / sizeof(uint64_t));
s->cluster_size / l2_entry_size(s));
/* The cluster range may not be aligned to L2 boundaries, so add one L2
* table for a potential head/tail */
nb_new_l2_tables++;
@ -4287,6 +4345,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
BDRV_REQ_ZERO_WRITE, NULL);
if (ret >= 0) {
flags &= ~BDRV_REQ_ZERO_WRITE;
/* Ensure that we read zeroes and not backing file data */
subclusters_need_allocation = true;
}
} else {
ret = -1;
@ -4325,6 +4385,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
.offset = nb_clusters << s->cluster_bits,
.nb_bytes = 0,
},
.prealloc = !subclusters_need_allocation,
};
qemu_co_queue_init(&allocation.dependent_requests);
@ -4349,15 +4410,16 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
}
if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->subcluster_size);
/*
* Use zero clusters as much as we can. qcow2_cluster_zeroize()
* requires a cluster-aligned start. The end may be unaligned if it is
* at the end of the image (which it is here).
* Use zero clusters as much as we can. qcow2_subcluster_zeroize()
* requires a subcluster-aligned start. The end may be unaligned if
* it is at the end of the image (which it is here).
*/
if (offset > zero_start) {
ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
ret = qcow2_subcluster_zeroize(bs, zero_start, offset - zero_start,
0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to zero out new clusters");
goto fail;
@ -4487,7 +4549,7 @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
{
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
assert(!t->cluster_type && !t->l2meta);
assert(!t->subcluster_type && !t->l2meta);
return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
t->qiov_offset);
@ -4562,7 +4624,7 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
static int coroutine_fn
qcow2_co_preadv_compressed(BlockDriverState *bs,
uint64_t file_cluster_offset,
uint64_t cluster_descriptor,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@ -4574,8 +4636,8 @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
uint8_t *buf, *out_buf;
int offset_in_cluster = offset_into_cluster(s, offset);
coffset = file_cluster_offset & s->cluster_offset_mask;
nb_csectors = ((file_cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
coffset = cluster_descriptor & s->cluster_offset_mask;
nb_csectors = ((cluster_descriptor >> s->csize_shift) & s->csize_mask) + 1;
csize = nb_csectors * QCOW2_COMPRESSED_SECTOR_SIZE -
(coffset & ~QCOW2_COMPRESSED_SECTOR_MASK);
@ -4829,9 +4891,14 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
PreallocMode prealloc;
bool has_backing_file;
bool has_luks;
bool extended_l2;
size_t l2e_size;
/* Parse image creation options */
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
extended_l2 = qemu_opt_get_bool_del(opts, BLOCK_OPT_EXTL2, false);
cluster_size = qcow2_opt_get_cluster_size_del(opts, extended_l2,
&local_err);
if (local_err) {
goto err;
}
@ -4887,8 +4954,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
virtual_size = ROUND_UP(virtual_size, cluster_size);
/* Check that virtual disk size is valid */
l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,
cluster_size / sizeof(uint64_t));
cluster_size / l2e_size);
if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) {
error_setg(&local_err, "The image size is too large "
"(try using a larger cluster size)");
@ -4951,9 +5019,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
}
info = g_new0(BlockMeasureInfo, 1);
info->fully_allocated =
info->fully_allocated = luks_payload_size +
qcow2_calc_prealloc_size(virtual_size, cluster_size,
ctz32(refcount_bits)) + luks_payload_size;
ctz32(refcount_bits), extended_l2);
/*
* Remove data clusters that are not required. This overestimates the
@ -5026,6 +5094,8 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
.corrupt = s->incompatible_features &
QCOW2_INCOMPAT_CORRUPT,
.has_corrupt = true,
.has_extended_l2 = true,
.extended_l2 = has_subclusters(s),
.refcount_bits = s->refcount_bits,
.has_bitmaps = !!bitmaps,
.bitmaps = bitmaps,
@ -5753,6 +5823,12 @@ static QemuOptsList qcow2_create_opts = {
.help = "qcow2 cluster size", \
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE) \
}, \
{ \
.name = BLOCK_OPT_EXTL2, \
.type = QEMU_OPT_BOOL, \
.help = "Extended L2 tables", \
.def_value_str = "off" \
}, \
{ \
.name = BLOCK_OPT_PREALLOC, \
.type = QEMU_OPT_STRING, \

View file

@ -78,6 +78,27 @@
/* The cluster reads as all zeros */
#define QCOW_OFLAG_ZERO (1ULL << 0)
#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
/* The subcluster X [0..31] is allocated */
#define QCOW_OFLAG_SUB_ALLOC(X) (1ULL << (X))
/* The subcluster X [0..31] reads as zeroes */
#define QCOW_OFLAG_SUB_ZERO(X) (QCOW_OFLAG_SUB_ALLOC(X) << 32)
/* Subclusters [X, Y) (0 <= X <= Y <= 32) are allocated */
#define QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) \
(QCOW_OFLAG_SUB_ALLOC(Y) - QCOW_OFLAG_SUB_ALLOC(X))
/* Subclusters [X, Y) (0 <= X <= Y <= 32) read as zeroes */
#define QCOW_OFLAG_SUB_ZERO_RANGE(X, Y) \
(QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) << 32)
/* L2 entry bitmap with all allocation bits set */
#define QCOW_L2_BITMAP_ALL_ALLOC (QCOW_OFLAG_SUB_ALLOC_RANGE(0, 32))
/* L2 entry bitmap with all "read as zeroes" bits set */
#define QCOW_L2_BITMAP_ALL_ZEROES (QCOW_OFLAG_SUB_ZERO_RANGE(0, 32))
/* Size of normal and extended L2 entries */
#define L2E_SIZE_NORMAL (sizeof(uint64_t))
#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2)
#define MIN_CLUSTER_BITS 9
#define MAX_CLUSTER_BITS 21
@ -225,15 +246,18 @@ enum {
QCOW2_INCOMPAT_CORRUPT_BITNR = 1,
QCOW2_INCOMPAT_DATA_FILE_BITNR = 2,
QCOW2_INCOMPAT_COMPRESSION_BITNR = 3,
QCOW2_INCOMPAT_EXTL2_BITNR = 4,
QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
QCOW2_INCOMPAT_DATA_FILE = 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR,
QCOW2_INCOMPAT_COMPRESSION = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR,
QCOW2_INCOMPAT_EXTL2 = 1 << QCOW2_INCOMPAT_EXTL2_BITNR,
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY
| QCOW2_INCOMPAT_CORRUPT
| QCOW2_INCOMPAT_DATA_FILE
| QCOW2_INCOMPAT_COMPRESSION,
| QCOW2_INCOMPAT_COMPRESSION
| QCOW2_INCOMPAT_EXTL2,
};
/* Compatible feature bits */
@ -295,6 +319,9 @@ typedef struct BDRVQcow2State {
int cluster_bits;
int cluster_size;
int l2_slice_size;
int subcluster_bits;
int subcluster_size;
int subclusters_per_cluster;
int l2_bits;
int l2_size;
int l1_size;
@ -439,6 +466,14 @@ typedef struct QCowL2Meta
*/
bool skip_cow;
/**
* Indicates that this is not a normal write request but a preallocation.
* If the image has extended L2 entries this means that no new individual
* subclusters will be marked as allocated in the L2 bitmap (but any
* existing contents of that bitmap will be kept).
*/
bool prealloc;
/**
* The I/O vector with the data from the actual guest write request.
* If non-NULL, this is meant to be merged together with the data
@ -453,6 +488,33 @@ typedef struct QCowL2Meta
QLIST_ENTRY(QCowL2Meta) next_in_flight;
} QCowL2Meta;
/*
* In images with standard L2 entries all clusters are treated as if
* they had one subcluster so QCow2ClusterType and QCow2SubclusterType
* can be mapped to each other and have the exact same meaning
* (QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC cannot happen in these images).
*
* In images with extended L2 entries QCow2ClusterType refers to the
* complete cluster and QCow2SubclusterType to each of the individual
* subclusters, so there are several possible combinations:
*
* |--------------+---------------------------|
* | Cluster type | Possible subcluster types |
* |--------------+---------------------------|
* | UNALLOCATED | UNALLOCATED_PLAIN |
* | | ZERO_PLAIN |
* |--------------+---------------------------|
* | NORMAL | UNALLOCATED_ALLOC |
* | | ZERO_ALLOC |
* | | NORMAL |
* |--------------+---------------------------|
* | COMPRESSED | COMPRESSED |
* |--------------+---------------------------|
*
* QCOW2_SUBCLUSTER_INVALID means that the L2 entry is incorrect and
* the image should be marked corrupt.
*/
typedef enum QCow2ClusterType {
QCOW2_CLUSTER_UNALLOCATED,
QCOW2_CLUSTER_ZERO_PLAIN,
@ -461,6 +523,16 @@ typedef enum QCow2ClusterType {
QCOW2_CLUSTER_COMPRESSED,
} QCow2ClusterType;
typedef enum QCow2SubclusterType {
QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN,
QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC,
QCOW2_SUBCLUSTER_ZERO_PLAIN,
QCOW2_SUBCLUSTER_ZERO_ALLOC,
QCOW2_SUBCLUSTER_NORMAL,
QCOW2_SUBCLUSTER_COMPRESSED,
QCOW2_SUBCLUSTER_INVALID,
} QCow2SubclusterType;
typedef enum QCow2MetadataOverlap {
QCOW2_OL_MAIN_HEADER_BITNR = 0,
QCOW2_OL_ACTIVE_L1_BITNR = 1,
@ -510,6 +582,49 @@ typedef enum QCow2MetadataOverlap {
#define INV_OFFSET (-1ULL)
static inline bool has_subclusters(BDRVQcow2State *s)
{
return s->incompatible_features & QCOW2_INCOMPAT_EXTL2;
}
static inline size_t l2_entry_size(BDRVQcow2State *s)
{
return has_subclusters(s) ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
}
static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
int idx)
{
idx *= l2_entry_size(s) / sizeof(uint64_t);
return be64_to_cpu(l2_slice[idx]);
}
static inline uint64_t get_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
int idx)
{
if (has_subclusters(s)) {
idx *= l2_entry_size(s) / sizeof(uint64_t);
return be64_to_cpu(l2_slice[idx + 1]);
} else {
return 0; /* For convenience only; this value has no meaning. */
}
}
static inline void set_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
int idx, uint64_t entry)
{
idx *= l2_entry_size(s) / sizeof(uint64_t);
l2_slice[idx] = cpu_to_be64(entry);
}
static inline void set_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
int idx, uint64_t bitmap)
{
assert(has_subclusters(s));
idx *= l2_entry_size(s) / sizeof(uint64_t);
l2_slice[idx + 1] = cpu_to_be64(bitmap);
}
static inline bool has_data_file(BlockDriverState *bs)
{
BDRVQcow2State *s = bs->opaque;
@ -532,11 +647,21 @@ static inline int64_t offset_into_cluster(BDRVQcow2State *s, int64_t offset)
return offset & (s->cluster_size - 1);
}
static inline int64_t offset_into_subcluster(BDRVQcow2State *s, int64_t offset)
{
return offset & (s->subcluster_size - 1);
}
static inline uint64_t size_to_clusters(BDRVQcow2State *s, uint64_t size)
{
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
}
static inline uint64_t size_to_subclusters(BDRVQcow2State *s, uint64_t size)
{
return (size + (s->subcluster_size - 1)) >> s->subcluster_bits;
}
static inline int64_t size_to_l1(BDRVQcow2State *s, int64_t size)
{
int shift = s->cluster_bits + s->l2_bits;
@ -558,6 +683,11 @@ static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset)
return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
}
static inline int offset_to_sc_index(BDRVQcow2State *s, int64_t offset)
{
return (offset >> s->subcluster_bits) & (s->subclusters_per_cluster - 1);
}
static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
{
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
@ -566,9 +696,11 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs,
uint64_t l2_entry)
{
BDRVQcow2State *s = bs->opaque;
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
return QCOW2_CLUSTER_COMPRESSED;
} else if (l2_entry & QCOW_OFLAG_ZERO) {
} else if ((l2_entry & QCOW_OFLAG_ZERO) && !has_subclusters(s)) {
if (l2_entry & L2E_OFFSET_MASK) {
return QCOW2_CLUSTER_ZERO_ALLOC;
}
@ -588,6 +720,72 @@ static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs,
}
}
/*
* In an image without subsclusters @l2_bitmap is ignored and
* @sc_index must be 0.
* Return QCOW2_SUBCLUSTER_INVALID if an invalid l2 entry is detected
* (this checks the whole entry and bitmap, not only the bits related
* to subcluster @sc_index).
*/
static inline
QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs,
uint64_t l2_entry,
uint64_t l2_bitmap,
unsigned sc_index)
{
BDRVQcow2State *s = bs->opaque;
QCow2ClusterType type = qcow2_get_cluster_type(bs, l2_entry);
assert(sc_index < s->subclusters_per_cluster);
if (has_subclusters(s)) {
switch (type) {
case QCOW2_CLUSTER_COMPRESSED:
return QCOW2_SUBCLUSTER_COMPRESSED;
case QCOW2_CLUSTER_NORMAL:
if ((l2_bitmap >> 32) & l2_bitmap) {
return QCOW2_SUBCLUSTER_INVALID;
} else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) {
return QCOW2_SUBCLUSTER_ZERO_ALLOC;
} else if (l2_bitmap & QCOW_OFLAG_SUB_ALLOC(sc_index)) {
return QCOW2_SUBCLUSTER_NORMAL;
} else {
return QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC;
}
case QCOW2_CLUSTER_UNALLOCATED:
if (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC) {
return QCOW2_SUBCLUSTER_INVALID;
} else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) {
return QCOW2_SUBCLUSTER_ZERO_PLAIN;
} else {
return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
}
default:
g_assert_not_reached();
}
} else {
switch (type) {
case QCOW2_CLUSTER_COMPRESSED:
return QCOW2_SUBCLUSTER_COMPRESSED;
case QCOW2_CLUSTER_ZERO_PLAIN:
return QCOW2_SUBCLUSTER_ZERO_PLAIN;
case QCOW2_CLUSTER_ZERO_ALLOC:
return QCOW2_SUBCLUSTER_ZERO_ALLOC;
case QCOW2_CLUSTER_NORMAL:
return QCOW2_SUBCLUSTER_NORMAL;
case QCOW2_CLUSTER_UNALLOCATED:
return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
default:
g_assert_not_reached();
}
}
}
static inline bool qcow2_cluster_is_allocated(QCow2ClusterType type)
{
return (type == QCOW2_CLUSTER_COMPRESSED || type == QCOW2_CLUSTER_NORMAL ||
type == QCOW2_CLUSTER_ZERO_ALLOC);
}
/* Check whether refcounts are eager or lazy */
static inline bool qcow2_need_accurate_refcounts(BDRVQcow2State *s)
{
@ -694,8 +892,9 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes, uint64_t *cluster_offset);
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes, uint64_t *host_offset,
QCow2SubclusterType *subcluster_type);
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes, uint64_t *host_offset,
QCowL2Meta **m);
@ -709,8 +908,8 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, enum qcow2_discard_type type,
bool full_discard);
int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, int flags);
int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, int flags);
int qcow2_expand_zero_clusters(BlockDriverState *bs,
BlockDriverAmendStatusCB *status_cb,

View file

@ -77,7 +77,7 @@ luring_io_uring_submit(void *s, int ret) "LuringState %p ret %d"
luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d"
# qcow2.c
qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t host_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
qcow2_writev_start_part(void *co) "co %p"

View file

@ -42,6 +42,9 @@ The first cluster of a qcow2 image contains the file header:
as the maximum cluster size and won't be able to open images
with larger cluster sizes.
Note: if the image has Extended L2 Entries then cluster_bits
must be at least 14 (i.e. 16384 byte clusters).
24 - 31: size
Virtual disk size in bytes.
@ -117,7 +120,12 @@ the next fields through header_length.
clusters. The compression_type field must be
present and not zero.
Bits 4-63: Reserved (set to 0)
Bit 4: Extended L2 Entries. If this bit is set then
L2 table entries use an extended format that
allows subcluster-based allocation. See the
Extended L2 Entries section for more details.
Bits 5-63: Reserved (set to 0)
80 - 87: compatible_features
Bitmask of compatible features. An implementation can
@ -498,7 +506,7 @@ cannot be relaxed without an incompatible layout change).
Given an offset into the virtual disk, the offset into the image file can be
obtained as follows:
l2_entries = (cluster_size / sizeof(uint64_t))
l2_entries = (cluster_size / sizeof(uint64_t)) [*]
l2_index = (offset / cluster_size) % l2_entries
l1_index = (offset / cluster_size) / l2_entries
@ -508,6 +516,8 @@ obtained as follows:
return cluster_offset + (offset % cluster_size)
[*] this changes if Extended L2 Entries are enabled, see next section
L1 table entry:
Bit 0 - 8: Reserved (set to 0)
@ -548,7 +558,8 @@ Standard Cluster Descriptor:
nor is data read from the backing file if the cluster is
unallocated.
With version 2, this is always 0.
With version 2 or with extended L2 entries (see the next
section), this is always 0.
1 - 8: Reserved (set to 0)
@ -585,6 +596,57 @@ file (except if bit 0 in the Standard Cluster Descriptor is set). If there is
no backing file or the backing file is smaller than the image, they shall read
zeros for all parts that are not covered by the backing file.
== Extended L2 Entries ==
An image uses Extended L2 Entries if bit 4 is set on the incompatible_features
field of the header.
In these images standard data clusters are divided into 32 subclusters of the
same size. They are contiguous and start from the beginning of the cluster.
Subclusters can be allocated independently and the L2 entry contains information
indicating the status of each one of them. Compressed data clusters don't have
subclusters so they are treated the same as in images without this feature.
The size of an extended L2 entry is 128 bits so the number of entries per table
is calculated using this formula:
l2_entries = (cluster_size / (2 * sizeof(uint64_t)))
The first 64 bits have the same format as the standard L2 table entry described
in the previous section, with the exception of bit 0 of the standard cluster
descriptor.
The last 64 bits contain a subcluster allocation bitmap with this format:
Subcluster Allocation Bitmap (for standard clusters):
Bit 0 - 31: Allocation status (one bit per subcluster)
1: the subcluster is allocated. In this case the
host cluster offset field must contain a valid
offset.
0: the subcluster is not allocated. In this case
read requests shall go to the backing file or
return zeros if there is no backing file data.
Bits are assigned starting from the least significant
one (i.e. bit x is used for subcluster x).
32 - 63 Subcluster reads as zeros (one bit per subcluster)
1: the subcluster reads as zeros. In this case the
allocation status bit must be unset. The host
cluster offset field may or may not be set.
0: no effect.
Bits are assigned starting from the least significant
one (i.e. bit x is used for subcluster x - 32).
Subcluster Allocation Bitmap (for compressed clusters):
Bit 0 - 63: Reserved (set to 0)
Compressed clusters don't have subclusters,
so this field is not used.
== Snapshots ==

View file

@ -1,6 +1,6 @@
qcow2 L2/refcount cache configuration
=====================================
Copyright (C) 2015, 2018 Igalia, S.L.
Copyright (C) 2015, 2018-2020 Igalia, S.L.
Author: Alberto Garcia <berto@igalia.com>
This work is licensed under the terms of the GNU GPL, version 2 or
@ -222,3 +222,20 @@ support this functionality, and is 0 (disabled) on other platforms.
This functionality currently relies on the MADV_DONTNEED argument for
madvise() to actually free the memory. This is a Linux-specific feature,
so cache-clean-interval is not supported on other systems.
Extended L2 Entries
-------------------
All numbers shown in this document are valid for qcow2 images with normal
64-bit L2 entries.
Images with extended L2 entries need twice as much L2 metadata, so the L2
cache size must be twice as large for the same disk space.
disk_size = l2_cache_size * cluster_size / 16
i.e.
l2_cache_size = disk_size * 16 / cluster_size
Refcount blocks are not affected by this.

View file

@ -59,6 +59,7 @@
#define BLOCK_OPT_DATA_FILE "data_file"
#define BLOCK_OPT_DATA_FILE_RAW "data_file_raw"
#define BLOCK_OPT_COMPRESSION_TYPE "compression_type"
#define BLOCK_OPT_EXTL2 "extended_l2"
#define BLOCK_PROBE_BUF_SIZE 512

View file

@ -67,6 +67,9 @@
# standalone (read-only) raw image without looking at qcow2
# metadata (since: 4.0)
#
# @extended-l2: true if the image has extended L2 entries; only valid for
# compat >= 1.1 (since 5.2)
#
# @lazy-refcounts: on or off; only valid for compat >= 1.1
#
# @corrupt: true if the image has been marked corrupt; only valid for
@ -88,6 +91,7 @@
'compat': 'str',
'*data-file': 'str',
'*data-file-raw': 'bool',
'*extended-l2': 'bool',
'*lazy-refcounts': 'bool',
'*corrupt': 'bool',
'refcount-bits': 'int',
@ -4304,6 +4308,8 @@
# @data-file-raw: True if the external data file must stay valid as a
# standalone (read-only) raw image without looking at qcow2
# metadata (default: false; since: 4.0)
# @extended-l2 True to make the image have extended L2 entries
# (default: false; since 5.2)
# @size: Size of the virtual disk in bytes
# @version: Compatibility level (default: v3)
# @backing-file: File name of the backing file if a backing file
@ -4324,6 +4330,7 @@
'data': { 'file': 'BlockdevRef',
'*data-file': 'BlockdevRef',
'*data-file-raw': 'bool',
'*extended-l2': 'bool',
'size': 'size',
'*version': 'BlockdevQcow2Version',
'*backing-file': 'str',

View file

@ -117,7 +117,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
Header extension:
@ -150,7 +150,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
Header extension:
@ -164,7 +164,7 @@ No errors were found on the image.
magic 0x514649fb
version 3
backing_file_offset 0x210
backing_file_offset 0x240
backing_file_size 0x17
cluster_bits 16
size 67108864
@ -188,7 +188,7 @@ data 'host_device'
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
Header extension:

View file

@ -26,7 +26,7 @@ compatible_features []
autoclear_features [63]
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
@ -38,7 +38,7 @@ compatible_features []
autoclear_features []
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
*** done

View file

@ -4,90 +4,90 @@ QA output created by 049
== 1. Traditional size parameter ==
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
== 2. Specifying size via -o ==
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
== 3. Invalid sizes ==
@ -129,84 +129,84 @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once
== Check correct interpretation of suffixes for cluster size ==
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
== Check compat level option ==
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
== Check preallocation option ==
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
== Check encryption option ==
qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
== Check lazy_refcounts option (only with v3) ==
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
*** done

View file

@ -21,6 +21,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: true
extended l2: false
qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
no file open, try 'help open'
read 512/512 bytes at offset 0
@ -320,7 +321,7 @@ discard 65536/65536 bytes at offset 0
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
write failed: Input/output error
--- Repairing ---
Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted.
Repairing offset=2a00: Preallocated cluster is not properly aligned; L2 entry corrupted.
The following inconsistencies were found and repaired:
0 leaked clusters

View file

@ -303,6 +303,12 @@ $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
_img_info --format-specific
_check_test_img
echo
echo "=== Testing version downgrade with extended L2 entries ==="
echo
_make_test_img -o "compat=1.1,extended_l2=on" 64M
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
echo
echo "=== Try changing the external data file ==="
echo

View file

@ -26,7 +26,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
magic 0x514649fb
@ -84,7 +84,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
magic 0x514649fb
@ -140,7 +140,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
ERROR cluster 5 refcount=0 reference=1
@ -195,7 +195,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
magic 0x514649fb
@ -264,7 +264,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
read 65536/65536 bytes at offset 44040192
@ -326,7 +326,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
ERROR cluster 5 refcount=0 reference=1
@ -355,7 +355,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
read 131072/131072 bytes at offset 0
@ -530,8 +530,14 @@ Format specific information:
data file: TEST_DIR/t.IMGFMT.data
data file raw: false
corrupt: false
extended l2: false
No errors were found on the image.
=== Testing version downgrade with extended L2 entries ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qemu-img: Cannot downgrade an image with incompatible features 0x10 set
=== Try changing the external data file ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
@ -551,6 +557,7 @@ Format specific information:
data file: foo
data file raw: false
corrupt: false
extended l2: false
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
image: TEST_DIR/t.IMGFMT
@ -564,6 +571,7 @@ Format specific information:
refcount bits: 16
data file raw: false
corrupt: false
extended l2: false
=== Clearing and setting data-file-raw ===
@ -580,6 +588,7 @@ Format specific information:
data file: TEST_DIR/t.IMGFMT.data
data file raw: true
corrupt: false
extended l2: false
No errors were found on the image.
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
@ -593,6 +602,7 @@ Format specific information:
data file: TEST_DIR/t.IMGFMT.data
data file raw: false
corrupt: false
extended l2: false
No errors were found on the image.
qemu-img: data-file-raw cannot be set on existing images
image: TEST_DIR/t.IMGFMT
@ -607,5 +617,6 @@ Format specific information:
data file: TEST_DIR/t.IMGFMT.data
data file raw: false
corrupt: false
extended l2: false
No errors were found on the image.
*** done

View file

@ -98,20 +98,20 @@ class TestQCow3NotLazy(TestQemuImgInfo):
img_options = 'compat=1.1,lazy_refcounts=off'
json_compare = { 'compat': '1.1', 'lazy-refcounts': False,
'refcount-bits': 16, 'corrupt': False,
'compression-type': 'zlib' }
'compression-type': 'zlib', 'extended-l2': False }
human_compare = [ 'compat: 1.1', 'compression type: zlib',
'lazy refcounts: false', 'refcount bits: 16',
'corrupt: false' ]
'corrupt: false', 'extended l2: false' ]
class TestQCow3Lazy(TestQemuImgInfo):
'''Testing a qcow2 version 3 image with lazy refcounts enabled'''
img_options = 'compat=1.1,lazy_refcounts=on'
json_compare = { 'compat': '1.1', 'lazy-refcounts': True,
'refcount-bits': 16, 'corrupt': False,
'compression-type': 'zlib' }
'compression-type': 'zlib', 'extended-l2': False }
human_compare = [ 'compat: 1.1', 'compression type: zlib',
'lazy refcounts: true', 'refcount bits: 16',
'corrupt: false' ]
'corrupt: false', 'extended l2: false' ]
class TestQCow3NotLazyQMP(TestQMP):
'''Testing a qcow2 version 3 image with lazy refcounts disabled, opening
@ -120,7 +120,7 @@ class TestQCow3NotLazyQMP(TestQMP):
qemu_options = 'lazy-refcounts=on'
compare = { 'compat': '1.1', 'lazy-refcounts': False,
'refcount-bits': 16, 'corrupt': False,
'compression-type': 'zlib' }
'compression-type': 'zlib', 'extended-l2': False }
class TestQCow3LazyQMP(TestQMP):
@ -130,7 +130,7 @@ class TestQCow3LazyQMP(TestQMP):
qemu_options = 'lazy-refcounts=off'
compare = { 'compat': '1.1', 'lazy-refcounts': True,
'refcount-bits': 16, 'corrupt': False,
'compression-type': 'zlib' }
'compression-type': 'zlib', 'extended-l2': False }
TestImageInfoSpecific = None
TestQemuImgInfo = None

View file

@ -3,14 +3,14 @@ QA output created by 082
=== create: Options specified more than once ===
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
cluster_size: 65536
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=4096 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=4096 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
@ -21,9 +21,10 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
@ -34,9 +35,10 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
@ -62,6 +64,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -87,6 +90,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -112,6 +116,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -137,6 +142,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -162,6 +168,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -187,6 +194,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -212,6 +220,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -237,6 +246,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -245,10 +255,10 @@ Supported options:
size=<size> - Virtual disk size
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help -F qcow2 TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? -F qcow2 TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
@ -277,6 +287,7 @@ Supported qcow2 options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
refcount_bits=<num> - Width of a reference count entry in bits
@ -298,7 +309,7 @@ qemu-img: Format driver 'bochs' does not support image creation
=== convert: Options specified more than once ===
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
image: TEST_DIR/t.IMGFMT.base
@ -322,6 +333,7 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
image: TEST_DIR/t.IMGFMT.base
@ -334,6 +346,7 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: convert -O qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
image: TEST_DIR/t.IMGFMT.base
@ -361,6 +374,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -386,6 +400,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -411,6 +426,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -436,6 +452,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -461,6 +478,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -486,6 +504,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -511,6 +530,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -536,6 +556,7 @@ Supported options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
@ -576,6 +597,7 @@ Supported qcow2 options:
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
extended_l2=<bool (on/off)> - Extended L2 tables
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
refcount_bits=<num> - Width of a reference count entry in bits
@ -621,6 +643,7 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2
image: TEST_DIR/t.IMGFMT
@ -633,6 +656,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2
image: TEST_DIR/t.IMGFMT
@ -645,6 +669,7 @@ Format specific information:
lazy refcounts: true
refcount bits: 16
corrupt: false
extended l2: false
Testing: amend -f qcow2 -o size=4M,size=148M TEST_DIR/t.qcow2
image: TEST_DIR/t.IMGFMT

View file

@ -13,7 +13,7 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
=== Create a single snapshot on virtio0 ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Invalid command - missing device and nodename ===
@ -30,40 +30,40 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compress
=== Create several transactional group snapshots ===
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Create a couple of snapshots using blockdev-snapshot ===

View file

@ -9,7 +9,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Performing block-commit on active layer ===
@ -31,6 +31,6 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 compression_type=z
=== Performing Live Snapshot 2 ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
*** done

View file

@ -13,7 +13,7 @@ Is another process using the image [TEST_DIR/t.qcow2]?
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
{"return": {}}
{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
{"return": {}}
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
{"return": {}}

View file

@ -9,14 +9,14 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
=== Creating backing chain ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
wrote 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Start commit job and exit qemu ===
@ -48,7 +48,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zli
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
@ -62,7 +62,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_typ
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}

View file

@ -94,6 +94,7 @@ echo "== checking image base =="
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
-e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
-e '/extended l2:/ D' \
| _filter_json_filename
echo
@ -101,6 +102,7 @@ echo "== checking image layer =="
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
-e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
-e '/extended l2:/ D' \
| _filter_json_filename

View file

@ -22,6 +22,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
=== Successful image creation (inline blockdev-add, explicit defaults) ===
@ -45,6 +46,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
=== Successful image creation (v3 non-default options) ===
@ -68,6 +70,7 @@ Format specific information:
lazy refcounts: true
refcount bits: 1
corrupt: false
extended l2: false
=== Successful image creation (v2 non-default options) ===
@ -146,6 +149,7 @@ Format specific information:
payload offset: 528384
master key iters: XXX
corrupt: false
extended l2: false
=== Invalid BlockdevRef ===
@ -199,7 +203,7 @@ Job failed: Different refcount widths than 16 bits require compatibility level 1
=== Invalid backing file options ===
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
{"return": {}}
Job failed: Backing file and preallocation cannot be used at the same time
Job failed: Backing file and preallocation can only be used at the same time if extended_l2 is on
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}

View file

@ -16,6 +16,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
No bitmap in JSON format output
@ -42,6 +43,7 @@ Format specific information:
granularity: 32768
refcount bits: 16
corrupt: false
extended l2: false
The same bitmaps in JSON format:
[
@ -80,6 +82,7 @@ Format specific information:
granularity: 65536
refcount bits: 16
corrupt: false
extended l2: false
The same bitmaps in JSON format:
[
@ -123,6 +126,7 @@ Format specific information:
granularity: 65536
refcount bits: 16
corrupt: false
extended l2: false
The same bitmaps in JSON format:
[
@ -167,5 +171,6 @@ Format specific information:
granularity: 16384
refcount bits: 16
corrupt: false
extended l2: false
Test complete

View file

@ -3,9 +3,9 @@ Finishing a commit job with background reads
=== Create backing chain and start VM ===
Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
=== Start background read requests ===
@ -23,9 +23,9 @@ Closing the VM while a job is being cancelled
=== Create images and start VM ===
Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)

901
tests/qemu-iotests/271 Executable file
View file

@ -0,0 +1,901 @@
#!/usr/bin/env bash
#
# Test qcow2 images with extended L2 entries
#
# Copyright (C) 2019-2020 Igalia, S.L.
# Author: Alberto Garcia <berto@igalia.com>
#
# 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/>.
#
# creator
owner=berto@igalia.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
rm -f "$TEST_IMG.raw"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
_supported_fmt qcow2
_supported_proto file nfs
_supported_os Linux
_unsupported_imgopts extended_l2 compat=0.10 cluster_size data_file refcount_bits=1[^0-9]
l2_offset=$((0x40000))
_verify_img()
{
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are identical'
$QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \
grep -v 'No errors were found on the image'
}
# Compare the bitmap of an extended L2 entry against an expected value
_verify_l2_bitmap()
{
entry_no="$1" # L2 entry number, starting from 0
expected_alloc="$alloc" # Space-separated list of allocated subcluster indexes
expected_zero="$zero" # Space-separated list of zero subcluster indexes
offset=$(($l2_offset + $entry_no * 16))
entry=$(peek_file_be "$TEST_IMG" $offset 8)
offset=$(($offset + 8))
bitmap=$(peek_file_be "$TEST_IMG" $offset 8)
expected_bitmap=0
for bit in $expected_alloc; do
expected_bitmap=$(($expected_bitmap | (1 << $bit)))
done
for bit in $expected_zero; do
expected_bitmap=$(($expected_bitmap | (1 << (32 + $bit))))
done
printf -v expected_bitmap "%u" $expected_bitmap # Convert to unsigned
printf "L2 entry #%d: 0x%016x %016x\n" "$entry_no" "$entry" "$bitmap"
if [ "$bitmap" != "$expected_bitmap" ]; then
printf "ERROR: expecting bitmap 0x%016x\n" "$expected_bitmap"
fi
}
# This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX
# c: cluster number (0 if unset)
# sc: subcluster number inside cluster @c (0 if unset)
# off: offset inside subcluster @sc, in kilobytes (0 if unset)
# len: request length, passed directly to qemu-io (e.g: 256, 4k, 1M, ...)
# cmd: the command to pass to qemu-io, must be one of
# write -> write
# zero -> write -z
# unmap -> write -z -u
# compress -> write -c
# discard -> discard
_run_test()
{
unset c sc off len cmd
for var in "$@"; do eval "$var"; done
case "${cmd:-write}" in
zero)
cmd="write -q -z";;
unmap)
cmd="write -q -z -u";;
compress)
pat=$((${pat:-0} + 1))
cmd="write -q -c -P ${pat}";;
write)
pat=$((${pat:-0} + 1))
cmd="write -q -P ${pat}";;
discard)
cmd="discard -q";;
*)
echo "Unknown option $cmd"
exit 1;;
esac
c="${c:-0}"
sc="${sc:-0}"
off="${off:-0}"
offset="$(($c * 64 + $sc * 2 + $off))"
[ "$offset" != 0 ] && offset="${offset}k"
cmd="$cmd ${offset} ${len}"
raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c
echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/'
$QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io
_verify_img
_verify_l2_bitmap "$c"
}
_reset_img()
{
size="$1"
$QEMU_IMG create -f raw "$TEST_IMG.raw" "$size" | _filter_img_create
if [ "$use_backing_file" = "yes" ]; then
$QEMU_IMG create -f raw "$TEST_IMG.base" "$size" | _filter_img_create
$QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.base" | _filter_qemu_io
$QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.raw" | _filter_qemu_io
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" "$size"
else
_make_test_img -o extended_l2=on "$size"
fi
}
############################################################
############################################################
############################################################
# Test that writing to an image with subclusters produces the expected
# results, in images with and without backing files
for use_backing_file in yes no; do
echo
echo "### Standard write tests (backing file: $use_backing_file) ###"
echo
_reset_img 1M
### Write subcluster #0 (beginning of subcluster) ###
alloc="0"; zero=""
_run_test sc=0 len=1k
### Write subcluster #1 (middle of subcluster) ###
alloc="0 1"; zero=""
_run_test sc=1 off=1 len=512
### Write subcluster #2 (end of subcluster) ###
alloc="0 1 2"; zero=""
_run_test sc=2 off=1 len=1k
### Write subcluster #3 (full subcluster) ###
alloc="0 1 2 3"; zero=""
_run_test sc=3 len=2k
### Write subclusters #4-6 (full subclusters) ###
alloc="$(seq 0 6)"; zero=""
_run_test sc=4 len=6k
### Write subclusters #7-9 (partial subclusters) ###
alloc="$(seq 0 9)"; zero=""
_run_test sc=7 off=1 len=4k
### Write subcluster #16 (partial subcluster) ###
alloc="$(seq 0 9) 16"; zero=""
_run_test sc=16 len=1k
### Write subcluster #31-#33 (cluster overlap) ###
alloc="$(seq 0 9) 16 31"; zero=""
_run_test sc=31 off=1 len=4k
alloc="0 1" ; zero=""
_verify_l2_bitmap 1
### Zero subcluster #1
alloc="0 $(seq 2 9) 16 31"; zero="1"
_run_test sc=1 len=2k cmd=zero
### Zero cluster #0
alloc=""; zero="$(seq 0 31)"
_run_test sc=0 len=64k cmd=zero
### Fill cluster #0 with data
alloc="$(seq 0 31)"; zero=""
_run_test sc=0 len=64k
### Zero and unmap half of cluster #0 (this won't unmap it)
alloc="$(seq 16 31)"; zero="$(seq 0 15)"
_run_test sc=0 len=32k cmd=unmap
### Zero and unmap cluster #0
alloc=""; zero="$(seq 0 31)"
_run_test sc=0 len=64k cmd=unmap
### Write subcluster #1 (middle of subcluster)
alloc="1"; zero="0 $(seq 2 31)"
_run_test sc=1 off=1 len=512
### Fill cluster #0 with data
alloc="$(seq 0 31)"; zero=""
_run_test sc=0 len=64k
### Discard cluster #0
alloc=""; zero="$(seq 0 31)"
_run_test sc=0 len=64k cmd=discard
### Write compressed data to cluster #0
alloc=""; zero=""
_run_test sc=0 len=64k cmd=compress
### Write subcluster #1 (middle of subcluster)
alloc="$(seq 0 31)"; zero=""
_run_test sc=1 off=1 len=512
done
############################################################
############################################################
############################################################
# calculate_l2_meta() checks if none of the clusters affected by a
# write operation need COW or changes to their L2 metadata and simply
# returns when they don't. This is a test for that optimization.
# Here clusters #0-#3 are overwritten but only #1 and #2 need changes.
echo
echo '### Overwriting several clusters without COW ###'
echo
use_backing_file="no" _reset_img 1M
# Write cluster #0, subclusters #12-#31
alloc="$(seq 12 31)"; zero=""
_run_test sc=12 len=40k
# Write cluster #1, subcluster #13
alloc="13"; zero=""
_run_test c=1 sc=13 len=2k
# Zeroize cluster #2, subcluster #14
alloc="14"; zero=""
_run_test c=2 sc=14 len=2k
alloc=""; zero="14"
_run_test c=2 sc=14 len=2k cmd=zero
# Write cluster #3, subclusters #0-#16
alloc="$(seq 0 16)"; zero=""
_run_test c=3 sc=0 len=34k
# Write from cluster #0, subcluster #12 to cluster #3, subcluster #11
alloc="$(seq 12 31)"; zero=""
_run_test sc=12 len=192k
alloc="$(seq 0 31)"; zero=""
_verify_l2_bitmap 1
_verify_l2_bitmap 2
alloc="$(seq 0 16)"; zero=""
_verify_l2_bitmap 3
############################################################
############################################################
############################################################
# Test different patterns of writing zeroes
for use_backing_file in yes no; do
echo
echo "### Writing zeroes 1: unallocated clusters (backing file: $use_backing_file) ###"
echo
# Note that the image size is not a multiple of the cluster size
_reset_img 2083k
# Cluster-aligned request from clusters #0 to #2
alloc=""; zero="$(seq 0 31)"
_run_test c=0 sc=0 len=192k cmd=zero
_verify_l2_bitmap 1
_verify_l2_bitmap 2
# Subcluster-aligned request from clusters #3 to #5
alloc=""; zero="$(seq 16 31)"
_run_test c=3 sc=16 len=128k cmd=zero
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 4
alloc=""; zero="$(seq 0 15)"
_verify_l2_bitmap 5
# Unaligned request from clusters #6 to #8
if [ "$use_backing_file" = "yes" ]; then
alloc="15"; zero="$(seq 16 31)" # copy-on-write happening here
else
alloc=""; zero="$(seq 15 31)"
fi
_run_test c=6 sc=15 off=1 len=128k cmd=zero
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 7
if [ "$use_backing_file" = "yes" ]; then
alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
else
alloc=""; zero="$(seq 0 15)"
fi
_verify_l2_bitmap 8
echo
echo "### Writing zeroes 2: allocated clusters (backing file: $use_backing_file) ###"
echo
alloc="$(seq 0 31)"; zero=""
_run_test c=9 sc=0 len=576k
_verify_l2_bitmap 10
_verify_l2_bitmap 11
_verify_l2_bitmap 12
_verify_l2_bitmap 13
_verify_l2_bitmap 14
_verify_l2_bitmap 15
_verify_l2_bitmap 16
_verify_l2_bitmap 17
# Cluster-aligned request from clusters #9 to #11
alloc=""; zero="$(seq 0 31)"
_run_test c=9 sc=0 len=192k cmd=zero
_verify_l2_bitmap 10
_verify_l2_bitmap 11
# Subcluster-aligned request from clusters #12 to #14
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=12 sc=16 len=128k cmd=zero
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 13
alloc="$(seq 16 31)"; zero="$(seq 0 15)"
_verify_l2_bitmap 14
# Unaligned request from clusters #15 to #17
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=15 sc=15 off=1 len=128k cmd=zero
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 16
alloc="$(seq 15 31)"; zero="$(seq 0 14)"
_verify_l2_bitmap 17
echo
echo "### Writing zeroes 3: compressed clusters (backing file: $use_backing_file) ###"
echo
alloc=""; zero=""
for c in $(seq 18 28); do
_run_test c=$c sc=0 len=64k cmd=compress
done
# Cluster-aligned request from clusters #18 to #20
alloc=""; zero="$(seq 0 31)"
_run_test c=18 sc=0 len=192k cmd=zero
_verify_l2_bitmap 19
_verify_l2_bitmap 20
# Subcluster-aligned request from clusters #21 to #23.
# We cannot partially zero a compressed cluster so the code
# returns -ENOTSUP, which means copy-on-write of the compressed
# data and fill the rest with actual zeroes on disk.
# TODO: cluster #22 should use the 'all zeroes' bits.
alloc="$(seq 0 31)"; zero=""
_run_test c=21 sc=16 len=128k cmd=zero
_verify_l2_bitmap 22
_verify_l2_bitmap 23
# Unaligned request from clusters #24 to #26
# In this case QEMU internally sends a 1k request followed by a
# subcluster-aligned 128k request. The first request decompresses
# cluster #24, but that's not enough to perform the second request
# efficiently because it partially writes to cluster #26 (which is
# compressed) so we hit the same problem as before.
alloc="$(seq 0 31)"; zero=""
_run_test c=24 sc=15 off=1 len=129k cmd=zero
_verify_l2_bitmap 25
_verify_l2_bitmap 26
# Unaligned request from clusters #27 to #29
# Similar to the previous case, but this time the tail of the
# request does not correspond to a compressed cluster, so it can
# be zeroed efficiently.
# Note that the very last subcluster is partially written, so if
# there's a backing file we need to perform cow.
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=27 sc=15 off=1 len=128k cmd=zero
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 28
if [ "$use_backing_file" = "yes" ]; then
alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
else
alloc=""; zero="$(seq 0 15)"
fi
_verify_l2_bitmap 29
echo
echo "### Writing zeroes 4: other tests (backing file: $use_backing_file) ###"
echo
# Unaligned request in the middle of cluster #30.
# If there's a backing file we need to allocate and do
# copy-on-write on the partially zeroed subclusters.
# If not we can set the 'all zeroes' bit on them.
if [ "$use_backing_file" = "yes" ]; then
alloc="15 19"; zero="$(seq 16 18)" # copy-on-write happening here
else
alloc=""; zero="$(seq 15 19)"
fi
_run_test c=30 sc=15 off=1 len=8k cmd=zero
# Fill the last cluster with zeroes, up to the end of the image
# (the image size is not a multiple of the cluster or subcluster size).
alloc=""; zero="$(seq 0 17)"
_run_test c=32 sc=0 len=35k cmd=zero
done
############################################################
############################################################
############################################################
# Zero + unmap
for use_backing_file in yes no; do
echo
echo "### Zero + unmap 1: allocated clusters (backing file: $use_backing_file) ###"
echo
# Note that the image size is not a multiple of the cluster size
_reset_img 2083k
alloc="$(seq 0 31)"; zero=""
_run_test c=9 sc=0 len=576k
_verify_l2_bitmap 10
_verify_l2_bitmap 11
_verify_l2_bitmap 12
_verify_l2_bitmap 13
_verify_l2_bitmap 14
_verify_l2_bitmap 15
_verify_l2_bitmap 16
_verify_l2_bitmap 17
# Cluster-aligned request from clusters #9 to #11
alloc=""; zero="$(seq 0 31)"
_run_test c=9 sc=0 len=192k cmd=unmap
_verify_l2_bitmap 10
_verify_l2_bitmap 11
# Subcluster-aligned request from clusters #12 to #14
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=12 sc=16 len=128k cmd=unmap
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 13
alloc="$(seq 16 31)"; zero="$(seq 0 15)"
_verify_l2_bitmap 14
# Unaligned request from clusters #15 to #17
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=15 sc=15 off=1 len=128k cmd=unmap
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 16
alloc="$(seq 15 31)"; zero="$(seq 0 14)"
_verify_l2_bitmap 17
echo
echo "### Zero + unmap 2: compressed clusters (backing file: $use_backing_file) ###"
echo
alloc=""; zero=""
for c in $(seq 18 28); do
_run_test c=$c sc=0 len=64k cmd=compress
done
# Cluster-aligned request from clusters #18 to #20
alloc=""; zero="$(seq 0 31)"
_run_test c=18 sc=0 len=192k cmd=unmap
_verify_l2_bitmap 19
_verify_l2_bitmap 20
# Subcluster-aligned request from clusters #21 to #23.
# We cannot partially zero a compressed cluster so the code
# returns -ENOTSUP, which means copy-on-write of the compressed
# data and fill the rest with actual zeroes on disk.
# TODO: cluster #22 should use the 'all zeroes' bits.
alloc="$(seq 0 31)"; zero=""
_run_test c=21 sc=16 len=128k cmd=unmap
_verify_l2_bitmap 22
_verify_l2_bitmap 23
# Unaligned request from clusters #24 to #26
# In this case QEMU internally sends a 1k request followed by a
# subcluster-aligned 128k request. The first request decompresses
# cluster #24, but that's not enough to perform the second request
# efficiently because it partially writes to cluster #26 (which is
# compressed) so we hit the same problem as before.
alloc="$(seq 0 31)"; zero=""
_run_test c=24 sc=15 off=1 len=129k cmd=unmap
_verify_l2_bitmap 25
_verify_l2_bitmap 26
# Unaligned request from clusters #27 to #29
# Similar to the previous case, but this time the tail of the
# request does not correspond to a compressed cluster, so it can
# be zeroed efficiently.
# Note that the very last subcluster is partially written, so if
# there's a backing file we need to perform cow.
alloc="$(seq 0 15)"; zero="$(seq 16 31)"
_run_test c=27 sc=15 off=1 len=128k cmd=unmap
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 28
if [ "$use_backing_file" = "yes" ]; then
alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
else
alloc=""; zero="$(seq 0 15)"
fi
_verify_l2_bitmap 29
done
############################################################
############################################################
############################################################
# Test qcow2_cluster_discard() with full and normal discards
for use_backing_file in yes no; do
echo
echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###"
echo
if [ "$use_backing_file" = "yes" ]; then
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 1M
else
_make_test_img -o extended_l2=on 1M
fi
# Write clusters #0-#2 and then discard them
$QEMU_IO -c 'write -q 0 128k' "$TEST_IMG"
$QEMU_IO -c 'discard -q 0 128k' "$TEST_IMG"
# 'qemu-io discard' doesn't do a full discard, it zeroizes the
# cluster, so both clusters have all zero bits set now
alloc=""; zero="$(seq 0 31)"
_verify_l2_bitmap 0
_verify_l2_bitmap 1
# Now mark the 2nd half of the subclusters from cluster #0 as unallocated
poke_file "$TEST_IMG" $(($l2_offset+8)) "\x00\x00"
# Discard cluster #0 again to see how the zero bits have changed
$QEMU_IO -c 'discard -q 0 64k' "$TEST_IMG"
# And do a full discard of cluster #1 by shrinking and growing the image
$QEMU_IMG resize --shrink "$TEST_IMG" 64k
$QEMU_IMG resize "$TEST_IMG" 1M
# A normal discard sets all 'zero' bits only if the image has a
# backing file, otherwise it won't touch them.
if [ "$use_backing_file" = "yes" ]; then
alloc=""; zero="$(seq 0 31)"
else
alloc=""; zero="$(seq 0 15)"
fi
_verify_l2_bitmap 0
# A full discard should clear the L2 entry completely. However
# when growing an image with a backing file the new clusters are
# zeroized to hide the stale data from the backing file
if [ "$use_backing_file" = "yes" ]; then
alloc=""; zero="$(seq 0 31)"
else
alloc=""; zero=""
fi
_verify_l2_bitmap 1
done
############################################################
############################################################
############################################################
# Test that corrupted L2 entries are detected in both read and write
# operations
for corruption_test_cmd in read write; do
echo
echo "### Corrupted L2 entries - $corruption_test_cmd test (allocated) ###"
echo
echo "# 'cluster is zero' bit set on the standard cluster descriptor"
echo
# We actually don't consider this a corrupted image.
# The 'cluster is zero' bit is unused in extended L2 entries so
# QEMU ignores it.
# TODO: maybe treat the image as corrupted and make qemu-img check fix it?
_make_test_img -o extended_l2=on 1M
$QEMU_IO -c 'write -q -P 0x11 0 2k' "$TEST_IMG"
poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01"
alloc="0"; zero=""
_verify_l2_bitmap 0
$QEMU_IO -c "$corruption_test_cmd -q -P 0x11 0 1k" "$TEST_IMG"
if [ "$corruption_test_cmd" = "write" ]; then
alloc="0"; zero=""
fi
_verify_l2_bitmap 0
echo
echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set"
echo
_make_test_img -o extended_l2=on 1M
# Write from the middle of cluster #0 to the middle of cluster #2
$QEMU_IO -c 'write -q 32k 128k' "$TEST_IMG"
# Corrupt the L2 entry from cluster #1
poke_file_be "$TEST_IMG" $(($l2_offset+24)) 4 1
alloc="$(seq 0 31)"; zero="0"
_verify_l2_bitmap 1
$QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG"
echo
echo "### Corrupted L2 entries - $corruption_test_cmd test (unallocated) ###"
echo
echo "# 'cluster is zero' bit set on the standard cluster descriptor"
echo
# We actually don't consider this a corrupted image.
# The 'cluster is zero' bit is unused in extended L2 entries so
# QEMU ignores it.
# TODO: maybe treat the image as corrupted and make qemu-img check fix it?
_make_test_img -o extended_l2=on 1M
# We want to modify the (empty) L2 entry from cluster #0,
# but we write to #4 in order to initialize the L2 table first
$QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01"
alloc=""; zero=""
_verify_l2_bitmap 0
$QEMU_IO -c "$corruption_test_cmd -q 0 1k" "$TEST_IMG"
if [ "$corruption_test_cmd" = "write" ]; then
alloc="0"; zero=""
fi
_verify_l2_bitmap 0
echo
echo "# 'subcluster is allocated' bit set"
echo
_make_test_img -o extended_l2=on 1M
# We want to corrupt the (empty) L2 entry from cluster #0,
# but we write to #4 in order to initialize the L2 table first
$QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
poke_file "$TEST_IMG" $(($l2_offset+15)) "\x01"
alloc="0"; zero=""
_verify_l2_bitmap 0
$QEMU_IO -c "$corruption_test_cmd 0 1k" "$TEST_IMG"
echo
echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set"
echo
_make_test_img -o extended_l2=on 1M
# We want to corrupt the (empty) L2 entry from cluster #1,
# but we write to #4 in order to initialize the L2 table first
$QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
# Corrupt the L2 entry from cluster #1
poke_file_be "$TEST_IMG" $(($l2_offset+24)) 8 $(((1 << 32) | 1))
alloc="0"; zero="0"
_verify_l2_bitmap 1
$QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG"
echo
echo "### Compressed cluster with subcluster bitmap != 0 - $corruption_test_cmd test ###"
echo
# We actually don't consider this a corrupted image.
# The bitmap in compressed clusters is unused so QEMU should just ignore it.
_make_test_img -o extended_l2=on 1M
$QEMU_IO -c 'write -q -P 11 -c 0 64k' "$TEST_IMG"
# Change the L2 bitmap to allocate subcluster #31 and zeroize subcluster #0
poke_file "$TEST_IMG" $(($l2_offset+11)) "\x01\x80"
alloc="31"; zero="0"
_verify_l2_bitmap 0
$QEMU_IO -c "$corruption_test_cmd -P 11 0 64k" "$TEST_IMG" | _filter_qemu_io
# Writing allocates a new uncompressed cluster so we get a new bitmap
if [ "$corruption_test_cmd" = "write" ]; then
alloc="$(seq 0 31)"; zero=""
fi
_verify_l2_bitmap 0
done
############################################################
############################################################
############################################################
echo
echo "### Detect and repair unaligned clusters ###"
echo
# Create a backing file and fill it with data
$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create
$QEMU_IO -c "write -q -P 0xff 0 128k" -f raw "$TEST_IMG.base" | _filter_qemu_io
echo "# Corrupted L2 entry, allocated subcluster #"
# Create a new image, allocate a cluster and write some data to it
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base"
$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG"
# Corrupt the L2 entry by making the offset unaligned
poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02"
# This cannot be repaired, qemu-img check will fail to fix it
_check_test_img -r all
# Attempting to read the image will still show that it's corrupted
$QEMU_IO -c 'read -q 0 2k' "$TEST_IMG"
echo "# Corrupted L2 entry, no allocated subclusters #"
# Create a new image, allocate a cluster and zeroize subcluster #2
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base"
$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG"
$QEMU_IO -c 'write -q -z 4k 2k' "$TEST_IMG"
# Corrupt the L2 entry by making the offset unaligned
poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02"
# This time none of the subclusters are allocated so we can repair the image
_check_test_img -r all
# And the data can be read normally
$QEMU_IO -c 'read -q -P 0xff 0 4k' "$TEST_IMG"
$QEMU_IO -c 'read -q -P 0x00 4k 2k' "$TEST_IMG"
$QEMU_IO -c 'read -q -P 0xff 6k 122k' "$TEST_IMG"
############################################################
############################################################
############################################################
echo
echo "### Image creation options ###"
echo
echo "# cluster_size < 16k"
_make_test_img -o extended_l2=on,cluster_size=8k 1M
echo "# backing file and preallocation=metadata"
# For preallocation with backing files, create a backing file first
$QEMU_IMG create -f raw "$TEST_IMG.base" 1M | _filter_img_create
$QEMU_IO -c "write -q -P 0xff 0 1M" -f raw "$TEST_IMG.base" | _filter_qemu_io
_make_test_img -o extended_l2=on,preallocation=metadata -F raw -b "$TEST_IMG.base" 512k
$QEMU_IMG resize "$TEST_IMG" 1M
$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG map "$TEST_IMG" | _filter_testdir
echo "# backing file and preallocation=falloc"
_make_test_img -o extended_l2=on,preallocation=falloc -F raw -b "$TEST_IMG.base" 512k
$QEMU_IMG resize "$TEST_IMG" 1M
$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG map "$TEST_IMG" | _filter_testdir
echo "# backing file and preallocation=full"
_make_test_img -o extended_l2=on,preallocation=full -F raw -b "$TEST_IMG.base" 512k
$QEMU_IMG resize "$TEST_IMG" 1M
$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG map "$TEST_IMG" | _filter_testdir
echo
echo "### Image resizing with preallocation and backing files ###"
echo
# In this case the new subclusters must have the 'all zeroes' bit set
echo "# resize --preallocation=metadata"
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
# In this case and the next one the new subclusters must be allocated
echo "# resize --preallocation=falloc"
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
echo "# resize --preallocation=full"
_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
echo
echo "### Image resizing with preallocation without backing files ###"
echo
# In this case the new subclusters must have the 'all zeroes' bit set
echo "# resize --preallocation=metadata"
_make_test_img -o extended_l2=on 503k
$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
# In this case and the next one the new subclusters must be allocated
echo "# resize --preallocation=falloc"
_make_test_img -o extended_l2=on 503k
$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
echo "# resize --preallocation=full"
_make_test_img -o extended_l2=on 503k
$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k
$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
echo
echo "### qemu-img measure ###"
echo
echo "# 512MB, extended_l2=off" # This needs one L2 table
$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=off
echo "# 512MB, extended_l2=on" # This needs two L2 tables
$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=on
echo "# 16K clusters, 64GB, extended_l2=off" # This needs one full L1 table cluster
$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=off
echo "# 16K clusters, 64GB, extended_l2=on" # This needs two full L2 table clusters
$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=on
echo "# 8k clusters" # This should fail
$QEMU_IMG measure --size 1M -O qcow2 -o cluster_size=8k,extended_l2=on
echo "# 1024 TB" # Maximum allowed size with extended_l2=on and 64K clusters
$QEMU_IMG measure --size 1024T -O qcow2 -o extended_l2=on
echo "# 1025 TB" # This should fail
$QEMU_IMG measure --size 1025T -O qcow2 -o extended_l2=on
echo
echo "### qemu-img amend ###"
echo
_make_test_img -o extended_l2=on 1M
$QEMU_IMG amend -o extended_l2=off "$TEST_IMG" && echo "Unexpected pass"
_make_test_img -o extended_l2=off 1M
$QEMU_IMG amend -o extended_l2=on "$TEST_IMG" && echo "Unexpected pass"
echo
echo "### Test copy-on-write on an image with snapshots ###"
echo
_make_test_img -o extended_l2=on 1M
# For each cluster from #0 to #9 this loop zeroes subcluster #7
# and allocates subclusters #13 and #18.
alloc="13 18"; zero="7"
for c in $(seq 0 9); do
$QEMU_IO -c "write -q -z $((64*$c+14))k 2k" \
-c "write -q -P $((0xd0+$c)) $((64*$c+26))k 2k" \
-c "write -q -P $((0xe0+$c)) $((64*$c+36))k 2k" "$TEST_IMG"
_verify_l2_bitmap "$c"
done
# Create a snapshot and set l2_offset to the new L2 table
$QEMU_IMG snapshot -c snap1 "$TEST_IMG"
l2_offset=$((0x110000))
# Write different patterns to each one of the clusters
# in order to see how copy-on-write behaves in each case.
$QEMU_IO -c "write -q -P 0xf0 $((64*0+30))k 1k" \
-c "write -q -P 0xf1 $((64*1+20))k 1k" \
-c "write -q -P 0xf2 $((64*2+40))k 1k" \
-c "write -q -P 0xf3 $((64*3+26))k 1k" \
-c "write -q -P 0xf4 $((64*4+14))k 1k" \
-c "write -q -P 0xf5 $((64*5+1))k 1k" \
-c "write -q -z $((64*6+30))k 3k" \
-c "write -q -z $((64*7+26))k 2k" \
-c "write -q -z $((64*8+26))k 1k" \
-c "write -q -z $((64*9+12))k 1k" \
"$TEST_IMG"
alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 0
alloc="$(seq 10 18)"; zero="7" _verify_l2_bitmap 1
alloc="$(seq 13 20)"; zero="7" _verify_l2_bitmap 2
alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 3
alloc="$(seq 7 18)"; zero="" _verify_l2_bitmap 4
alloc="$(seq 0 18)"; zero="" _verify_l2_bitmap 5
alloc="13 18"; zero="7 15 16" _verify_l2_bitmap 6
alloc="18"; zero="7 13" _verify_l2_bitmap 7
alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 8
alloc="13 18"; zero="6 7" _verify_l2_bitmap 9
echo
echo "### Test concurrent requests ###"
echo
_concurrent_io()
{
# Allocate three subclusters in the same cluster.
# This works because handle_dependencies() checks whether the requests
# allocate the same cluster, even if the COW regions don't overlap (in
# this case they don't).
cat <<EOF
open -o driver=$IMGFMT blkdebug::$TEST_IMG
break write_aio A
aio_write -P 10 30k 2k
wait_break A
aio_write -P 11 20k 2k
aio_write -P 12 40k 2k
resume A
aio_flush
EOF
}
_concurrent_verify()
{
cat <<EOF
open -o driver=$IMGFMT $TEST_IMG
read -q -P 10 30k 2k
read -q -P 11 20k 2k
read -q -P 12 40k 2k
EOF
}
_make_test_img -o extended_l2=on 1M
_concurrent_io | $QEMU_IO | _filter_qemu_io
_concurrent_verify | $QEMU_IO | _filter_qemu_io
# success, all done
echo "*** done"
rm -f $seq.full
status=0

726
tests/qemu-iotests/271.out Normal file
View file

@ -0,0 +1,726 @@
QA output created by 271
### Standard write tests (backing file: yes) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=1048576
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
write -q -P PATTERN 0 1k
L2 entry #0: 0x8000000000050000 0000000000000001
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000050000 0000000000000003
write -q -P PATTERN 5k 1k
L2 entry #0: 0x8000000000050000 0000000000000007
write -q -P PATTERN 6k 2k
L2 entry #0: 0x8000000000050000 000000000000000f
write -q -P PATTERN 8k 6k
L2 entry #0: 0x8000000000050000 000000000000007f
write -q -P PATTERN 15k 4k
L2 entry #0: 0x8000000000050000 00000000000003ff
write -q -P PATTERN 32k 1k
L2 entry #0: 0x8000000000050000 00000000000103ff
write -q -P PATTERN 63k 4k
L2 entry #0: 0x8000000000050000 00000000800103ff
L2 entry #1: 0x8000000000060000 0000000000000003
write -q -z 2k 2k
L2 entry #0: 0x8000000000050000 00000002800103fd
write -q -z 0 64k
L2 entry #0: 0x8000000000050000 ffffffff00000000
write -q -P PATTERN 0 64k
L2 entry #0: 0x8000000000050000 00000000ffffffff
write -q -z -u 0 32k
L2 entry #0: 0x8000000000050000 0000ffffffff0000
write -q -z -u 0 64k
L2 entry #0: 0x0000000000000000 ffffffff00000000
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000050000 fffffffd00000002
write -q -P PATTERN 0 64k
L2 entry #0: 0x8000000000050000 00000000ffffffff
discard -q 0 64k
L2 entry #0: 0x0000000000000000 ffffffff00000000
write -q -c -P PATTERN 0 64k
L2 entry #0: 0x4000000000050000 0000000000000000
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000070000 00000000ffffffff
### Standard write tests (backing file: no) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
write -q -P PATTERN 0 1k
L2 entry #0: 0x8000000000050000 0000000000000001
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000050000 0000000000000003
write -q -P PATTERN 5k 1k
L2 entry #0: 0x8000000000050000 0000000000000007
write -q -P PATTERN 6k 2k
L2 entry #0: 0x8000000000050000 000000000000000f
write -q -P PATTERN 8k 6k
L2 entry #0: 0x8000000000050000 000000000000007f
write -q -P PATTERN 15k 4k
L2 entry #0: 0x8000000000050000 00000000000003ff
write -q -P PATTERN 32k 1k
L2 entry #0: 0x8000000000050000 00000000000103ff
write -q -P PATTERN 63k 4k
L2 entry #0: 0x8000000000050000 00000000800103ff
L2 entry #1: 0x8000000000060000 0000000000000003
write -q -z 2k 2k
L2 entry #0: 0x8000000000050000 00000002800103fd
write -q -z 0 64k
L2 entry #0: 0x8000000000050000 ffffffff00000000
write -q -P PATTERN 0 64k
L2 entry #0: 0x8000000000050000 00000000ffffffff
write -q -z -u 0 32k
L2 entry #0: 0x8000000000050000 0000ffffffff0000
write -q -z -u 0 64k
L2 entry #0: 0x0000000000000000 ffffffff00000000
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000050000 fffffffd00000002
write -q -P PATTERN 0 64k
L2 entry #0: 0x8000000000050000 00000000ffffffff
discard -q 0 64k
L2 entry #0: 0x0000000000000000 ffffffff00000000
write -q -c -P PATTERN 0 64k
L2 entry #0: 0x4000000000050000 0000000000000000
write -q -P PATTERN 3k 512
L2 entry #0: 0x8000000000070000 00000000ffffffff
### Overwriting several clusters without COW ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
write -q -P PATTERN 24k 40k
L2 entry #0: 0x8000000000050000 00000000fffff000
write -q -P PATTERN 90k 2k
L2 entry #1: 0x8000000000060000 0000000000002000
write -q -P PATTERN 156k 2k
L2 entry #2: 0x8000000000070000 0000000000004000
write -q -z 156k 2k
L2 entry #2: 0x8000000000070000 0000400000000000
write -q -P PATTERN 192k 34k
L2 entry #3: 0x8000000000080000 000000000001ffff
write -q -P PATTERN 24k 192k
L2 entry #0: 0x8000000000050000 00000000fffff000
L2 entry #1: 0x8000000000060000 00000000ffffffff
L2 entry #2: 0x8000000000070000 00000000ffffffff
L2 entry #3: 0x8000000000080000 000000000001ffff
### Writing zeroes 1: unallocated clusters (backing file: yes) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
write -q -z 0 192k
L2 entry #0: 0x0000000000000000 ffffffff00000000
L2 entry #1: 0x0000000000000000 ffffffff00000000
L2 entry #2: 0x0000000000000000 ffffffff00000000
write -q -z 224k 128k
L2 entry #3: 0x0000000000000000 ffff000000000000
L2 entry #4: 0x0000000000000000 ffffffff00000000
L2 entry #5: 0x0000000000000000 0000ffff00000000
write -q -z 415k 128k
L2 entry #6: 0x8000000000050000 ffff000000008000
L2 entry #7: 0x0000000000000000 ffffffff00000000
L2 entry #8: 0x8000000000060000 00007fff00008000
### Writing zeroes 2: allocated clusters (backing file: yes) ###
write -q -P PATTERN 576k 576k
L2 entry #9: 0x8000000000070000 00000000ffffffff
L2 entry #10: 0x8000000000080000 00000000ffffffff
L2 entry #11: 0x8000000000090000 00000000ffffffff
L2 entry #12: 0x80000000000a0000 00000000ffffffff
L2 entry #13: 0x80000000000b0000 00000000ffffffff
L2 entry #14: 0x80000000000c0000 00000000ffffffff
L2 entry #15: 0x80000000000d0000 00000000ffffffff
L2 entry #16: 0x80000000000e0000 00000000ffffffff
L2 entry #17: 0x80000000000f0000 00000000ffffffff
write -q -z 576k 192k
L2 entry #9: 0x8000000000070000 ffffffff00000000
L2 entry #10: 0x8000000000080000 ffffffff00000000
L2 entry #11: 0x8000000000090000 ffffffff00000000
write -q -z 800k 128k
L2 entry #12: 0x80000000000a0000 ffff00000000ffff
L2 entry #13: 0x80000000000b0000 ffffffff00000000
L2 entry #14: 0x80000000000c0000 0000ffffffff0000
write -q -z 991k 128k
L2 entry #15: 0x80000000000d0000 ffff00000000ffff
L2 entry #16: 0x80000000000e0000 ffffffff00000000
L2 entry #17: 0x80000000000f0000 00007fffffff8000
### Writing zeroes 3: compressed clusters (backing file: yes) ###
write -q -c -P PATTERN 1152k 64k
L2 entry #18: 0x4000000000100000 0000000000000000
write -q -c -P PATTERN 1216k 64k
L2 entry #19: 0x4000000000110000 0000000000000000
write -q -c -P PATTERN 1280k 64k
L2 entry #20: 0x4000000000120000 0000000000000000
write -q -c -P PATTERN 1344k 64k
L2 entry #21: 0x4000000000130000 0000000000000000
write -q -c -P PATTERN 1408k 64k
L2 entry #22: 0x4000000000140000 0000000000000000
write -q -c -P PATTERN 1472k 64k
L2 entry #23: 0x4000000000150000 0000000000000000
write -q -c -P PATTERN 1536k 64k
L2 entry #24: 0x4000000000160000 0000000000000000
write -q -c -P PATTERN 1600k 64k
L2 entry #25: 0x4000000000170000 0000000000000000
write -q -c -P PATTERN 1664k 64k
L2 entry #26: 0x4000000000180000 0000000000000000
write -q -c -P PATTERN 1728k 64k
L2 entry #27: 0x4000000000190000 0000000000000000
write -q -c -P PATTERN 1792k 64k
L2 entry #28: 0x40000000001a0000 0000000000000000
write -q -z 1152k 192k
L2 entry #18: 0x0000000000000000 ffffffff00000000
L2 entry #19: 0x0000000000000000 ffffffff00000000
L2 entry #20: 0x0000000000000000 ffffffff00000000
write -q -z 1376k 128k
L2 entry #21: 0x8000000000100000 00000000ffffffff
L2 entry #22: 0x8000000000110000 00000000ffffffff
L2 entry #23: 0x8000000000120000 00000000ffffffff
write -q -z 1567k 129k
L2 entry #24: 0x8000000000130000 00000000ffffffff
L2 entry #25: 0x8000000000140000 00000000ffffffff
L2 entry #26: 0x8000000000150000 00000000ffffffff
write -q -z 1759k 128k
L2 entry #27: 0x8000000000160000 ffff00000000ffff
L2 entry #28: 0x0000000000000000 ffffffff00000000
L2 entry #29: 0x8000000000170000 00007fff00008000
### Writing zeroes 4: other tests (backing file: yes) ###
write -q -z 1951k 8k
L2 entry #30: 0x8000000000180000 0007000000088000
write -q -z 2048k 35k
L2 entry #32: 0x0000000000000000 0003ffff00000000
### Writing zeroes 1: unallocated clusters (backing file: no) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992
write -q -z 0 192k
L2 entry #0: 0x0000000000000000 ffffffff00000000
L2 entry #1: 0x0000000000000000 ffffffff00000000
L2 entry #2: 0x0000000000000000 ffffffff00000000
write -q -z 224k 128k
L2 entry #3: 0x0000000000000000 ffff000000000000
L2 entry #4: 0x0000000000000000 ffffffff00000000
L2 entry #5: 0x0000000000000000 0000ffff00000000
write -q -z 415k 128k
L2 entry #6: 0x0000000000000000 ffff800000000000
L2 entry #7: 0x0000000000000000 ffffffff00000000
L2 entry #8: 0x0000000000000000 0000ffff00000000
### Writing zeroes 2: allocated clusters (backing file: no) ###
write -q -P PATTERN 576k 576k
L2 entry #9: 0x8000000000050000 00000000ffffffff
L2 entry #10: 0x8000000000060000 00000000ffffffff
L2 entry #11: 0x8000000000070000 00000000ffffffff
L2 entry #12: 0x8000000000080000 00000000ffffffff
L2 entry #13: 0x8000000000090000 00000000ffffffff
L2 entry #14: 0x80000000000a0000 00000000ffffffff
L2 entry #15: 0x80000000000b0000 00000000ffffffff
L2 entry #16: 0x80000000000c0000 00000000ffffffff
L2 entry #17: 0x80000000000d0000 00000000ffffffff
write -q -z 576k 192k
L2 entry #9: 0x8000000000050000 ffffffff00000000
L2 entry #10: 0x8000000000060000 ffffffff00000000
L2 entry #11: 0x8000000000070000 ffffffff00000000
write -q -z 800k 128k
L2 entry #12: 0x8000000000080000 ffff00000000ffff
L2 entry #13: 0x8000000000090000 ffffffff00000000
L2 entry #14: 0x80000000000a0000 0000ffffffff0000
write -q -z 991k 128k
L2 entry #15: 0x80000000000b0000 ffff00000000ffff
L2 entry #16: 0x80000000000c0000 ffffffff00000000
L2 entry #17: 0x80000000000d0000 00007fffffff8000
### Writing zeroes 3: compressed clusters (backing file: no) ###
write -q -c -P PATTERN 1152k 64k
L2 entry #18: 0x40000000000e0000 0000000000000000
write -q -c -P PATTERN 1216k 64k
L2 entry #19: 0x40000000000f0000 0000000000000000
write -q -c -P PATTERN 1280k 64k
L2 entry #20: 0x4000000000100000 0000000000000000
write -q -c -P PATTERN 1344k 64k
L2 entry #21: 0x4000000000110000 0000000000000000
write -q -c -P PATTERN 1408k 64k
L2 entry #22: 0x4000000000120000 0000000000000000
write -q -c -P PATTERN 1472k 64k
L2 entry #23: 0x4000000000130000 0000000000000000
write -q -c -P PATTERN 1536k 64k
L2 entry #24: 0x4000000000140000 0000000000000000
write -q -c -P PATTERN 1600k 64k
L2 entry #25: 0x4000000000150000 0000000000000000
write -q -c -P PATTERN 1664k 64k
L2 entry #26: 0x4000000000160000 0000000000000000
write -q -c -P PATTERN 1728k 64k
L2 entry #27: 0x4000000000170000 0000000000000000
write -q -c -P PATTERN 1792k 64k
L2 entry #28: 0x4000000000180000 0000000000000000
write -q -z 1152k 192k
L2 entry #18: 0x0000000000000000 ffffffff00000000
L2 entry #19: 0x0000000000000000 ffffffff00000000
L2 entry #20: 0x0000000000000000 ffffffff00000000
write -q -z 1376k 128k
L2 entry #21: 0x80000000000e0000 00000000ffffffff
L2 entry #22: 0x80000000000f0000 00000000ffffffff
L2 entry #23: 0x8000000000100000 00000000ffffffff
write -q -z 1567k 129k
L2 entry #24: 0x8000000000110000 00000000ffffffff
L2 entry #25: 0x8000000000120000 00000000ffffffff
L2 entry #26: 0x8000000000130000 00000000ffffffff
write -q -z 1759k 128k
L2 entry #27: 0x8000000000140000 ffff00000000ffff
L2 entry #28: 0x0000000000000000 ffffffff00000000
L2 entry #29: 0x0000000000000000 0000ffff00000000
### Writing zeroes 4: other tests (backing file: no) ###
write -q -z 1951k 8k
L2 entry #30: 0x0000000000000000 000f800000000000
write -q -z 2048k 35k
L2 entry #32: 0x0000000000000000 0003ffff00000000
### Zero + unmap 1: allocated clusters (backing file: yes) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
write -q -P PATTERN 576k 576k
L2 entry #9: 0x8000000000050000 00000000ffffffff
L2 entry #10: 0x8000000000060000 00000000ffffffff
L2 entry #11: 0x8000000000070000 00000000ffffffff
L2 entry #12: 0x8000000000080000 00000000ffffffff
L2 entry #13: 0x8000000000090000 00000000ffffffff
L2 entry #14: 0x80000000000a0000 00000000ffffffff
L2 entry #15: 0x80000000000b0000 00000000ffffffff
L2 entry #16: 0x80000000000c0000 00000000ffffffff
L2 entry #17: 0x80000000000d0000 00000000ffffffff
write -q -z -u 576k 192k
L2 entry #9: 0x0000000000000000 ffffffff00000000
L2 entry #10: 0x0000000000000000 ffffffff00000000
L2 entry #11: 0x0000000000000000 ffffffff00000000
write -q -z -u 800k 128k
L2 entry #12: 0x8000000000080000 ffff00000000ffff
L2 entry #13: 0x0000000000000000 ffffffff00000000
L2 entry #14: 0x80000000000a0000 0000ffffffff0000
write -q -z -u 991k 128k
L2 entry #15: 0x80000000000b0000 ffff00000000ffff
L2 entry #16: 0x0000000000000000 ffffffff00000000
L2 entry #17: 0x80000000000d0000 00007fffffff8000
### Zero + unmap 2: compressed clusters (backing file: yes) ###
write -q -c -P PATTERN 1152k 64k
L2 entry #18: 0x4000000000050000 0000000000000000
write -q -c -P PATTERN 1216k 64k
L2 entry #19: 0x4000000000060000 0000000000000000
write -q -c -P PATTERN 1280k 64k
L2 entry #20: 0x4000000000070000 0000000000000000
write -q -c -P PATTERN 1344k 64k
L2 entry #21: 0x4000000000090000 0000000000000000
write -q -c -P PATTERN 1408k 64k
L2 entry #22: 0x40000000000c0000 0000000000000000
write -q -c -P PATTERN 1472k 64k
L2 entry #23: 0x40000000000e0000 0000000000000000
write -q -c -P PATTERN 1536k 64k
L2 entry #24: 0x40000000000f0000 0000000000000000
write -q -c -P PATTERN 1600k 64k
L2 entry #25: 0x4000000000100000 0000000000000000
write -q -c -P PATTERN 1664k 64k
L2 entry #26: 0x4000000000110000 0000000000000000
write -q -c -P PATTERN 1728k 64k
L2 entry #27: 0x4000000000120000 0000000000000000
write -q -c -P PATTERN 1792k 64k
L2 entry #28: 0x4000000000130000 0000000000000000
write -q -z -u 1152k 192k
L2 entry #18: 0x0000000000000000 ffffffff00000000
L2 entry #19: 0x0000000000000000 ffffffff00000000
L2 entry #20: 0x0000000000000000 ffffffff00000000
write -q -z -u 1376k 128k
L2 entry #21: 0x8000000000050000 00000000ffffffff
L2 entry #22: 0x8000000000060000 00000000ffffffff
L2 entry #23: 0x8000000000070000 00000000ffffffff
write -q -z -u 1567k 129k
L2 entry #24: 0x8000000000090000 00000000ffffffff
L2 entry #25: 0x80000000000e0000 00000000ffffffff
L2 entry #26: 0x80000000000f0000 00000000ffffffff
write -q -z -u 1759k 128k
L2 entry #27: 0x80000000000c0000 ffff00000000ffff
L2 entry #28: 0x0000000000000000 ffffffff00000000
L2 entry #29: 0x8000000000100000 00007fff00008000
### Zero + unmap 1: allocated clusters (backing file: no) ###
Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992
write -q -P PATTERN 576k 576k
L2 entry #9: 0x8000000000050000 00000000ffffffff
L2 entry #10: 0x8000000000060000 00000000ffffffff
L2 entry #11: 0x8000000000070000 00000000ffffffff
L2 entry #12: 0x8000000000080000 00000000ffffffff
L2 entry #13: 0x8000000000090000 00000000ffffffff
L2 entry #14: 0x80000000000a0000 00000000ffffffff
L2 entry #15: 0x80000000000b0000 00000000ffffffff
L2 entry #16: 0x80000000000c0000 00000000ffffffff
L2 entry #17: 0x80000000000d0000 00000000ffffffff
write -q -z -u 576k 192k
L2 entry #9: 0x0000000000000000 ffffffff00000000
L2 entry #10: 0x0000000000000000 ffffffff00000000
L2 entry #11: 0x0000000000000000 ffffffff00000000
write -q -z -u 800k 128k
L2 entry #12: 0x8000000000080000 ffff00000000ffff
L2 entry #13: 0x0000000000000000 ffffffff00000000
L2 entry #14: 0x80000000000a0000 0000ffffffff0000
write -q -z -u 991k 128k
L2 entry #15: 0x80000000000b0000 ffff00000000ffff
L2 entry #16: 0x0000000000000000 ffffffff00000000
L2 entry #17: 0x80000000000d0000 00007fffffff8000
### Zero + unmap 2: compressed clusters (backing file: no) ###
write -q -c -P PATTERN 1152k 64k
L2 entry #18: 0x4000000000050000 0000000000000000
write -q -c -P PATTERN 1216k 64k
L2 entry #19: 0x4000000000060000 0000000000000000
write -q -c -P PATTERN 1280k 64k
L2 entry #20: 0x4000000000070000 0000000000000000
write -q -c -P PATTERN 1344k 64k
L2 entry #21: 0x4000000000090000 0000000000000000
write -q -c -P PATTERN 1408k 64k
L2 entry #22: 0x40000000000c0000 0000000000000000
write -q -c -P PATTERN 1472k 64k
L2 entry #23: 0x40000000000e0000 0000000000000000
write -q -c -P PATTERN 1536k 64k
L2 entry #24: 0x40000000000f0000 0000000000000000
write -q -c -P PATTERN 1600k 64k
L2 entry #25: 0x4000000000100000 0000000000000000
write -q -c -P PATTERN 1664k 64k
L2 entry #26: 0x4000000000110000 0000000000000000
write -q -c -P PATTERN 1728k 64k
L2 entry #27: 0x4000000000120000 0000000000000000
write -q -c -P PATTERN 1792k 64k
L2 entry #28: 0x4000000000130000 0000000000000000
write -q -z -u 1152k 192k
L2 entry #18: 0x0000000000000000 ffffffff00000000
L2 entry #19: 0x0000000000000000 ffffffff00000000
L2 entry #20: 0x0000000000000000 ffffffff00000000
write -q -z -u 1376k 128k
L2 entry #21: 0x8000000000050000 00000000ffffffff
L2 entry #22: 0x8000000000060000 00000000ffffffff
L2 entry #23: 0x8000000000070000 00000000ffffffff
write -q -z -u 1567k 129k
L2 entry #24: 0x8000000000090000 00000000ffffffff
L2 entry #25: 0x80000000000e0000 00000000ffffffff
L2 entry #26: 0x80000000000f0000 00000000ffffffff
write -q -z -u 1759k 128k
L2 entry #27: 0x80000000000c0000 ffff00000000ffff
L2 entry #28: 0x0000000000000000 ffffffff00000000
L2 entry #29: 0x0000000000000000 0000ffff00000000
### Discarding clusters with non-zero bitmaps (backing file: yes) ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
L2 entry #0: 0x0000000000000000 ffffffff00000000
L2 entry #1: 0x0000000000000000 ffffffff00000000
Image resized.
Image resized.
L2 entry #0: 0x0000000000000000 ffffffff00000000
L2 entry #1: 0x0000000000000000 ffffffff00000000
### Discarding clusters with non-zero bitmaps (backing file: no) ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000000 ffffffff00000000
L2 entry #1: 0x0000000000000000 ffffffff00000000
Image resized.
Image resized.
L2 entry #0: 0x0000000000000000 0000ffff00000000
L2 entry #1: 0x0000000000000000 0000000000000000
### Corrupted L2 entries - read test (allocated) ###
# 'cluster is zero' bit set on the standard cluster descriptor
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x8000000000050001 0000000000000001
L2 entry #0: 0x8000000000050001 0000000000000001
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x8000000000060000 00000001ffffffff
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
read failed: Input/output error
### Corrupted L2 entries - read test (unallocated) ###
# 'cluster is zero' bit set on the standard cluster descriptor
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000001 0000000000000000
L2 entry #0: 0x0000000000000001 0000000000000000
# 'subcluster is allocated' bit set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000000 0000000000000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
read failed: Input/output error
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x0000000000000000 0000000100000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
read failed: Input/output error
### Compressed cluster with subcluster bitmap != 0 - read test ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x4000000000050000 0000000180000000
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
L2 entry #0: 0x4000000000050000 0000000180000000
### Corrupted L2 entries - write test (allocated) ###
# 'cluster is zero' bit set on the standard cluster descriptor
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x8000000000050001 0000000000000001
L2 entry #0: 0x8000000000050001 0000000000000001
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x8000000000060000 00000001ffffffff
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
write failed: Input/output error
### Corrupted L2 entries - write test (unallocated) ###
# 'cluster is zero' bit set on the standard cluster descriptor
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000001 0000000000000000
L2 entry #0: 0x8000000000060000 0000000000000001
# 'subcluster is allocated' bit set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000000 0000000000000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
write failed: Input/output error
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x0000000000000000 0000000100000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
write failed: Input/output error
### Compressed cluster with subcluster bitmap != 0 - write test ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x4000000000050000 0000000180000000
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
L2 entry #0: 0x8000000000060000 00000000ffffffff
### Detect and repair unaligned clusters ###
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072
# Corrupted L2 entry, allocated subcluster #
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
ERROR cluster 6 refcount=0 reference=1
Rebuilding refcount structure
ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
Repairing cluster 1 refcount=1 reference=0
Repairing cluster 2 refcount=1 reference=0
ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
The following inconsistencies were found and repaired:
0 leaked clusters
1 corruptions
Double checking the fixed image now...
1 errors were found on the image.
Data may be corrupted, or further writes to the image may corrupt it.
qcow2: Marking image as corrupt: Cluster allocation offset 0x50200 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
read failed: Input/output error
# Corrupted L2 entry, no allocated subclusters #
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
Repairing offset=50200: Preallocated cluster is not properly aligned; L2 entry corrupted.
Leaked cluster 5 refcount=1 reference=0
Repairing cluster 5 refcount=1 reference=0
The following inconsistencies were found and repaired:
1 leaked clusters
1 corruptions
Double checking the fixed image now...
No errors were found on the image.
### Image creation options ###
# cluster_size < 16k
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
qemu-img: TEST_DIR/t.IMGFMT: Extended L2 entries are only supported with cluster sizes of at least 16384 bytes
# backing file and preallocation=metadata
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=1048576
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=metadata
Image resized.
read 524288/524288 bytes at offset 0
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 524288/524288 bytes at offset 524288
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Offset Length Mapped to File
0 0x80000 0 TEST_DIR/t.qcow2.base
# backing file and preallocation=falloc
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=falloc
Image resized.
read 524288/524288 bytes at offset 0
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 524288/524288 bytes at offset 524288
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Offset Length Mapped to File
0 0x80000 0 TEST_DIR/t.qcow2.base
# backing file and preallocation=full
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=full
Image resized.
read 524288/524288 bytes at offset 0
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 524288/524288 bytes at offset 524288
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Offset Length Mapped to File
0 0x80000 0 TEST_DIR/t.qcow2.base
### Image resizing with preallocation and backing files ###
# resize --preallocation=metadata
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
# resize --preallocation=falloc
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
# resize --preallocation=full
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
### Image resizing with preallocation without backing files ###
# resize --preallocation=metadata
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
wrote 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
# resize --preallocation=falloc
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
wrote 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
# resize --preallocation=full
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
wrote 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image resized.
read 515072/515072 bytes at offset 0
503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 522240/522240 bytes at offset 515072
510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
### qemu-img measure ###
# 512MB, extended_l2=off
required size: 327680
fully allocated size: 537198592
# 512MB, extended_l2=on
required size: 393216
fully allocated size: 537264128
# 16K clusters, 64GB, extended_l2=off
required size: 42008576
fully allocated size: 68761485312
# 16K clusters, 64GB, extended_l2=on
required size: 75579392
fully allocated size: 68795056128
# 8k clusters
qemu-img: Extended L2 entries are only supported with cluster sizes of at least 16384 bytes
# 1024 TB
required size: 309285027840
fully allocated size: 1126209191870464
# 1025 TB
qemu-img: The image size is too large (try using a larger cluster size)
### qemu-img amend ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
qemu-img: Invalid parameter 'extended_l2'
This option is only supported for image creation
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
qemu-img: Invalid parameter 'extended_l2'
This option is only supported for image creation
### Test copy-on-write on an image with snapshots ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x8000000000050000 0000008000042000
L2 entry #1: 0x8000000000060000 0000008000042000
L2 entry #2: 0x8000000000070000 0000008000042000
L2 entry #3: 0x8000000000080000 0000008000042000
L2 entry #4: 0x8000000000090000 0000008000042000
L2 entry #5: 0x80000000000a0000 0000008000042000
L2 entry #6: 0x80000000000b0000 0000008000042000
L2 entry #7: 0x80000000000c0000 0000008000042000
L2 entry #8: 0x80000000000d0000 0000008000042000
L2 entry #9: 0x80000000000e0000 0000008000042000
L2 entry #0: 0x8000000000120000 000000800007e000
L2 entry #1: 0x8000000000130000 000000800007fc00
L2 entry #2: 0x8000000000140000 00000080001fe000
L2 entry #3: 0x8000000000150000 000000800007e000
L2 entry #4: 0x8000000000160000 000000000007ff80
L2 entry #5: 0x8000000000170000 000000000007ffff
L2 entry #6: 0x00000000000b0000 0001808000042000
L2 entry #7: 0x00000000000c0000 0000208000040000
L2 entry #8: 0x8000000000180000 000000800007e000
L2 entry #9: 0x00000000000e0000 000000c000042000
### Test concurrent requests ###
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
blkdebug: Suspended request 'A'
blkdebug: Resuming request 'A'
wrote 2048/2048 bytes at offset 30720
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 2048/2048 bytes at offset 20480
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 2048/2048 bytes at offset 40960
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done

View file

@ -1,9 +1,9 @@
== Commit tests ==
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -57,6 +57,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -65,11 +66,11 @@ read 1048576/1048576 bytes at offset 1048576
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing HMP commit (top -> mid) ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -88,6 +89,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -96,11 +98,11 @@ read 1048576/1048576 bytes at offset 1048576
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing QMP active commit (top -> mid) ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -125,6 +127,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -134,9 +137,9 @@ read 1048576/1048576 bytes at offset 1048576
== Resize tests ==
=== preallocation=off ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 5368709120
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -153,9 +156,9 @@ read 65536/65536 bytes at offset 5368709120
{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
=== preallocation=metadata ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 33285996544
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -177,9 +180,9 @@ read 65536/65536 bytes at offset 33285996544
{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
=== preallocation=falloc ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 9437184
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -196,9 +199,9 @@ read 65536/65536 bytes at offset 9437184
{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
=== preallocation=full ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 11534336
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -215,9 +218,9 @@ read 65536/65536 bytes at offset 11534336
{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
=== preallocation=off ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 259072
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -235,9 +238,9 @@ read 65536/65536 bytes at offset 259072
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
=== preallocation=off ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 344064
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -254,9 +257,9 @@ read 65536/65536 bytes at offset 344064
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
=== preallocation=off ===
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
wrote 65536/65536 bytes at offset 446464
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)

View file

@ -1,4 +1,4 @@
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
=== Launch VM ===
Enabling migration QMP events on VM...

View file

@ -41,6 +41,7 @@ Format specific information:
granularity: 65536
refcount bits: 16
corrupt: false
extended l2: false
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 10 MiB (10485760 bytes)
@ -65,6 +66,7 @@ Format specific information:
granularity: 65536
refcount bits: 16
corrupt: false
extended l2: false
=== Check bitmap contents ===

View file

@ -17,6 +17,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
=== Converted image check ===
No errors were found on the image.

View file

@ -47,7 +47,7 @@ header_length 112
Header extension:
magic 0x6803f857 (Feature table)
length 336
length 384
data <binary>
Header extension:
@ -105,7 +105,7 @@ Bitmap table type size offset
{
"name": "Feature table",
"magic": 1745090647,
"length": 336,
"length": 384,
"data_str": "<binary>"
},
{

View file

@ -239,6 +239,7 @@ _filter_img_info()
-e "/adapter_type: '[^']*'/d" \
-e "/hwversion: '[^']*'/d" \
-e "/lazy_refcounts: \\(on\\|off\\)/d" \
-e "/extended_l2=\\(on\\|off\\)/d" \
-e "/block_size: [0-9]\\+/d" \
-e "/block_state_zero: \\(on\\|off\\)/d" \
-e "/log_size: [0-9]\\+/d" \

View file

@ -284,6 +284,7 @@
267 rw auto quick snapshot
268 rw auto quick
270 rw backing quick
271 rw auto
272 rw
273 backing quick
274 rw backing