Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c918cb0ab | ||
|
|
ecc23c6e95 | ||
|
|
fa020ef10b | ||
|
|
8ec90598e9 | ||
|
|
219cea653e | ||
|
|
3b53bfd4c8 | ||
|
|
e9eb53c5fe | ||
|
|
415f21c723 | ||
|
|
06e11b7589 | ||
|
|
b67924a048 | ||
|
|
024e8945fa | ||
|
|
7837d7e31d | ||
|
|
5bdc6b9571 | ||
|
|
fd4e677c79 | ||
|
|
528496a5d4 | ||
|
|
16f6a650a8 | ||
|
|
d56cc9b5e5 | ||
|
|
06679ac8b5 | ||
|
|
a290e43f58 | ||
|
|
7d6aebaec5 | ||
|
|
6abbb26bbc | ||
|
|
15e207b9ed | ||
|
|
2ad4ebb350 | ||
|
|
c59ce9fef6 | ||
|
|
9222f3ee43 | ||
|
|
dbf80fdef8 | ||
|
|
c0a2b77dd8 | ||
|
|
0eab8d42e1 | ||
|
|
c6f64736de | ||
|
|
ad24078e3f | ||
|
|
a629fee99b |
@@ -637,7 +637,10 @@ pages:
|
||||
- mkdir -p public
|
||||
# HTML-ised source tree
|
||||
- make gtags
|
||||
- htags -anT --tree-view=filetree -m qemu_init
|
||||
# We unset variables to work around a bug in some htags versions
|
||||
# which causes it to fail when the environment is large
|
||||
- CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags
|
||||
-anT --tree-view=filetree -m qemu_init
|
||||
-t "Welcome to the QEMU sourcecode"
|
||||
- mv HTML public/src
|
||||
# Project documentation
|
||||
|
||||
+12
-7
@@ -5,16 +5,21 @@
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# We recommend specifying your dependencies to enable reproducible builds:
|
||||
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
# We want all the document formats
|
||||
formats: all
|
||||
|
||||
# For consistency, we require that QEMU's Sphinx extensions
|
||||
# run with at least the same minimum version of Python that
|
||||
# we require for other Python in our codebase (our conf.py
|
||||
# enforces this, and some code needs it.)
|
||||
python:
|
||||
version: 3.6
|
||||
|
||||
@@ -186,7 +186,7 @@ static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
const TranslationBlock *tb = p;
|
||||
const struct tb_desc *desc = d;
|
||||
|
||||
if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
|
||||
if (tb_pc(tb) == desc->pc &&
|
||||
tb_page_addr0(tb) == desc->page_addr0 &&
|
||||
tb->cs_base == desc->cs_base &&
|
||||
tb->flags == desc->flags &&
|
||||
@@ -238,7 +238,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
|
||||
return NULL;
|
||||
}
|
||||
desc.page_addr0 = phys_pc;
|
||||
h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
|
||||
h = tb_hash_func(phys_pc, pc,
|
||||
flags, cflags, *cpu->trace_dstate);
|
||||
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ static bool tb_cmp(const void *ap, const void *bp)
|
||||
const TranslationBlock *a = ap;
|
||||
const TranslationBlock *b = bp;
|
||||
|
||||
return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
|
||||
return (tb_pc(a) == tb_pc(b) &&
|
||||
a->cs_base == b->cs_base &&
|
||||
a->flags == b->flags &&
|
||||
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
|
||||
@@ -269,7 +269,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
|
||||
/* remove the TB from the hash list */
|
||||
phys_pc = tb_page_addr0(tb);
|
||||
h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
|
||||
h = tb_hash_func(phys_pc, tb_pc(tb),
|
||||
tb->flags, orig_cflags, tb->trace_vcpu_dstate);
|
||||
if (!qht_remove(&tb_ctx.htable, tb, h)) {
|
||||
return;
|
||||
@@ -459,7 +459,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
}
|
||||
|
||||
/* add in the hash table */
|
||||
h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
|
||||
h = tb_hash_func(phys_pc, tb_pc(tb),
|
||||
tb->flags, tb->cflags, tb->trace_vcpu_dstate);
|
||||
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
|
||||
|
||||
|
||||
@@ -818,9 +818,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
gen_code_buf = tcg_ctx->code_gen_ptr;
|
||||
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
|
||||
#if !TARGET_TB_PCREL
|
||||
tb->pc = pc;
|
||||
#endif
|
||||
tb->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
tb->cflags = cflags;
|
||||
|
||||
+25
-8
@@ -321,22 +321,39 @@ typedef struct {
|
||||
static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
|
||||
{
|
||||
BDRVBlkLogWritesState *s = lr->bs->opaque;
|
||||
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
|
||||
|
||||
/*
|
||||
* Determine the offsets and sizes of different parts of the entry, and
|
||||
* update the state of the driver.
|
||||
*
|
||||
* This needs to be done in one go, before any actual I/O is done, as the
|
||||
* log entry may have to be written in two parts, and the state of the
|
||||
* driver may be modified by other driver operations while waiting for the
|
||||
* I/O to complete.
|
||||
*/
|
||||
const uint64_t entry_start_sector = s->cur_log_sector;
|
||||
const uint64_t entry_offset = entry_start_sector << s->sectorbits;
|
||||
const uint64_t qiov_aligned_size = ROUND_UP(lr->qiov->size, s->sectorsize);
|
||||
const uint64_t entry_aligned_size = qiov_aligned_size +
|
||||
ROUND_UP(lr->zero_size, s->sectorsize);
|
||||
const uint64_t entry_nr_sectors = entry_aligned_size >> s->sectorbits;
|
||||
|
||||
s->nr_entries++;
|
||||
s->cur_log_sector +=
|
||||
ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits;
|
||||
s->cur_log_sector += entry_nr_sectors;
|
||||
|
||||
lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size,
|
||||
/*
|
||||
* Write the log entry. Note that if this is a "write zeroes" operation,
|
||||
* only the entry header is written here, with the zeroing being done
|
||||
* separately below.
|
||||
*/
|
||||
lr->log_ret = bdrv_co_pwritev(s->log_file, entry_offset, lr->qiov->size,
|
||||
lr->qiov, 0);
|
||||
|
||||
/* Logging for the "write zeroes" operation */
|
||||
if (lr->log_ret == 0 && lr->zero_size) {
|
||||
cur_log_offset = s->cur_log_sector << s->sectorbits;
|
||||
s->cur_log_sector +=
|
||||
ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits;
|
||||
const uint64_t zeroes_offset = entry_offset + qiov_aligned_size;
|
||||
|
||||
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset,
|
||||
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_offset,
|
||||
lr->zero_size, 0);
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -2595,6 +2595,16 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
||||
ret |= (ret2 & BDRV_BLOCK_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the recursive search was done, clear the flag. Otherwise,
|
||||
* with more complicated block graphs like snapshot-access ->
|
||||
* copy-before-write -> qcow2, where the return value will be propagated
|
||||
* further up to a parent bdrv_co_do_block_status() call, both the
|
||||
* BDRV_BLOCK_RECURSE and BDRV_BLOCK_ZERO flags would be set, which is
|
||||
* not allowed.
|
||||
*/
|
||||
ret &= ~BDRV_BLOCK_RECURSE;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
+3
-1
@@ -190,8 +190,10 @@ static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
|
||||
int bdrv_can_snapshot(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
||||
|
||||
if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -519,7 +519,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
|
||||
|
||||
if (object_class_is_abstract(oc)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||
"an abstract device type");
|
||||
"a non-abstract device type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
sphinx==5.3.0
|
||||
sphinx_rtd_theme==1.1.1
|
||||
+91
-80
@@ -81,16 +81,39 @@ struct PFlashCFI01 {
|
||||
uint16_t ident3;
|
||||
uint8_t cfi_table[0x52];
|
||||
uint64_t counter;
|
||||
unsigned int writeblock_size;
|
||||
uint32_t writeblock_size;
|
||||
MemoryRegion mem;
|
||||
char *name;
|
||||
void *storage;
|
||||
VMChangeStateEntry *vmstate;
|
||||
bool old_multiple_chip_handling;
|
||||
|
||||
/* block update buffer */
|
||||
unsigned char *blk_bytes;
|
||||
uint32_t blk_offset;
|
||||
};
|
||||
|
||||
static int pflash_post_load(void *opaque, int version_id);
|
||||
|
||||
static bool pflash_blk_write_state_needed(void *opaque)
|
||||
{
|
||||
PFlashCFI01 *pfl = opaque;
|
||||
|
||||
return (pfl->blk_offset != -1);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pflash_blk_write = {
|
||||
.name = "pflash_cfi01_blk_write",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pflash_blk_write_state_needed,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
|
||||
VMSTATE_UINT32(blk_offset, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pflash = {
|
||||
.name = "pflash_cfi01",
|
||||
.version_id = 1,
|
||||
@@ -102,6 +125,10 @@ static const VMStateDescription vmstate_pflash = {
|
||||
VMSTATE_UINT8(status, PFlashCFI01),
|
||||
VMSTATE_UINT64(counter, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription * []) {
|
||||
&vmstate_pflash_blk_write,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -226,34 +253,10 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
|
||||
uint32_t ret;
|
||||
|
||||
p = pfl->storage;
|
||||
switch (width) {
|
||||
case 1:
|
||||
ret = p[offset];
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
ret = p[offset] << 8;
|
||||
ret |= p[offset + 1];
|
||||
} else {
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
ret = p[offset] << 24;
|
||||
ret |= p[offset + 1] << 16;
|
||||
ret |= p[offset + 2] << 8;
|
||||
ret |= p[offset + 3];
|
||||
} else {
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
ret |= p[offset + 2] << 16;
|
||||
ret |= p[offset + 3] << 24;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
if (be) {
|
||||
ret = ldn_be_p(p + offset, width);
|
||||
} else {
|
||||
ret = ldn_le_p(p + offset, width);
|
||||
}
|
||||
trace_pflash_data_read(pfl->name, offset, width, ret);
|
||||
return ret;
|
||||
@@ -401,40 +404,61 @@ static void pflash_update(PFlashCFI01 *pfl, int offset,
|
||||
}
|
||||
}
|
||||
|
||||
/* copy current flash content to block update buffer */
|
||||
static void pflash_blk_write_start(PFlashCFI01 *pfl, hwaddr offset)
|
||||
{
|
||||
hwaddr mask = ~(pfl->writeblock_size - 1);
|
||||
|
||||
trace_pflash_write_block_start(pfl->name, pfl->counter);
|
||||
pfl->blk_offset = offset & mask;
|
||||
memcpy(pfl->blk_bytes, pfl->storage + pfl->blk_offset,
|
||||
pfl->writeblock_size);
|
||||
}
|
||||
|
||||
/* commit block update buffer changes */
|
||||
static void pflash_blk_write_flush(PFlashCFI01 *pfl)
|
||||
{
|
||||
g_assert(pfl->blk_offset != -1);
|
||||
trace_pflash_write_block_flush(pfl->name);
|
||||
memcpy(pfl->storage + pfl->blk_offset, pfl->blk_bytes,
|
||||
pfl->writeblock_size);
|
||||
pflash_update(pfl, pfl->blk_offset, pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
/* discard block update buffer changes */
|
||||
static void pflash_blk_write_abort(PFlashCFI01 *pfl)
|
||||
{
|
||||
trace_pflash_write_block_abort(pfl->name);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
uint32_t value, int width, int be)
|
||||
{
|
||||
uint8_t *p = pfl->storage;
|
||||
uint8_t *p;
|
||||
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
|
||||
switch (width) {
|
||||
case 1:
|
||||
p[offset] = value;
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
p[offset] = value >> 8;
|
||||
p[offset + 1] = value;
|
||||
} else {
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
if (pfl->blk_offset != -1) {
|
||||
/* block write: redirect writes to block update buffer */
|
||||
if ((offset < pfl->blk_offset) ||
|
||||
(offset + width > pfl->blk_offset + pfl->writeblock_size)) {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
p[offset] = value >> 24;
|
||||
p[offset + 1] = value >> 16;
|
||||
p[offset + 2] = value >> 8;
|
||||
p[offset + 3] = value;
|
||||
} else {
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
p[offset + 2] = value >> 16;
|
||||
p[offset + 3] = value >> 24;
|
||||
}
|
||||
break;
|
||||
trace_pflash_data_write_block(pfl->name, offset, width, value,
|
||||
pfl->counter);
|
||||
p = pfl->blk_bytes + (offset - pfl->blk_offset);
|
||||
} else {
|
||||
/* write directly to storage */
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
p = pfl->storage + offset;
|
||||
}
|
||||
|
||||
if (be) {
|
||||
stn_be_p(p, width, value);
|
||||
} else {
|
||||
stn_le_p(p, width, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
@@ -549,9 +573,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
} else {
|
||||
value = extract32(value, 0, pfl->bank_width * 8);
|
||||
}
|
||||
trace_pflash_write_block(pfl->name, value);
|
||||
pfl->counter = value;
|
||||
pfl->wcycle++;
|
||||
pflash_blk_write_start(pfl, offset);
|
||||
break;
|
||||
case 0x60:
|
||||
if (cmd == 0xd0) {
|
||||
@@ -582,12 +606,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
/* FIXME check @offset, @width */
|
||||
if (!pfl->ro) {
|
||||
/*
|
||||
* FIXME writing straight to memory is *wrong*. We
|
||||
* should write to a buffer, and flush it to memory
|
||||
* only on confirm command (see below).
|
||||
*/
|
||||
if (!pfl->ro && (pfl->blk_offset != -1)) {
|
||||
pflash_data_write(pfl, offset, value, width, be);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
@@ -596,18 +615,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
pfl->status |= 0x80;
|
||||
|
||||
if (!pfl->counter) {
|
||||
hwaddr mask = pfl->writeblock_size - 1;
|
||||
mask = ~mask;
|
||||
|
||||
trace_pflash_write(pfl->name, "block write finished");
|
||||
pfl->wcycle++;
|
||||
if (!pfl->ro) {
|
||||
/* Flush the entire write buffer onto backing storage. */
|
||||
/* FIXME premature! */
|
||||
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
}
|
||||
}
|
||||
|
||||
pfl->counter--;
|
||||
@@ -619,20 +628,17 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
case 3: /* Confirm mode */
|
||||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
if (cmd == 0xd0) {
|
||||
/* FIXME this is where we should write out the buffer */
|
||||
if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
|
||||
pflash_blk_write_flush(pfl);
|
||||
pfl->wcycle = 0;
|
||||
pfl->status |= 0x80;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: Aborting write to buffer not implemented,"
|
||||
" the data is already written to storage!\n"
|
||||
"Flash device reset into READ mode.\n",
|
||||
__func__);
|
||||
pflash_blk_write_abort(pfl);
|
||||
goto mode_read_array;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pflash_blk_write_abort(pfl);
|
||||
goto error_flash;
|
||||
}
|
||||
break;
|
||||
@@ -866,6 +872,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
||||
pfl->cmd = 0x00;
|
||||
pfl->status = 0x80; /* WSM ready */
|
||||
pflash_cfi01_fill_cfi_table(pfl);
|
||||
|
||||
pfl->blk_bytes = g_malloc(pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||
@@ -885,6 +894,8 @@ static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||
* This model deliberately ignores this delay.
|
||||
*/
|
||||
pfl->status = 0x80;
|
||||
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static Property pflash_cfi01_properties[] = {
|
||||
|
||||
@@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
}
|
||||
goto reset_flash;
|
||||
}
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, 0);
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
if (!pfl->ro) {
|
||||
p = (uint8_t *)pfl->storage + offset;
|
||||
if (pfl->be) {
|
||||
|
||||
@@ -12,7 +12,8 @@ fdctrl_tc_pulse(int level) "TC pulse: %u"
|
||||
pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64
|
||||
pflash_chip_erase_start(const char *name) "%s: start chip erase"
|
||||
pflash_data_read(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x"
|
||||
pflash_device_info(const char *name, uint64_t offset) "%s: read device information offset:0x%04" PRIx64
|
||||
pflash_erase_complete(const char *name) "%s: sector erase complete"
|
||||
@@ -32,7 +33,9 @@ pflash_unlock0_failed(const char *name, uint64_t offset, uint8_t cmd, uint16_t a
|
||||
pflash_unlock1_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: unlock0 failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_unsupported_device_configuration(const char *name, uint8_t width, uint8_t max) "%s: unsupported device configuration: device_width:%d max_device_width:%d"
|
||||
pflash_write(const char *name, const char *str) "%s: %s"
|
||||
pflash_write_block(const char *name, uint32_t value) "%s: block write: bytes:0x%x"
|
||||
pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x"
|
||||
pflash_write_block_flush(const char *name) "%s: block write flush"
|
||||
pflash_write_block_abort(const char *name) "%s: block write abort"
|
||||
pflash_write_block_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64
|
||||
pflash_write_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: command failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_write_invalid(const char *name, uint8_t cmd) "%s: invalid write for command 0x%02x"
|
||||
|
||||
@@ -1432,16 +1432,25 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
idx = icv_find_active(cs, irq);
|
||||
|
||||
if (idx < 0) {
|
||||
/* No valid list register corresponding to EOI ID */
|
||||
icv_increment_eoicount(cs);
|
||||
/*
|
||||
* No valid list register corresponding to EOI ID; if this is a vLPI
|
||||
* not in the list regs then do nothing; otherwise increment EOI count
|
||||
*/
|
||||
if (irq < GICV3_LPI_INTID_START) {
|
||||
icv_increment_eoicount(cs);
|
||||
}
|
||||
} else {
|
||||
uint64_t lr = cs->ich_lr_el2[idx];
|
||||
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
|
||||
int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
|
||||
|
||||
if (thisgrp == grp && lr_gprio == dropprio) {
|
||||
if (!icv_eoi_split(env, cs)) {
|
||||
/* Priority drop and deactivate not split: deactivate irq now */
|
||||
if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) {
|
||||
/*
|
||||
* Priority drop and deactivate not split: deactivate irq now.
|
||||
* LPIs always get their active state cleared immediately
|
||||
* because no separate deactivate is expected.
|
||||
*/
|
||||
icv_deactivate_irq(cs, idx);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -664,6 +664,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
|
||||
|
||||
n->mergeable_rx_bufs = mergeable_rx_bufs;
|
||||
|
||||
/*
|
||||
* Note: when extending the vnet header, please make sure to
|
||||
* change the vnet header copying logic in virtio_net_flush_tx()
|
||||
* as well.
|
||||
*/
|
||||
if (version_1) {
|
||||
n->guest_hdr_len = hash_report ?
|
||||
sizeof(struct virtio_net_hdr_v1_hash) :
|
||||
@@ -2630,7 +2635,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
||||
ssize_t ret;
|
||||
unsigned int out_num;
|
||||
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
|
||||
struct virtio_net_hdr_mrg_rxbuf mhdr;
|
||||
struct virtio_net_hdr_v1_hash vhdr;
|
||||
|
||||
elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
@@ -2647,7 +2652,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
||||
}
|
||||
|
||||
if (n->has_vnet_hdr) {
|
||||
if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
|
||||
if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
|
||||
n->guest_hdr_len) {
|
||||
virtio_error(vdev, "virtio-net header incorrect");
|
||||
virtqueue_detach_element(q->tx_vq, elem, 0);
|
||||
@@ -2655,8 +2660,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (n->needs_vnet_hdr_swap) {
|
||||
virtio_net_hdr_swap(vdev, (void *) &mhdr);
|
||||
sg2[0].iov_base = &mhdr;
|
||||
virtio_net_hdr_swap(vdev, (void *) &vhdr);
|
||||
sg2[0].iov_base = &vhdr;
|
||||
sg2[0].iov_len = n->guest_hdr_len;
|
||||
out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
|
||||
out_sg, out_num,
|
||||
|
||||
+41
-20
@@ -77,6 +77,41 @@ struct PCIESPState {
|
||||
ESPState esp;
|
||||
};
|
||||
|
||||
static void esp_pci_update_irq(PCIESPState *pci)
|
||||
{
|
||||
int scsi_level = !!(pci->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT);
|
||||
int dma_level = (pci->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ?
|
||||
!!(pci->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0;
|
||||
int level = scsi_level || dma_level;
|
||||
|
||||
pci_set_irq(PCI_DEVICE(pci), level);
|
||||
}
|
||||
|
||||
static void esp_irq_handler(void *opaque, int irq_num, int level)
|
||||
{
|
||||
PCIESPState *pci = PCI_ESP(opaque);
|
||||
|
||||
if (level) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT;
|
||||
|
||||
/*
|
||||
* If raising the ESP IRQ to indicate end of DMA transfer, set
|
||||
* DMA_STAT_DONE at the same time. In theory this should be done in
|
||||
* esp_pci_dma_memory_rw(), however there is a delay between setting
|
||||
* DMA_STAT_DONE and the ESP IRQ arriving which is visible to the
|
||||
* guest that can cause confusion e.g. Linux
|
||||
*/
|
||||
if ((pci->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 &&
|
||||
pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
} else {
|
||||
pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT;
|
||||
}
|
||||
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
|
||||
static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
|
||||
{
|
||||
ESPState *s = ESP(&pci->esp);
|
||||
@@ -89,6 +124,7 @@ static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val)
|
||||
{
|
||||
trace_esp_pci_dma_blast(val);
|
||||
qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT;
|
||||
}
|
||||
|
||||
static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
|
||||
@@ -151,6 +187,7 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
|
||||
/* clear some bits on write */
|
||||
uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
|
||||
pci->dma_regs[DMA_STAT] &= ~(val & mask);
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -161,17 +198,14 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
|
||||
|
||||
static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
|
||||
{
|
||||
ESPState *s = ESP(&pci->esp);
|
||||
uint32_t val;
|
||||
|
||||
val = pci->dma_regs[saddr];
|
||||
if (saddr == DMA_STAT) {
|
||||
if (s->rregs[ESP_RSTAT] & STAT_INT) {
|
||||
val |= DMA_STAT_SCSIINT;
|
||||
}
|
||||
if (!(pci->sbac & SBAC_STATUS)) {
|
||||
pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
|
||||
DMA_STAT_DONE);
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +309,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
||||
qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
|
||||
}
|
||||
|
||||
addr = pci->dma_regs[DMA_SPA];
|
||||
addr = pci->dma_regs[DMA_WAC];
|
||||
if (pci->dma_regs[DMA_WBC] < len) {
|
||||
len = pci->dma_regs[DMA_WBC];
|
||||
}
|
||||
@@ -285,9 +319,6 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
||||
/* update status registers */
|
||||
pci->dma_regs[DMA_WBC] -= len;
|
||||
pci->dma_regs[DMA_WAC] += len;
|
||||
if (pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
|
||||
@@ -342,23 +373,13 @@ static const VMStateDescription vmstate_esp_pci_scsi = {
|
||||
}
|
||||
};
|
||||
|
||||
static void esp_pci_command_complete(SCSIRequest *req, size_t resid)
|
||||
{
|
||||
ESPState *s = req->hba_private;
|
||||
PCIESPState *pci = container_of(s, PCIESPState, esp);
|
||||
|
||||
esp_command_complete(req, resid);
|
||||
pci->dma_regs[DMA_WBC] = 0;
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
|
||||
static const struct SCSIBusInfo esp_pci_scsi_info = {
|
||||
.tcq = false,
|
||||
.max_target = ESP_MAX_DEVS,
|
||||
.max_lun = 7,
|
||||
|
||||
.transfer_data = esp_transfer_data,
|
||||
.complete = esp_pci_command_complete,
|
||||
.complete = esp_command_complete,
|
||||
.cancel = esp_request_cancelled,
|
||||
};
|
||||
|
||||
@@ -386,7 +407,7 @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
|
||||
"esp-io", 0x80);
|
||||
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
|
||||
s->irq = pci_allocate_irq(dev);
|
||||
s->irq = qemu_allocate_irq(esp_irq_handler, pci, 0);
|
||||
|
||||
scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
|
||||
}
|
||||
|
||||
@@ -503,7 +503,6 @@ struct tb_tc {
|
||||
};
|
||||
|
||||
struct TranslationBlock {
|
||||
#if !TARGET_TB_PCREL
|
||||
/*
|
||||
* Guest PC corresponding to this block. This must be the true
|
||||
* virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
|
||||
@@ -518,7 +517,6 @@ struct TranslationBlock {
|
||||
* deposited into the "current" PC.
|
||||
*/
|
||||
target_ulong pc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Target-specific data associated with the TranslationBlock, e.g.:
|
||||
@@ -604,11 +602,7 @@ struct TranslationBlock {
|
||||
/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
|
||||
static inline target_ulong tb_pc(const TranslationBlock *tb)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
qemu_build_not_reached();
|
||||
#else
|
||||
return tb->pc;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Hide the qatomic_read to make code a little easier on the eyes */
|
||||
|
||||
@@ -499,7 +499,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
|
||||
}
|
||||
|
||||
if (data_swab) {
|
||||
int j;
|
||||
elf_word j;
|
||||
for (j = 0; j < file_size; j += (1 << data_swab)) {
|
||||
uint8_t *dp = data + j;
|
||||
switch (data_swab) {
|
||||
|
||||
@@ -296,14 +296,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the coroutine from iohandler_ctx to qemu_aio_context for
|
||||
* executing the command handler so that it can make progress if it
|
||||
* involves an AIO_WAIT_WHILE().
|
||||
*/
|
||||
aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co);
|
||||
qemu_coroutine_yield();
|
||||
|
||||
/* Process request */
|
||||
if (req_obj->req) {
|
||||
if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
|
||||
@@ -330,15 +322,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||
}
|
||||
|
||||
qmp_request_free(req_obj);
|
||||
|
||||
/*
|
||||
* Yield and reschedule so the main loop stays responsive.
|
||||
*
|
||||
* Move back to iohandler_ctx so that nested event loops for
|
||||
* qemu_aio_context don't start new monitor commands.
|
||||
*/
|
||||
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -206,9 +206,31 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
|
||||
assert(!(oob && qemu_in_coroutine()));
|
||||
assert(monitor_cur() == NULL);
|
||||
if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
|
||||
if (qemu_in_coroutine()) {
|
||||
/*
|
||||
* Move the coroutine from iohandler_ctx to qemu_aio_context for
|
||||
* executing the command handler so that it can make progress if it
|
||||
* involves an AIO_WAIT_WHILE().
|
||||
*/
|
||||
aio_co_schedule(qemu_get_aio_context(), qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
monitor_set_cur(qemu_coroutine_self(), cur_mon);
|
||||
cmd->fn(args, &ret, &err);
|
||||
monitor_set_cur(qemu_coroutine_self(), NULL);
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
/*
|
||||
* Yield and reschedule so the main loop stays responsive.
|
||||
*
|
||||
* Move back to iohandler_ctx so that nested event loops for
|
||||
* qemu_aio_context don't start new monitor commands.
|
||||
*/
|
||||
aio_co_schedule(iohandler_get_aio_context(),
|
||||
qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Actual context doesn't match the one the command needs.
|
||||
@@ -232,7 +254,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
|
||||
.errp = &err,
|
||||
.co = qemu_coroutine_self(),
|
||||
};
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh,
|
||||
aio_bh_schedule_oneshot(iohandler_get_aio_context(), do_qmp_dispatch_bh,
|
||||
&data);
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
@@ -2321,6 +2321,10 @@ static void qemu_validate_options(const QDict *machine_opts)
|
||||
}
|
||||
}
|
||||
|
||||
if (loadvm && incoming) {
|
||||
error_report("'incoming' and 'loadvm' options are mutually exclusive");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (loadvm && preconfig_requested) {
|
||||
error_report("'preconfig' and 'loadvm' options are "
|
||||
"mutually exclusive");
|
||||
|
||||
+7
-2
@@ -2217,10 +2217,15 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
|
||||
static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*cs_base = env->segs[R_CS].base;
|
||||
*pc = *cs_base + env->eip;
|
||||
*flags = env->hflags |
|
||||
(env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK));
|
||||
if (env->hflags & HF_CS64_MASK) {
|
||||
*cs_base = 0;
|
||||
*pc = env->eip;
|
||||
} else {
|
||||
*cs_base = env->segs[R_CS].base;
|
||||
*pc = (uint32_t)(*cs_base + env->eip);
|
||||
}
|
||||
}
|
||||
|
||||
void do_cpu_init(X86CPU *cpu);
|
||||
|
||||
@@ -52,7 +52,12 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
|
||||
/* The instruction pointer is always up to date with TARGET_TB_PCREL. */
|
||||
if (!TARGET_TB_PCREL) {
|
||||
CPUX86State *env = cs->env_ptr;
|
||||
env->eip = tb_pc(tb) - tb->cs_base;
|
||||
|
||||
if (tb->flags & HF_CS64_MASK) {
|
||||
env->eip = tb_pc(tb);
|
||||
} else {
|
||||
env->eip = (uint32_t)(tb_pc(tb) - tb->cs_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +68,26 @@ static void x86_restore_state_to_opc(CPUState *cs,
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
int cc_op = data[1];
|
||||
uint64_t new_pc;
|
||||
|
||||
if (TARGET_TB_PCREL) {
|
||||
env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
|
||||
/*
|
||||
* data[0] in PC-relative TBs is also a linear address, i.e. an address with
|
||||
* the CS base added, because it is not guaranteed that EIP bits 12 and higher
|
||||
* stay the same across the translation block. Add the CS base back before
|
||||
* replacing the low bits, and subtract it below just like for !CF_PCREL.
|
||||
*/
|
||||
uint64_t pc = env->eip + tb->cs_base;
|
||||
new_pc = (pc & TARGET_PAGE_MASK) | data[0];
|
||||
} else {
|
||||
env->eip = data[0] - tb->cs_base;
|
||||
new_pc = data[0];
|
||||
}
|
||||
if (tb->flags & HF_CS64_MASK) {
|
||||
env->eip = new_pc;
|
||||
} else {
|
||||
env->eip = (uint32_t)(new_pc - tb->cs_base);
|
||||
}
|
||||
|
||||
if (cc_op != CC_OP_DYNAMIC) {
|
||||
env->cc_op = cc_op;
|
||||
}
|
||||
|
||||
@@ -547,8 +547,10 @@ static void gen_update_eip_cur(DisasContext *s)
|
||||
assert(s->pc_save != -1);
|
||||
if (TARGET_TB_PCREL) {
|
||||
tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save);
|
||||
} else if (CODE64(s)) {
|
||||
tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base);
|
||||
tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
|
||||
}
|
||||
s->pc_save = s->base.pc_next;
|
||||
}
|
||||
@@ -558,8 +560,10 @@ static void gen_update_eip_next(DisasContext *s)
|
||||
assert(s->pc_save != -1);
|
||||
if (TARGET_TB_PCREL) {
|
||||
tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
|
||||
} else if (CODE64(s)) {
|
||||
tcg_gen_movi_tl(cpu_eip, s->pc);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base);
|
||||
tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->pc - s->cs_base));
|
||||
}
|
||||
s->pc_save = s->pc;
|
||||
}
|
||||
@@ -605,8 +609,10 @@ static TCGv eip_next_tl(DisasContext *s)
|
||||
TCGv ret = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
|
||||
return ret;
|
||||
} else if (CODE64(s)) {
|
||||
return tcg_constant_tl(s->pc);
|
||||
} else {
|
||||
return tcg_constant_tl(s->pc - s->cs_base);
|
||||
return tcg_constant_tl((uint32_t)(s->pc - s->cs_base));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,8 +623,10 @@ static TCGv eip_cur_tl(DisasContext *s)
|
||||
TCGv ret = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save);
|
||||
return ret;
|
||||
} else if (CODE64(s)) {
|
||||
return tcg_constant_tl(s->base.pc_next);
|
||||
} else {
|
||||
return tcg_constant_tl(s->base.pc_next - s->cs_base);
|
||||
return tcg_constant_tl((uint32_t)(s->base.pc_next - s->cs_base));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2890,10 +2898,11 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
|
||||
tcg_gen_andi_tl(cpu_eip, cpu_eip, mask);
|
||||
use_goto_tb = false;
|
||||
}
|
||||
} else if (!CODE64(s)) {
|
||||
new_pc = (uint32_t)(new_eip + s->cs_base);
|
||||
}
|
||||
|
||||
if (use_goto_tb &&
|
||||
translator_use_goto_tb(&s->base, new_eip + s->cs_base)) {
|
||||
if (use_goto_tb && translator_use_goto_tb(&s->base, new_pc)) {
|
||||
/* jump to same page: we can use a direct jump */
|
||||
tcg_gen_goto_tb(tb_num);
|
||||
if (!TARGET_TB_PCREL) {
|
||||
@@ -6974,7 +6983,6 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||
|
||||
dc->prev_insn_end = tcg_last_op();
|
||||
if (TARGET_TB_PCREL) {
|
||||
pc_arg -= dc->cs_base;
|
||||
pc_arg &= ~TARGET_PAGE_MASK;
|
||||
}
|
||||
tcg_gen_insn_start(pc_arg, dc->cc_op);
|
||||
|
||||
+7
-7
@@ -697,11 +697,11 @@ static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val)
|
||||
static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
|
||||
bool upper_half, uint32_t ctr_idx)
|
||||
{
|
||||
PMUCTRState counter = env->pmu_ctrs[ctr_idx];
|
||||
target_ulong ctr_prev = upper_half ? counter.mhpmcounterh_prev :
|
||||
counter.mhpmcounter_prev;
|
||||
target_ulong ctr_val = upper_half ? counter.mhpmcounterh_val :
|
||||
counter.mhpmcounter_val;
|
||||
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
|
||||
target_ulong ctr_prev = upper_half ? counter->mhpmcounterh_prev :
|
||||
counter->mhpmcounter_prev;
|
||||
target_ulong ctr_val = upper_half ? counter->mhpmcounterh_val :
|
||||
counter->mhpmcounter_val;
|
||||
|
||||
if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
|
||||
/**
|
||||
@@ -709,12 +709,12 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
|
||||
* stop the icount counting. Just return the counter value written by
|
||||
* the supervisor to indicate that counter was not incremented.
|
||||
*/
|
||||
if (!counter.started) {
|
||||
if (!counter->started) {
|
||||
*val = ctr_val;
|
||||
return RISCV_EXCP_NONE;
|
||||
} else {
|
||||
/* Mark that the counter has been stopped */
|
||||
counter.started = false;
|
||||
counter->started = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3394,6 +3394,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int b2 = get_field(s, b2);
|
||||
TCGv ar1 = tcg_temp_new_i64();
|
||||
int r1 = get_field(s, r1);
|
||||
|
||||
o->out = o->in2;
|
||||
o->g_out = o->g_in2;
|
||||
@@ -3419,7 +3420,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o)
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1]));
|
||||
tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
|
||||
tcg_temp_free_i64(ar1);
|
||||
|
||||
return DISAS_NEXT;
|
||||
|
||||
+35
-12
@@ -226,22 +226,31 @@ static void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v,
|
||||
* Split TLB address into TLB way, entry index and VPN (with index).
|
||||
* See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
|
||||
*/
|
||||
static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
|
||||
uint32_t *vpn, uint32_t *wi, uint32_t *ei)
|
||||
static bool split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
|
||||
uint32_t *vpn, uint32_t *wi, uint32_t *ei)
|
||||
{
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
|
||||
*wi = v & (dtlb ? 0xf : 0x7);
|
||||
split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
|
||||
if (*wi < (dtlb ? env->config->dtlb.nways : env->config->itlb.nways)) {
|
||||
split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*vpn = v & REGION_PAGE_MASK;
|
||||
*wi = 0;
|
||||
*ei = (v >> 29) & 0x7;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb,
|
||||
unsigned wi, unsigned ei)
|
||||
{
|
||||
const xtensa_tlb *tlb = dtlb ? &env->config->dtlb : &env->config->itlb;
|
||||
|
||||
assert(wi < tlb->nways && ei < tlb->way_size[wi]);
|
||||
return dtlb ?
|
||||
env->dtlb[wi] + ei :
|
||||
env->itlb[wi] + ei;
|
||||
@@ -254,11 +263,14 @@ static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
|
||||
uint32_t wi;
|
||||
uint32_t ei;
|
||||
|
||||
split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
|
||||
if (pwi) {
|
||||
*pwi = wi;
|
||||
if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
|
||||
if (pwi) {
|
||||
*pwi = wi;
|
||||
}
|
||||
return xtensa_tlb_get_entry(env, dtlb, wi, ei);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return xtensa_tlb_get_entry(env, dtlb, wi, ei);
|
||||
}
|
||||
|
||||
static void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
|
||||
@@ -484,7 +496,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
|
||||
uint32_t wi;
|
||||
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
|
||||
return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
|
||||
|
||||
if (entry) {
|
||||
return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return v & REGION_PAGE_MASK;
|
||||
}
|
||||
@@ -493,7 +510,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
|
||||
uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
|
||||
{
|
||||
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
|
||||
return entry->paddr | entry->attr;
|
||||
|
||||
if (entry) {
|
||||
return entry->paddr | entry->attr;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
|
||||
@@ -501,7 +523,7 @@ void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
|
||||
uint32_t wi;
|
||||
xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
|
||||
if (entry->variable && entry->asid) {
|
||||
if (entry && entry->variable && entry->asid) {
|
||||
tlb_flush_page(env_cpu(env), entry->vaddr);
|
||||
entry->asid = 0;
|
||||
}
|
||||
@@ -539,8 +561,9 @@ void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
|
||||
uint32_t vpn;
|
||||
uint32_t wi;
|
||||
uint32_t ei;
|
||||
split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
|
||||
xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
|
||||
if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
|
||||
xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -421,8 +421,8 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}}
|
||||
write failed: Input/output error
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Testing incoming inactive corrupted image ===
|
||||
|
||||
@@ -432,8 +432,8 @@ QMP_VERSION
|
||||
qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}}
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
corrupt: false
|
||||
*** done
|
||||
|
||||
@@ -45,8 +45,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
read failed: Input/output error
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Testing blkverify on existing block device ===
|
||||
@@ -84,9 +84,9 @@ wrote 512/512 bytes at offset 0
|
||||
{"return": ""}
|
||||
read failed: Input/output error
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
|
||||
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
|
||||
{"return": {}}
|
||||
|
||||
*** done
|
||||
|
||||
@@ -35,8 +35,8 @@ QMP_VERSION
|
||||
read 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
== using quorum rewrite corrupted mode ==
|
||||
@@ -67,8 +67,8 @@ QMP_VERSION
|
||||
read 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
-- checking that the image has been corrected --
|
||||
read 10485760/10485760 bytes at offset 0
|
||||
@@ -106,8 +106,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
@@ -115,8 +115,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
== dynamically removing a child from a quorum ==
|
||||
@@ -125,31 +125,31 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
|
||||
{"error": {"class": "GenericError", "desc": "Cannot find device='drive0-quorum' nor node-name='drive0-quorum'"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
*** done
|
||||
|
||||
@@ -7,8 +7,8 @@ Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Duplicate ID ===
|
||||
@@ -18,8 +18,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
|
||||
{"error": {"class": "GenericError", "desc": "Duplicate nodes with node-name='test-node'"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== aio=native without O_DIRECT ===
|
||||
@@ -28,8 +28,8 @@ Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Encrypted image QCow ===
|
||||
@@ -40,8 +40,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Encrypted image LUKS ===
|
||||
@@ -52,8 +52,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Missing driver ===
|
||||
@@ -63,7 +63,7 @@ Testing: -S
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
*** done
|
||||
|
||||
@@ -173,8 +173,8 @@ OK: Reftable is where we expect it
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}}
|
||||
{"return": {}}
|
||||
{ "execute": "quit" }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
@@ -57,13 +57,13 @@ run_qemu()
|
||||
_launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},aio=${AIOMODE},id=src
|
||||
_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return"
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
capture_events="$qmp_event" _send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': '$raw_img', $qmp_format
|
||||
'mode': 'existing', 'sync': 'full'}}" \
|
||||
"return"
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE '' "$qmp_event"
|
||||
capture_events="$qmp_event JOB_STATUS_CHANGE" _wait_event $QEMU_HANDLE "$qmp_event"
|
||||
if test "$qmp_event" = BLOCK_JOB_ERROR; then
|
||||
_send_qemu_cmd $QEMU_HANDLE '' '"status": "null"'
|
||||
fi
|
||||
|
||||
+33
-45
@@ -7,7 +7,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -23,8 +23,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -35,12 +35,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -48,6 +46,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Writing a qcow2 header into raw ===
|
||||
@@ -57,7 +56,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -73,8 +72,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -85,12 +84,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -98,6 +95,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Writing a qed header into raw ===
|
||||
@@ -107,7 +105,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -123,8 +121,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -135,12 +133,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -148,6 +144,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Writing a vdi header into raw ===
|
||||
@@ -157,7 +154,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -173,8 +170,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -185,12 +182,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -198,6 +193,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Writing a vmdk header into raw ===
|
||||
@@ -207,7 +203,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -223,8 +219,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -235,12 +231,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -248,6 +242,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Writing a vpc header into raw ===
|
||||
@@ -257,7 +252,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -273,8 +268,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -285,12 +280,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -298,6 +291,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Copying sample image empty.bochs into raw ===
|
||||
@@ -306,7 +300,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -322,8 +316,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -334,12 +328,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -347,6 +339,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
|
||||
@@ -355,7 +348,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -371,8 +364,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -383,12 +376,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -396,6 +387,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Copying sample image parallels-v1 into raw ===
|
||||
@@ -404,7 +396,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -420,8 +412,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -432,12 +424,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -445,6 +435,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Copying sample image simple-pattern.cloop into raw ===
|
||||
@@ -453,7 +444,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -469,8 +460,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": []}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
@@ -481,12 +472,10 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -494,6 +483,7 @@ read 512/512 bytes at offset 0
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
|
||||
=== Write legitimate MBR into raw ===
|
||||
@@ -502,7 +492,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
{'execute':'drive-mirror', 'arguments':{
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
|
||||
'mode': 'existing', 'sync': 'full'}}
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
@@ -510,12 +500,10 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -523,6 +511,7 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{"return": {}}
|
||||
@@ -532,12 +521,10 @@ Images are identical.
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
|
||||
{"execute":"query-block-jobs"}
|
||||
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
|
||||
@@ -545,5 +532,6 @@ Images are identical.
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
|
||||
{"return": {}}
|
||||
Images are identical.
|
||||
*** done
|
||||
|
||||
@@ -18,8 +18,8 @@ wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": ""}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
No errors were found on the image.
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
@@ -5,8 +5,8 @@ QMP_VERSION
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{"return": ""}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
|
||||
@@ -28,6 +28,6 @@ wrote 42/42 bytes at offset 0
|
||||
{ 'execute': 'quit' }
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "mirror"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -19,6 +19,6 @@ read 65536/65536 bytes at offset 0
|
||||
qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available
|
||||
server reported: export 'drv' not present
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
+114
-159
@@ -1,9 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env python3
|
||||
# group: rw auto quick
|
||||
#
|
||||
# Test case for ejecting BDSs with block jobs still running on them
|
||||
#
|
||||
# Copyright (C) 2016 Red Hat, Inc.
|
||||
# Originally written in bash by Hanna Czenczek, ported to Python by Stefan
|
||||
# Hajnoczi.
|
||||
#
|
||||
# Copyright Red Hat
|
||||
#
|
||||
# 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
|
||||
@@ -19,177 +22,129 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=hreitz@redhat.com
|
||||
import iotests
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_qemu
|
||||
_cleanup_test_img
|
||||
for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
|
||||
_rm_test_img "$img"
|
||||
done
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.qemu
|
||||
|
||||
# Needs backing file and backing format support
|
||||
_supported_fmt qcow2 qed
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
# Common filters to mask values that vary in the test output
|
||||
QMP_FILTERS = [iotests.filter_qmp_testfiles, \
|
||||
iotests.filter_qmp_imgfmt]
|
||||
|
||||
|
||||
test_blockjob()
|
||||
{
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': '$IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': '$TEST_IMG'
|
||||
}}}" \
|
||||
'return'
|
||||
class TestCase:
|
||||
def __init__(self, name, vm, image_path, cancel_event):
|
||||
self.name = name
|
||||
self.vm = vm
|
||||
self.image_path = image_path
|
||||
self.cancel_event = cancel_event
|
||||
|
||||
# If "$2" is an event, we may or may not see it before the
|
||||
# {"return": {}}. Therefore, filter the {"return": {}} out both
|
||||
# here and in the next command. (Naturally, if we do not see it
|
||||
# here, we will see it before the next command can be executed,
|
||||
# so it will appear in the next _send_qemu_cmd's output.)
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"$1" \
|
||||
"$2" \
|
||||
| _filter_img_create | _filter_qmp_empty_return
|
||||
def __enter__(self):
|
||||
iotests.log(f'=== Testing {self.name} ===')
|
||||
self.vm.qmp_log('blockdev-add', \
|
||||
node_name='drv0', \
|
||||
driver=iotests.imgfmt, \
|
||||
file={'driver': 'file', 'filename': self.image_path}, \
|
||||
filters=QMP_FILTERS)
|
||||
|
||||
# We want this to return an error because the block job is still running
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}" \
|
||||
'error' | _filter_generated_node_ids | _filter_qmp_empty_return
|
||||
def __exit__(self, *exc_details):
|
||||
# This is expected to fail because the job still exists
|
||||
self.vm.qmp_log('blockdev-del', node_name='drv0', \
|
||||
filters=[iotests.filter_qmp_generated_node_ids])
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}" \
|
||||
"$3"
|
||||
self.vm.qmp_log('block-job-cancel', device='job0')
|
||||
event = self.vm.event_wait(self.cancel_event)
|
||||
iotests.log(event, filters=[iotests.filter_qmp_event])
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}" \
|
||||
'return'
|
||||
}
|
||||
# This time it succeeds
|
||||
self.vm.qmp_log('blockdev-del', node_name='drv0')
|
||||
|
||||
# Separate test cases in output
|
||||
iotests.log('')
|
||||
|
||||
|
||||
TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
|
||||
TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M
|
||||
_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT
|
||||
def main() -> None:
|
||||
with iotests.FilePath('bottom', 'middle', 'top', 'target') as \
|
||||
(bottom_path, middle_path, top_path, target_path), \
|
||||
iotests.VM() as vm:
|
||||
|
||||
_launch_qemu -nodefaults
|
||||
iotests.log('Creating bottom <- middle <- top backing file chain...')
|
||||
IMAGE_SIZE='1M'
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, bottom_path, IMAGE_SIZE)
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, \
|
||||
'-F', iotests.imgfmt, \
|
||||
'-b', bottom_path, \
|
||||
middle_path, \
|
||||
IMAGE_SIZE)
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, \
|
||||
'-F', iotests.imgfmt, \
|
||||
'-b', middle_path, \
|
||||
top_path, \
|
||||
IMAGE_SIZE)
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'qmp_capabilities'}" \
|
||||
'return'
|
||||
iotests.log('Starting VM...')
|
||||
vm.add_args('-nodefaults')
|
||||
vm.launch()
|
||||
|
||||
echo
|
||||
echo '=== Testing drive-backup ==='
|
||||
echo
|
||||
# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling
|
||||
# the job will consequently result in BLOCK_JOB_CANCELLED being
|
||||
# emitted.
|
||||
with TestCase('drive-backup', vm, top_path, 'BLOCK_JOB_CANCELLED'):
|
||||
vm.qmp_log('drive-backup', \
|
||||
job_id='job0', \
|
||||
device='drv0', \
|
||||
target=target_path, \
|
||||
format=iotests.imgfmt, \
|
||||
sync='none', \
|
||||
filters=QMP_FILTERS)
|
||||
|
||||
# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
|
||||
# will consequently result in BLOCK_JOB_CANCELLED being emitted.
|
||||
# drive-mirror will send BLOCK_JOB_READY basically immediately, and
|
||||
# cancelling the job will consequently result in BLOCK_JOB_COMPLETED
|
||||
# being emitted.
|
||||
with TestCase('drive-mirror', vm, top_path, 'BLOCK_JOB_COMPLETED'):
|
||||
vm.qmp_log('drive-mirror', \
|
||||
job_id='job0', \
|
||||
device='drv0', \
|
||||
target=target_path, \
|
||||
format=iotests.imgfmt, \
|
||||
sync='none', \
|
||||
filters=QMP_FILTERS)
|
||||
event = vm.event_wait('BLOCK_JOB_READY')
|
||||
assert event is not None # silence mypy
|
||||
iotests.log(event, filters=[iotests.filter_qmp_event])
|
||||
|
||||
test_blockjob \
|
||||
"{'execute': 'drive-backup',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'target': '$TEST_DIR/o.$IMGFMT',
|
||||
'format': '$IMGFMT',
|
||||
'sync': 'none'}}" \
|
||||
'return' \
|
||||
'"status": "null"'
|
||||
# An active block-commit will send BLOCK_JOB_READY basically
|
||||
# immediately, and cancelling the job will consequently result in
|
||||
# BLOCK_JOB_COMPLETED being emitted.
|
||||
with TestCase('active block-commit', vm, top_path, \
|
||||
'BLOCK_JOB_COMPLETED'):
|
||||
vm.qmp_log('block-commit', \
|
||||
job_id='job0', \
|
||||
device='drv0')
|
||||
event = vm.event_wait('BLOCK_JOB_READY')
|
||||
assert event is not None # silence mypy
|
||||
iotests.log(event, filters=[iotests.filter_qmp_event])
|
||||
|
||||
echo
|
||||
echo '=== Testing drive-mirror ==='
|
||||
echo
|
||||
# Give block-commit something to work on, otherwise it would be done
|
||||
# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
|
||||
# work just fine without the block job still running.
|
||||
iotests.qemu_io(middle_path, '-c', f'write 0 {IMAGE_SIZE}')
|
||||
with TestCase('non-active block-commit', vm, top_path, \
|
||||
'BLOCK_JOB_CANCELLED'):
|
||||
vm.qmp_log('block-commit', \
|
||||
job_id='job0', \
|
||||
device='drv0', \
|
||||
top=middle_path, \
|
||||
speed=1, \
|
||||
filters=[iotests.filter_qmp_testfiles])
|
||||
|
||||
# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
|
||||
# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
|
||||
# Give block-stream something to work on, otherwise it would be done
|
||||
# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
|
||||
# work just fine without the block job still running.
|
||||
iotests.qemu_io(bottom_path, '-c', f'write 0 {IMAGE_SIZE}')
|
||||
with TestCase('block-stream', vm, top_path, 'BLOCK_JOB_CANCELLED'):
|
||||
vm.qmp_log('block-stream', \
|
||||
job_id='job0', \
|
||||
device='drv0', \
|
||||
speed=1)
|
||||
|
||||
test_blockjob \
|
||||
"{'execute': 'drive-mirror',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'target': '$TEST_DIR/o.$IMGFMT',
|
||||
'format': '$IMGFMT',
|
||||
'sync': 'none'}}" \
|
||||
'BLOCK_JOB_READY' \
|
||||
'"status": "null"'
|
||||
|
||||
echo
|
||||
echo '=== Testing active block-commit ==='
|
||||
echo
|
||||
|
||||
# An active block-commit will send BLOCK_JOB_READY basically immediately, and
|
||||
# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
|
||||
# emitted.
|
||||
|
||||
test_blockjob \
|
||||
"{'execute': 'block-commit',
|
||||
'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \
|
||||
'BLOCK_JOB_READY' \
|
||||
'"status": "null"'
|
||||
|
||||
echo
|
||||
echo '=== Testing non-active block-commit ==='
|
||||
echo
|
||||
|
||||
# Give block-commit something to work on, otherwise it would be done
|
||||
# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
|
||||
# fine without the block job still running.
|
||||
|
||||
$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
|
||||
|
||||
test_blockjob \
|
||||
"{'execute': 'block-commit',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'top': '$TEST_DIR/m.$IMGFMT',
|
||||
'speed': 1}}" \
|
||||
'return' \
|
||||
'"status": "null"'
|
||||
|
||||
echo
|
||||
echo '=== Testing block-stream ==='
|
||||
echo
|
||||
|
||||
# Give block-stream something to work on, otherwise it would be done
|
||||
# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
|
||||
# fine without the block job still running.
|
||||
|
||||
$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
|
||||
|
||||
# With some data to stream (and @speed set to 1), block-stream will not complete
|
||||
# until we send the block-job-cancel command.
|
||||
|
||||
test_blockjob \
|
||||
"{'execute': 'block-stream',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'speed': 1}}" \
|
||||
'return' \
|
||||
'"status": "null"'
|
||||
|
||||
_cleanup_qemu
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
||||
if __name__ == '__main__':
|
||||
iotests.script_main(main, supported_fmts=['qcow2', 'qed'],
|
||||
supported_protocols=['file'])
|
||||
|
||||
+40
-150
@@ -1,179 +1,69 @@
|
||||
QA output created by 141
|
||||
Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
|
||||
Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT
|
||||
{'execute': 'qmp_capabilities'}
|
||||
{"return": {}}
|
||||
|
||||
Creating bottom <- middle <- top backing file chain...
|
||||
Starting VM...
|
||||
=== Testing drive-backup ===
|
||||
|
||||
{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': 'IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': 'TEST_DIR/t.IMGFMT'
|
||||
}}}
|
||||
{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
{'execute': 'drive-backup',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'target': 'TEST_DIR/o.IMGFMT',
|
||||
'format': 'IMGFMT',
|
||||
'sync': 'none'}}
|
||||
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"execute": "drive-backup", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
|
||||
{"return": {}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
|
||||
{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}
|
||||
{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Testing drive-mirror ===
|
||||
|
||||
{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': 'IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': 'TEST_DIR/t.IMGFMT'
|
||||
}}}
|
||||
{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
{'execute': 'drive-mirror',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'target': 'TEST_DIR/o.IMGFMT',
|
||||
'format': 'IMGFMT',
|
||||
'sync': 'none'}}
|
||||
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"execute": "drive-mirror", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
|
||||
{"return": {}}
|
||||
{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
|
||||
{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}
|
||||
{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Testing active block-commit ===
|
||||
|
||||
{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': 'IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': 'TEST_DIR/t.IMGFMT'
|
||||
}}}
|
||||
{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
{'execute': 'block-commit',
|
||||
'arguments': {'job-id': 'job0', 'device': 'drv0'}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0"}}
|
||||
{"return": {}}
|
||||
{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
|
||||
{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}
|
||||
{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Testing non-active block-commit ===
|
||||
|
||||
wrote 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': 'IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': 'TEST_DIR/t.IMGFMT'
|
||||
}}}
|
||||
{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
{'execute': 'block-commit',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'top': 'TEST_DIR/m.IMGFMT',
|
||||
'speed': 1}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1, "top": "TEST_DIR/PID-middle"}}
|
||||
{"return": {}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
|
||||
{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}
|
||||
{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Testing block-stream ===
|
||||
|
||||
wrote 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{'execute': 'blockdev-add',
|
||||
'arguments': {
|
||||
'node-name': 'drv0',
|
||||
'driver': 'IMGFMT',
|
||||
'file': {
|
||||
'driver': 'file',
|
||||
'filename': 'TEST_DIR/t.IMGFMT'
|
||||
}}}
|
||||
{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
{'execute': 'block-stream',
|
||||
'arguments': {'job-id': 'job0',
|
||||
'device': 'drv0',
|
||||
'speed': 1}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"execute": "block-stream", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1}}
|
||||
{"return": {}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
|
||||
{'execute': 'block-job-cancel',
|
||||
'arguments': {'device': 'job0'}}
|
||||
{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}
|
||||
{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@ server reported: export 'no_such_export' not present
|
||||
qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available
|
||||
server reported: export 'aa--aa...' not present
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -72,8 +72,8 @@ read 65536/65536 bytes at offset 196608
|
||||
{"return": ""}
|
||||
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
@@ -169,8 +169,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
@@ -206,8 +206,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {"sha256": HASH}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Test pass bitmap.1 ===
|
||||
|
||||
@@ -218,8 +218,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
@@ -256,8 +256,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {"sha256": HASH}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Test pass bitmap.2 ===
|
||||
|
||||
@@ -268,8 +268,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
@@ -306,8 +306,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {"sha256": HASH}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Test pass bitmap.3 ===
|
||||
|
||||
@@ -318,8 +318,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
@@ -353,6 +353,6 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {"sha256": HASH}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -53,6 +53,6 @@ Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=
|
||||
{'execute': 'qmp_capabilities'}
|
||||
{"return": {}}
|
||||
{'execute': 'quit'}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -53,11 +53,11 @@ wrote 65536/65536 bytes at offset 1048576
|
||||
=== Shut down and check image ===
|
||||
|
||||
{"execute":"quit"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
{"execute":"quit"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
No errors were found on the image.
|
||||
No errors were found on the image.
|
||||
wrote 65536/65536 bytes at offset 1048576
|
||||
|
||||
+16
-16
@@ -89,10 +89,6 @@ Testing:
|
||||
"return": [
|
||||
]
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -104,6 +100,10 @@ Testing:
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
== property changes in ThrottleGroup ==
|
||||
@@ -169,10 +169,6 @@ Testing:
|
||||
"iops-total-max": 0
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -184,6 +180,10 @@ Testing:
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
== object creation/set errors ==
|
||||
@@ -211,10 +211,6 @@ Testing:
|
||||
"desc": "bps/iops/max total values and read/write values cannot be used at the same time"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -226,6 +222,10 @@ Testing:
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
== don't specify group ==
|
||||
@@ -247,10 +247,6 @@ Testing:
|
||||
"desc": "Parameter 'throttle-group' is missing"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -262,6 +258,10 @@ Testing:
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*** done
|
||||
|
||||
@@ -344,14 +344,14 @@ wait_for_job_and_quit() {
|
||||
|
||||
sleep 1
|
||||
|
||||
# List of expected events
|
||||
capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
|
||||
|
||||
_send_qemu_cmd $h \
|
||||
'{"execute": "quit"}' \
|
||||
'return'
|
||||
|
||||
# List of expected events
|
||||
capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
|
||||
_wait_event $h 'SHUTDOWN'
|
||||
QEMU_EVENTS= # Ignore all JOB_STATUS_CHANGE events that came before SHUTDOWN
|
||||
_wait_event $h 'JOB_STATUS_CHANGE' # standby
|
||||
_wait_event $h 'JOB_STATUS_CHANGE' # ready
|
||||
_wait_event $h 'JOB_STATUS_CHANGE' # aborting
|
||||
|
||||
@@ -40,9 +40,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Start active commit job and exit qemu ===
|
||||
|
||||
@@ -56,9 +63,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Start mirror job and exit qemu ===
|
||||
|
||||
@@ -75,9 +89,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Start backup job and exit qemu ===
|
||||
|
||||
@@ -97,9 +118,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 65536, "speed": 65536, "type": "backup"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Start streaming job and exit qemu ===
|
||||
|
||||
@@ -112,9 +140,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"return": {}}
|
||||
{ 'execute': 'quit' }
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "stream"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
|
||||
{"return": {}}
|
||||
No errors were found on the image.
|
||||
|
||||
=== Start mirror to throttled QSD and exit qemu ===
|
||||
|
||||
@@ -378,10 +378,6 @@ wrote 65536/65536 bytes at offset 1048576
|
||||
]
|
||||
}
|
||||
{ 'execute': 'quit' }
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -393,6 +389,10 @@ wrote 65536/65536 bytes at offset 1048576
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
@@ -796,10 +796,6 @@ wrote 65536/65536 bytes at offset 1048576
|
||||
]
|
||||
}
|
||||
{ 'execute': 'quit' }
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -811,6 +807,10 @@ wrote 65536/65536 bytes at offset 1048576
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
|
||||
@@ -17,10 +17,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -32,6 +28,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
image: TEST_DIR/t.IMGFMT.mid
|
||||
file format: IMGFMT
|
||||
@@ -55,10 +55,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -70,6 +66,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
|
||||
@@ -11,8 +11,8 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
|
||||
=== Write part of the file under active bitmap ===
|
||||
@@ -142,14 +142,14 @@ read 2097152/2097152 bytes at offset 2097152
|
||||
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
|
||||
{"execute":"nbd-server-stop"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
|
||||
@@ -261,14 +261,14 @@ read 2097152/2097152 bytes at offset 2097152
|
||||
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
|
||||
{"return": {}}
|
||||
{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}
|
||||
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
|
||||
{"execute":"nbd-server-stop"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
|
||||
@@ -276,8 +276,8 @@ read 2097152/2097152 bytes at offset 2097152
|
||||
{"execute":"nbd-server-stop"}
|
||||
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
|
||||
{"execute":"quit"}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Use qemu-nbd as server ===
|
||||
|
||||
|
||||
+16
-16
@@ -48,10 +48,6 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -63,6 +59,10 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=== blockstats with -drive if=none ===
|
||||
@@ -112,10 +112,6 @@ Testing: -drive driver=null-co,if=none
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -127,6 +123,10 @@ Testing: -drive driver=null-co,if=none
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=== blockstats with -blockdev ===
|
||||
@@ -143,10 +143,6 @@ Testing: -blockdev driver=null-co,node-name=null
|
||||
"return": [
|
||||
]
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -158,6 +154,10 @@ Testing: -blockdev driver=null-co,node-name=null
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=== blockstats with -blockdev and -device ===
|
||||
@@ -208,10 +208,6 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -223,5 +219,9 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
*** done
|
||||
|
||||
@@ -17,6 +17,6 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -282,10 +282,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
{
|
||||
"timestamp": {
|
||||
"seconds": TIMESTAMP,
|
||||
@@ -297,5 +293,9 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
|
||||
"reason": "host-qmp-quit"
|
||||
}
|
||||
}
|
||||
{
|
||||
"return": {
|
||||
}
|
||||
}
|
||||
|
||||
*** done
|
||||
|
||||
@@ -77,6 +77,7 @@ fuse_export_add()
|
||||
# $1: Export ID
|
||||
fuse_export_del()
|
||||
{
|
||||
capture_events="BLOCK_EXPORT_DELETED" \
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'block-export-del',
|
||||
'arguments': {
|
||||
@@ -84,8 +85,7 @@ fuse_export_del()
|
||||
} }" \
|
||||
'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
'' \
|
||||
_wait_event $QEMU_HANDLE \
|
||||
'BLOCK_EXPORT_DELETED'
|
||||
}
|
||||
|
||||
|
||||
@@ -165,9 +165,9 @@ OK: Post-truncate image size is as expected
|
||||
|
||||
=== Tear down ===
|
||||
{'execute': 'quit'}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Compare copy with original ===
|
||||
Images are identical.
|
||||
|
||||
@@ -642,6 +642,13 @@ def filter_qmp_virtio_scsi(qmsg):
|
||||
def filter_generated_node_ids(msg):
|
||||
return re.sub("#block[0-9]+", "NODE_NAME", msg)
|
||||
|
||||
def filter_qmp_generated_node_ids(qmsg):
|
||||
def _filter(_key, value):
|
||||
if is_str(value):
|
||||
return filter_generated_node_ids(value)
|
||||
return value
|
||||
return filter_qmp(qmsg, _filter)
|
||||
|
||||
def filter_img_info(output, filename):
|
||||
lines = []
|
||||
for line in output.split('\n'):
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
# group: rw quick
|
||||
#
|
||||
# Test case for internal snapshots in qcow2
|
||||
#
|
||||
# Copyright (C) 2023 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=kwolf@redhat.com
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ../common.rc
|
||||
. ../common.filter
|
||||
|
||||
# This tests qcow2-specific low-level functionality
|
||||
_supported_fmt qcow2
|
||||
_supported_proto generic
|
||||
# Internal snapshots are (currently) impossible with refcount_bits=1,
|
||||
# and generally impossible with external data files
|
||||
_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
|
||||
|
||||
IMG_SIZE=64M
|
||||
|
||||
_qemu()
|
||||
{
|
||||
$QEMU -no-shutdown -nographic -monitor stdio -serial none \
|
||||
-blockdev file,filename="$TEST_IMG",node-name=disk0-file \
|
||||
-blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \
|
||||
-object iothread,id=iothread0 \
|
||||
-device virtio-scsi,iothread=iothread0 \
|
||||
-device scsi-hd,drive=disk0,share-rw=on \
|
||||
"$@" 2>&1 |\
|
||||
_filter_qemu | _filter_hmp | _filter_qemu_io
|
||||
}
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
|
||||
echo
|
||||
echo "=== Write some data, take a snapshot and overwrite part of it ==="
|
||||
echo
|
||||
|
||||
{
|
||||
echo 'qemu-io disk0 "write -P0x11 0 1M"'
|
||||
# Give qemu some time to boot before saving the VM state
|
||||
sleep 0.5
|
||||
echo "savevm snap0"
|
||||
echo 'qemu-io disk0 "write -P0x22 0 512k"'
|
||||
echo "quit"
|
||||
} | _qemu
|
||||
|
||||
echo
|
||||
$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo "=== Verify that loading the snapshot reverts to the old content ==="
|
||||
echo
|
||||
|
||||
{
|
||||
# -loadvm reverted the write from the previous QEMU instance
|
||||
echo 'qemu-io disk0 "read -P0x11 0 1M"'
|
||||
|
||||
# Verify that it works without restarting QEMU, too
|
||||
echo 'qemu-io disk0 "write -P0x33 512k 512k"'
|
||||
echo "loadvm snap0"
|
||||
echo 'qemu-io disk0 "read -P0x11 0 1M"'
|
||||
|
||||
# Verify COW by writing a partial cluster
|
||||
echo 'qemu-io disk0 "write -P0x33 63k 2k"'
|
||||
echo 'qemu-io disk0 "read -P0x11 0 63k"'
|
||||
echo 'qemu-io disk0 "read -P0x33 63k 2k"'
|
||||
echo 'qemu-io disk0 "read -P0x11 65k 63k"'
|
||||
|
||||
# Take a second snapshot
|
||||
echo "savevm snap1"
|
||||
|
||||
echo "quit"
|
||||
} | _qemu -loadvm snap0
|
||||
|
||||
echo
|
||||
$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo "=== qemu-img snapshot can revert to snapshots ==="
|
||||
echo
|
||||
|
||||
$QEMU_IMG snapshot -a snap0 "$TEST_IMG"
|
||||
$QEMU_IO -c "read -P0x11 0 1M" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IMG snapshot -a snap1 "$TEST_IMG"
|
||||
$QEMU_IO \
|
||||
-c "read -P0x11 0 63k" \
|
||||
-c "read -P0x33 63k 2k" \
|
||||
-c "read -P0x11 65k 63k" \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "=== Deleting snapshots ==="
|
||||
echo
|
||||
{
|
||||
# The active layer stays unaffected by deleting the snapshot
|
||||
echo "delvm snap1"
|
||||
echo 'qemu-io disk0 "read -P0x11 0 63k"'
|
||||
echo 'qemu-io disk0 "read -P0x33 63k 2k"'
|
||||
echo 'qemu-io disk0 "read -P0x11 65k 63k"'
|
||||
|
||||
echo "quit"
|
||||
} | _qemu
|
||||
|
||||
|
||||
echo
|
||||
$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo "=== Error cases ==="
|
||||
echo
|
||||
|
||||
# snap1 should not exist any more
|
||||
_qemu -loadvm snap1
|
||||
|
||||
echo
|
||||
{
|
||||
echo "loadvm snap1"
|
||||
echo "quit"
|
||||
} | _qemu
|
||||
|
||||
# Snapshot operations and inactive images are incompatible
|
||||
echo
|
||||
_qemu -loadvm snap0 -incoming defer
|
||||
{
|
||||
echo "loadvm snap0"
|
||||
echo "delvm snap0"
|
||||
echo "savevm snap1"
|
||||
echo "quit"
|
||||
} | _qemu -incoming defer
|
||||
|
||||
# -loadvm and -preconfig are incompatible
|
||||
echo
|
||||
_qemu -loadvm snap0 -preconfig
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
||||
@@ -0,0 +1,107 @@
|
||||
QA output created by qcow2-internal-snapshots
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
||||
=== Write some data, take a snapshot and overwrite part of it ===
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) qemu-io disk0 "write -P0x11 0 1M"
|
||||
wrote 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) savevm snap0
|
||||
(qemu) qemu-io disk0 "write -P0x22 0 512k"
|
||||
wrote 524288/524288 bytes at offset 0
|
||||
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) quit
|
||||
|
||||
Snapshot list:
|
||||
ID TAG VM SIZE DATE VM CLOCK ICOUNT
|
||||
1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
|
||||
No errors were found on the image.
|
||||
|
||||
=== Verify that loading the snapshot reverts to the old content ===
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) qemu-io disk0 "read -P0x11 0 1M"
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "write -P0x33 512k 512k"
|
||||
wrote 524288/524288 bytes at offset 524288
|
||||
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) loadvm snap0
|
||||
(qemu) qemu-io disk0 "read -P0x11 0 1M"
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "write -P0x33 63k 2k"
|
||||
wrote 2048/2048 bytes at offset 64512
|
||||
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "read -P0x11 0 63k"
|
||||
read 64512/64512 bytes at offset 0
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "read -P0x33 63k 2k"
|
||||
read 2048/2048 bytes at offset 64512
|
||||
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "read -P0x11 65k 63k"
|
||||
read 64512/64512 bytes at offset 66560
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) savevm snap1
|
||||
(qemu) quit
|
||||
|
||||
Snapshot list:
|
||||
ID TAG VM SIZE DATE VM CLOCK ICOUNT
|
||||
1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
|
||||
2 snap1 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
|
||||
No errors were found on the image.
|
||||
|
||||
=== qemu-img snapshot can revert to snapshots ===
|
||||
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 64512/64512 bytes at offset 0
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 2048/2048 bytes at offset 64512
|
||||
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 64512/64512 bytes at offset 66560
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Deleting snapshots ===
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) delvm snap1
|
||||
(qemu) qemu-io disk0 "read -P0x11 0 63k"
|
||||
read 64512/64512 bytes at offset 0
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "read -P0x33 63k 2k"
|
||||
read 2048/2048 bytes at offset 64512
|
||||
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) qemu-io disk0 "read -P0x11 65k 63k"
|
||||
read 64512/64512 bytes at offset 66560
|
||||
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
(qemu) quit
|
||||
|
||||
Snapshot list:
|
||||
ID TAG VM SIZE DATE VM CLOCK ICOUNT
|
||||
1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
|
||||
No errors were found on the image.
|
||||
|
||||
=== Error cases ===
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: Snapshot 'snap1' does not exist in one or more devices
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) loadvm snap1
|
||||
Error: Snapshot 'snap1' does not exist in one or more devices
|
||||
(qemu) quit
|
||||
|
||||
QEMU_PROG: 'incoming' and 'loadvm' options are mutually exclusive
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) loadvm snap0
|
||||
Error: Device 'disk0' is writable but does not support snapshots
|
||||
(qemu) delvm snap0
|
||||
Error: Device 'disk0' is writable but does not support snapshots
|
||||
(qemu) savevm snap1
|
||||
Error: Device 'disk0' is writable but does not support snapshots
|
||||
(qemu) quit
|
||||
|
||||
QEMU_PROG: 'preconfig' and 'loadvm' options are mutually exclusive
|
||||
*** done
|
||||
@@ -7,8 +7,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
|
||||
{"return": {}}
|
||||
|
||||
=== Streaming can't get permission on base node ===
|
||||
|
||||
@@ -17,6 +17,6 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
|
||||
{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt_base': permissions 'write' are both required by an unnamed block device (uses node 'fmt_base' as 'root' child) and unshared by stream job 'job0' (uses node 'fmt_base' as 'intermediate node' child)."}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
|
||||
@@ -6,6 +6,7 @@ endif
|
||||
|
||||
slow_qtests = {
|
||||
'ahci-test' : 60,
|
||||
'aspeed_smc-test': 360,
|
||||
'bios-tables-test' : 120,
|
||||
'boot-serial-test' : 60,
|
||||
'migration-test' : 150,
|
||||
|
||||
Reference in New Issue
Block a user