summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile15
-rw-r--r--block.c3
-rw-r--r--block/blkdebug.c13
-rw-r--r--block/io.c334
-rw-r--r--block/mirror.c26
-rw-r--r--block/qcow2-cluster.c2
-rw-r--r--block/qcow2.c116
-rw-r--r--block/trace-events2
m---------capstone0
-rwxr-xr-xconfigure74
-rw-r--r--disas.c308
-rw-r--r--disas/arm.c21
-rw-r--r--hw/block/xen_disk.c34
-rw-r--r--hw/i386/xen/xen-hvm.c2
-rw-r--r--hw/xen/xen_backend.c11
-rw-r--r--include/block/block.h29
-rw-r--r--include/block/block_int.h11
-rw-r--r--include/disas/bfd.h11
-rw-r--r--include/disas/capstone.h38
-rw-r--r--include/disas/disas.h4
-rw-r--r--include/exec/log.h4
-rw-r--r--include/hw/xen/xen_backend.h1
-rw-r--r--monitor.c29
-rw-r--r--qemu-img.c381
-rw-r--r--qemu-img.texi9
-rw-r--r--qemu-io-cmds.c13
-rw-r--r--qga/commands-posix.c74
-rw-r--r--qga/commands-win32.c86
-rw-r--r--qga/qapi-schema.json38
-rw-r--r--qga/vss-win32/install.cpp13
-rw-r--r--qga/vss-win32/requester.cpp12
-rw-r--r--target/alpha/translate.c2
-rw-r--r--target/arm/cpu.c49
-rw-r--r--target/arm/translate-a64.c3
-rw-r--r--target/arm/translate.c3
-rw-r--r--target/cris/translate.c3
-rw-r--r--target/hppa/translate.c2
-rw-r--r--target/i386/cpu.c19
-rw-r--r--target/i386/translate.c8
-rw-r--r--target/lm32/translate.c2
-rw-r--r--target/m68k/translate.c2
-rw-r--r--target/microblaze/translate.c2
-rw-r--r--target/mips/translate.c2
-rw-r--r--target/nios2/translate.c2
-rw-r--r--target/openrisc/translate.c2
-rw-r--r--target/ppc/translate.c5
-rw-r--r--target/ppc/translate_init.c29
-rw-r--r--target/s390x/translate.c2
-rw-r--r--target/sh4/translate.c2
-rw-r--r--target/sparc/translate.c2
-rw-r--r--target/tricore/translate.c2
-rw-r--r--target/unicore32/translate.c2
-rw-r--r--target/xtensa/translate.c2
-rwxr-xr-xtests/qemu-iotests/0672
-rw-r--r--tests/qemu-iotests/074.out2
-rwxr-xr-xtests/qemu-iotests/0872
-rwxr-xr-xtests/qemu-iotests/1257
-rw-r--r--tests/qemu-iotests/125.out480
-rwxr-xr-xtests/qemu-iotests/12797
-rw-r--r--tests/qemu-iotests/127.out14
-rwxr-xr-xtests/qemu-iotests/17712
-rw-r--r--tests/qemu-iotests/177.out19
-rwxr-xr-xtests/qemu-iotests/1843
-rw-r--r--tests/qemu-iotests/184.out6
-rwxr-xr-xtests/qemu-iotests/1917
-rw-r--r--tests/qemu-iotests/191.out48
-rw-r--r--tests/qemu-iotests/common.filter6
-rw-r--r--tests/qemu-iotests/group1
69 files changed, 1817 insertions, 753 deletions
diff --git a/.gitmodules b/.gitmodules
index 7c981a42b6..1500579638 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -37,3 +37,6 @@
[submodule "ui/keycodemapdb"]
path = ui/keycodemapdb
url = git://git.qemu.org/keycodemapdb.git
+[submodule "capstone"]
+ path = capstone
+ url = git://git.qemu.org/capstone.git
diff --git a/Makefile b/Makefile
index 9372742f86..ec73acfa9a 100644
--- a/Makefile
+++ b/Makefile
@@ -383,6 +383,21 @@ subdir-dtc: .git-submodule-status dtc/libfdt dtc/tests
dtc/%: .git-submodule-status
mkdir -p $@
+# Overriding CFLAGS causes us to lose defines added in the sub-makefile.
+# Not overriding CFLAGS leads to mis-matches between compilation modes.
+# Therefore we replicate some of the logic in the sub-makefile.
+# Remove all the extra -Warning flags that QEMU uses that Capstone doesn't;
+# no need to annoy QEMU developers with such things.
+CAP_CFLAGS = $(patsubst -W%,,$(CFLAGS) $(QEMU_CFLAGS))
+CAP_CFLAGS += -DCAPSTONE_USE_SYS_DYN_MEM
+CAP_CFLAGS += -DCAPSTONE_HAS_ARM
+CAP_CFLAGS += -DCAPSTONE_HAS_ARM64
+CAP_CFLAGS += -DCAPSTONE_HAS_POWERPC
+CAP_CFLAGS += -DCAPSTONE_HAS_X86
+
+subdir-capstone: .git-submodule-status
+ $(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
+
$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
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
- * BDRV_BLOCK_EOF and 'pnum' is set to 0.
+ * 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'.
*
- * '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.
+ * If 'offset' is beyond the end of the disk image the return value is
+ * BDRV_BLOCK_EOF and 'pnum' is set to 0.
*
- * '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)
-{
- int64_t total_sectors;
- int64_t n;
- int64_t ret, ret2;
+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_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(&params);
+ } else {
+ Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
+ 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;
-
- 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;
-
- ret = bdrv_get_block_status_above(in_bs, NULL,
- offset >> BDRV_SECTOR_BITS,
- nb_sectors,
- &pnum, &file);
+ int64_t pnum = 0;
+
+ for (offset = 0; offset < ssize; offset += pnum) {
+ int ret;
+
+ 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/capstone b/capstone
new file mode 160000
+Subproject 22ead3e0bfdb87516656453336160e0a37b066b
diff --git a/configure b/configure
index 03547cea6a..285d123dbf 100755
--- a/configure
+++ b/configure
@@ -375,6 +375,7 @@ opengl_dmabuf="no"
cpuid_h="no"
avx2_opt="no"
zlib="yes"
+capstone=""
lzo=""
snappy=""
bzip2=""
@@ -827,7 +828,7 @@ if test "$mingw32" = "yes" ; then
sysconfdir="\${prefix}"
local_statedir=
confsuffix=""
- libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 $libs_qga"
+ libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -lwininet -liphlpapi -lnetapi32 $libs_qga"
fi
werror=""
@@ -1294,6 +1295,14 @@ for opt do
error_exit "vhost-user isn't available on win32"
fi
;;
+ --disable-capstone) capstone="no"
+ ;;
+ --enable-capstone) capstone="yes"
+ ;;
+ --enable-capstone=git) capstone="git"
+ ;;
+ --enable-capstone=system) capstone="system"
+ ;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -1541,6 +1550,7 @@ disabled with --disable-FEATURE, default is enabled if available:
vxhs Veritas HyperScale vDisk backend support
crypto-afalg Linux AF_ALG crypto backend driver
vhost-user vhost-user support
+ capstone capstone disassembler support
NOTE: The object files are built at the place where configure is launched
EOF
@@ -4411,6 +4421,58 @@ EOF
fi
##########################################
+# capstone
+
+case "$capstone" in
+ "" | yes)
+ if $pkg_config capstone; then
+ capstone=system
+ elif test -e "${source_path}/.git" ; then
+ capstone=git
+ elif test -e "${source_path}/capstone/Makefile" ; then
+ capstone=internal
+ elif test -z "$capstone" ; then
+ capstone=no
+ else
+ feature_not_found "capstone" "Install capstone devel or git submodule"
+ fi
+ ;;
+
+ system)
+ if ! $pkg_config capstone; then
+ feature_not_found "capstone" "Install capstone devel"
+ fi
+ ;;
+esac
+
+case "$capstone" in
+ git | internal)
+ if test "$capstone" = git; then
+ git_submodules="${git_submodules} capstone"
+ fi
+ mkdir -p capstone
+ QEMU_CFLAGS="$QEMU_CFLAGS -I\$(SRC_PATH)/capstone/include"
+ if test "$mingw32" = "yes"; then
+ LIBCAPSTONE=capstone.lib
+ else
+ LIBCAPSTONE=libcapstone.a
+ fi
+ LIBS="-L\$(BUILD_DIR)/capstone -lcapstone $LIBS"
+ ;;
+
+ system)
+ QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags capstone)"
+ LIBS="$($pkg_config --libs capstone) $LIBS"
+ ;;
+
+ no)
+ ;;
+ *)
+ error_exit "Unknown state for capstone: $capstone"
+ ;;
+esac
+
+##########################################
# check if we have fdatasync
fdatasync=no
@@ -5468,6 +5530,7 @@ echo "jemalloc support $jemalloc"
echo "avx2 optimization $avx2_opt"
echo "replication support $replication"
echo "VxHS block device $vxhs"
+echo "capstone $capstone"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -6142,6 +6205,9 @@ fi
if test "$ivshmem" = "yes" ; then
echo "CONFIG_IVSHMEM=y" >> $config_host_mak
fi
+if test "$capstone" != "no" ; then
+ echo "CONFIG_CAPSTONE=y" >> $config_host_mak
+fi
# Hold two types of flag:
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
@@ -6624,6 +6690,12 @@ done # for target in $targets
if [ "$dtc_internal" = "yes" ]; then
echo "config-host.h: subdir-dtc" >> $config_host_mak
fi
+if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then
+ echo "config-host.h: subdir-capstone" >> $config_host_mak
+fi
+if test -n "$LIBCAPSTONE"; then
+ echo "LIBCAPSTONE=$LIBCAPSTONE" >> $config_host_mak
+fi
if test "$numa" = "yes"; then
echo "CONFIG_NUMA=y" >> $config_host_mak
diff --git a/disas.c b/disas.c
index 54eea3f9c9..92b389d25f 100644
--- a/disas.c
+++ b/disas.c
@@ -6,6 +6,7 @@
#include "cpu.h"
#include "disas/disas.h"
+#include "disas/capstone.h"
typedef struct CPUDebug {
struct disassemble_info info;
@@ -171,15 +172,195 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
return print_insn_objdump(pc, info, "OBJD-T");
}
-/* Disassemble this for me please... (debugging). 'flags' has the following
- values:
- i386 - 1 means 16 bit code, 2 means 64 bit code
- ppc - bits 0:15 specify (optionally) the machine instruction set;
- bit 16 indicates little endian.
- other targets - unused
- */
+#ifdef CONFIG_CAPSTONE
+/* Temporary storage for the capstone library. This will be alloced via
+ malloc with a size private to the library; thus there's no reason not
+ to share this across calls and across host vs target disassembly. */
+static __thread cs_insn *cap_insn;
+
+/* Initialize the Capstone library. */
+/* ??? It would be nice to cache this. We would need one handle for the
+ host and one for the target. For most targets we can reset specific
+ parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change
+ CS_ARCH_* in this way. Thus we would need to be able to close and
+ re-open the target handle with a different arch for the target in order
+ to handle AArch64 vs AArch32 mode switching. */
+static cs_err cap_disas_start(disassemble_info *info, csh *handle)
+{
+ cs_mode cap_mode = info->cap_mode;
+ cs_err err;
+
+ cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
+ : CS_MODE_LITTLE_ENDIAN);
+
+ err = cs_open(info->cap_arch, cap_mode, handle);
+ if (err != CS_ERR_OK) {
+ return err;
+ }
+
+ /* ??? There probably ought to be a better place to put this. */
+ if (info->cap_arch == CS_ARCH_X86) {
+ /* We don't care about errors (if for some reason the library
+ is compiled without AT&T syntax); the user will just have
+ to deal with the Intel syntax. */
+ cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
+ }
+
+ /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
+ cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+
+ /* Allocate temp space for cs_disasm_iter. */
+ if (cap_insn == NULL) {
+ cap_insn = cs_malloc(*handle);
+ if (cap_insn == NULL) {
+ cs_close(handle);
+ return CS_ERR_MEM;
+ }
+ }
+ return CS_ERR_OK;
+}
+
+/* Disassemble SIZE bytes at PC for the target. */
+static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
+{
+ uint8_t cap_buf[1024];
+ csh handle;
+ cs_insn *insn;
+ size_t csize = 0;
+
+ if (cap_disas_start(info, &handle) != CS_ERR_OK) {
+ return false;
+ }
+ insn = cap_insn;
+
+ while (1) {
+ size_t tsize = MIN(sizeof(cap_buf) - csize, size);
+ const uint8_t *cbuf = cap_buf;
+
+ target_read_memory(pc + csize, cap_buf + csize, tsize, info);
+ csize += tsize;
+ size -= tsize;
+
+ while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
+ (*info->fprintf_func)(info->stream,
+ "0x%08" PRIx64 ": %-12s %s\n",
+ insn->address, insn->mnemonic,
+ insn->op_str);
+ }
+
+ /* If the target memory is not consumed, go back for more... */
+ if (size != 0) {
+ /* ... taking care to move any remaining fractional insn
+ to the beginning of the buffer. */
+ if (csize != 0) {
+ memmove(cap_buf, cbuf, csize);
+ }
+ continue;
+ }
+
+ /* Since the target memory is consumed, we should not have
+ a remaining fractional insn. */
+ if (csize != 0) {
+ (*info->fprintf_func)(info->stream,
+ "Disassembler disagrees with translator "
+ "over instruction decoding\n"
+ "Please report this to qemu-devel@nongnu.org\n");
+ }
+ break;
+ }
+
+ cs_close(&handle);
+ return true;
+}
+
+/* Disassemble SIZE bytes at CODE for the host. */
+static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
+{
+ csh handle;
+ const uint8_t *cbuf;
+ cs_insn *insn;
+ uint64_t pc;
+
+ if (cap_disas_start(info, &handle) != CS_ERR_OK) {
+ return false;
+ }
+ insn = cap_insn;
+
+ cbuf = code;
+ pc = (uintptr_t)code;
+
+ while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
+ (*info->fprintf_func)(info->stream,
+ "0x%08" PRIx64 ": %-12s %s\n",
+ insn->address, insn->mnemonic,
+ insn->op_str);
+ }
+ if (size != 0) {
+ (*info->fprintf_func)(info->stream,
+ "Disassembler disagrees with TCG over instruction encoding\n"
+ "Please report this to qemu-devel@nongnu.org\n");
+ }
+
+ cs_close(&handle);
+ return true;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+/* Disassemble COUNT insns at PC for the target. */
+static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
+{
+ uint8_t cap_buf[32];
+ csh handle;
+ cs_insn *insn;
+ size_t csize = 0;
+
+ if (cap_disas_start(info, &handle) != CS_ERR_OK) {
+ return false;
+ }
+ insn = cap_insn;
+
+ while (1) {
+ /* We want to read memory for one insn, but generically we do not
+ know how much memory that is. We have a small buffer which is
+ known to be sufficient for all supported targets. Try to not
+ read beyond the page, Just In Case. For even more simplicity,
+ ignore the actual target page size and use a 1k boundary. If
+ that turns out to be insufficient, we'll come back around the
+ loop and read more. */
+ uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
+ size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
+ const uint8_t *cbuf = cap_buf;
+
+ /* Make certain that we can make progress. */
+ assert(tsize != 0);
+ info->read_memory_func(pc, cap_buf + csize, tsize, info);
+ csize += tsize;
+
+ if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
+ (*info->fprintf_func)(info->stream,
+ "0x%08" PRIx64 ": %-12s %s\n",
+ insn->address, insn->mnemonic,
+ insn->op_str);
+ if (--count <= 0) {
+ break;
+ }
+ }
+ memmove(cap_buf, cbuf, csize);
+ }
+
+ cs_close(&handle);
+ return true;
+}
+#endif /* !CONFIG_USER_ONLY */
+#else
+# define cap_disas_target(i, p, s) false
+# define cap_disas_host(i, p, s) false
+# define cap_disas_monitor(i, p, c) false
+#endif /* CONFIG_CAPSTONE */
+
+/* Disassemble this for me please... (debugging). */
void target_disas(FILE *out, CPUState *cpu, target_ulong code,
- target_ulong size, int flags)
+ target_ulong size)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
target_ulong pc;
@@ -193,6 +374,8 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
s.info.buffer_vma = code;
s.info.buffer_length = size;
s.info.print_address_func = generic_print_address;
+ s.info.cap_arch = -1;
+ s.info.cap_mode = 0;
#ifdef TARGET_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
@@ -204,32 +387,10 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
cc->disas_set_info(cpu, &s.info);
}
-#if defined(TARGET_I386)
- if (flags == 2) {
- s.info.mach = bfd_mach_x86_64;
- } else if (flags == 1) {
- s.info.mach = bfd_mach_i386_i8086;
- } else {
- s.info.mach = bfd_mach_i386_i386;
- }
- s.info.print_insn = print_insn_i386;
-#elif defined(TARGET_PPC)
- if ((flags >> 16) & 1) {
- s.info.endian = BFD_ENDIAN_LITTLE;
- }
- if (flags & 0xFFFF) {
- /* If we have a precise definition of the instruction set, use it. */
- s.info.mach = flags & 0xFFFF;
- } else {
-#ifdef TARGET_PPC64
- s.info.mach = bfd_mach_ppc64;
-#else
- s.info.mach = bfd_mach_ppc;
-#endif
+ if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
+ return;
}
- s.info.disassembler_options = (char *)"any";
- s.info.print_insn = print_insn_ppc;
-#endif
+
if (s.info.print_insn == NULL) {
s.info.print_insn = print_insn_od_target;
}
@@ -237,18 +398,6 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
for (pc = code; size > 0; pc += count, size -= count) {
fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
count = s.info.print_insn(pc, &s.info);
-#if 0
- {
- int i;
- uint8_t b;
- fprintf(out, " {");
- for(i = 0; i < count; i++) {
- target_read_memory(pc + i, &b, 1, &s.info);
- fprintf(out, " %02x", b);
- }
- fprintf(out, " }");
- }
-#endif
fprintf(out, "\n");
if (count < 0)
break;
@@ -276,6 +425,8 @@ void disas(FILE *out, void *code, unsigned long size)
s.info.buffer = code;
s.info.buffer_vma = (uintptr_t)code;
s.info.buffer_length = size;
+ s.info.cap_arch = -1;
+ s.info.cap_mode = 0;
#ifdef HOST_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
@@ -287,14 +438,23 @@ void disas(FILE *out, void *code, unsigned long size)
#elif defined(__i386__)
s.info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
+ s.info.cap_arch = CS_ARCH_X86;
+ s.info.cap_mode = CS_MODE_32;
#elif defined(__x86_64__)
s.info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
+ s.info.cap_arch = CS_ARCH_X86;
+ s.info.cap_mode = CS_MODE_64;
#elif defined(_ARCH_PPC)
s.info.disassembler_options = (char *)"any";
print_insn = print_insn_ppc;
+ s.info.cap_arch = CS_ARCH_PPC;
+# ifdef _ARCH_PPC64
+ s.info.cap_mode = CS_MODE_64;
+# endif
#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
print_insn = print_insn_arm_a64;
+ s.info.cap_arch = CS_ARCH_ARM64;
#elif defined(__alpha__)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
@@ -302,6 +462,8 @@ void disas(FILE *out, void *code, unsigned long size)
s.info.mach = bfd_mach_sparc_v9b;
#elif defined(__arm__)
print_insn = print_insn_arm;
+ s.info.cap_arch = CS_ARCH_ARM;
+ /* TCG only generates code for arm mode. */
#elif defined(__MIPSEB__)
print_insn = print_insn_big_mips;
#elif defined(__MIPSEL__)
@@ -313,6 +475,11 @@ void disas(FILE *out, void *code, unsigned long size)
#elif defined(__hppa__)
print_insn = print_insn_hppa;
#endif
+
+ if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
+ return;
+ }
+
if (print_insn == NULL) {
print_insn = print_insn_od_host;
}
@@ -345,26 +512,17 @@ const char *lookup_symbol(target_ulong orig_addr)
#include "monitor/monitor.h"
-static int monitor_disas_is_physical;
-
static int
-monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
+physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info)
{
- CPUDebug *s = container_of(info, CPUDebug, info);
-
- if (monitor_disas_is_physical) {
- cpu_physical_memory_read(memaddr, myaddr, length);
- } else {
- cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
- }
+ cpu_physical_memory_read(memaddr, myaddr, length);
return 0;
}
-/* Disassembler for the monitor.
- See target_disas for a description of flags. */
+/* Disassembler for the monitor. */
void monitor_disas(Monitor *mon, CPUState *cpu,
- target_ulong pc, int nb_insn, int is_physical, int flags)
+ target_ulong pc, int nb_insn, int is_physical)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
int count, i;
@@ -373,11 +531,12 @@ void monitor_disas(Monitor *mon, CPUState *cpu,
INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
s.cpu = cpu;
- monitor_disas_is_physical = is_physical;
- s.info.read_memory_func = monitor_read_memory;
+ s.info.read_memory_func
+ = (is_physical ? physical_read_memory : target_read_memory);
s.info.print_address_func = generic_print_address;
-
s.info.buffer_vma = pc;
+ s.info.cap_arch = -1;
+ s.info.cap_mode = 0;
#ifdef TARGET_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
@@ -389,31 +548,10 @@ void monitor_disas(Monitor *mon, CPUState *cpu,
cc->disas_set_info(cpu, &s.info);
}
-#if defined(TARGET_I386)
- if (flags == 2) {
- s.info.mach = bfd_mach_x86_64;
- } else if (flags == 1) {
- s.info.mach = bfd_mach_i386_i8086;
- } else {
- s.info.mach = bfd_mach_i386_i386;
- }
- s.info.print_insn = print_insn_i386;
-#elif defined(TARGET_PPC)
- if (flags & 0xFFFF) {
- /* If we have a precise definition of the instruction set, use it. */
- s.info.mach = flags & 0xFFFF;
- } else {
-#ifdef TARGET_PPC64
- s.info.mach = bfd_mach_ppc64;
-#else
- s.info.mach = bfd_mach_ppc;
-#endif
- }
- if ((flags >> 16) & 1) {
- s.info.endian = BFD_ENDIAN_LITTLE;
+ if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
+ return;
}
- s.info.print_insn = print_insn_ppc;
-#endif
+
if (!s.info.print_insn) {
monitor_printf(mon, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", pc);
diff --git a/disas/arm.c b/disas/arm.c
index 27396dd3e1..9967c45990 100644
--- a/disas/arm.c
+++ b/disas/arm.c
@@ -70,6 +70,17 @@ static void floatformat_to_double (unsigned char *data, double *dest)
*dest = u.f;
}
+static int arm_read_memory(bfd_vma memaddr, bfd_byte *b, int length,
+ struct disassemble_info *info)
+{
+ assert((info->flags & INSN_ARM_BE32) == 0 || length == 2 || length == 4);
+
+ if ((info->flags & INSN_ARM_BE32) != 0 && length == 2) {
+ memaddr ^= 2;
+ }
+ return info->read_memory_func(memaddr, b, length, info);
+}
+
/* End of qemu specific additions. */
struct opcode32
@@ -3810,7 +3821,7 @@ find_ifthen_state (bfd_vma pc, struct disassemble_info *info,
return;
}
addr -= 2;
- status = info->read_memory_func (addr, (bfd_byte *)b, 2, info);
+ status = arm_read_memory (addr, (bfd_byte *)b, 2, info);
if (status)
return;
@@ -3882,7 +3893,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
info->bytes_per_chunk = size;
printer = print_insn_data;
- status = info->read_memory_func (pc, (bfd_byte *)b, size, info);
+ status = arm_read_memory (pc, (bfd_byte *)b, size, info);
given = 0;
if (little)
for (i = size - 1; i >= 0; i--)
@@ -3899,7 +3910,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
info->bytes_per_chunk = 4;
size = 4;
- status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
+ status = arm_read_memory (pc, (bfd_byte *)b, 4, info);
if (little)
given = (b[0]) | (b[1] << 8) | (b[2] << 16) | ((unsigned)b[3] << 24);
else
@@ -3915,7 +3926,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
info->bytes_per_chunk = 2;
size = 2;
- status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
+ status = arm_read_memory (pc, (bfd_byte *)b, 2, info);
if (little)
given = (b[0]) | (b[1] << 8);
else
@@ -3929,7 +3940,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
|| (given & 0xF800) == 0xF000
|| (given & 0xF800) == 0xE800)
{
- status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
+ status = arm_read_memory (pc + 2, (bfd_byte *)b, 2, info);
if (little)
given = (b[0]) | (b[1] << 8) | (given << 16);
else
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 536e2ee735..e431bd89e8 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -121,9 +121,6 @@ struct XenBlkDev {
unsigned int persistent_gnt_count;
unsigned int max_grants;
- /* Grant copy */
- gboolean feature_grant_copy;
-
/* qemu block driver */
DriveInfo *dinfo;
BlockBackend *blk;
@@ -616,7 +613,7 @@ static void qemu_aio_complete(void *opaque, int ret)
return;
}
- if (ioreq->blkdev->feature_grant_copy) {
+ if (xen_feature_grant_copy) {
switch (ioreq->req.operation) {
case BLKIF_OP_READ:
/* in case of failure ioreq->aio_errors is increased */
@@ -638,7 +635,7 @@ static void qemu_aio_complete(void *opaque, int ret)
}
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
- if (!ioreq->blkdev->feature_grant_copy) {
+ if (!xen_feature_grant_copy) {
ioreq_unmap(ioreq);
}
ioreq_finish(ioreq);
@@ -698,7 +695,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
{
struct XenBlkDev *blkdev = ioreq->blkdev;
- if (ioreq->blkdev->feature_grant_copy) {
+ if (xen_feature_grant_copy) {
ioreq_init_copy_buffers(ioreq);
if (ioreq->req.nr_segments && (ioreq->req.operation == BLKIF_OP_WRITE ||
ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE) &&
@@ -750,7 +747,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
}
default:
/* unknown operation (shouldn't happen -- parse catches this) */
- if (!ioreq->blkdev->feature_grant_copy) {
+ if (!xen_feature_grant_copy) {
ioreq_unmap(ioreq);
}
goto err;
@@ -1010,18 +1007,15 @@ static int blk_init(struct XenDevice *xendev)
blkdev->file_blk = BLOCK_SIZE;
- blkdev->feature_grant_copy =
- (xengnttab_grant_copy(blkdev->xendev.gnttabdev, 0, NULL) == 0);
-
xen_pv_printf(&blkdev->xendev, 3, "grant copy operation %s\n",
- blkdev->feature_grant_copy ? "enabled" : "disabled");
+ xen_feature_grant_copy ? "enabled" : "disabled");
/* fill info
* blk_connect supplies sector-size and sectors
*/
xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
xenstore_write_be_int(&blkdev->xendev, "feature-persistent",
- !blkdev->feature_grant_copy);
+ !xen_feature_grant_copy);
xenstore_write_be_int(&blkdev->xendev, "info", info);
xenstore_write_be_int(&blkdev->xendev, "max-ring-page-order",
@@ -1226,6 +1220,12 @@ static int blk_connect(struct XenDevice *xendev)
/* Add on the number needed for the ring pages */
max_grants += blkdev->nr_ring_ref;
+ blkdev->xendev.gnttabdev = xengnttab_open(NULL, 0);
+ if (blkdev->xendev.gnttabdev == NULL) {
+ xen_pv_printf(xendev, 0, "xengnttab_open failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
if (xengnttab_set_max_grants(blkdev->xendev.gnttabdev, max_grants)) {
xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
strerror(errno));
@@ -1333,6 +1333,11 @@ static void blk_disconnect(struct XenDevice *xendev)
}
blkdev->feature_persistent = false;
}
+
+ if (blkdev->xendev.gnttabdev) {
+ xengnttab_close(blkdev->xendev.gnttabdev);
+ blkdev->xendev.gnttabdev = NULL;
+ }
}
static int blk_free(struct XenDevice *xendev)
@@ -1340,9 +1345,7 @@ static int blk_free(struct XenDevice *xendev)
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
struct ioreq *ioreq;
- if (blkdev->blk || blkdev->sring) {
- blk_disconnect(xendev);
- }
+ blk_disconnect(xendev);
while (!QLIST_EMPTY(&blkdev->freelist)) {
ioreq = QLIST_FIRST(&blkdev->freelist);
@@ -1369,7 +1372,6 @@ static void blk_event(struct XenDevice *xendev)
struct XenDevOps xen_blkdev_ops = {
.size = sizeof(struct XenBlkDev),
- .flags = DEVOPS_FLAG_NEED_GNTDEV,
.alloc = blk_alloc,
.init = blk_init,
.initialise = blk_connect,
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index d9ccd5d0d6..8028bed6fd 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1446,7 +1446,7 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
if (rc) {
fprintf(stderr,
"%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n",
- __func__, start, nb_pages, rc, strerror(-rc));
+ __func__, start, nb_pages, errno, strerror(errno));
}
}
}
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index c46cbb0759..0f849a26d2 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -44,6 +44,7 @@ BusState *xen_sysbus;
/* public */
struct xs_handle *xenstore = NULL;
const char *xen_protocol;
+bool xen_feature_grant_copy;
/* private */
static int debug;
@@ -519,6 +520,8 @@ void xenstore_update_fe(char *watch, struct XenDevice *xendev)
int xen_be_init(void)
{
+ xengnttab_handle *gnttabdev;
+
xenstore = xs_daemon_open();
if (!xenstore) {
xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
@@ -532,6 +535,14 @@ int xen_be_init(void)
goto err;
}
+ gnttabdev = xengnttab_open(NULL, 0);
+ if (gnttabdev != NULL) {
+ if (xengnttab_grant_copy(gnttabdev, 0, NULL) == 0) {
+ xen_feature_grant_copy = true;
+ }
+ xengnttab_close(gnttabdev);
+ }
+
xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
qdev_init_nofail(xen_sysdev);
xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
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/include/disas/bfd.h b/include/disas/bfd.h
index d99da68267..1f88c9e9d5 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -307,12 +307,6 @@ typedef struct disassemble_info {
(bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info);
- /* A place to stash the real read_memory_func if read_memory_func wants to
- do some funky address arithmetic or similar (e.g. for ARM BE32 mode). */
- int (*read_memory_inner_func)
- (bfd_vma memaddr, bfd_byte *myaddr, int length,
- struct disassemble_info *info);
-
/* Function which should be called if we get an error that we can't
recover from. STATUS is the errno value from read_memory_func and
MEMADDR is the address that we were trying to read. INFO is a
@@ -377,6 +371,10 @@ typedef struct disassemble_info {
/* Command line options specific to the target disassembler. */
char * disassembler_options;
+ /* Options for Capstone disassembly. */
+ int cap_arch;
+ int cap_mode;
+
} disassemble_info;
@@ -479,7 +477,6 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *);
(INFO).buffer_vma = 0, \
(INFO).buffer_length = 0, \
(INFO).read_memory_func = buffer_read_memory, \
- (INFO).read_memory_inner_func = NULL, \
(INFO).memory_error_func = perror_memory, \
(INFO).print_address_func = generic_print_address, \
(INFO).print_insn = NULL, \
diff --git a/include/disas/capstone.h b/include/disas/capstone.h
new file mode 100644
index 0000000000..84e214956d
--- /dev/null
+++ b/include/disas/capstone.h
@@ -0,0 +1,38 @@
+#ifndef QEMU_CAPSTONE_H
+#define QEMU_CAPSTONE_H 1
+
+#ifdef CONFIG_CAPSTONE
+
+#include <capstone.h>
+
+#else
+
+/* Just enough to allow backends to init without ifdefs. */
+
+#define CS_ARCH_ARM -1
+#define CS_ARCH_ARM64 -1
+#define CS_ARCH_MIPS -1
+#define CS_ARCH_X86 -1
+#define CS_ARCH_PPC -1
+#define CS_ARCH_SPARC -1
+#define CS_ARCH_SYSZ -1
+
+#define CS_MODE_LITTLE_ENDIAN 0
+#define CS_MODE_BIG_ENDIAN 0
+#define CS_MODE_ARM 0
+#define CS_MODE_16 0
+#define CS_MODE_32 0
+#define CS_MODE_64 0
+#define CS_MODE_THUMB 0
+#define CS_MODE_MCLASS 0
+#define CS_MODE_V8 0
+#define CS_MODE_MICRO 0
+#define CS_MODE_MIPS3 0
+#define CS_MODE_MIPS32R6 0
+#define CS_MODE_MIPSGP64 0
+#define CS_MODE_V9 0
+#define CS_MODE_MIPS32 0
+#define CS_MODE_MIPS64 0
+
+#endif /* CONFIG_CAPSTONE */
+#endif /* QEMU_CAPSTONE_H */
diff --git a/include/disas/disas.h b/include/disas/disas.h
index e549ca24a1..4d48c13c65 100644
--- a/include/disas/disas.h
+++ b/include/disas/disas.h
@@ -9,10 +9,10 @@
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, CPUState *cpu, target_ulong code,
- target_ulong size, int flags);
+ target_ulong size);
void monitor_disas(Monitor *mon, CPUState *cpu,
- target_ulong pc, int nb_insn, int is_physical, int flags);
+ target_ulong pc, int nb_insn, int is_physical);
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(target_ulong orig_addr);
diff --git a/include/exec/log.h b/include/exec/log.h
index ba1c9b5682..c249307911 100644
--- a/include/exec/log.h
+++ b/include/exec/log.h
@@ -38,9 +38,9 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
#ifdef NEED_CPU_H
/* disas() and target_disas() to qemu_logfile: */
static inline void log_target_disas(CPUState *cpu, target_ulong start,
- target_ulong len, int flags)
+ target_ulong len)
{
- target_disas(qemu_logfile, cpu, start, len, flags);
+ target_disas(qemu_logfile, cpu, start, len);
}
static inline void log_disas(void *code, unsigned long size)
diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
index 8a6fbcbe20..3a27692407 100644
--- a/include/hw/xen/xen_backend.h
+++ b/include/hw/xen/xen_backend.h
@@ -16,6 +16,7 @@
/* variables */
extern struct xs_handle *xenstore;
extern const char *xen_protocol;
+extern bool xen_feature_grant_copy;
extern DeviceState *xen_sysdev;
extern BusState *xen_sysbus;
diff --git a/monitor.c b/monitor.c
index fe0d1bdbb4..7a802a345e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1309,34 +1309,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
}
if (format == 'i') {
- int flags = 0;
-#ifdef TARGET_I386
- CPUArchState *env = mon_get_cpu_env();
- if (wsize == 2) {
- flags = 1;
- } else if (wsize == 4) {
- flags = 0;
- } else {
- /* as default we use the current CS size */
- flags = 0;
- if (env) {
-#ifdef TARGET_X86_64
- if ((env->efer & MSR_EFER_LMA) &&
- (env->segs[R_CS].flags & DESC_L_MASK))
- flags = 2;
- else
-#endif
- if (!(env->segs[R_CS].flags & DESC_B_MASK))
- flags = 1;
- }
- }
-#endif
-#ifdef TARGET_PPC
- CPUArchState *env = mon_get_cpu_env();
- flags = msr_le << 16;
- flags |= env->bfd_mach;
-#endif
- monitor_disas(mon, cs, addr, count, is_physical, flags);
+ monitor_disas(mon, cs, addr, count, is_physical);
return;
}
diff --git a/qemu-img.c b/qemu-img.c
index d6007b2a6d..02a6e27beb 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1065,6 +1065,28 @@ done:
}
/*
+ * 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);
+ 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), filename1,
- strerror(-ret));
+ error_report("Error while reading offset %" PRId64
+ " of %s: %s",
+ offset, filename1, strerror(-ret));
ret = 4;
goto out;
}
- ret = blk_pread(blk2, sector_num << BDRV_SECTOR_BITS, buf2,
- nb_sectors << BDRV_SECTOR_BITS);
+ ret = blk_pread(blk2, offset, buf2, 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, filename2, strerror(-ret));
ret = 4;
goto out;
}
- ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
- if (ret || pnum != nb_sectors) {
+ 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/qga/commands-posix.c b/qga/commands-posix.c
index ab0c63d931..e809e382eb 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1643,6 +1643,67 @@ guest_find_interface(GuestNetworkInterfaceList *head,
return head;
}
+static int guest_get_network_stats(const char *name,
+ GuestNetworkInterfaceStat *stats)
+{
+ int name_len;
+ char const *devinfo = "/proc/net/dev";
+ FILE *fp;
+ char *line = NULL, *colon;
+ size_t n = 0;
+ fp = fopen(devinfo, "r");
+ if (!fp) {
+ return -1;
+ }
+ name_len = strlen(name);
+ while (getline(&line, &n, fp) != -1) {
+ long long dummy;
+ long long rx_bytes;
+ long long rx_packets;
+ long long rx_errs;
+ long long rx_dropped;
+ long long tx_bytes;
+ long long tx_packets;
+ long long tx_errs;
+ long long tx_dropped;
+ char *trim_line;
+ trim_line = g_strchug(line);
+ if (trim_line[0] == '\0') {
+ continue;
+ }
+ colon = strchr(trim_line, ':');
+ if (!colon) {
+ continue;
+ }
+ if (colon - name_len == trim_line &&
+ strncmp(trim_line, name, name_len) == 0) {
+ if (sscanf(colon + 1,
+ "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
+ &rx_bytes, &rx_packets, &rx_errs, &rx_dropped,
+ &dummy, &dummy, &dummy, &dummy,
+ &tx_bytes, &tx_packets, &tx_errs, &tx_dropped,
+ &dummy, &dummy, &dummy, &dummy) != 16) {
+ continue;
+ }
+ stats->rx_bytes = rx_bytes;
+ stats->rx_packets = rx_packets;
+ stats->rx_errs = rx_errs;
+ stats->rx_dropped = rx_dropped;
+ stats->tx_bytes = tx_bytes;
+ stats->tx_packets = tx_packets;
+ stats->tx_errs = tx_errs;
+ stats->tx_dropped = tx_dropped;
+ fclose(fp);
+ g_free(line);
+ return 0;
+ }
+ }
+ fclose(fp);
+ g_free(line);
+ g_debug("/proc/net/dev: Interface '%s' not found", name);
+ return -1;
+}
+
/*
* Build information about guest interfaces
*/
@@ -1659,6 +1720,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
GuestNetworkInterfaceList *info;
GuestIpAddressList **address_list = NULL, *address_item = NULL;
+ GuestNetworkInterfaceStat *interface_stat = NULL;
char addr4[INET_ADDRSTRLEN];
char addr6[INET6_ADDRSTRLEN];
int sock;
@@ -1778,7 +1840,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
info->value->has_ip_addresses = true;
-
+ if (!info->value->has_statistics) {
+ interface_stat = g_malloc0(sizeof(*interface_stat));
+ if (guest_get_network_stats(info->value->name,
+ interface_stat) == -1) {
+ info->value->has_statistics = false;
+ g_free(interface_stat);
+ } else {
+ info->value->statistics = interface_stat;
+ info->value->has_statistics = true;
+ }
+ }
}
freeifaddrs(ifap);
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 619dbd2bc2..0322188a73 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -29,6 +29,7 @@
#endif
#include <lm.h>
#include <wtsapi32.h>
+#include <wininet.h>
#include "qga/guest-agent-core.h"
#include "qga/vss-win32.h"
@@ -1152,6 +1153,44 @@ out:
}
#endif
+#define INTERFACE_PATH_BUF_SZ 512
+
+static DWORD get_interface_index(const char *guid)
+{
+ ULONG index;
+ DWORD status;
+ wchar_t wbuf[INTERFACE_PATH_BUF_SZ];
+ snwprintf(wbuf, INTERFACE_PATH_BUF_SZ, L"\\device\\tcpip_%s", guid);
+ wbuf[INTERFACE_PATH_BUF_SZ - 1] = 0;
+ status = GetAdapterIndex (wbuf, &index);
+ if (status != NO_ERROR) {
+ return (DWORD)~0;
+ } else {
+ return index;
+ }
+}
+static int guest_get_network_stats(const char *name,
+ GuestNetworkInterfaceStat *stats)
+{
+ DWORD if_index = 0;
+ MIB_IFROW a_mid_ifrow;
+ memset(&a_mid_ifrow, 0, sizeof(a_mid_ifrow));
+ if_index = get_interface_index(name);
+ a_mid_ifrow.dwIndex = if_index;
+ if (NO_ERROR == GetIfEntry(&a_mid_ifrow)) {
+ stats->rx_bytes = a_mid_ifrow.dwInOctets;
+ stats->rx_packets = a_mid_ifrow.dwInUcastPkts;
+ stats->rx_errs = a_mid_ifrow.dwInErrors;
+ stats->rx_dropped = a_mid_ifrow.dwInDiscards;
+ stats->tx_bytes = a_mid_ifrow.dwOutOctets;
+ stats->tx_packets = a_mid_ifrow.dwOutUcastPkts;
+ stats->tx_errs = a_mid_ifrow.dwOutErrors;
+ stats->tx_dropped = a_mid_ifrow.dwOutDiscards;
+ return 0;
+ }
+ return -1;
+}
+
GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
{
IP_ADAPTER_ADDRESSES *adptr_addrs, *addr;
@@ -1159,6 +1198,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
GuestIpAddressList *head_addr, *cur_addr;
GuestNetworkInterfaceList *info;
+ GuestNetworkInterfaceStat *interface_stat = NULL;
GuestIpAddressList *address_item = NULL;
unsigned char *mac_addr;
char *addr_str;
@@ -1238,6 +1278,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
info->value->has_ip_addresses = true;
info->value->ip_addresses = head_addr;
}
+ if (!info->value->has_statistics) {
+ interface_stat = g_malloc0(sizeof(*interface_stat));
+ if (guest_get_network_stats(addr->AdapterName,
+ interface_stat) == -1) {
+ info->value->has_statistics = false;
+ g_free(interface_stat);
+ } else {
+ info->value->statistics = interface_stat;
+ info->value->has_statistics = true;
+ }
+ }
}
WSACleanup();
out:
@@ -1277,8 +1328,41 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
* RTC yet:
*
* https://msdn.microsoft.com/en-us/library/aa908981.aspx
+ *
+ * Instead, a workaround is to use the Windows win32tm command to
+ * resync the time using the Windows Time service.
*/
- error_setg(errp, "Time argument is required on this platform");
+ LPVOID msg_buffer;
+ DWORD ret_flags;
+
+ HRESULT hr = system("w32tm /resync /nowait");
+
+ if (GetLastError() != 0) {
+ strerror_s((LPTSTR) & msg_buffer, 0, errno);
+ error_setg(errp, "system(...) failed: %s", (LPCTSTR)msg_buffer);
+ } else if (hr != 0) {
+ if (hr == HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE)) {
+ error_setg(errp, "Windows Time service not running on the "
+ "guest");
+ } else {
+ if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
+ (DWORD)hr, MAKELANGID(LANG_NEUTRAL,
+ SUBLANG_DEFAULT), (LPTSTR) & msg_buffer, 0,
+ NULL)) {
+ error_setg(errp, "w32tm failed with error (0x%lx), couldn'"
+ "t retrieve error message", hr);
+ } else {
+ error_setg(errp, "w32tm failed with error (0x%lx): %s", hr,
+ (LPCTSTR)msg_buffer);
+ LocalFree(msg_buffer);
+ }
+ }
+ } else if (!InternetGetConnectedState(&ret_flags, 0)) {
+ error_setg(errp, "No internet connection on guest, sync not "
+ "accurate");
+ }
return;
}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 90a0c8602b..17884c7c70 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -643,6 +643,38 @@
'prefix': 'int'} }
##
+# @GuestNetworkInterfaceStat:
+#
+# @rx-bytes: total bytes received
+#
+# @rx-packets: total packets received
+#
+# @rx-errs: bad packets received
+#
+# @rx-dropped: receiver dropped packets
+#
+# @tx-bytes: total bytes transmitted
+#
+# @tx-packets: total packets transmitted
+#
+# @tx-errs: packet transmit problems
+#
+# @tx-dropped: dropped packets transmitted
+#
+# Since: 2.11
+##
+{ 'struct': 'GuestNetworkInterfaceStat',
+ 'data': {'rx-bytes': 'uint64',
+ 'rx-packets': 'uint64',
+ 'rx-errs': 'uint64',
+ 'rx-dropped': 'uint64',
+ 'tx-bytes': 'uint64',
+ 'tx-packets': 'uint64',
+ 'tx-errs': 'uint64',
+ 'tx-dropped': 'uint64'
+ } }
+
+##
# @GuestNetworkInterface:
#
# @name: The name of interface for which info are being delivered
@@ -651,12 +683,16 @@
#
# @ip-addresses: List of addresses assigned to @name
#
+# @statistics: various statistic counters related to @name
+# (since 2.11)
+#
# Since: 1.1
##
{ 'struct': 'GuestNetworkInterface',
'data': {'name': 'str',
'*hardware-address': 'str',
- '*ip-addresses': ['GuestIpAddress'] } }
+ '*ip-addresses': ['GuestIpAddress'],
+ '*statistics': 'GuestNetworkInterfaceStat' } }
##
# @guest-network-get-interfaces:
diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
index ba7c94eb25..6713e58670 100644
--- a/qga/vss-win32/install.cpp
+++ b/qga/vss-win32/install.cpp
@@ -148,10 +148,15 @@ static HRESULT getNameByStringSID(
DWORD domainNameLen = BUFFER_SIZE;
wchar_t domainName[BUFFER_SIZE];
- chk(ConvertStringSidToSidW(sid, &psid));
- LookupAccountSidW(NULL, psid, buffer, bufferLen,
- domainName, &domainNameLen, &groupType);
- hr = HRESULT_FROM_WIN32(GetLastError());
+ if (!ConvertStringSidToSidW(sid, &psid)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto out;
+ }
+ if (!LookupAccountSidW(NULL, psid, buffer, bufferLen,
+ domainName, &domainNameLen, &groupType)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ /* Fall through and free psid */
+ }
LocalFree(psid);
diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp
index 301762d8b1..3d9c9716c0 100644
--- a/qga/vss-win32/requester.cpp
+++ b/qga/vss-win32/requester.cpp
@@ -419,6 +419,16 @@ void requester_freeze(int *num_vols, ErrorSet *errset)
break;
}
}
+
+ if (wait_status == WAIT_TIMEOUT) {
+ err_set(errset, E_FAIL,
+ "timeout when try to receive Frozen event from VSS provider");
+ /* If we are here, VSS had timeout.
+ * Don't call AbortBackup, just return directly.
+ */
+ goto out1;
+ }
+
if (wait_status != WAIT_OBJECT_0) {
err_set(errset, E_FAIL,
"couldn't receive Frozen event from VSS provider");
@@ -432,6 +442,8 @@ out:
if (vss_ctx.pVssbc) {
vss_ctx.pVssbc->AbortBackup();
}
+
+out1:
requester_cleanup();
CoUninitialize();
}
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index cfd63d5c1f..629f35ec8e 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -3038,7 +3038,7 @@ static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
static void alpha_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
{
qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
- log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size, 1);
+ log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
}
static const TranslatorOps alpha_tr_ops = {
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a7f03eabe8..47c8b2a85c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -33,6 +33,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/hw_accel.h"
#include "kvm_arm.h"
+#include "disas/capstone.h"
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -473,25 +474,11 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
return print_insn_arm(pc | 1, info);
}
-static int arm_read_memory_func(bfd_vma memaddr, bfd_byte *b,
- int length, struct disassemble_info *info)
-{
- assert(info->read_memory_inner_func);
- assert((info->flags & INSN_ARM_BE32) == 0 || length == 2 || length == 4);
-
- if ((info->flags & INSN_ARM_BE32) != 0 && length == 2) {
- assert(info->endian == BFD_ENDIAN_LITTLE);
- return info->read_memory_inner_func(memaddr ^ 2, (bfd_byte *)b, 2,
- info);
- } else {
- return info->read_memory_inner_func(memaddr, b, length, info);
- }
-}
-
static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
{
ARMCPU *ac = ARM_CPU(cpu);
CPUARMState *env = &ac->env;
+ bool sctlr_b;
if (is_a64(env)) {
/* We might not be compiled with the A64 disassembler
@@ -501,26 +488,40 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
#if defined(CONFIG_ARM_A64_DIS)
info->print_insn = print_insn_arm_a64;
#endif
- } else if (env->thumb) {
- info->print_insn = print_insn_thumb1;
+ info->cap_arch = CS_ARCH_ARM64;
} else {
- info->print_insn = print_insn_arm;
+ int cap_mode;
+ if (env->thumb) {
+ info->print_insn = print_insn_thumb1;
+ cap_mode = CS_MODE_THUMB;
+ } else {
+ info->print_insn = print_insn_arm;
+ cap_mode = CS_MODE_ARM;
+ }
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ cap_mode |= CS_MODE_V8;
+ }
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ cap_mode |= CS_MODE_MCLASS;
+ }
+ info->cap_arch = CS_ARCH_ARM;
+ info->cap_mode = cap_mode;
}
- if (bswap_code(arm_sctlr_b(env))) {
+
+ sctlr_b = arm_sctlr_b(env);
+ if (bswap_code(sctlr_b)) {
#ifdef TARGET_WORDS_BIGENDIAN
info->endian = BFD_ENDIAN_LITTLE;
#else
info->endian = BFD_ENDIAN_BIG;
#endif
}
- if (info->read_memory_inner_func == NULL) {
- info->read_memory_inner_func = info->read_memory_func;
- info->read_memory_func = arm_read_memory_func;
- }
info->flags &= ~INSN_ARM_BE32;
- if (arm_sctlr_b(env)) {
+#ifndef CONFIG_USER_ONLY
+ if (sctlr_b) {
info->flags |= INSN_ARM_BE32;
}
+#endif
}
uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index f6b364c04b..e98fbcf261 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11423,8 +11423,7 @@ static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
DisasContext *dc = container_of(dcbase, DisasContext, base);
qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
- log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size,
- 4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+ log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
}
const TranslatorOps aarch64_translator_ops = {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a252429e68..6ba4ae92dc 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12372,8 +12372,7 @@ static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
DisasContext *dc = container_of(dcbase, DisasContext, base);
qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
- log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size,
- dc->thumb | (dc->sctlr_b << 1));
+ log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
}
static const TranslatorOps arm_translator_ops = {
diff --git a/target/cris/translate.c b/target/cris/translate.c
index aa95f6701a..2831419845 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3296,8 +3296,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc->pc - pc_start,
- env->pregs[PR_VR]);
+ log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index dbd4cd8615..53aa1f88c4 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3902,7 +3902,7 @@ static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
break;
default:
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
- log_target_disas(cs, tb->pc, tb->size, 1);
+ log_target_disas(cs, tb->pc, tb->size);
break;
}
}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 2f556c0ea3..6f21a5e518 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -51,6 +51,8 @@
#include "hw/i386/apic_internal.h"
#endif
+#include "disas/capstone.h"
+
/* Cache topology CPUID constants: */
@@ -4093,6 +4095,22 @@ static bool x86_cpu_has_work(CPUState *cs)
!(env->hflags & HF_SMM_MASK));
}
+static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ info->mach = (env->hflags & HF_CS64_MASK ? bfd_mach_x86_64
+ : env->hflags & HF_CS32_MASK ? bfd_mach_i386_i386
+ : bfd_mach_i386_i8086);
+ info->print_insn = print_insn_i386;
+
+ info->cap_arch = CS_ARCH_X86;
+ info->cap_mode = (env->hflags & HF_CS64_MASK ? CS_MODE_64
+ : env->hflags & HF_CS32_MASK ? CS_MODE_32
+ : CS_MODE_16);
+}
+
static Property x86_cpu_properties[] = {
#ifdef CONFIG_USER_ONLY
/* apic_id = 0 by default for *-user, see commit 9886e834 */
@@ -4215,6 +4233,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
#ifdef CONFIG_TCG
cc->tcg_initialize = tcg_x86_init;
#endif
+ cc->disas_set_info = x86_disas_set_info;
dc->user_creatable = true;
}
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 7df9233ded..088a9d9766 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8548,15 +8548,9 @@ static void i386_tr_disas_log(const DisasContextBase *dcbase,
CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
- int disas_flags = !dc->code32;
qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-#ifdef TARGET_X86_64
- if (dc->code64) {
- disas_flags = 2;
- }
-#endif
- log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, disas_flags);
+ log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
}
static const TranslatorOps i386_tr_ops = {
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 02ad3edad3..b8b2b13e36 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -1155,7 +1155,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("\n");
- log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index e7eaf03e55..b60909222c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5623,7 +5623,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index e51821d6bd..e7b5597c46 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1809,7 +1809,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
qemu_log_lock();
qemu_log("--------------\n");
#if DISAS_GNU
- log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc->pc - pc_start);
#endif
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 1848500625..b022f840c9 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -20369,7 +20369,7 @@ done_generating:
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+ log_target_disas(cs, pc_start, ctx.pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index b5aaf56e86..72329002ac 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -906,7 +906,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
&& qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
- log_target_disas(cs, tb->pc, dc->pc - tb->pc, 0);
+ log_target_disas(cs, tb->pc, dc->pc - tb->pc);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index c9cbd2319f..2747b24cf0 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1650,7 +1650,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- log_target_disas(cs, pc_start, tb->size, 0);
+ log_target_disas(cs, pc_start, tb->size);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e7e4983cbf..998fbed848 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7397,12 +7397,9 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- int flags;
- flags = env->bfd_mach;
- flags |= ctx.le_mode << 16;
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
+ log_target_disas(cs, pc_start, ctx.nip - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 61a9552c1c..b9c49c22f2 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -35,6 +35,7 @@
#include "mmu-book3s-v3.h"
#include "sysemu/qtest.h"
#include "qemu/cutils.h"
+#include "disas/capstone.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -10515,6 +10516,31 @@ static gchar *ppc_gdb_arch_name(CPUState *cs)
#endif
}
+static void ppc_disas_set_info(CPUState *cs, disassemble_info *info)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ if ((env->hflags >> MSR_LE) & 1) {
+ info->endian = BFD_ENDIAN_LITTLE;
+ }
+ info->mach = env->bfd_mach;
+ if (!env->bfd_mach) {
+#ifdef TARGET_PPC64
+ info->mach = bfd_mach_ppc64;
+#else
+ info->mach = bfd_mach_ppc;
+#endif
+ }
+ info->disassembler_options = (char *)"any";
+ info->print_insn = print_insn_ppc;
+
+ info->cap_arch = CS_ARCH_PPC;
+#ifdef TARGET_PPC64
+ info->cap_mode = CS_MODE_64;
+#endif
+}
+
static Property ppc_cpu_properties[] = {
DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false),
DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration,
@@ -10581,7 +10607,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
#ifdef CONFIG_TCG
cc->tcg_initialize = ppc_translate_init;
#endif
-
+ cc->disas_set_info = ppc_disas_set_info;
+
dc->fw_name = "PowerPC,UNKNOWN";
}
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 55db8f3446..dee72a787d 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -5982,7 +5982,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value);
} else {
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
+ log_target_disas(cs, pc_start, dc.pc - pc_start);
qemu_log("\n");
}
qemu_log_unlock();
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index c98f8d31e3..703020fe87 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -2336,7 +2336,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
- log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+ log_target_disas(cs, pc_start, ctx.pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index d5e866fe0d..849a02aebd 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -5849,7 +5849,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock * tb)
qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
+ log_target_disas(cs, pc_start, last_pc + 4 - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index 18102e54cb..4e5b083665 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -8837,7 +8837,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+ log_target_disas(cs, pc_start, ctx.pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index de2a7ceee7..384aa86027 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -2027,7 +2027,7 @@ done_generating:
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 32c4159949..20f7ddf042 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -3247,7 +3247,7 @@ done:
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc.pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc.pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
}
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 <http://www.gnu.org/licenses/>.
+#
+
+# 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
@@ -82,6 +82,13 @@ $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 =="
function verify_io()
@@ -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