mirror of https://github.com/xemu-project/xemu.git
Block layer patches:
- block: Fix update of BDRV_O_AUTO_RDONLY in update_flags_from_options() - block: Fix option inheritance after stream/commit job graph changes - qemu-img: Fix memory leak and typo in error message - nvme: Fixes for lockups and crashes - scsi-disk: Fix crash if underlying host file or disk returns error - Several qemu-iotests fixes and improvements -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJb9vemAAoJEH8JsnLIjy/WWJQQAKiW7/Ku1i4DgZz6n97+HumE CryEgO/Hx9YnQPJPcEWNQVNtdO311rJSprLkmt83tOwQ1ew9lvqdcq9ptEUb4dW9 9bV31nP2nRkR3/cyLgWuYALH3Y6eSMwLQiYb0DaWKL2sxiMdghvK3gALXb3r+AtI F2uuQC6N6xNKj5srrTcxMman22QYIqkeuONWY9La9mQWG44WI5Gc+mF1LKMNk7x9 bBsvP5+ukm3O4+vvGylZjOXYpCgwQngSLvGG/rsHwBTBrDQiy3m1JoxxXzqr+Z4K p2b5wU2vFgfJ6cDGZJQWHQ/XAH3njmuPJEg+DOe7SUuGio2gQZCHlHU0xtp0GrQh BkYMfRUfb+rJ/t/mamX1y45XSBdvR0hJkgdgZYeHbFfV80Do63GqfqzOCDkKBocg /cbcDAvLiztoQpSa3aLMCHobs2X4Jn41ODUEidRbWsn3W099R2vIAUnxht/RI8Dm A5a7zfzXgMyEeXywxdCGM2k2oQsDnZoZLqNYJjkVmn3eqSIt3aLaSWtX0U7EVbEC PwNXAhz0Gl1YFhkgzEd8qkNH60lUb7Lone+3471iKACY0gjEeN5Ljsv/+HhaTQi/ a5HTAf+eUUO9OJt3DNE4pbUORDH0XMZBb3vTqfqf9a0iKWxXnuX25xm5YfVyagDi 54ZVHTqL+4zskS7uHD1O =dCUx -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - block: Fix update of BDRV_O_AUTO_RDONLY in update_flags_from_options() - block: Fix option inheritance after stream/commit job graph changes - qemu-img: Fix memory leak and typo in error message - nvme: Fixes for lockups and crashes - scsi-disk: Fix crash if underlying host file or disk returns error - Several qemu-iotests fixes and improvements # gpg: Signature made Thu 22 Nov 2018 18:38:30 GMT # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: block: Update BlockDriverState.inherits_from on bdrv_drop_intermediate() block: Update BlockDriverState.inherits_from on bdrv_set_backing_hd() iotests: Enhance 223 to cover multiple bitmap granularities nvme: fix bug with PCI IRQ pins on teardown nvme: fix CMB endianness confusion Revert "nvme: fix oob access issue(CVE-2018-16847)" nvme: fix out-of-bounds access to the CMB nvme: call blk_drain in NVMe reset code to avoid lockups iotests: fix nbd test 233 to work correctly with raw images block: Fix update of BDRV_O_AUTO_RDONLY in update_flags_from_options() scsi-disk: Fix crash if underlying host file or disk returns error qemu-img: Fix leak qemu-img: Fix typo iotests: Skip 233 if certtool not installed iotests: Replace assertEquals() with assertEqual() iotests: Replace time.clock() with Timeout Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5298f4d67a
41
block.c
41
block.c
|
@ -1137,7 +1137,7 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||||
|
|
||||||
static void update_flags_from_options(int *flags, QemuOpts *opts)
|
static void update_flags_from_options(int *flags, QemuOpts *opts)
|
||||||
{
|
{
|
||||||
*flags &= ~BDRV_O_CACHE_MASK;
|
*flags &= ~(BDRV_O_CACHE_MASK | BDRV_O_RDWR | BDRV_O_AUTO_RDONLY);
|
||||||
|
|
||||||
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
|
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
|
||||||
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
||||||
|
@ -1149,8 +1149,6 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
|
||||||
*flags |= BDRV_O_NOCACHE;
|
*flags |= BDRV_O_NOCACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*flags &= ~BDRV_O_RDWR;
|
|
||||||
|
|
||||||
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
|
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
|
||||||
if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
|
if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
|
||||||
*flags |= BDRV_O_RDWR;
|
*flags |= BDRV_O_RDWR;
|
||||||
|
@ -2262,6 +2260,18 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if you can reach parent going through child->inherits_from
|
||||||
|
* recursively. If parent or child are NULL, return false */
|
||||||
|
static bool bdrv_inherits_from_recursive(BlockDriverState *child,
|
||||||
|
BlockDriverState *parent)
|
||||||
|
{
|
||||||
|
while (child && child != parent) {
|
||||||
|
child = child->inherits_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
return child != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the backing file link of a BDS. A new reference is created; callers
|
* Sets the backing file link of a BDS. A new reference is created; callers
|
||||||
* which don't need their own reference any more must call bdrv_unref().
|
* which don't need their own reference any more must call bdrv_unref().
|
||||||
|
@ -2269,6 +2279,9 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
|
||||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) &&
|
||||||
|
bdrv_inherits_from_recursive(backing_hd, bs);
|
||||||
|
|
||||||
if (backing_hd) {
|
if (backing_hd) {
|
||||||
bdrv_ref(backing_hd);
|
bdrv_ref(backing_hd);
|
||||||
}
|
}
|
||||||
|
@ -2284,6 +2297,12 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||||
|
|
||||||
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
|
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
|
||||||
errp);
|
errp);
|
||||||
|
/* If backing_hd was already part of bs's backing chain, and
|
||||||
|
* inherits_from pointed recursively to bs then let's update it to
|
||||||
|
* point directly to bs (else it will become NULL). */
|
||||||
|
if (update_inherits_from) {
|
||||||
|
backing_hd->inherits_from = bs;
|
||||||
|
}
|
||||||
if (!bs->backing) {
|
if (!bs->backing) {
|
||||||
bdrv_unref(backing_hd);
|
bdrv_unref(backing_hd);
|
||||||
}
|
}
|
||||||
|
@ -3836,6 +3855,8 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
|
||||||
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||||
const char *backing_file_str)
|
const char *backing_file_str)
|
||||||
{
|
{
|
||||||
|
BlockDriverState *explicit_top = top;
|
||||||
|
bool update_inherits_from;
|
||||||
BdrvChild *c, *next;
|
BdrvChild *c, *next;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
@ -3851,6 +3872,16 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If 'base' recursively inherits from 'top' then we should set
|
||||||
|
* base->inherits_from to top->inherits_from after 'top' and all
|
||||||
|
* other intermediate nodes have been dropped.
|
||||||
|
* If 'top' is an implicit node (e.g. "commit_top") we should skip
|
||||||
|
* it because no one inherits from it. We use explicit_top for that. */
|
||||||
|
while (explicit_top && explicit_top->implicit) {
|
||||||
|
explicit_top = backing_bs(explicit_top);
|
||||||
|
}
|
||||||
|
update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
|
||||||
|
|
||||||
/* success - we can delete the intermediate states, and link top->base */
|
/* success - we can delete the intermediate states, and link top->base */
|
||||||
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
|
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
|
||||||
* we've figured out how they should work. */
|
* we've figured out how they should work. */
|
||||||
|
@ -3886,6 +3917,10 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||||
bdrv_unref(top);
|
bdrv_unref(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (update_inherits_from) {
|
||||||
|
base->inherits_from = explicit_top->inherits_from;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
exit:
|
exit:
|
||||||
bdrv_unref(top);
|
bdrv_unref(top);
|
||||||
|
|
|
@ -554,6 +554,7 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd)
|
||||||
trace_nvme_err_invalid_del_cq_notempty(qid);
|
trace_nvme_err_invalid_del_cq_notempty(qid);
|
||||||
return NVME_INVALID_QUEUE_DEL;
|
return NVME_INVALID_QUEUE_DEL;
|
||||||
}
|
}
|
||||||
|
nvme_irq_deassert(n, cq);
|
||||||
trace_nvme_del_cq(qid);
|
trace_nvme_del_cq(qid);
|
||||||
nvme_free_cq(cq, n);
|
nvme_free_cq(cq, n);
|
||||||
return NVME_SUCCESS;
|
return NVME_SUCCESS;
|
||||||
|
@ -797,6 +798,8 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
blk_drain(n->conf.blk);
|
||||||
|
|
||||||
for (i = 0; i < n->num_queues; i++) {
|
for (i = 0; i < n->num_queues; i++) {
|
||||||
if (n->sq[i] != NULL) {
|
if (n->sq[i] != NULL) {
|
||||||
nvme_free_sq(n->sq[i], n);
|
nvme_free_sq(n->sq[i], n);
|
||||||
|
@ -1175,23 +1178,13 @@ static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
||||||
|
stn_le_p(&n->cmbuf[addr], size, data);
|
||||||
if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(&n->cmbuf[addr], &data, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
|
static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
{
|
{
|
||||||
uint64_t val;
|
|
||||||
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
||||||
|
return ldn_le_p(&n->cmbuf[addr], size);
|
||||||
if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(&val, &n->cmbuf[addr], size);
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps nvme_cmb_ops = {
|
static const MemoryRegionOps nvme_cmb_ops = {
|
||||||
|
@ -1199,7 +1192,7 @@ static const MemoryRegionOps nvme_cmb_ops = {
|
||||||
.write = nvme_cmb_write,
|
.write = nvme_cmb_write,
|
||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
.impl = {
|
.impl = {
|
||||||
.min_access_size = 2,
|
.min_access_size = 1,
|
||||||
.max_access_size = 8,
|
.max_access_size = 8,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -482,7 +482,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||||
scsi_req_retry(&r->req);
|
scsi_req_retry(&r->req);
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
|
static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
|
||||||
|
|
|
@ -261,8 +261,9 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!proto_drv->create_opts) {
|
if (!proto_drv->create_opts) {
|
||||||
error_report("Protocal driver '%s' does not support image creation",
|
error_report("Protocol driver '%s' does not support image creation",
|
||||||
proto_drv->format_name);
|
proto_drv->format_name);
|
||||||
|
qemu_opts_free(create_opts);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||||
|
|
|
@ -730,7 +730,7 @@ tests/test-hmp$(EXESUF): tests/test-hmp.o
|
||||||
tests/machine-none-test$(EXESUF): tests/machine-none-test.o
|
tests/machine-none-test$(EXESUF): tests/machine-none-test.o
|
||||||
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
|
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
|
||||||
tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
|
tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
|
||||||
tests/nvme-test$(EXESUF): tests/nvme-test.o
|
tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y)
|
||||||
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
|
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
|
||||||
tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
|
tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
|
||||||
tests/ac97-test$(EXESUF): tests/ac97-test.o
|
tests/ac97-test$(EXESUF): tests/ac97-test.o
|
||||||
|
|
|
@ -8,25 +8,73 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/units.h"
|
||||||
#include "libqtest.h"
|
#include "libqtest.h"
|
||||||
|
#include "libqos/libqos-pc.h"
|
||||||
|
|
||||||
|
static QOSState *qnvme_start(const char *extra_opts)
|
||||||
|
{
|
||||||
|
QOSState *qs;
|
||||||
|
const char *arch = qtest_get_arch();
|
||||||
|
const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw "
|
||||||
|
"-device nvme,addr=0x4.0,serial=foo,drive=drv0 %s";
|
||||||
|
|
||||||
|
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||||
|
qs = qtest_pc_boot(cmd, extra_opts ? : "");
|
||||||
|
global_qtest = qs->qts;
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_printerr("nvme tests are only available on x86\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qnvme_stop(QOSState *qs)
|
||||||
|
{
|
||||||
|
qtest_shutdown(qs);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tests only initialization so far. TODO: Replace with functional tests */
|
|
||||||
static void nop(void)
|
static void nop(void)
|
||||||
{
|
{
|
||||||
|
QOSState *qs;
|
||||||
|
|
||||||
|
qs = qnvme_start(NULL);
|
||||||
|
qnvme_stop(qs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nvmetest_cmb_test(void)
|
||||||
|
{
|
||||||
|
const int cmb_bar_size = 2 * MiB;
|
||||||
|
QOSState *qs;
|
||||||
|
QPCIDevice *pdev;
|
||||||
|
QPCIBar bar;
|
||||||
|
|
||||||
|
qs = qnvme_start("-global nvme.cmb_size_mb=2");
|
||||||
|
pdev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0));
|
||||||
|
g_assert(pdev != NULL);
|
||||||
|
|
||||||
|
qpci_device_enable(pdev);
|
||||||
|
bar = qpci_iomap(pdev, 2, NULL);
|
||||||
|
|
||||||
|
qpci_io_writel(pdev, bar, 0, 0xccbbaa99);
|
||||||
|
g_assert_cmpint(qpci_io_readb(pdev, bar, 0), ==, 0x99);
|
||||||
|
g_assert_cmpint(qpci_io_readw(pdev, bar, 0), ==, 0xaa99);
|
||||||
|
|
||||||
|
/* Test partially out-of-bounds accesses. */
|
||||||
|
qpci_io_writel(pdev, bar, cmb_bar_size - 1, 0x44332211);
|
||||||
|
g_assert_cmpint(qpci_io_readb(pdev, bar, cmb_bar_size - 1), ==, 0x11);
|
||||||
|
g_assert_cmpint(qpci_io_readw(pdev, bar, cmb_bar_size - 1), !=, 0x2211);
|
||||||
|
g_assert_cmpint(qpci_io_readl(pdev, bar, cmb_bar_size - 1), !=, 0x44332211);
|
||||||
|
g_free(pdev);
|
||||||
|
|
||||||
|
qnvme_stop(qs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
g_test_init(&argc, &argv, NULL);
|
g_test_init(&argc, &argv, NULL);
|
||||||
qtest_add_func("/nvme/nop", nop);
|
qtest_add_func("/nvme/nop", nop);
|
||||||
|
qtest_add_func("/nvme/cmb_test", nvmetest_cmb_test);
|
||||||
|
|
||||||
qtest_start("-drive id=drv0,if=none,file=null-co://,format=raw "
|
return g_test_run();
|
||||||
"-device nvme,drive=drv0,serial=foo");
|
|
||||||
ret = g_test_run();
|
|
||||||
|
|
||||||
qtest_end();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,7 +469,7 @@ new_state = "1"
|
||||||
self.assert_qmp(event, 'data/id', 'drive0')
|
self.assert_qmp(event, 'data/id', 'drive0')
|
||||||
event = self.vm.get_qmp_event(wait=True)
|
event = self.vm.get_qmp_event(wait=True)
|
||||||
|
|
||||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||||
self.assert_qmp(event, 'data/device', 'drive0')
|
self.assert_qmp(event, 'data/device', 'drive0')
|
||||||
self.assert_qmp(event, 'data/operation', 'read')
|
self.assert_qmp(event, 'data/operation', 'read')
|
||||||
result = self.vm.qmp('query-block-jobs')
|
result = self.vm.qmp('query-block-jobs')
|
||||||
|
@ -494,7 +494,7 @@ new_state = "1"
|
||||||
self.assert_qmp(event, 'data/id', 'drive0')
|
self.assert_qmp(event, 'data/id', 'drive0')
|
||||||
event = self.vm.get_qmp_event(wait=True)
|
event = self.vm.get_qmp_event(wait=True)
|
||||||
|
|
||||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||||
self.assert_qmp(event, 'data/device', 'drive0')
|
self.assert_qmp(event, 'data/device', 'drive0')
|
||||||
self.assert_qmp(event, 'data/operation', 'read')
|
self.assert_qmp(event, 'data/operation', 'read')
|
||||||
result = self.vm.qmp('query-block-jobs')
|
result = self.vm.qmp('query-block-jobs')
|
||||||
|
@ -625,7 +625,7 @@ new_state = "1"
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
event = self.vm.event_wait(name='BLOCK_JOB_ERROR')
|
event = self.vm.event_wait(name='BLOCK_JOB_ERROR')
|
||||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||||
self.assert_qmp(event, 'data/device', 'drive0')
|
self.assert_qmp(event, 'data/device', 'drive0')
|
||||||
self.assert_qmp(event, 'data/operation', 'write')
|
self.assert_qmp(event, 'data/operation', 'write')
|
||||||
result = self.vm.qmp('query-block-jobs')
|
result = self.vm.qmp('query-block-jobs')
|
||||||
|
|
|
@ -53,21 +53,17 @@ class ChangeBaseClass(iotests.QMPTestCase):
|
||||||
if not self.has_real_tray:
|
if not self.has_real_tray:
|
||||||
return
|
return
|
||||||
|
|
||||||
timeout = time.clock() + 3
|
with iotests.Timeout(3, 'Timeout while waiting for the tray to open'):
|
||||||
while not self.has_opened and time.clock() < timeout:
|
while not self.has_opened:
|
||||||
self.process_events()
|
self.process_events()
|
||||||
if not self.has_opened:
|
|
||||||
self.fail('Timeout while waiting for the tray to open')
|
|
||||||
|
|
||||||
def wait_for_close(self):
|
def wait_for_close(self):
|
||||||
if not self.has_real_tray:
|
if not self.has_real_tray:
|
||||||
return
|
return
|
||||||
|
|
||||||
timeout = time.clock() + 3
|
with iotests.Timeout(3, 'Timeout while waiting for the tray to close'):
|
||||||
while not self.has_closed and time.clock() < timeout:
|
while not self.has_closed:
|
||||||
self.process_events()
|
self.process_events()
|
||||||
if not self.has_opened:
|
|
||||||
self.fail('Timeout while waiting for the tray to close')
|
|
||||||
|
|
||||||
class GeneralChangeTestsBaseClass(ChangeBaseClass):
|
class GeneralChangeTestsBaseClass(ChangeBaseClass):
|
||||||
|
|
||||||
|
@ -265,7 +261,7 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
|
||||||
result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
|
result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
|
||||||
# Should be a no-op
|
# Should be a no-op
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
|
self.assertEqual(self.vm.get_qmp_events(wait=False), [])
|
||||||
|
|
||||||
def test_remove_on_closed(self):
|
def test_remove_on_closed(self):
|
||||||
if not self.has_real_tray:
|
if not self.has_real_tray:
|
||||||
|
@ -452,7 +448,7 @@ class TestChangeReadOnly(ChangeBaseClass):
|
||||||
read_only_mode='retain')
|
read_only_mode='retain')
|
||||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
self.assert_qmp(result, 'error/class', 'GenericError')
|
||||||
|
|
||||||
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
|
self.assertEqual(self.vm.get_qmp_events(wait=False), [])
|
||||||
|
|
||||||
result = self.vm.qmp('query-block')
|
result = self.vm.qmp('query-block')
|
||||||
self.assert_qmp(result, 'return[0]/inserted/ro', False)
|
self.assert_qmp(result, 'return[0]/inserted/ro', False)
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test reopening a backing image after block-stream and block-commit
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018 Igalia, S.L.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# creator
|
||||||
|
owner=berto@igalia.com
|
||||||
|
|
||||||
|
seq=`basename $0`
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
here=`pwd`
|
||||||
|
status=1 # failure is the default!
|
||||||
|
|
||||||
|
_cleanup()
|
||||||
|
{
|
||||||
|
_cleanup_test_img
|
||||||
|
rm -f "$TEST_IMG.base"
|
||||||
|
rm -f "$TEST_IMG.int"
|
||||||
|
}
|
||||||
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
|
# get standard environment, filters and checks
|
||||||
|
. ./common.rc
|
||||||
|
. ./common.filter
|
||||||
|
. ./common.qemu
|
||||||
|
|
||||||
|
# Any format implementing BlockDriver.bdrv_change_backing_file
|
||||||
|
_supported_fmt qcow2 qed
|
||||||
|
_supported_proto file
|
||||||
|
_supported_os Linux
|
||||||
|
|
||||||
|
IMG_SIZE=1M
|
||||||
|
|
||||||
|
# Create the images
|
||||||
|
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt
|
||||||
|
TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt
|
||||||
|
_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt
|
||||||
|
|
||||||
|
# First test: reopen $TEST.IMG changing the detect-zeroes option on
|
||||||
|
# its backing file ($TEST_IMG.int).
|
||||||
|
echo
|
||||||
|
echo "*** Change an option on the backing file"
|
||||||
|
echo
|
||||||
|
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'qmp_capabilities' }" \
|
||||||
|
'return'
|
||||||
|
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'human-monitor-command',
|
||||||
|
'arguments': { 'command-line':
|
||||||
|
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||||
|
"return"
|
||||||
|
|
||||||
|
_cleanup_qemu
|
||||||
|
|
||||||
|
# Second test: stream $TEST_IMG.base into $TEST_IMG.int and then
|
||||||
|
# reopen $TEST.IMG changing the detect-zeroes option on its new
|
||||||
|
# backing file ($TEST_IMG.base).
|
||||||
|
echo
|
||||||
|
echo "*** Stream and then change an option on the backing file"
|
||||||
|
echo
|
||||||
|
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'qmp_capabilities' }" \
|
||||||
|
'return'
|
||||||
|
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'block-stream', \
|
||||||
|
'arguments': { 'device': 'none0',
|
||||||
|
'base': '${TEST_IMG}.base' } }" \
|
||||||
|
'return'
|
||||||
|
|
||||||
|
# Wait for block-stream to finish
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'human-monitor-command',
|
||||||
|
'arguments': { 'command-line':
|
||||||
|
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||||
|
"return"
|
||||||
|
|
||||||
|
_cleanup_qemu
|
||||||
|
|
||||||
|
# Third test: commit $TEST_IMG.int into $TEST_IMG.base and then reopen
|
||||||
|
# $TEST.IMG changing the detect-zeroes option on its new backing file
|
||||||
|
# ($TEST_IMG.base).
|
||||||
|
echo
|
||||||
|
echo "*** Commit and then change an option on the backing file"
|
||||||
|
echo
|
||||||
|
# Create the images again
|
||||||
|
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt
|
||||||
|
TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt
|
||||||
|
_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt
|
||||||
|
|
||||||
|
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'qmp_capabilities' }" \
|
||||||
|
'return'
|
||||||
|
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'block-commit', \
|
||||||
|
'arguments': { 'device': 'none0',
|
||||||
|
'top': '${TEST_IMG}.int' } }" \
|
||||||
|
'return'
|
||||||
|
|
||||||
|
# Wait for block-commit to finish
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
"{ 'execute': 'human-monitor-command',
|
||||||
|
'arguments': { 'command-line':
|
||||||
|
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||||
|
"return"
|
||||||
|
|
||||||
|
_cleanup_qemu
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo "*** done"
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
|
@ -0,0 +1,39 @@
|
||||||
|
QA output created by 161
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int
|
||||||
|
|
||||||
|
*** Change an option on the backing file
|
||||||
|
|
||||||
|
{"return": {}}
|
||||||
|
{"return": ""}
|
||||||
|
|
||||||
|
*** Stream and then change an option on the backing file
|
||||||
|
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "stream"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
|
||||||
|
{"return": ""}
|
||||||
|
|
||||||
|
*** Commit and then change an option on the backing file
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
|
||||||
|
{"return": ""}
|
||||||
|
*** done
|
|
@ -57,10 +57,11 @@ run_qemu()
|
||||||
}
|
}
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== Create partially sparse image, then add dirty bitmap ==="
|
echo "=== Create partially sparse image, then add dirty bitmaps ==="
|
||||||
echo
|
echo
|
||||||
|
|
||||||
_make_test_img 4M
|
# Two bitmaps, to contrast granularity issues
|
||||||
|
_make_test_img -o cluster_size=4k 4M
|
||||||
$QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io
|
||||||
run_qemu <<EOF
|
run_qemu <<EOF
|
||||||
{ "execute": "qmp_capabilities" }
|
{ "execute": "qmp_capabilities" }
|
||||||
|
@ -78,7 +79,16 @@ run_qemu <<EOF
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"node": "n",
|
"node": "n",
|
||||||
"name": "b",
|
"name": "b",
|
||||||
"persistent": true
|
"persistent": true,
|
||||||
|
"granularity": 65536
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ "execute": "block-dirty-bitmap-add",
|
||||||
|
"arguments": {
|
||||||
|
"node": "n",
|
||||||
|
"name": "b2",
|
||||||
|
"persistent": true,
|
||||||
|
"granularity": 512
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ "execute": "quit" }
|
{ "execute": "quit" }
|
||||||
|
@ -88,10 +98,11 @@ echo
|
||||||
echo "=== Write part of the file under active bitmap ==="
|
echo "=== Write part of the file under active bitmap ==="
|
||||||
echo
|
echo
|
||||||
|
|
||||||
$QEMU_IO -c 'w -P 0x22 2M 2M' "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c 'w -P 0x22 512 512' -c 'w -P 0x33 2M 2M' "$TEST_IMG" \
|
||||||
|
| _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== End dirty bitmap, and start serving image over NBD ==="
|
echo "=== End dirty bitmaps, and start serving image over NBD ==="
|
||||||
echo
|
echo
|
||||||
|
|
||||||
_launch_qemu 2> >(_filter_nbd)
|
_launch_qemu 2> >(_filter_nbd)
|
||||||
|
@ -103,6 +114,8 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"blockdev-add",
|
||||||
"file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return"
|
"file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return"
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable",
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable",
|
||||||
"arguments":{"node":"n", "name":"b"}}' "return"
|
"arguments":{"node":"n", "name":"b"}}' "return"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable",
|
||||||
|
"arguments":{"node":"n", "name":"b2"}}' "return"
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
|
||||||
"arguments":{"addr":{"type":"unix",
|
"arguments":{"addr":{"type":"unix",
|
||||||
"data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return"
|
"data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return"
|
||||||
|
@ -110,26 +123,40 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
||||||
"arguments":{"device":"n"}}' "return"
|
"arguments":{"device":"n"}}' "return"
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
|
||||||
"arguments":{"name":"n", "bitmap":"b"}}' "return"
|
"arguments":{"name":"n", "bitmap":"b"}}' "return"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
||||||
|
"arguments":{"device":"n", "name":"n2"}}' "return"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
|
||||||
|
"arguments":{"name":"n2", "bitmap":"b2"}}' "return"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== Contrast normal status with dirty-bitmap status ==="
|
echo "=== Contrast normal status to large granularity dirty-bitmap ==="
|
||||||
echo
|
echo
|
||||||
|
|
||||||
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||||
IMG="driver=nbd,export=n,server.type=unix,server.path=$TEST_DIR/nbd"
|
IMG="driver=nbd,export=n,server.type=unix,server.path=$TEST_DIR/nbd"
|
||||||
$QEMU_IO -r -c 'r -P 0 0 1m' -c 'r -P 0x11 1m 1m' \
|
$QEMU_IO -r -c 'r -P 0x22 512 512' -c 'r -P 0 512k 512k' -c 'r -P 0x11 1m 1m' \
|
||||||
-c 'r -P 0x22 2m 2m' --image-opts "$IMG" | _filter_qemu_io
|
-c 'r -P 0x33 2m 2m' --image-opts "$IMG" | _filter_qemu_io
|
||||||
$QEMU_IMG map --output=json --image-opts \
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
"$IMG" | _filter_qemu_img_map
|
"$IMG" | _filter_qemu_img_map
|
||||||
$QEMU_IMG map --output=json --image-opts \
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b" | _filter_qemu_img_map
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b" | _filter_qemu_img_map
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Contrast to small granularity dirty-bitmap ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
IMG="driver=nbd,export=n2,server.type=unix,server.path=$TEST_DIR/nbd"
|
||||||
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== End NBD server ==="
|
echo "=== End NBD server ==="
|
||||||
echo
|
echo
|
||||||
|
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
||||||
"arguments":{"name":"n"}}' "return"
|
"arguments":{"name":"n"}}' "return"
|
||||||
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
||||||
|
"arguments":{"name":"n2"}}' "return"
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return"
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return"
|
||||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return"
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
QA output created by 223
|
QA output created by 223
|
||||||
|
|
||||||
=== Create partially sparse image, then add dirty bitmap ===
|
=== Create partially sparse image, then add dirty bitmaps ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
|
||||||
wrote 2097152/2097152 bytes at offset 1048576
|
wrote 2097152/2097152 bytes at offset 1048576
|
||||||
|
@ -11,15 +11,18 @@ QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
{"return": {}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||||
|
|
||||||
|
|
||||||
=== Write part of the file under active bitmap ===
|
=== Write part of the file under active bitmap ===
|
||||||
|
|
||||||
|
wrote 512/512 bytes at offset 512
|
||||||
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 2097152/2097152 bytes at offset 2097152
|
wrote 2097152/2097152 bytes at offset 2097152
|
||||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
=== End dirty bitmap, and start serving image over NBD ===
|
=== End dirty bitmaps, and start serving image over NBD ===
|
||||||
|
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
@ -27,18 +30,32 @@ wrote 2097152/2097152 bytes at offset 2097152
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
{"return": {}}
|
||||||
|
{"return": {}}
|
||||||
|
{"return": {}}
|
||||||
|
|
||||||
=== Contrast normal status with dirty-bitmap status ===
|
=== Contrast normal status to large granularity dirty-bitmap ===
|
||||||
|
|
||||||
read 1048576/1048576 bytes at offset 0
|
read 512/512 bytes at offset 512
|
||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 524288/524288 bytes at offset 524288
|
||||||
|
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
read 1048576/1048576 bytes at offset 1048576
|
read 1048576/1048576 bytes at offset 1048576
|
||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
read 2097152/2097152 bytes at offset 2097152
|
read 2097152/2097152 bytes at offset 2097152
|
||||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false},
|
[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true},
|
||||||
|
{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false},
|
||||||
{ "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": true}]
|
{ "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": true}]
|
||||||
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true},
|
[{ "start": 0, "length": 65536, "depth": 0, "zero": false, "data": false},
|
||||||
|
{ "start": 65536, "length": 2031616, "depth": 0, "zero": false, "data": true},
|
||||||
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
||||||
|
|
||||||
|
=== Contrast to small granularity dirty-bitmap ===
|
||||||
|
|
||||||
|
[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true},
|
||||||
|
{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false},
|
||||||
|
{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true},
|
||||||
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
||||||
|
|
||||||
=== End NBD server ===
|
=== End NBD server ===
|
||||||
|
@ -46,4 +63,5 @@ read 2097152/2097152 bytes at offset 2097152
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
{"return": {}}
|
||||||
*** done
|
*** done
|
||||||
|
|
|
@ -66,7 +66,7 @@ $QEMU_IO -c 'w -P 0x11 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== check TLS client to plain server fails =="
|
echo "== check TLS client to plain server fails =="
|
||||||
nbd_server_start_tcp_socket "$TEST_IMG"
|
nbd_server_start_tcp_socket -f $IMGFMT "$TEST_IMG"
|
||||||
|
|
||||||
$QEMU_IMG info --image-opts \
|
$QEMU_IMG info --image-opts \
|
||||||
--object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \
|
--object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \
|
||||||
|
@ -78,7 +78,10 @@ nbd_server_stop
|
||||||
echo
|
echo
|
||||||
echo "== check plain client to TLS server fails =="
|
echo "== check plain client to TLS server fails =="
|
||||||
|
|
||||||
nbd_server_start_tcp_socket --object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes --tls-creds tls0 "$TEST_IMG"
|
nbd_server_start_tcp_socket \
|
||||||
|
--object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes \
|
||||||
|
--tls-creds tls0 \
|
||||||
|
-f $IMGFMT "$TEST_IMG"
|
||||||
|
|
||||||
$QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
$QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||||
|
|
||||||
|
@ -104,7 +107,7 @@ $QEMU_IO -c 'r -P 0x11 1m 1m' -c 'w -P 0x22 1m 1m' --image-opts \
|
||||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||||
2>&1 | _filter_qemu_io
|
2>&1 | _filter_qemu_io
|
||||||
|
|
||||||
$QEMU_IO -f qcow2 -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
|
|
|
@ -31,6 +31,9 @@ tls_x509_cleanup()
|
||||||
|
|
||||||
tls_x509_init()
|
tls_x509_init()
|
||||||
{
|
{
|
||||||
|
(certtool --help) >/dev/null 2>&1 || \
|
||||||
|
_notrun "certtool utility not found, skipping test"
|
||||||
|
|
||||||
mkdir -p "${tls_dir}"
|
mkdir -p "${tls_dir}"
|
||||||
|
|
||||||
# use a fixed key so we don't waste system entropy on
|
# use a fixed key so we don't waste system entropy on
|
||||||
|
|
|
@ -167,6 +167,7 @@
|
||||||
158 rw auto quick
|
158 rw auto quick
|
||||||
159 rw auto quick
|
159 rw auto quick
|
||||||
160 rw auto quick
|
160 rw auto quick
|
||||||
|
161 rw auto quick
|
||||||
162 auto quick
|
162 auto quick
|
||||||
163 rw auto
|
163 rw auto
|
||||||
165 rw auto quick
|
165 rw auto quick
|
||||||
|
|
|
@ -581,7 +581,7 @@ class QMPTestCase(unittest.TestCase):
|
||||||
def wait_ready_and_cancel(self, drive='drive0'):
|
def wait_ready_and_cancel(self, drive='drive0'):
|
||||||
self.wait_ready(drive=drive)
|
self.wait_ready(drive=drive)
|
||||||
event = self.cancel_and_wait(drive=drive)
|
event = self.cancel_and_wait(drive=drive)
|
||||||
self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
|
self.assertEqual(event['event'], 'BLOCK_JOB_COMPLETED')
|
||||||
self.assert_qmp(event, 'data/type', 'mirror')
|
self.assert_qmp(event, 'data/type', 'mirror')
|
||||||
self.assert_qmp(event, 'data/offset', event['data']['len'])
|
self.assert_qmp(event, 'data/offset', event['data']['len'])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue