diff --git a/block.c b/block.c index 46eb1728da..684cb018da 100644 --- a/block.c +++ b/block.c @@ -2245,7 +2245,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, goto free_exit; } - if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { + if (!reference && + bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { qdict_put_str(options, "driver", bs->backing_format); } diff --git a/block/blkdebug.c b/block/blkdebug.c index dfdf9b91aa..e21669979d 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -627,6 +627,17 @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs, return bdrv_co_pdiscard(bs->file->bs, offset, bytes); } +static int64_t coroutine_fn blkdebug_co_get_block_status( + BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum, + BlockDriverState **file) +{ + assert(QEMU_IS_ALIGNED(sector_num | nb_sectors, + DIV_ROUND_UP(bs->bl.request_alignment, + BDRV_SECTOR_SIZE))); + return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors, + pnum, file); +} + static void blkdebug_close(BlockDriverState *bs) { BDRVBlkdebugState *s = bs->opaque; @@ -896,7 +907,7 @@ static BlockDriver bdrv_blkdebug = { .bdrv_co_flush_to_disk = blkdebug_co_flush, .bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes, .bdrv_co_pdiscard = blkdebug_co_pdiscard, - .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file, + .bdrv_co_get_block_status = blkdebug_co_get_block_status, .bdrv_debug_event = blkdebug_debug_event, .bdrv_debug_breakpoint = blkdebug_debug_breakpoint, diff --git a/block/io.c b/block/io.c index 0854e0fdac..3d5ef2cabe 100644 --- a/block/io.c +++ b/block/io.c @@ -469,9 +469,9 @@ static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) * Round a region to cluster boundaries */ void bdrv_round_to_clusters(BlockDriverState *bs, - int64_t offset, unsigned int bytes, + int64_t offset, int64_t bytes, int64_t *cluster_offset, - unsigned int *cluster_bytes) + int64_t *cluster_bytes) { BlockDriverInfo bdi; @@ -716,39 +716,37 @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset, */ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) { - int64_t target_sectors, ret, nb_sectors, sector_num = 0; + int ret; + int64_t target_size, bytes, offset = 0; BlockDriverState *bs = child->bs; - BlockDriverState *file; - int n; - target_sectors = bdrv_nb_sectors(bs); - if (target_sectors < 0) { - return target_sectors; + target_size = bdrv_getlength(bs); + if (target_size < 0) { + return target_size; } for (;;) { - nb_sectors = MIN(target_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS); - if (nb_sectors <= 0) { + bytes = MIN(target_size - offset, BDRV_REQUEST_MAX_BYTES); + if (bytes <= 0) { return 0; } - ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n, &file); + ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); if (ret < 0) { - error_report("error getting block status at sector %" PRId64 ": %s", - sector_num, strerror(-ret)); + error_report("error getting block status at offset %" PRId64 ": %s", + offset, strerror(-ret)); return ret; } if (ret & BDRV_BLOCK_ZERO) { - sector_num += n; + offset += bytes; continue; } - ret = bdrv_pwrite_zeroes(child, sector_num << BDRV_SECTOR_BITS, - n << BDRV_SECTOR_BITS, flags); + ret = bdrv_pwrite_zeroes(child, offset, bytes, flags); if (ret < 0) { - error_report("error writing zeroes at sector %" PRId64 ": %s", - sector_num, strerror(-ret)); + error_report("error writing zeroes at offset %" PRId64 ": %s", + offset, strerror(-ret)); return ret; } - sector_num += n; + offset += bytes; } } @@ -970,7 +968,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, struct iovec iov; QEMUIOVector local_qiov; int64_t cluster_offset; - unsigned int cluster_bytes; + int64_t cluster_bytes; size_t skip_bytes; int ret; int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, @@ -1126,18 +1124,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, } if (flags & BDRV_REQ_COPY_ON_READ) { - /* TODO: Simplify further once bdrv_is_allocated no longer - * requires sector alignment */ - int64_t start = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); - int64_t end = QEMU_ALIGN_UP(offset + bytes, BDRV_SECTOR_SIZE); int64_t pnum; - ret = bdrv_is_allocated(bs, start, end - start, &pnum); + ret = bdrv_is_allocated(bs, offset, bytes, &pnum); if (ret < 0) { goto out; } - if (!ret || pnum != end - start) { + if (!ret || pnum != bytes) { ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov); goto out; } @@ -1767,16 +1761,18 @@ int bdrv_flush_all(void) } -typedef struct BdrvCoGetBlockStatusData { +typedef struct BdrvCoBlockStatusData { BlockDriverState *bs; BlockDriverState *base; + bool want_zero; + int64_t offset; + int64_t bytes; + int64_t *pnum; + int64_t *map; BlockDriverState **file; - int64_t sector_num; - int nb_sectors; - int *pnum; - int64_t ret; + int ret; bool done; -} BdrvCoGetBlockStatusData; +} BdrvCoBlockStatusData; int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs, int64_t sector_num, @@ -1809,99 +1805,157 @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs, * Drivers not implementing the functionality are assumed to not support * backing files, hence all their sectors are reported as allocated. * - * If 'sector_num' is beyond the end of the disk image the return value is + * If 'want_zero' is true, the caller is querying for mapping purposes, + * and the result should include BDRV_BLOCK_OFFSET_VALID and + * BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those + * bits particularly if it allows for a larger value in 'pnum'. + * + * If 'offset' is beyond the end of the disk image the return value is * BDRV_BLOCK_EOF and 'pnum' is set to 0. * - * 'pnum' is set to the number of sectors (including and immediately following - * the specified sector) that are known to be in the same - * allocated/unallocated state. - * - * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes + * 'bytes' is the max value 'pnum' should be set to. If bytes goes * beyond the end of the disk image it will be clamped; if 'pnum' is set to * the end of the image, then the returned value will include BDRV_BLOCK_EOF. * - * If returned value is positive and BDRV_BLOCK_OFFSET_VALID bit is set, 'file' - * points to the BDS which the sector range is allocated in. + * 'pnum' is set to the number of bytes (including and immediately + * following the specified offset) that are easily known to be in the + * same allocated/unallocated state. Note that a second call starting + * at the original offset plus returned pnum may have the same status. + * The returned value is non-zero on success except at end-of-file. + * + * Returns negative errno on failure. Otherwise, if the + * BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are + * set to the host mapping and BDS corresponding to the guest offset. */ -static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file) +static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, + bool want_zero, + int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, + BlockDriverState **file) { - int64_t total_sectors; - int64_t n; - int64_t ret, ret2; + int64_t total_size; + int64_t n; /* bytes */ + int ret; + int64_t local_map = 0; + BlockDriverState *local_file = NULL; + int64_t aligned_offset, aligned_bytes; + uint32_t align; - *file = NULL; - total_sectors = bdrv_nb_sectors(bs); - if (total_sectors < 0) { - return total_sectors; + assert(pnum); + *pnum = 0; + total_size = bdrv_getlength(bs); + if (total_size < 0) { + ret = total_size; + goto early_out; } - if (sector_num >= total_sectors) { - *pnum = 0; - return BDRV_BLOCK_EOF; + if (offset >= total_size) { + ret = BDRV_BLOCK_EOF; + goto early_out; } - if (!nb_sectors) { - *pnum = 0; - return 0; + if (!bytes) { + ret = 0; + goto early_out; } - n = total_sectors - sector_num; - if (n < nb_sectors) { - nb_sectors = n; + n = total_size - offset; + if (n < bytes) { + bytes = n; } if (!bs->drv->bdrv_co_get_block_status) { - *pnum = nb_sectors; + *pnum = bytes; ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED; - if (sector_num + nb_sectors == total_sectors) { + if (offset + bytes == total_size) { ret |= BDRV_BLOCK_EOF; } if (bs->drv->protocol_name) { - ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE); - *file = bs; + ret |= BDRV_BLOCK_OFFSET_VALID; + local_map = offset; + local_file = bs; } - return ret; + goto early_out; } bdrv_inc_in_flight(bs); - ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum, - file); - if (ret < 0) { - *pnum = 0; - goto out; + + /* Round out to request_alignment boundaries */ + /* TODO: until we have a byte-based driver callback, we also have to + * round out to sectors, even if that is bigger than request_alignment */ + align = MAX(bs->bl.request_alignment, BDRV_SECTOR_SIZE); + aligned_offset = QEMU_ALIGN_DOWN(offset, align); + aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset; + + { + int count; /* sectors */ + int64_t longret; + + assert(QEMU_IS_ALIGNED(aligned_offset | aligned_bytes, + BDRV_SECTOR_SIZE)); + /* + * The contract allows us to return pnum smaller than bytes, even + * if the next query would see the same status; we truncate the + * request to avoid overflowing the driver's 32-bit interface. + */ + longret = bs->drv->bdrv_co_get_block_status( + bs, aligned_offset >> BDRV_SECTOR_BITS, + MIN(INT_MAX, aligned_bytes) >> BDRV_SECTOR_BITS, &count, + &local_file); + if (longret < 0) { + assert(INT_MIN <= longret); + ret = longret; + goto out; + } + if (longret & BDRV_BLOCK_OFFSET_VALID) { + local_map = longret & BDRV_BLOCK_OFFSET_MASK; + } + ret = longret & ~BDRV_BLOCK_OFFSET_MASK; + *pnum = count * BDRV_SECTOR_SIZE; + } + + /* + * The driver's result must be a multiple of request_alignment. + * Clamp pnum and adjust map to original request. + */ + assert(QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset); + *pnum -= offset - aligned_offset; + if (*pnum > bytes) { + *pnum = bytes; + } + if (ret & BDRV_BLOCK_OFFSET_VALID) { + local_map += offset - aligned_offset; } if (ret & BDRV_BLOCK_RAW) { - assert(ret & BDRV_BLOCK_OFFSET_VALID && *file); - ret = bdrv_co_get_block_status(*file, ret >> BDRV_SECTOR_BITS, - *pnum, pnum, file); + assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file); + ret = bdrv_co_block_status(local_file, want_zero, local_map, + *pnum, pnum, &local_map, &local_file); goto out; } if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) { ret |= BDRV_BLOCK_ALLOCATED; - } else { + } else if (want_zero) { if (bdrv_unallocated_blocks_are_zero(bs)) { ret |= BDRV_BLOCK_ZERO; } else if (bs->backing) { BlockDriverState *bs2 = bs->backing->bs; - int64_t nb_sectors2 = bdrv_nb_sectors(bs2); - if (nb_sectors2 >= 0 && sector_num >= nb_sectors2) { + int64_t size2 = bdrv_getlength(bs2); + + if (size2 >= 0 && offset >= size2) { ret |= BDRV_BLOCK_ZERO; } } } - if (*file && *file != bs && + if (want_zero && local_file && local_file != bs && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_OFFSET_VALID)) { - BlockDriverState *file2; - int file_pnum; + int64_t file_pnum; + int ret2; - ret2 = bdrv_co_get_block_status(*file, ret >> BDRV_SECTOR_BITS, - *pnum, &file_pnum, &file2); + ret2 = bdrv_co_block_status(local_file, want_zero, local_map, + *pnum, &file_pnum, NULL, NULL); if (ret2 >= 0) { /* Ignore errors. This is just providing extra information, it * is useful but not necessary. @@ -1924,26 +1978,36 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, out: bdrv_dec_in_flight(bs); - if (ret >= 0 && sector_num + *pnum == total_sectors) { + if (ret >= 0 && offset + *pnum == total_size) { ret |= BDRV_BLOCK_EOF; } +early_out: + if (file) { + *file = local_file; + } + if (map) { + *map = local_map; + } return ret; } -static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, - int *pnum, - BlockDriverState **file) +static int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool want_zero, + int64_t offset, + int64_t bytes, + int64_t *pnum, + int64_t *map, + BlockDriverState **file) { BlockDriverState *p; - int64_t ret = 0; + int ret = 0; bool first = true; assert(bs != base); for (p = bs; p != base; p = backing_bs(p)) { - ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum, file); + ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map, + file); if (ret < 0) { break; } @@ -1954,94 +2018,94 @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs, * unallocated length we learned from an earlier * iteration. */ - *pnum = nb_sectors; + *pnum = bytes; } if (ret & (BDRV_BLOCK_ZERO | BDRV_BLOCK_DATA)) { break; } - /* [sector_num, pnum] unallocated on this layer, which could be only - * the first part of [sector_num, nb_sectors]. */ - nb_sectors = MIN(nb_sectors, *pnum); + /* [offset, pnum] unallocated on this layer, which could be only + * the first part of [offset, bytes]. */ + bytes = MIN(bytes, *pnum); first = false; } return ret; } -/* Coroutine wrapper for bdrv_get_block_status_above() */ -static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque) +/* Coroutine wrapper for bdrv_block_status_above() */ +static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque) { - BdrvCoGetBlockStatusData *data = opaque; + BdrvCoBlockStatusData *data = opaque; - data->ret = bdrv_co_get_block_status_above(data->bs, data->base, - data->sector_num, - data->nb_sectors, - data->pnum, - data->file); + data->ret = bdrv_co_block_status_above(data->bs, data->base, + data->want_zero, + data->offset, data->bytes, + data->pnum, data->map, data->file); data->done = true; } /* - * Synchronous wrapper around bdrv_co_get_block_status_above(). + * Synchronous wrapper around bdrv_co_block_status_above(). * - * See bdrv_co_get_block_status_above() for details. + * See bdrv_co_block_status_above() for details. */ -int64_t bdrv_get_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file) +static int bdrv_common_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool want_zero, int64_t offset, + int64_t bytes, int64_t *pnum, + int64_t *map, + BlockDriverState **file) { Coroutine *co; - BdrvCoGetBlockStatusData data = { + BdrvCoBlockStatusData data = { .bs = bs, .base = base, - .file = file, - .sector_num = sector_num, - .nb_sectors = nb_sectors, + .want_zero = want_zero, + .offset = offset, + .bytes = bytes, .pnum = pnum, + .map = map, + .file = file, .done = false, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ - bdrv_get_block_status_above_co_entry(&data); + bdrv_block_status_above_co_entry(&data); } else { - co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry, - &data); + co = qemu_coroutine_create(bdrv_block_status_above_co_entry, &data); bdrv_coroutine_enter(bs, co); BDRV_POLL_WHILE(bs, !data.done); } return data.ret; } -int64_t bdrv_get_block_status(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file) +int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { - return bdrv_get_block_status_above(bs, backing_bs(bs), - sector_num, nb_sectors, pnum, file); + return bdrv_common_block_status_above(bs, base, true, offset, bytes, + pnum, map, file); +} + +int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, BlockDriverState **file) +{ + return bdrv_block_status_above(bs, backing_bs(bs), + offset, bytes, pnum, map, file); } int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum) { - BlockDriverState *file; - int64_t sector_num = offset >> BDRV_SECTOR_BITS; - int nb_sectors = bytes >> BDRV_SECTOR_BITS; - int64_t ret; - int psectors; + int ret; + int64_t dummy; - assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); - assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX); - ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors, - &file); + ret = bdrv_common_block_status_above(bs, backing_bs(bs), false, offset, + bytes, pnum ? pnum : &dummy, NULL, + NULL); if (ret < 0) { return ret; } - if (pnum) { - *pnum = psectors * BDRV_SECTOR_SIZE; - } return !!(ret & BDRV_BLOCK_ALLOCATED); } diff --git a/block/mirror.c b/block/mirror.c index 153758ca9f..307b6391a8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -190,10 +190,9 @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset, bool need_cow; int ret = 0; int64_t align_offset = *offset; - unsigned int align_bytes = *bytes; + int64_t align_bytes = *bytes; int max_bytes = s->granularity * s->max_iov; - assert(*bytes < INT_MAX); need_cow = !test_bit(*offset / s->granularity, s->cow_bitmap); need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity, s->cow_bitmap); @@ -329,7 +328,6 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) uint64_t delay_ns = 0; /* At least the first dirty chunk is mirrored in one iteration. */ int nb_chunks = 1; - int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)); int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES); @@ -377,7 +375,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) } /* Clear dirty bits before querying the block status, because - * calling bdrv_get_block_status_above could yield - if some blocks are + * calling bdrv_block_status_above could yield - if some blocks are * marked dirty in this window, we need to know. */ bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset, @@ -386,11 +384,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) bitmap_set(s->in_flight_bitmap, offset / s->granularity, nb_chunks); while (nb_chunks > 0 && offset < s->bdev_length) { - int64_t ret; - int io_sectors; - unsigned int io_bytes; + int ret; + int64_t io_bytes; int64_t io_bytes_acct; - BlockDriverState *file; enum MirrorMethod { MIRROR_METHOD_COPY, MIRROR_METHOD_ZERO, @@ -398,11 +394,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) } mirror_method = MIRROR_METHOD_COPY; assert(!(offset % s->granularity)); - ret = bdrv_get_block_status_above(source, NULL, - offset >> BDRV_SECTOR_BITS, - nb_chunks * sectors_per_chunk, - &io_sectors, &file); - io_bytes = io_sectors * BDRV_SECTOR_SIZE; + ret = bdrv_block_status_above(source, NULL, offset, + nb_chunks * s->granularity, + &io_bytes, NULL, NULL); if (ret < 0) { io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes); } else if (ret & BDRV_BLOCK_DATA) { @@ -414,7 +408,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) io_bytes = s->granularity; } else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) { int64_t target_offset; - unsigned int target_bytes; + int64_t target_bytes; bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes, &target_offset, &target_bytes); if (target_offset == offset && @@ -1133,9 +1127,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, granularity = bdrv_get_default_bitmap_granularity(target); } - assert ((granularity & (granularity - 1)) == 0); - /* Granularity must be large enough for sector-based dirty bitmap */ - assert(granularity >= BDRV_SECTOR_SIZE); + assert(is_power_of_2(granularity)); if (buf_size < 0) { error_setg(errp, "Invalid parameter 'buf-size'"); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 0e5aec81cb..fb10e26068 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1632,7 +1632,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, * cluster is already marked as zero, or if it's unallocated and we * don't have a backing file. * - * TODO We might want to use bdrv_get_block_status(bs) here, but we're + * TODO We might want to use bdrv_block_status(bs) here, but we're * holding s->lock, so that doesn't work today. * * If full_discard is true, the sector should not read back as zeroes, diff --git a/block/qcow2.c b/block/qcow2.c index f63d1831f8..92cb9f9bfa 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1139,7 +1139,7 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, s->cluster_bits = header.cluster_bits; s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); + s->cluster_sectors = 1 << (s->cluster_bits - BDRV_SECTOR_BITS); /* Initialise version 3 header fields */ if (header.version == 2) { @@ -1636,7 +1636,7 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, bytes = MIN(INT_MAX, nb_sectors * BDRV_SECTOR_SIZE); qemu_co_mutex_lock(&s->lock); - ret = qcow2_get_cluster_offset(bs, sector_num << 9, &bytes, + ret = qcow2_get_cluster_offset(bs, sector_num << BDRV_SECTOR_BITS, &bytes, &cluster_offset); qemu_co_mutex_unlock(&s->lock); if (ret < 0) { @@ -2460,6 +2460,14 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt, } +typedef struct PreallocCo { + BlockDriverState *bs; + uint64_t offset; + uint64_t new_length; + + int ret; +} PreallocCo; + /** * Preallocates metadata structures for data clusters between @offset (in the * guest disk) and @new_length (which is thus generally the new guest disk @@ -2467,9 +2475,12 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt, * * Returns: 0 on success, -errno on failure. */ -static int preallocate(BlockDriverState *bs, - uint64_t offset, uint64_t new_length) +static void coroutine_fn preallocate_co(void *opaque) { + PreallocCo *params = opaque; + BlockDriverState *bs = params->bs; + uint64_t offset = params->offset; + uint64_t new_length = params->new_length; BDRVQcow2State *s = bs->opaque; uint64_t bytes; uint64_t host_offset = 0; @@ -2477,9 +2488,7 @@ static int preallocate(BlockDriverState *bs, int ret; QCowL2Meta *meta; - if (qemu_in_coroutine()) { - qemu_co_mutex_lock(&s->lock); - } + qemu_co_mutex_lock(&s->lock); assert(offset <= new_length); bytes = new_length - offset; @@ -2533,10 +2542,28 @@ static int preallocate(BlockDriverState *bs, ret = 0; done: + qemu_co_mutex_unlock(&s->lock); + params->ret = ret; +} + +static int preallocate(BlockDriverState *bs, + uint64_t offset, uint64_t new_length) +{ + PreallocCo params = { + .bs = bs, + .offset = offset, + .new_length = new_length, + .ret = -EINPROGRESS, + }; + if (qemu_in_coroutine()) { - qemu_co_mutex_unlock(&s->lock); + preallocate_co(¶ms); + } else { + Coroutine *co = qemu_coroutine_create(preallocate_co, ¶ms); + bdrv_coroutine_enter(bs, co); + BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS); } - return ret; + return params.ret; } /* qcow2_refcount_metadata_size: @@ -2972,23 +2999,21 @@ finish: } -static bool is_zero_sectors(BlockDriverState *bs, int64_t start, - uint32_t count) +static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes) { - int nr; - BlockDriverState *file; - int64_t res; + int64_t nr; + int res; - if (start + count > bs->total_sectors) { - count = bs->total_sectors - start; + /* Clamp to image length, before checking status of underlying sectors */ + if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) { + bytes = bs->total_sectors * BDRV_SECTOR_SIZE - offset; } - if (!count) { + if (!bytes) { return true; } - res = bdrv_get_block_status_above(bs, NULL, start, count, - &nr, &file); - return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == count; + res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL); + return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes; } static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, @@ -3006,24 +3031,21 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, } if (head || tail) { - int64_t cl_start = (offset - head) >> BDRV_SECTOR_BITS; uint64_t off; unsigned int nr; assert(head + bytes <= s->cluster_size); /* check whether remainder of cluster already reads as zero */ - if (!(is_zero_sectors(bs, cl_start, - DIV_ROUND_UP(head, BDRV_SECTOR_SIZE)) && - is_zero_sectors(bs, (offset + bytes) >> BDRV_SECTOR_BITS, - DIV_ROUND_UP(-tail & (s->cluster_size - 1), - BDRV_SECTOR_SIZE)))) { + if (!(is_zero(bs, offset - head, head) && + is_zero(bs, offset + bytes, + tail ? s->cluster_size - tail : 0))) { return -ENOTSUP; } qemu_co_mutex_lock(&s->lock); /* We can have new write after previous check */ - offset = cl_start << BDRV_SECTOR_BITS; + 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); @@ -3150,12 +3172,13 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, return last_cluster; } if ((last_cluster + 1) * s->cluster_size < old_file_size) { - ret = bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size, - PREALLOC_MODE_OFF, NULL); - if (ret < 0) { - warn_report("Failed to truncate the tail of the image: %s", - strerror(-ret)); - ret = 0; + Error *local_err = NULL; + + bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size, + PREALLOC_MODE_OFF, &local_err); + if (local_err) { + warn_reportf_err(local_err, + "Failed to truncate the tail of the image: "); } } } else { @@ -3192,6 +3215,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, "Failed to inquire current file length"); return old_file_size; } + old_file_size = ROUND_UP(old_file_size, s->cluster_size); nb_new_data_clusters = DIV_ROUND_UP(offset - old_length, s->cluster_size); @@ -3697,19 +3721,14 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, required = virtual_size; } else { int64_t offset; - int pnum = 0; + int64_t pnum = 0; - for (offset = 0; offset < ssize; - offset += pnum * BDRV_SECTOR_SIZE) { - int nb_sectors = MIN(ssize - offset, - BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE; - BlockDriverState *file; - int64_t ret; + for (offset = 0; offset < ssize; offset += pnum) { + int ret; - ret = bdrv_get_block_status_above(in_bs, NULL, - offset >> BDRV_SECTOR_BITS, - nb_sectors, - &pnum, &file); + ret = bdrv_block_status_above(in_bs, NULL, offset, + ssize - offset, &pnum, NULL, + NULL); if (ret < 0) { error_setg_errno(&local_err, -ret, "Unable to get block status"); @@ -3721,11 +3740,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, } else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) == (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) { /* Extend pnum to end of cluster for next iteration */ - pnum = (ROUND_UP(offset + pnum * BDRV_SECTOR_SIZE, - cluster_size) - offset) >> BDRV_SECTOR_BITS; + pnum = ROUND_UP(offset + pnum, cluster_size) - offset; /* Count clusters we've seen */ - required += offset % cluster_size + pnum * BDRV_SECTOR_SIZE; + required += offset % cluster_size + pnum; } } } diff --git a/block/trace-events b/block/trace-events index 25dd5a3026..11c8d5f590 100644 --- a/block/trace-events +++ b/block/trace-events @@ -12,7 +12,7 @@ blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, int flag bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x" bdrv_co_pwritev(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x" bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p offset %"PRId64" count %d flags 0x%x" -bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, unsigned int cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %u" +bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %"PRId64 # block/stream.c stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d" diff --git a/include/block/block.h b/include/block/block.h index d5c2731a03..fbc21daf62 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -121,7 +121,7 @@ typedef struct HDGeometry { #define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS) /* - * Allocation status flags for bdrv_get_block_status() and friends. + * Allocation status flags for bdrv_block_status() and friends. * * Public flags: * BDRV_BLOCK_DATA: allocation for data at offset is tied to this layer @@ -136,10 +136,11 @@ typedef struct HDGeometry { * that the block layer recompute the answer from the returned * BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID. * - * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) - * represent the offset in the returned BDS that is allocated for the - * corresponding raw data; however, whether that offset actually contains - * data also depends on BDRV_BLOCK_DATA and BDRV_BLOCK_ZERO, as follows: + * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) of + * the return value (old interface) or the entire map parameter (new + * interface) represent the offset in the returned BDS that is allocated for + * the corresponding raw data. However, whether that offset actually + * contains data also depends on BDRV_BLOCK_DATA, as follows: * * DATA ZERO OFFSET_VALID * t t t sectors read as zero, returned file is zero at offset @@ -421,14 +422,12 @@ int bdrv_has_zero_init_1(BlockDriverState *bs); int bdrv_has_zero_init(BlockDriverState *bs); bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs); bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); -int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file); -int64_t bdrv_get_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file); +int bdrv_block_status(BlockDriverState *bs, int64_t offset, + int64_t bytes, int64_t *pnum, int64_t *map, + BlockDriverState **file); +int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file); int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum); int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, @@ -474,9 +473,9 @@ int bdrv_get_flags(BlockDriverState *bs); int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs); void bdrv_round_to_clusters(BlockDriverState *bs, - int64_t offset, unsigned int bytes, + int64_t offset, int64_t bytes, int64_t *cluster_offset, - unsigned int *cluster_bytes); + int64_t *cluster_bytes); const char *bdrv_get_encrypted_filename(BlockDriverState *bs); void bdrv_get_backing_filename(BlockDriverState *bs, diff --git a/include/block/block_int.h b/include/block/block_int.h index 885c08e989..a5482775ec 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -202,10 +202,13 @@ struct BlockDriver { int64_t offset, int bytes); /* - * Building block for bdrv_block_status[_above]. The driver should - * answer only according to the current layer, and should not - * set BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h - * for the meaning of _DATA, _ZERO, and _OFFSET_VALID. + * Building block for bdrv_block_status[_above] and + * bdrv_is_allocated[_above]. The driver should answer only + * according to the current layer, and should not set + * BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h + * for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block + * layer guarantees input aligned to request_alignment, as well as + * non-NULL pnum and file. */ int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum, diff --git a/qemu-img.c b/qemu-img.c index d6007b2a6d..02a6e27beb 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1064,6 +1064,28 @@ done: return 0; } +/* + * Returns -1 if 'buf' contains only zeroes, otherwise the byte index + * of the first sector boundary within buf where the sector contains a + * non-zero byte. This function is robust to a buffer that is not + * sector-aligned. + */ +static int64_t find_nonzero(const uint8_t *buf, int64_t n) +{ + int64_t i; + int64_t end = QEMU_ALIGN_DOWN(n, BDRV_SECTOR_SIZE); + + for (i = 0; i < end; i += BDRV_SECTOR_SIZE) { + if (!buffer_is_zero(buf + i, BDRV_SECTOR_SIZE)) { + return i; + } + } + if (i < n && !buffer_is_zero(buf + i, n - end)) { + return i; + } + return -1; +} + /* * Returns true iff the first sector pointed to by 'buf' contains at least * a non-NUL byte. @@ -1134,31 +1156,28 @@ static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum, } /* - * Compares two buffers sector by sector. Returns 0 if the first sector of both - * buffers matches, non-zero otherwise. + * Compares two buffers sector by sector. Returns 0 if the first + * sector of each buffer matches, non-zero otherwise. * - * pnum is set to the number of sectors (including and immediately following - * the first one) that are known to have the same comparison result + * pnum is set to the sector-aligned size of the buffer prefix that + * has the same matching status as the first sector. */ -static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n, - int *pnum) +static int compare_buffers(const uint8_t *buf1, const uint8_t *buf2, + int64_t bytes, int64_t *pnum) { bool res; - int i; + int64_t i = MIN(bytes, BDRV_SECTOR_SIZE); - if (n <= 0) { - *pnum = 0; - return 0; - } + assert(bytes > 0); - res = !!memcmp(buf1, buf2, 512); - for(i = 1; i < n; i++) { - buf1 += 512; - buf2 += 512; + res = !!memcmp(buf1, buf2, i); + while (i < bytes) { + int64_t len = MIN(bytes - i, BDRV_SECTOR_SIZE); - if (!!memcmp(buf1, buf2, 512) != res) { + if (!!memcmp(buf1 + i, buf2 + i, len) != res) { break; } + i += len; } *pnum = i; @@ -1167,45 +1186,38 @@ static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n, #define IO_BUF_SIZE (2 * 1024 * 1024) -static int64_t sectors_to_bytes(int64_t sectors) -{ - return sectors << BDRV_SECTOR_BITS; -} - -static int64_t sectors_to_process(int64_t total, int64_t from) -{ - return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS); -} - /* * Check if passed sectors are empty (not allocated or contain only 0 bytes) * - * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero - * data and negative value on error. + * Intended for use by 'qemu-img compare': Returns 0 in case sectors are + * filled with 0, 1 if sectors contain non-zero data (this is a comparison + * failure), and 4 on error (the exit status for read errors), after emitting + * an error message. * * @param blk: BlockBackend for the image - * @param sect_num: Number of first sector to check - * @param sect_count: Number of sectors to check + * @param offset: Starting offset to check + * @param bytes: Number of bytes to check * @param filename: Name of disk file we are checking (logging purpose) * @param buffer: Allocated buffer for storing read data * @param quiet: Flag for quiet mode */ -static int check_empty_sectors(BlockBackend *blk, int64_t sect_num, - int sect_count, const char *filename, +static int check_empty_sectors(BlockBackend *blk, int64_t offset, + int64_t bytes, const char *filename, uint8_t *buffer, bool quiet) { - int pnum, ret = 0; - ret = blk_pread(blk, sect_num << BDRV_SECTOR_BITS, buffer, - sect_count << BDRV_SECTOR_BITS); + int ret = 0; + int64_t idx; + + ret = blk_pread(blk, offset, buffer, bytes); if (ret < 0) { error_report("Error while reading offset %" PRId64 " of %s: %s", - sectors_to_bytes(sect_num), filename, strerror(-ret)); - return ret; + offset, filename, strerror(-ret)); + return 4; } - ret = is_allocated_sectors(buffer, sect_count, &pnum); - if (ret || pnum != sect_count) { + idx = find_nonzero(buffer, bytes); + if (idx >= 0) { qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n", - sectors_to_bytes(ret ? sect_num : sect_num + pnum)); + offset + idx); return 1; } @@ -1224,18 +1236,18 @@ static int img_compare(int argc, char **argv) const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2; BlockBackend *blk1, *blk2; BlockDriverState *bs1, *bs2; - int64_t total_sectors1, total_sectors2; + int64_t total_size1, total_size2; uint8_t *buf1 = NULL, *buf2 = NULL; - int pnum1, pnum2; + int64_t pnum1, pnum2; int allocated1, allocated2; int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */ bool progress = false, quiet = false, strict = false; int flags; bool writethrough; - int64_t total_sectors; - int64_t sector_num = 0; - int64_t nb_sectors; - int c, pnum; + int64_t total_size; + int64_t offset = 0; + int64_t chunk; + int c; uint64_t progress_base; bool image_opts = false; bool force_share = false; @@ -1348,42 +1360,37 @@ static int img_compare(int argc, char **argv) buf1 = blk_blockalign(blk1, IO_BUF_SIZE); buf2 = blk_blockalign(blk2, IO_BUF_SIZE); - total_sectors1 = blk_nb_sectors(blk1); - if (total_sectors1 < 0) { + total_size1 = blk_getlength(blk1); + if (total_size1 < 0) { error_report("Can't get size of %s: %s", - filename1, strerror(-total_sectors1)); + filename1, strerror(-total_size1)); ret = 4; goto out; } - total_sectors2 = blk_nb_sectors(blk2); - if (total_sectors2 < 0) { + total_size2 = blk_getlength(blk2); + if (total_size2 < 0) { error_report("Can't get size of %s: %s", - filename2, strerror(-total_sectors2)); + filename2, strerror(-total_size2)); ret = 4; goto out; } - total_sectors = MIN(total_sectors1, total_sectors2); - progress_base = MAX(total_sectors1, total_sectors2); + total_size = MIN(total_size1, total_size2); + progress_base = MAX(total_size1, total_size2); qemu_progress_print(0, 100); - if (strict && total_sectors1 != total_sectors2) { + if (strict && total_size1 != total_size2) { ret = 1; qprintf(quiet, "Strict mode: Image size mismatch!\n"); goto out; } - for (;;) { - int64_t status1, status2; - BlockDriverState *file; + while (offset < total_size) { + int status1, status2; - nb_sectors = sectors_to_process(total_sectors, sector_num); - if (nb_sectors <= 0) { - break; - } - status1 = bdrv_get_block_status_above(bs1, NULL, sector_num, - total_sectors1 - sector_num, - &pnum1, &file); + status1 = bdrv_block_status_above(bs1, NULL, offset, + total_size1 - offset, &pnum1, NULL, + NULL); if (status1 < 0) { ret = 3; error_report("Sector allocation test failed for %s", filename1); @@ -1391,112 +1398,92 @@ static int img_compare(int argc, char **argv) } allocated1 = status1 & BDRV_BLOCK_ALLOCATED; - status2 = bdrv_get_block_status_above(bs2, NULL, sector_num, - total_sectors2 - sector_num, - &pnum2, &file); + status2 = bdrv_block_status_above(bs2, NULL, offset, + total_size2 - offset, &pnum2, NULL, + NULL); if (status2 < 0) { ret = 3; error_report("Sector allocation test failed for %s", filename2); goto out; } allocated2 = status2 & BDRV_BLOCK_ALLOCATED; - if (pnum1) { - nb_sectors = MIN(nb_sectors, pnum1); - } - if (pnum2) { - nb_sectors = MIN(nb_sectors, pnum2); - } + + assert(pnum1 && pnum2); + chunk = MIN(pnum1, pnum2); if (strict) { - if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) != - (status2 & ~BDRV_BLOCK_OFFSET_MASK)) { + if (status1 != status2) { ret = 1; qprintf(quiet, "Strict mode: Offset %" PRId64 - " block status mismatch!\n", - sectors_to_bytes(sector_num)); + " block status mismatch!\n", offset); goto out; } } if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) { - nb_sectors = MIN(pnum1, pnum2); + /* nothing to do */ } else if (allocated1 == allocated2) { if (allocated1) { - ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1, - nb_sectors << BDRV_SECTOR_BITS); - if (ret < 0) { - error_report("Error while reading offset %" PRId64 " of %s:" - " %s", sectors_to_bytes(sector_num), filename1, - strerror(-ret)); - ret = 4; - goto out; - } - ret = blk_pread(blk2, sector_num << BDRV_SECTOR_BITS, buf2, - nb_sectors << BDRV_SECTOR_BITS); + int64_t pnum; + + chunk = MIN(chunk, IO_BUF_SIZE); + ret = blk_pread(blk1, offset, buf1, chunk); if (ret < 0) { error_report("Error while reading offset %" PRId64 - " of %s: %s", sectors_to_bytes(sector_num), - filename2, strerror(-ret)); + " of %s: %s", + offset, filename1, strerror(-ret)); ret = 4; goto out; } - ret = compare_sectors(buf1, buf2, nb_sectors, &pnum); - if (ret || pnum != nb_sectors) { + ret = blk_pread(blk2, offset, buf2, chunk); + if (ret < 0) { + error_report("Error while reading offset %" PRId64 + " of %s: %s", + offset, filename2, strerror(-ret)); + ret = 4; + goto out; + } + ret = compare_buffers(buf1, buf2, chunk, &pnum); + if (ret || pnum != chunk) { qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n", - sectors_to_bytes( - ret ? sector_num : sector_num + pnum)); + offset + (ret ? 0 : pnum)); ret = 1; goto out; } } } else { - + chunk = MIN(chunk, IO_BUF_SIZE); if (allocated1) { - ret = check_empty_sectors(blk1, sector_num, nb_sectors, + ret = check_empty_sectors(blk1, offset, chunk, filename1, buf1, quiet); } else { - ret = check_empty_sectors(blk2, sector_num, nb_sectors, + ret = check_empty_sectors(blk2, offset, chunk, filename2, buf1, quiet); } if (ret) { - if (ret < 0) { - error_report("Error while reading offset %" PRId64 ": %s", - sectors_to_bytes(sector_num), strerror(-ret)); - ret = 4; - } goto out; } } - sector_num += nb_sectors; - qemu_progress_print(((float) nb_sectors / progress_base)*100, 100); + offset += chunk; + qemu_progress_print(((float) chunk / progress_base) * 100, 100); } - if (total_sectors1 != total_sectors2) { + if (total_size1 != total_size2) { BlockBackend *blk_over; - int64_t total_sectors_over; const char *filename_over; qprintf(quiet, "Warning: Image size mismatch!\n"); - if (total_sectors1 > total_sectors2) { - total_sectors_over = total_sectors1; + if (total_size1 > total_size2) { blk_over = blk1; filename_over = filename1; } else { - total_sectors_over = total_sectors2; blk_over = blk2; filename_over = filename2; } - for (;;) { - int64_t count; - - nb_sectors = sectors_to_process(total_sectors_over, sector_num); - if (nb_sectors <= 0) { - break; - } - ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL, - sector_num * BDRV_SECTOR_SIZE, - nb_sectors * BDRV_SECTOR_SIZE, - &count); + while (offset < progress_base) { + ret = bdrv_block_status_above(blk_bs(blk_over), NULL, offset, + progress_base - offset, &chunk, + NULL, NULL); if (ret < 0) { ret = 3; error_report("Sector allocation test failed for %s", @@ -1504,25 +1491,16 @@ static int img_compare(int argc, char **argv) goto out; } - /* TODO relax this once bdrv_is_allocated_above does not enforce - * sector alignment */ - assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)); - nb_sectors = count >> BDRV_SECTOR_BITS; - if (ret) { - ret = check_empty_sectors(blk_over, sector_num, nb_sectors, + if (ret & BDRV_BLOCK_ALLOCATED && !(ret & BDRV_BLOCK_ZERO)) { + chunk = MIN(chunk, IO_BUF_SIZE); + ret = check_empty_sectors(blk_over, offset, chunk, filename_over, buf1, quiet); if (ret) { - if (ret < 0) { - error_report("Error while reading offset %" PRId64 - " of %s: %s", sectors_to_bytes(sector_num), - filename_over, strerror(-ret)); - ret = 4; - } goto out; } } - sector_num += nb_sectors; - qemu_progress_print(((float) nb_sectors / progress_base)*100, 100); + offset += chunk; + qemu_progress_print(((float) chunk / progress_base) * 100, 100); } } @@ -1590,8 +1568,8 @@ static void convert_select_part(ImgConvertState *s, int64_t sector_num, static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) { - int64_t ret, src_cur_offset; - int n, src_cur; + int64_t src_cur_offset; + int ret, n, src_cur; convert_select_part(s, sector_num, &src_cur, &src_cur_offset); @@ -1599,19 +1577,24 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS); if (s->sector_next_status <= sector_num) { - BlockDriverState *file; + int64_t count = n * BDRV_SECTOR_SIZE; + if (s->target_has_backing) { - ret = bdrv_get_block_status(blk_bs(s->src[src_cur]), - sector_num - src_cur_offset, - n, &n, &file); + + ret = bdrv_block_status(blk_bs(s->src[src_cur]), + (sector_num - src_cur_offset) * + BDRV_SECTOR_SIZE, + count, &count, NULL, NULL); } else { - ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL, - sector_num - src_cur_offset, - n, &n, &file); + ret = bdrv_block_status_above(blk_bs(s->src[src_cur]), NULL, + (sector_num - src_cur_offset) * + BDRV_SECTOR_SIZE, + count, &count, NULL, NULL); } if (ret < 0) { return ret; } + n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE); if (ret & BDRV_BLOCK_ZERO) { s->status = BLK_ZERO; @@ -2673,13 +2656,14 @@ static void dump_map_entry(OutputFormat output_format, MapEntry *e, } } -static int get_block_status(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, MapEntry *e) +static int get_block_status(BlockDriverState *bs, int64_t offset, + int64_t bytes, MapEntry *e) { - int64_t ret; + int ret; int depth; BlockDriverState *file; bool has_offset; + int64_t map; /* As an optimization, we could cache the current range of unallocated * clusters in each file of the chain, and avoid querying the same @@ -2688,12 +2672,11 @@ static int get_block_status(BlockDriverState *bs, int64_t sector_num, depth = 0; for (;;) { - ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &nb_sectors, - &file); + ret = bdrv_block_status(bs, offset, bytes, &bytes, &map, &file); if (ret < 0) { return ret; } - assert(nb_sectors); + assert(bytes); if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) { break; } @@ -2709,11 +2692,11 @@ static int get_block_status(BlockDriverState *bs, int64_t sector_num, has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID); *e = (MapEntry) { - .start = sector_num * BDRV_SECTOR_SIZE, - .length = nb_sectors * BDRV_SECTOR_SIZE, + .start = offset, + .length = bytes, .data = !!(ret & BDRV_BLOCK_DATA), .zero = !!(ret & BDRV_BLOCK_ZERO), - .offset = ret & BDRV_BLOCK_OFFSET_MASK, + .offset = map, .has_offset = has_offset, .depth = depth, .has_filename = file && has_offset, @@ -2839,16 +2822,12 @@ static int img_map(int argc, char **argv) length = blk_getlength(blk); while (curr.start + curr.length < length) { - int64_t nsectors_left; - int64_t sector_num; - int n; - - sector_num = (curr.start + curr.length) >> BDRV_SECTOR_BITS; + int64_t offset = curr.start + curr.length; + int64_t n; /* Probe up to 1 GiB at a time. */ - nsectors_left = DIV_ROUND_UP(length, BDRV_SECTOR_SIZE) - sector_num; - n = MIN(1 << (30 - BDRV_SECTOR_BITS), nsectors_left); - ret = get_block_status(bs, sector_num, n, &next); + n = QEMU_ALIGN_DOWN(MIN(1 << 30, length - offset), BDRV_SECTOR_SIZE); + ret = get_block_status(bs, offset, n, &next); if (ret < 0) { error_report("Could not read file metadata: %s", strerror(-ret)); @@ -3241,70 +3220,58 @@ static int img_rebase(int argc, char **argv) * the image is the same as the original one at any time. */ if (!unsafe) { - int64_t num_sectors; - int64_t old_backing_num_sectors; - int64_t new_backing_num_sectors = 0; - uint64_t sector; - int n; - int64_t count; + int64_t size; + int64_t old_backing_size; + int64_t new_backing_size = 0; + uint64_t offset; + int64_t n; float local_progress = 0; buf_old = blk_blockalign(blk, IO_BUF_SIZE); buf_new = blk_blockalign(blk, IO_BUF_SIZE); - num_sectors = blk_nb_sectors(blk); - if (num_sectors < 0) { + size = blk_getlength(blk); + if (size < 0) { error_report("Could not get size of '%s': %s", - filename, strerror(-num_sectors)); + filename, strerror(-size)); ret = -1; goto out; } - old_backing_num_sectors = blk_nb_sectors(blk_old_backing); - if (old_backing_num_sectors < 0) { + old_backing_size = blk_getlength(blk_old_backing); + if (old_backing_size < 0) { char backing_name[PATH_MAX]; bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); error_report("Could not get size of '%s': %s", - backing_name, strerror(-old_backing_num_sectors)); + backing_name, strerror(-old_backing_size)); ret = -1; goto out; } if (blk_new_backing) { - new_backing_num_sectors = blk_nb_sectors(blk_new_backing); - if (new_backing_num_sectors < 0) { + new_backing_size = blk_getlength(blk_new_backing); + if (new_backing_size < 0) { error_report("Could not get size of '%s': %s", - out_baseimg, strerror(-new_backing_num_sectors)); + out_baseimg, strerror(-new_backing_size)); ret = -1; goto out; } } - if (num_sectors != 0) { - local_progress = (float)100 / - (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512)); + if (size != 0) { + local_progress = (float)100 / (size / MIN(size, IO_BUF_SIZE)); } - for (sector = 0; sector < num_sectors; sector += n) { - - /* How many sectors can we handle with the next read? */ - if (sector + (IO_BUF_SIZE / 512) <= num_sectors) { - n = (IO_BUF_SIZE / 512); - } else { - n = num_sectors - sector; - } + for (offset = 0; offset < size; offset += n) { + /* How many bytes can we handle with the next read? */ + n = MIN(IO_BUF_SIZE, size - offset); /* If the cluster is allocated, we don't need to take action */ - ret = bdrv_is_allocated(bs, sector << BDRV_SECTOR_BITS, - n << BDRV_SECTOR_BITS, &count); + ret = bdrv_is_allocated(bs, offset, n, &n); if (ret < 0) { error_report("error while reading image metadata: %s", strerror(-ret)); goto out; } - /* TODO relax this once bdrv_is_allocated does not enforce - * sector alignment */ - assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)); - n = count >> BDRV_SECTOR_BITS; if (ret) { continue; } @@ -3313,30 +3280,28 @@ static int img_rebase(int argc, char **argv) * Read old and new backing file and take into consideration that * backing files may be smaller than the COW image. */ - if (sector >= old_backing_num_sectors) { - memset(buf_old, 0, n * BDRV_SECTOR_SIZE); + if (offset >= old_backing_size) { + memset(buf_old, 0, n); } else { - if (sector + n > old_backing_num_sectors) { - n = old_backing_num_sectors - sector; + if (offset + n > old_backing_size) { + n = old_backing_size - offset; } - ret = blk_pread(blk_old_backing, sector << BDRV_SECTOR_BITS, - buf_old, n << BDRV_SECTOR_BITS); + ret = blk_pread(blk_old_backing, offset, buf_old, n); if (ret < 0) { error_report("error while reading from old backing file"); goto out; } } - if (sector >= new_backing_num_sectors || !blk_new_backing) { - memset(buf_new, 0, n * BDRV_SECTOR_SIZE); + if (offset >= new_backing_size || !blk_new_backing) { + memset(buf_new, 0, n); } else { - if (sector + n > new_backing_num_sectors) { - n = new_backing_num_sectors - sector; + if (offset + n > new_backing_size) { + n = new_backing_size - offset; } - ret = blk_pread(blk_new_backing, sector << BDRV_SECTOR_BITS, - buf_new, n << BDRV_SECTOR_BITS); + ret = blk_pread(blk_new_backing, offset, buf_new, n); if (ret < 0) { error_report("error while reading from new backing file"); goto out; @@ -3347,15 +3312,13 @@ static int img_rebase(int argc, char **argv) uint64_t written = 0; while (written < n) { - int pnum; + int64_t pnum; - if (compare_sectors(buf_old + written * 512, - buf_new + written * 512, n - written, &pnum)) + if (compare_buffers(buf_old + written, buf_new + written, + n - written, &pnum)) { - ret = blk_pwrite(blk, - (sector + written) << BDRV_SECTOR_BITS, - buf_old + written * 512, - pnum << BDRV_SECTOR_BITS, 0); + ret = blk_pwrite(blk, offset + written, + buf_old + written, pnum, 0); if (ret < 0) { error_report("Error while writing to COW image: %s", strerror(-ret)); diff --git a/qemu-img.texi b/qemu-img.texi index ee5c5940d3..fdcf120f36 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -274,11 +274,10 @@ If the backing chain of the given image file @var{filename} has more than one layer, the backing file into which the changes will be committed may be specified as @var{base} (which has to be part of @var{filename}'s backing chain). If @var{base} is not specified, the immediate backing file of the top -image (which is @var{filename}) will be used. For reasons of consistency, -explicitly specifying @var{base} will always imply @code{-d} (since emptying an -image after committing to an indirect backing file would lead to different data -being read from the image due to content in the intermediate backing chain -overruling the commit target). +image (which is @var{filename}) will be used. Note that after a commit operation +all images between @var{base} and the top image will be invalid and may return +garbage data when read. For this reason, @code{-b} implies @code{-d} (so that +the top image stays valid). @item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2} diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 3727fb43f3..de8e3de726 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1769,10 +1769,6 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv) if (offset < 0) { print_cvtnum_err(offset, argv[1]); return 0; - } else if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) { - printf("%" PRId64 " is not a sector-aligned value for 'offset'\n", - offset); - return 0; } if (argc == 3) { @@ -1780,19 +1776,10 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv) if (count < 0) { print_cvtnum_err(count, argv[2]); return 0; - } else if (count > INT_MAX * BDRV_SECTOR_SIZE) { - printf("length argument cannot exceed %llu, given %s\n", - INT_MAX * BDRV_SECTOR_SIZE, argv[2]); - return 0; } } else { count = BDRV_SECTOR_SIZE; } - if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) { - printf("%" PRId64 " is not a sector-aligned value for 'count'\n", - count); - return 0; - } remaining = count; sum_alloc = 0; diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index ee9595f0da..9d561ef786 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -56,7 +56,7 @@ _filter_qmp_events() function run_qemu() { do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \ - | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' \ + | _filter_actual_image_size \ | _filter_generated_node_ids | _filter_qmp_events } diff --git a/tests/qemu-iotests/074.out b/tests/qemu-iotests/074.out index 8fba5aea9c..ede66c3f81 100644 --- a/tests/qemu-iotests/074.out +++ b/tests/qemu-iotests/074.out @@ -4,7 +4,6 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 wrote 512/512 bytes at offset 512 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error -qemu-img: Error while reading offset 0: Input/output error 4 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0 @@ -12,7 +11,6 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0 wrote 512/512 bytes at offset 512 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error -qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error Warning: Image size mismatch! 4 Cleanup diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087 index f8e4903f4f..27ab6c5151 100755 --- a/tests/qemu-iotests/087 +++ b/tests/qemu-iotests/087 @@ -46,7 +46,7 @@ function run_qemu() { do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ | _filter_qemu | _filter_imgfmt \ - | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' + | _filter_actual_image_size } size=128M diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 index 9424313e82..c20c71570c 100755 --- a/tests/qemu-iotests/125 +++ b/tests/qemu-iotests/125 @@ -69,13 +69,15 @@ fi # in B CREATION_SIZE=$((2 * 1024 * 1024 - 48 * 1024)) +# 512 is the actual test -- but it's good to test 64k as well, just to be sure. +for cluster_size in 512 64k; do # in kB for GROWTH_SIZE in 16 48 80; do for create_mode in off metadata falloc full; do for growth_mode in off metadata falloc full; do - echo "--- growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---" + echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---" - IMGOPTS="preallocation=$create_mode,cluster_size=512" _make_test_img ${CREATION_SIZE} + IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE} $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K host_size_0=$(get_image_size_on_host) @@ -123,6 +125,7 @@ for GROWTH_SIZE in 16 48 80; do done done done +done # success, all done echo '*** done' diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out index 3f4d6e31a6..596905f533 100644 --- a/tests/qemu-iotests/125.out +++ b/tests/qemu-iotests/125.out @@ -1,5 +1,5 @@ QA output created by 125 ---- growth_size=16 create_mode=off growth_mode=off --- +--- cluster_size=512 growth_size=16 create_mode=off growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -7,7 +7,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=off growth_mode=metadata --- +--- cluster_size=512 growth_size=16 create_mode=off growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -15,7 +15,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=off growth_mode=falloc --- +--- cluster_size=512 growth_size=16 create_mode=off growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -23,7 +23,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=off growth_mode=full --- +--- cluster_size=512 growth_size=16 create_mode=off growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -31,7 +31,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=metadata growth_mode=off --- +--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -39,7 +39,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=metadata growth_mode=metadata --- +--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -47,7 +47,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=metadata growth_mode=falloc --- +--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -55,7 +55,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=metadata growth_mode=full --- +--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -63,7 +63,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=falloc growth_mode=off --- +--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -71,7 +71,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=falloc growth_mode=metadata --- +--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -79,7 +79,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=falloc growth_mode=falloc --- +--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -87,7 +87,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=falloc growth_mode=full --- +--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -95,7 +95,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=full growth_mode=off --- +--- cluster_size=512 growth_size=16 create_mode=full growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -103,7 +103,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=full growth_mode=metadata --- +--- cluster_size=512 growth_size=16 create_mode=full growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -111,7 +111,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=full growth_mode=falloc --- +--- cluster_size=512 growth_size=16 create_mode=full growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -119,7 +119,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=16 create_mode=full growth_mode=full --- +--- cluster_size=512 growth_size=16 create_mode=full growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -127,7 +127,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 16384/16384 bytes at offset 2048000 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=off growth_mode=off --- +--- cluster_size=512 growth_size=48 create_mode=off growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -135,7 +135,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=off growth_mode=metadata --- +--- cluster_size=512 growth_size=48 create_mode=off growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -143,7 +143,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=off growth_mode=falloc --- +--- cluster_size=512 growth_size=48 create_mode=off growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -151,7 +151,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=off growth_mode=full --- +--- cluster_size=512 growth_size=48 create_mode=off growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -159,7 +159,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=metadata growth_mode=off --- +--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -167,7 +167,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=metadata growth_mode=metadata --- +--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -175,7 +175,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=metadata growth_mode=falloc --- +--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -183,7 +183,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=metadata growth_mode=full --- +--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -191,7 +191,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=falloc growth_mode=off --- +--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -199,7 +199,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=falloc growth_mode=metadata --- +--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -207,7 +207,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=falloc growth_mode=falloc --- +--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -215,7 +215,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=falloc growth_mode=full --- +--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -223,7 +223,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=full growth_mode=off --- +--- cluster_size=512 growth_size=48 create_mode=full growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -231,7 +231,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=full growth_mode=metadata --- +--- cluster_size=512 growth_size=48 create_mode=full growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -239,7 +239,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=full growth_mode=falloc --- +--- cluster_size=512 growth_size=48 create_mode=full growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -247,7 +247,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=48 create_mode=full growth_mode=full --- +--- cluster_size=512 growth_size=48 create_mode=full growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -255,7 +255,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 49152/49152 bytes at offset 2048000 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=off growth_mode=off --- +--- cluster_size=512 growth_size=80 create_mode=off growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -263,7 +263,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=off growth_mode=metadata --- +--- cluster_size=512 growth_size=80 create_mode=off growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -271,7 +271,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=off growth_mode=falloc --- +--- cluster_size=512 growth_size=80 create_mode=off growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -279,7 +279,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=off growth_mode=full --- +--- cluster_size=512 growth_size=80 create_mode=off growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -287,7 +287,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=metadata growth_mode=off --- +--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -295,7 +295,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=metadata growth_mode=metadata --- +--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -303,7 +303,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=metadata growth_mode=falloc --- +--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -311,7 +311,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=metadata growth_mode=full --- +--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -319,7 +319,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=falloc growth_mode=off --- +--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -327,7 +327,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=falloc growth_mode=metadata --- +--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -335,7 +335,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=falloc growth_mode=falloc --- +--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -343,7 +343,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=falloc growth_mode=full --- +--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -351,7 +351,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=full growth_mode=off --- +--- cluster_size=512 growth_size=80 create_mode=full growth_mode=off --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -359,7 +359,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=full growth_mode=metadata --- +--- cluster_size=512 growth_size=80 create_mode=full growth_mode=metadata --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -367,7 +367,7 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=full growth_mode=falloc --- +--- cluster_size=512 growth_size=80 create_mode=full growth_mode=falloc --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 @@ -375,7 +375,391 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ---- growth_size=80 create_mode=full growth_mode=full --- +--- cluster_size=512 growth_size=80 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=16 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=48 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- cluster_size=64k growth_size=80 create_mode=full growth_mode=full --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full Image resized. wrote 2048000/2048000 bytes at offset 0 diff --git a/tests/qemu-iotests/127 b/tests/qemu-iotests/127 new file mode 100755 index 0000000000..9e0d7d3be8 --- /dev/null +++ b/tests/qemu-iotests/127 @@ -0,0 +1,97 @@ +#!/bin/bash +# +# Test case for mirroring with dataplane +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=mreitz@redhat.com + +seq=$(basename $0) +echo "QA output created by $seq" + +here=$PWD +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_qemu + _cleanup_test_img + _rm_test_img "$TEST_IMG.overlay0" + _rm_test_img "$TEST_IMG.overlay1" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and qemu instance handling +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +IMG_SIZE=64K + +_make_test_img $IMG_SIZE +TEST_IMG="$TEST_IMG.overlay0" _make_test_img -b "$TEST_IMG" $IMG_SIZE +TEST_IMG="$TEST_IMG.overlay1" _make_test_img -b "$TEST_IMG" $IMG_SIZE + +# So that we actually have something to mirror and the job does not return +# immediately (which may be bad because then we cannot know whether the +# 'return' or the 'BLOCK_JOB_READY' comes first). +$QEMU_IO -c 'write 0 42' "$TEST_IMG.overlay0" | _filter_qemu_io + +# We cannot use virtio-blk here because that does not actually set the attached +# BB's AioContext in qtest mode +_launch_qemu \ + -object iothread,id=iothr \ + -blockdev node-name=source,driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG.overlay0" \ + -device virtio-scsi,id=scsi-bus,iothread=iothr \ + -device scsi-hd,bus=scsi-bus.0,drive=source + +_send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'qmp_capabilities' }" \ + 'return' + +_send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'drive-mirror', + 'arguments': { + 'job-id': 'mirror', + 'device': 'source', + 'target': '$TEST_IMG.overlay1', + 'mode': 'existing', + 'sync': 'top' + } }" \ + 'BLOCK_JOB_READY' + +# The backing BDS should be assigned the overlay's AioContext +_send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'block-job-complete', + 'arguments': { 'device': 'mirror' } }" \ + 'BLOCK_JOB_COMPLETED' + +_send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'quit' }" \ + 'return' + +wait=yes _cleanup_qemu + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out new file mode 100644 index 0000000000..543d075005 --- /dev/null +++ b/tests/qemu-iotests/127.out @@ -0,0 +1,14 @@ +QA output created by 127 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +Formatting 'TEST_DIR/t.IMGFMT.overlay0', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT +wrote 42/42 bytes at offset 0 +42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +*** done diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177 index f8ed8fb86b..28990977f1 100755 --- a/tests/qemu-iotests/177 +++ b/tests/qemu-iotests/177 @@ -51,7 +51,7 @@ echo "== setting up files ==" TEST_IMG="$TEST_IMG.base" _make_test_img $size $QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io _make_test_img -b "$TEST_IMG.base" -$QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io # Limited to 64k max-transfer echo @@ -81,6 +81,13 @@ limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-disca $QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \ -c "discard 80000001 30M" | _filter_qemu_io +echo +echo "== block status smaller than alignment ==" +limits=align=4k +$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \ + -c "alloc 1 1" -c "alloc 0x6dffff0 1000" -c "alloc 127m 5P" \ + -c map | _filter_qemu_io + echo echo "== verify image content ==" @@ -103,7 +110,8 @@ function verify_io() echo read -P 0 32M 32M echo read -P 22 64M 13M echo read -P $discarded 77M 29M - echo read -P 22 106M 22M + echo read -P 22 106M 4M + echo read -P 11 110M 18M } verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out index 43a777836c..f788b55e20 100644 --- a/tests/qemu-iotests/177.out +++ b/tests/qemu-iotests/177.out @@ -5,8 +5,8 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base -wrote 134217728/134217728 bytes at offset 0 -128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 115343360/115343360 bytes at offset 0 +110 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == constrained alignment and max-transfer == wrote 131072/131072 bytes at offset 1000 @@ -26,6 +26,13 @@ wrote 33554432/33554432 bytes at offset 33554432 discard 31457280/31457280 bytes at offset 80000001 30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== block status smaller than alignment == +1/1 bytes allocated at offset 1 bytes +16/1000 bytes allocated at offset 110 MiB +0/1048576 bytes allocated at offset 127 MiB +110 MiB (0x6e00000) bytes allocated at offset 0 bytes (0x0) +18 MiB (0x1200000) bytes not allocated at offset 110 MiB (0x6e00000) + == verify image content == read 1000/1000 bytes at offset 0 1000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -43,12 +50,14 @@ read 13631488/13631488 bytes at offset 67108864 13 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 30408704/30408704 bytes at offset 80740352 29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 23068672/23068672 bytes at offset 111149056 -22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4194304/4194304 bytes at offset 111149056 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 18874368/18874368 bytes at offset 115343360 +18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File 0 0x800000 TEST_DIR/t.IMGFMT 0x900000 0x2400000 TEST_DIR/t.IMGFMT 0x3c00000 0x1100000 TEST_DIR/t.IMGFMT -0x6a00000 0x1600000 TEST_DIR/t.IMGFMT +0x6a00000 0x400000 TEST_DIR/t.IMGFMT No errors were found on the image. *** done diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184 index 704f38f936..ee96c99af3 100755 --- a/tests/qemu-iotests/184 +++ b/tests/qemu-iotests/184 @@ -51,7 +51,8 @@ function do_run_qemu() function run_qemu() { do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\ - | _filter_qemu_io | _filter_generated_node_ids + | _filter_qemu_io | _filter_generated_node_ids \ + | _filter_actual_image_size } _make_test_img 64M diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out index 0aed1a2220..4dc7984a85 100644 --- a/tests/qemu-iotests/184.out +++ b/tests/qemu-iotests/184.out @@ -32,7 +32,7 @@ Testing: "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}", "cluster-size": 65536, "format": "throttle", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -62,7 +62,7 @@ Testing: "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -100,7 +100,7 @@ Testing: "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191 index ac2b88fd78..ad785e10b1 100755 --- a/tests/qemu-iotests/191 +++ b/tests/qemu-iotests/191 @@ -56,7 +56,8 @@ echo === Preparing and starting VM === echo TEST_IMG="${TEST_IMG}.base" _make_test_img $size -TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base" +IMGOPTS=$(_optstr_add "$IMGOPTS" "backing_fmt=$IMGFMT") \ + TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base" _make_test_img -b "${TEST_IMG}.mid" TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid" @@ -91,7 +92,7 @@ echo === Check that both top and top2 point to base now === echo _send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" | - _filter_generated_node_ids + _filter_generated_node_ids | _filter_actual_image_size _send_qemu_cmd $h "{ 'execute': 'quit' }" "^}" wait=1 _cleanup_qemu @@ -139,7 +140,7 @@ echo === Check that both top and top2 point to base now === echo _send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" | - _filter_generated_node_ids + _filter_generated_node_ids | _filter_actual_image_size _send_qemu_cmd $h "{ 'execute': 'quit' }" "^}" wait=1 _cleanup_qemu diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out index 7bfcd2d5d8..73c0ed454c 100644 --- a/tests/qemu-iotests/191.out +++ b/tests/qemu-iotests/191.out @@ -3,7 +3,7 @@ QA output created by 191 === Preparing and starting VM === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid wrote 65536/65536 bytes at offset 1048576 @@ -47,7 +47,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -64,7 +64,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.ovl2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -105,7 +105,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2.ovl2", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -136,7 +136,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -153,7 +153,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -194,7 +194,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -225,7 +225,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -242,7 +242,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.mid", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -283,7 +283,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 393216, "filename": "TEST_DIR/t.qcow2.mid", "format": "file", - "actual-size": 397312, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -313,7 +313,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -351,7 +351,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 393216, "filename": "TEST_DIR/t.qcow2.base", "format": "file", - "actual-size": 397312, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -450,7 +450,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -467,7 +467,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.ovl2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -508,7 +508,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2.ovl2", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -540,7 +540,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -557,7 +557,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.ovl2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -576,7 +576,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.ovl3", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -617,7 +617,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2.ovl3", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -647,7 +647,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -685,7 +685,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 393216, "filename": "TEST_DIR/t.qcow2.base", "format": "file", - "actual-size": 397312, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, @@ -716,7 +716,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2.base", "cluster-size": 65536, "format": "qcow2", - "actual-size": 397312, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -733,7 +733,7 @@ wrote 65536/65536 bytes at offset 1048576 "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", - "actual-size": 200704, + "actual-size": SIZE, "format-specific": { "type": "qcow2", "data": { @@ -774,7 +774,7 @@ wrote 65536/65536 bytes at offset 1048576 "virtual-size": 197120, "filename": "TEST_DIR/t.qcow2", "format": "file", - "actual-size": 200704, + "actual-size": SIZE, "dirty-flag": false }, "iops_wr": 0, diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 227b37e941..873ca6b104 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -105,6 +105,12 @@ _filter_block_job_len() sed -e 's/, "len": [0-9]\+,/, "len": LEN,/g' } +# replace actual image size (depends on the host filesystem) +_filter_actual_image_size() +{ + sed -s 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' +} + # replace driver-specific options in the "Formatting..." line _filter_img_create() { diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 83da427c0a..24e5ad1b79 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -133,6 +133,7 @@ 124 rw auto backing 125 rw auto 126 rw auto backing +127 rw auto backing quick 128 rw auto quick 129 rw auto quick 130 rw auto quick