diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-03-10 14:01:22 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-03-10 14:01:22 +0000 |
commit | 1976058109890892db8ec88bfd3273f79c459f6b (patch) | |
tree | 3819ee5d4406491751f99828f961a4b938f1e180 /tests | |
parent | 8437f7be3b1c49631e435c652707f2cee477149d (diff) | |
parent | 280458a34abcca2ba70843a089a35468c81e3740 (diff) | |
download | hqemu-1976058109890892db8ec88bfd3273f79c459f6b.zip hqemu-1976058109890892db8ec88bfd3273f79c459f6b.tar.gz |
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches for 2.3
# gpg: Signature made Tue Mar 10 13:03:17 2015 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
* remotes/kevin/tags/for-upstream: (73 commits)
MAINTAINERS: Add jcody as blockjobs, block devices maintainer
iotests: add O_DIRECT alignment probing test
block/raw-posix: fix launching with failed disks
MAINTAINERS: Add jsnow as IDE maintainer
sheepdog: Fix misleading error messages in sd_snapshot_create()
Add testcase for scsi-hd devices without drive property
scsi-hd: fix property unset case
block/vdi: Add locking for parallel requests
iotests: Drop vpc from 004's and 104's format list
iotests: Remove 006
iotests: Fix 051's reference output
virtio-blk: Remove the stale FIXME comment
tests: Check QVIRTIO_F_ANY_LAYOUT flag in virtio-blk test
libqos: Solve bug in interrupt checking when using MSIX in virtio-pci.c
sheepdog: fix confused return values
qtest/ahci: add fragmented dma test
qtest/ahci: Add PIO and LBA48 tests
qtest/ahci: Add DMA test variants
libqos/ahci: add ahci command helpers
qtest/ahci: Add a macro bootup routine
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
45 files changed, 1412 insertions, 354 deletions
diff --git a/tests/Makefile b/tests/Makefile index 307035c..fed8096 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -191,6 +191,8 @@ gcov-files-sparc-y += hw/timer/m48t59.c gcov-files-sparc64-y += hw/timer/m48t59.c check-qtest-arm-y = tests/tmp105-test$(EXESUF) gcov-files-arm-y += hw/misc/tmp105.c +check-qtest-arm-y += tests/virtio-blk-test$(EXESUF) +gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/spapr-phb-test$(EXESUF) @@ -315,8 +317,8 @@ libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o libqos-pc-obj-y += tests/libqos/ahci.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o -libqos-virtio-obj-y = $(libqos-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o +libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 53fd068..cf0b98b 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -107,6 +107,21 @@ static void ahci_shutdown(AHCIQState *ahci) qtest_shutdown(qs); } +/** + * Boot and fully enable the HBA device. + * @see ahci_boot, ahci_pci_enable and ahci_hba_enable. + */ +static AHCIQState *ahci_boot_and_enable(void) +{ + AHCIQState *ahci; + ahci = ahci_boot(); + + ahci_pci_enable(ahci); + ahci_hba_enable(ahci); + + return ahci; +} + /*** Specification Adherence Tests ***/ /** @@ -716,12 +731,12 @@ static void ahci_test_identify(AHCIQState *ahci) g_assert_cmphex(sect_size, ==, 0x200); } -static void ahci_test_dma_rw_simple(AHCIQState *ahci) +static void ahci_test_io_rw_simple(AHCIQState *ahci, unsigned bufsize, + uint8_t read_cmd, uint8_t write_cmd) { uint64_t ptr; uint8_t port; unsigned i; - const unsigned bufsize = 4096; unsigned char *tx = g_malloc(bufsize); unsigned char *rx = g_malloc0(bufsize); @@ -736,16 +751,16 @@ static void ahci_test_dma_rw_simple(AHCIQState *ahci) ptr = ahci_alloc(ahci, bufsize); g_assert(ptr); - /* Write some indicative pattern to our 4K buffer. */ + /* Write some indicative pattern to our buffer. */ for (i = 0; i < bufsize; i++) { tx[i] = (bufsize - i); } memwrite(ptr, tx, bufsize); /* Write this buffer to disk, then read it back to the DMA buffer. */ - ahci_guest_io(ahci, port, CMD_WRITE_DMA, ptr, bufsize); + ahci_guest_io(ahci, port, write_cmd, ptr, bufsize); qmemset(ptr, 0x00, bufsize); - ahci_guest_io(ahci, port, CMD_READ_DMA, ptr, bufsize); + ahci_guest_io(ahci, port, read_cmd, ptr, bufsize); /*** Read back the Data ***/ memread(ptr, rx, bufsize); @@ -831,25 +846,204 @@ static void test_identify(void) { AHCIQState *ahci; - ahci = ahci_boot(); - ahci_pci_enable(ahci); - ahci_hba_enable(ahci); + ahci = ahci_boot_and_enable(); ahci_test_identify(ahci); ahci_shutdown(ahci); } /** - * Perform a simple DMA R/W test, using a single PRD and non-NCQ commands. + * Fragmented DMA test: Perform a standard 4K DMA read/write + * test, but make sure the physical regions are fragmented to + * be very small, each just 32 bytes, to see how AHCI performs + * with chunks defined to be much less than a sector. */ -static void test_dma_rw_simple(void) +static void test_dma_fragmented(void) { AHCIQState *ahci; + AHCICommand *cmd; + uint8_t px; + size_t bufsize = 4096; + unsigned char *tx = g_malloc(bufsize); + unsigned char *rx = g_malloc0(bufsize); + unsigned i; + uint64_t ptr; + + ahci = ahci_boot_and_enable(); + px = ahci_port_select(ahci); + ahci_port_clear(ahci, px); + + /* create pattern */ + for (i = 0; i < bufsize; i++) { + tx[i] = (bufsize - i); + } + + /* Create a DMA buffer in guest memory, and write our pattern to it. */ + ptr = guest_alloc(ahci->parent->alloc, bufsize); + g_assert(ptr); + memwrite(ptr, tx, bufsize); + + cmd = ahci_command_create(CMD_WRITE_DMA); + ahci_command_adjust(cmd, 0, ptr, bufsize, 32); + ahci_command_commit(ahci, cmd, px); + ahci_command_issue(ahci, cmd); + ahci_command_verify(ahci, cmd); + g_free(cmd); + + cmd = ahci_command_create(CMD_READ_DMA); + ahci_command_adjust(cmd, 0, ptr, bufsize, 32); + ahci_command_commit(ahci, cmd, px); + ahci_command_issue(ahci, cmd); + ahci_command_verify(ahci, cmd); + g_free(cmd); + + /* Read back the guest's receive buffer into local memory */ + memread(ptr, rx, bufsize); + guest_free(ahci->parent->alloc, ptr); + + g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0); - ahci = ahci_boot(); - ahci_pci_enable(ahci); - ahci_hba_enable(ahci); - ahci_test_dma_rw_simple(ahci); ahci_shutdown(ahci); + + g_free(rx); + g_free(tx); +} + +/******************************************************************************/ +/* AHCI I/O Test Matrix Definitions */ + +enum BuffLen { + LEN_BEGIN = 0, + LEN_SIMPLE = LEN_BEGIN, + LEN_DOUBLE, + LEN_LONG, + LEN_SHORT, + NUM_LENGTHS +}; + +static const char *buff_len_str[NUM_LENGTHS] = { "simple", "double", + "long", "short" }; + +enum AddrMode { + ADDR_MODE_BEGIN = 0, + ADDR_MODE_LBA28 = ADDR_MODE_BEGIN, + ADDR_MODE_LBA48, + NUM_ADDR_MODES +}; + +static const char *addr_mode_str[NUM_ADDR_MODES] = { "lba28", "lba48" }; + +enum IOMode { + MODE_BEGIN = 0, + MODE_PIO = MODE_BEGIN, + MODE_DMA, + NUM_MODES +}; + +static const char *io_mode_str[NUM_MODES] = { "pio", "dma" }; + +enum IOOps { + IO_BEGIN = 0, + IO_READ = IO_BEGIN, + IO_WRITE, + NUM_IO_OPS +}; + +typedef struct AHCIIOTestOptions { + enum BuffLen length; + enum AddrMode address_type; + enum IOMode io_type; +} AHCIIOTestOptions; + +/** + * Table of possible I/O ATA commands given a set of enumerations. + */ +static const uint8_t io_cmds[NUM_MODES][NUM_ADDR_MODES][NUM_IO_OPS] = { + [MODE_PIO] = { + [ADDR_MODE_LBA28] = { + [IO_READ] = CMD_READ_PIO, + [IO_WRITE] = CMD_WRITE_PIO }, + [ADDR_MODE_LBA48] = { + [IO_READ] = CMD_READ_PIO_EXT, + [IO_WRITE] = CMD_WRITE_PIO_EXT } + }, + [MODE_DMA] = { + [ADDR_MODE_LBA28] = { + [IO_READ] = CMD_READ_DMA, + [IO_WRITE] = CMD_WRITE_DMA }, + [ADDR_MODE_LBA48] = { + [IO_READ] = CMD_READ_DMA_EXT, + [IO_WRITE] = CMD_WRITE_DMA_EXT } + } +}; + +/** + * Test a Read/Write pattern using various commands, addressing modes, + * transfer modes, and buffer sizes. + */ +static void test_io_rw_interface(enum AddrMode lba48, enum IOMode dma, + unsigned bufsize) +{ + AHCIQState *ahci; + + ahci = ahci_boot_and_enable(); + ahci_test_io_rw_simple(ahci, bufsize, + io_cmds[dma][lba48][IO_READ], + io_cmds[dma][lba48][IO_WRITE]); + ahci_shutdown(ahci); +} + +/** + * Demultiplex the test data and invoke the actual test routine. + */ +static void test_io_interface(gconstpointer opaque) +{ + AHCIIOTestOptions *opts = (AHCIIOTestOptions *)opaque; + unsigned bufsize; + + switch (opts->length) { + case LEN_SIMPLE: + bufsize = 4096; + break; + case LEN_DOUBLE: + bufsize = 8192; + break; + case LEN_LONG: + bufsize = 4096 * 64; + break; + case LEN_SHORT: + bufsize = 512; + break; + default: + g_assert_not_reached(); + } + + test_io_rw_interface(opts->address_type, opts->io_type, bufsize); + g_free(opts); + return; +} + +static void create_ahci_io_test(enum IOMode type, enum AddrMode addr, + enum BuffLen len) +{ + static const char *arch; + char *name; + AHCIIOTestOptions *opts = g_malloc(sizeof(AHCIIOTestOptions)); + + opts->length = len; + opts->address_type = addr; + opts->io_type = type; + + if (!arch) { + arch = qtest_get_arch(); + } + + name = g_strdup_printf("/%s/ahci/io/%s/%s/%s", arch, + io_mode_str[type], + addr_mode_str[addr], + buff_len_str[len]); + + g_test_add_data_func(name, opts, test_io_interface); + g_free(name); } /******************************************************************************/ @@ -860,6 +1054,7 @@ int main(int argc, char **argv) int fd; int ret; int c; + int i, j, k; static struct option long_options[] = { {"pedantic", no_argument, 0, 'p' }, @@ -907,7 +1102,16 @@ int main(int argc, char **argv) qtest_add_func("/ahci/hba_spec", test_hba_spec); qtest_add_func("/ahci/hba_enable", test_hba_enable); qtest_add_func("/ahci/identify", test_identify); - qtest_add_func("/ahci/dma/simple", test_dma_rw_simple); + + for (i = MODE_BEGIN; i < NUM_MODES; i++) { + for (j = ADDR_MODE_BEGIN; j < NUM_ADDR_MODES; j++) { + for (k = LEN_BEGIN; k < NUM_LENGTHS; k++) { + create_ahci_io_test(i, j, k); + } + } + } + + qtest_add_func("/ahci/io/dma/lba28/fragmented", test_dma_fragmented); ret = g_test_run(); diff --git a/tests/ide-test.c b/tests/ide-test.c index 29f4039..b28a302 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -118,7 +118,6 @@ static void ide_test_start(const char *cmdline_fmt, ...) va_end(ap); qtest_start(cmdline); - qtest_irq_intercept_in(global_qtest, "ioapic"); guest_malloc = pc_alloc_init(); g_free(cmdline); @@ -388,6 +387,7 @@ static void test_bmdma_setup(void) "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw " "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); + qtest_irq_intercept_in(global_qtest, "ioapic"); } static void test_bmdma_teardown(void) @@ -516,7 +516,7 @@ static void prepare_blkdebug_script(const char *debug_fn, const char *event) g_assert(ret == 0); } -static void test_retry_flush(void) +static void test_retry_flush(const char *machine) { uint8_t data; const char *s; @@ -580,6 +580,16 @@ static void test_flush_nodev(void) ide_test_quit(); } +static void test_pci_retry_flush(const char *machine) +{ + test_retry_flush("pc"); +} + +static void test_isa_retry_flush(const char *machine) +{ + test_retry_flush("isapc"); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -617,9 +627,9 @@ int main(int argc, char **argv) qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown); qtest_add_func("/ide/flush", test_flush); - qtest_add_func("/ide/flush_nodev", test_flush_nodev); - - qtest_add_func("/ide/retry/flush", test_retry_flush); + qtest_add_func("/ide/flush/nodev", test_flush_nodev); + qtest_add_func("/ide/flush/retry_pci", test_pci_retry_flush); + qtest_add_func("/ide/flush/retry_isa", test_isa_retry_flush); ret = g_test_run(); diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c index a6105c7..b0f39a5 100644 --- a/tests/libqos/ahci.c +++ b/tests/libqos/ahci.c @@ -487,7 +487,7 @@ void ahci_get_command_header(AHCIQState *ahci, uint8_t port, void ahci_set_command_header(AHCIQState *ahci, uint8_t port, uint8_t slot, AHCICommandHeader *cmd) { - AHCICommandHeader tmp; + AHCICommandHeader tmp = { .flags = 0 }; uint64_t ba = ahci->port[port].clb; ba += slot * sizeof(AHCICommandHeader); @@ -713,6 +713,40 @@ void ahci_command_free(AHCICommand *cmd) g_free(cmd); } +void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags) +{ + cmd->header.flags |= cmdh_flags; +} + +void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags) +{ + cmd->header.flags &= ~cmdh_flags; +} + +void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect) +{ + RegH2DFIS *fis = &(cmd->fis); + if (cmd->props->lba28) { + g_assert_cmphex(lba_sect, <=, 0xFFFFFFF); + } else if (cmd->props->lba48) { + g_assert_cmphex(lba_sect, <=, 0xFFFFFFFFFFFF); + } else { + /* Can't set offset if we don't know the format. */ + g_assert_not_reached(); + } + + /* LBA28 uses the low nibble of the device/control register for LBA24:27 */ + fis->lba_lo[0] = (lba_sect & 0xFF); + fis->lba_lo[1] = (lba_sect >> 8) & 0xFF; + fis->lba_lo[2] = (lba_sect >> 16) & 0xFF; + if (cmd->props->lba28) { + fis->device = (fis->device & 0xF0) || (lba_sect >> 24) & 0x0F; + } + fis->lba_hi[0] = (lba_sect >> 24) & 0xFF; + fis->lba_hi[1] = (lba_sect >> 32) & 0xFF; + fis->lba_hi[2] = (lba_sect >> 40) & 0xFF; +} + void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer) { cmd->buffer = buffer; @@ -740,6 +774,14 @@ void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size) ahci_command_set_sizes(cmd, cmd->xbytes, prd_size); } +void ahci_command_adjust(AHCICommand *cmd, uint64_t offset, uint64_t buffer, + uint64_t xbytes, unsigned prd_size) +{ + ahci_command_set_sizes(cmd, xbytes, prd_size); + ahci_command_set_buffer(cmd, buffer); + ahci_command_set_offset(cmd, offset); +} + void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port) { uint16_t i, prdtl; diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h index 39b99d3..888545d 100644 --- a/tests/libqos/ahci.h +++ b/tests/libqos/ahci.h @@ -537,11 +537,16 @@ void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd); void ahci_command_free(AHCICommand *cmd); /* Command adjustments */ +void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags); +void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags); +void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect); void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer); void ahci_command_set_size(AHCICommand *cmd, uint64_t xbytes); void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size); void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes, unsigned prd_size); +void ahci_command_adjust(AHCICommand *cmd, uint64_t lba_sect, uint64_t gbuffer, + uint64_t xbytes, unsigned prd_size); /* Command Misc */ uint8_t ahci_command_slot(AHCICommand *cmd); diff --git a/tests/libqos/malloc-generic.c b/tests/libqos/malloc-generic.c new file mode 100644 index 0000000..d30a2f4 --- /dev/null +++ b/tests/libqos/malloc-generic.c @@ -0,0 +1,39 @@ +/* + * Basic libqos generic malloc support + * + * Copyright (c) 2014 Marc Marí + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include "libqos/malloc-generic.h" +#include "libqos/malloc.h" + +/* + * Mostly for valgrind happiness, but it does offer + * a chokepoint for debugging guest memory leaks, too. + */ +void generic_alloc_uninit(QGuestAllocator *allocator) +{ + alloc_uninit(allocator); +} + +QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size, + uint32_t page_size, QAllocOpts flags) +{ + QGuestAllocator *s; + uint64_t start = base_addr + (1 << 20); /* Start at 1MB */ + + s = alloc_init_flags(flags, start, start + size); + alloc_set_page_size(s, page_size); + + return s; +} + +inline QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size, + uint32_t page_size) +{ + return generic_alloc_init_flags(base_addr, size, page_size, ALLOC_NO_FLAGS); +} diff --git a/tests/libqos/malloc-generic.h b/tests/libqos/malloc-generic.h new file mode 100644 index 0000000..90104ec --- /dev/null +++ b/tests/libqos/malloc-generic.h @@ -0,0 +1,21 @@ +/* + * Basic libqos generic malloc support + * + * Copyright (c) 2014 Marc Marí + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LIBQOS_MALLOC_GENERIC_H +#define LIBQOS_MALLOC_GENERIC_H + +#include "libqos/malloc.h" + +QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size, + uint32_t page_size); +QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size, + uint32_t page_size, QAllocOpts flags); +void generic_alloc_uninit(QGuestAllocator *allocator); + +#endif diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c new file mode 100644 index 0000000..b3e62e7 --- /dev/null +++ b/tests/libqos/virtio-mmio.c @@ -0,0 +1,198 @@ +/* + * libqos virtio MMIO driver + * + * Copyright (c) 2014 Marc Marí + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <stdio.h> +#include "libqtest.h" +#include "libqos/virtio.h" +#include "libqos/virtio-mmio.h" +#include "libqos/malloc.h" +#include "libqos/malloc-generic.h" + +static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return readb(dev->addr + addr); +} + +static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return readw(dev->addr + addr); +} + +static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return readl(dev->addr + addr); +} + +static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return readq(dev->addr + addr); +} + +static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + writel(dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 0); + return readl(dev->addr + QVIRTIO_MMIO_HOST_FEATURES); +} + +static void qvirtio_mmio_set_features(QVirtioDevice *d, uint32_t features) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + dev->features = features; + writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 0); + writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES, features); +} + +static uint32_t qvirtio_mmio_get_guest_features(QVirtioDevice *d) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return dev->features; +} + +static uint8_t qvirtio_mmio_get_status(QVirtioDevice *d) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return (uint8_t)readl(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS); +} + +static void qvirtio_mmio_set_status(QVirtioDevice *d, uint8_t status) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + writel(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS, (uint32_t)status); +} + +static bool qvirtio_mmio_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + uint32_t isr; + + isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 1; + if (isr != 0) { + writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 1); + return true; + } + + return false; +} + +static bool qvirtio_mmio_get_config_isr_status(QVirtioDevice *d) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + uint32_t isr; + + isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 2; + if (isr != 0) { + writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 2); + return true; + } + + return false; +} + +static void qvirtio_mmio_queue_select(QVirtioDevice *d, uint16_t index) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + writel(dev->addr + QVIRTIO_MMIO_QUEUE_SEL, (uint32_t)index); + + g_assert_cmphex(readl(dev->addr + QVIRTIO_MMIO_QUEUE_PFN), ==, 0); +} + +static uint16_t qvirtio_mmio_get_queue_size(QVirtioDevice *d) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + return (uint16_t)readl(dev->addr + QVIRTIO_MMIO_QUEUE_NUM_MAX); +} + +static void qvirtio_mmio_set_queue_address(QVirtioDevice *d, uint32_t pfn) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + writel(dev->addr + QVIRTIO_MMIO_QUEUE_PFN, pfn); +} + +static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d, + QGuestAllocator *alloc, uint16_t index) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtQueue *vq; + uint64_t addr; + + vq = g_malloc0(sizeof(*vq)); + qvirtio_mmio_queue_select(d, index); + writel(dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, dev->page_size); + + vq->index = index; + vq->size = qvirtio_mmio_get_queue_size(d); + vq->free_head = 0; + vq->num_free = vq->size; + vq->align = dev->page_size; + vq->indirect = (dev->features & QVIRTIO_F_RING_INDIRECT_DESC) != 0; + vq->event = (dev->features & QVIRTIO_F_RING_EVENT_IDX) != 0; + + writel(dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size); + + /* Check different than 0 */ + g_assert_cmpint(vq->size, !=, 0); + + /* Check power of 2 */ + g_assert_cmpint(vq->size & (vq->size - 1), ==, 0); + + addr = guest_alloc(alloc, qvring_size(vq->size, dev->page_size)); + qvring_init(alloc, vq, addr); + qvirtio_mmio_set_queue_address(d, vq->desc / dev->page_size); + + return vq; +} + +static void qvirtio_mmio_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + writel(dev->addr + QVIRTIO_MMIO_QUEUE_NOTIFY, vq->index); +} + +const QVirtioBus qvirtio_mmio = { + .config_readb = qvirtio_mmio_config_readb, + .config_readw = qvirtio_mmio_config_readw, + .config_readl = qvirtio_mmio_config_readl, + .config_readq = qvirtio_mmio_config_readq, + .get_features = qvirtio_mmio_get_features, + .set_features = qvirtio_mmio_set_features, + .get_guest_features = qvirtio_mmio_get_guest_features, + .get_status = qvirtio_mmio_get_status, + .set_status = qvirtio_mmio_set_status, + .get_queue_isr_status = qvirtio_mmio_get_queue_isr_status, + .get_config_isr_status = qvirtio_mmio_get_config_isr_status, + .queue_select = qvirtio_mmio_queue_select, + .get_queue_size = qvirtio_mmio_get_queue_size, + .set_queue_address = qvirtio_mmio_set_queue_address, + .virtqueue_setup = qvirtio_mmio_virtqueue_setup, + .virtqueue_kick = qvirtio_mmio_virtqueue_kick, +}; + +QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size) +{ + QVirtioMMIODevice *dev; + uint32_t magic; + dev = g_malloc0(sizeof(*dev)); + + magic = readl(addr + QVIRTIO_MMIO_MAGIC_VALUE); + g_assert(magic == ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)); + + dev->addr = addr; + dev->page_size = page_size; + dev->vdev.device_type = readl(addr + QVIRTIO_MMIO_DEVICE_ID); + + writel(addr + QVIRTIO_MMIO_GUEST_PAGE_SIZE, page_size); + + return dev; +} diff --git a/tests/libqos/virtio-mmio.h b/tests/libqos/virtio-mmio.h new file mode 100644 index 0000000..e3e52b9 --- /dev/null +++ b/tests/libqos/virtio-mmio.h @@ -0,0 +1,46 @@ +/* + * libqos virtio MMIO definitions + * + * Copyright (c) 2014 Marc Marí + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LIBQOS_VIRTIO_MMIO_H +#define LIBQOS_VIRTIO_MMIO_H + +#include "libqos/virtio.h" + +#define QVIRTIO_MMIO_MAGIC_VALUE 0x000 +#define QVIRTIO_MMIO_VERSION 0x004 +#define QVIRTIO_MMIO_DEVICE_ID 0x008 +#define QVIRTIO_MMIO_VENDOR_ID 0x00C +#define QVIRTIO_MMIO_HOST_FEATURES 0x010 +#define QVIRTIO_MMIO_HOST_FEATURES_SEL 0x014 +#define QVIRTIO_MMIO_GUEST_FEATURES 0x020 +#define QVIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 +#define QVIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 +#define QVIRTIO_MMIO_QUEUE_SEL 0x030 +#define QVIRTIO_MMIO_QUEUE_NUM_MAX 0x034 +#define QVIRTIO_MMIO_QUEUE_NUM 0x038 +#define QVIRTIO_MMIO_QUEUE_ALIGN 0x03C +#define QVIRTIO_MMIO_QUEUE_PFN 0x040 +#define QVIRTIO_MMIO_QUEUE_NOTIFY 0x050 +#define QVIRTIO_MMIO_INTERRUPT_STATUS 0x060 +#define QVIRTIO_MMIO_INTERRUPT_ACK 0x064 +#define QVIRTIO_MMIO_DEVICE_STATUS 0x070 +#define QVIRTIO_MMIO_DEVICE_SPECIFIC 0x100 + +typedef struct QVirtioMMIODevice { + QVirtioDevice vdev; + uint64_t addr; + uint32_t page_size; + uint32_t features; /* As it cannot be read later, save it */ +} QVirtioMMIODevice; + +extern const QVirtioBus qvirtio_mmio; + +QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size); + +#endif diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c index 788ebaf..f9fb924 100644 --- a/tests/libqos/virtio-pci.c +++ b/tests/libqos/virtio-pci.c @@ -60,25 +60,25 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data) *vpcidev = (QVirtioPCIDevice *)d; } -static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, void *addr) +static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readb(dev->pdev, addr); + return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr); } -static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, void *addr) +static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readw(dev->pdev, addr); + return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr); } -static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, void *addr) +static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readl(dev->pdev, addr); + return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr); } -static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, void *addr) +static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; int i; @@ -86,11 +86,13 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, void *addr) if (qtest_big_endian()) { for (i = 0; i < 8; ++i) { - u64 |= (uint64_t)qpci_io_readb(dev->pdev, addr + i) << (7 - i) * 8; + u64 |= (uint64_t)qpci_io_readb(dev->pdev, + (void *)(uintptr_t)addr + i) << (7 - i) * 8; } } else { for (i = 0; i < 8; ++i) { - u64 |= (uint64_t)qpci_io_readb(dev->pdev, addr + i) << i * 8; + u64 |= (uint64_t)qpci_io_readb(dev->pdev, + (void *)(uintptr_t)addr + i) << i * 8; } } @@ -100,31 +102,31 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, void *addr) static uint32_t qvirtio_pci_get_features(QVirtioDevice *d) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_DEVICE_FEATURES); + return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_FEATURES); } static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_GUEST_FEATURES, features); + qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES, features); } static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_GUEST_FEATURES); + return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES); } static uint8_t qvirtio_pci_get_status(QVirtioDevice *d) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_DEVICE_STATUS); + return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS); } static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_DEVICE_STATUS, status); + qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS, status); } static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) @@ -140,11 +142,15 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) return qpci_msix_pending(dev->pdev, vqpci->msix_entry); } else { data = readl(vqpci->msix_addr); - writel(vqpci->msix_addr, 0); - return data == vqpci->msix_data; + if (data == vqpci->msix_data) { + writel(vqpci->msix_addr, 0); + return true; + } else { + return false; + } } } else { - return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_ISR_STATUS) & 1; + return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 1; } } @@ -160,30 +166,34 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d) return qpci_msix_pending(dev->pdev, dev->config_msix_entry); } else { data = readl(dev->config_msix_addr); - writel(dev->config_msix_addr, 0); - return data == dev->config_msix_data; + if (data == dev->config_msix_data) { + writel(dev->config_msix_addr, 0); + return true; + } else { + return false; + } } } else { - return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_ISR_STATUS) & 2; + return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 2; } } static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_QUEUE_SELECT, index); + qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SELECT, index); } static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - return qpci_io_readw(dev->pdev, dev->addr + QVIRTIO_QUEUE_SIZE); + return qpci_io_readw(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SIZE); } static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_QUEUE_ADDRESS, pfn); + qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_ADDRESS, pfn); } static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d, @@ -225,7 +235,7 @@ static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d, static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; - qpci_io_writew(dev->pdev, dev->addr + QVIRTIO_QUEUE_NOTIFY, vq->index); + qpci_io_writew(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_NOTIFY, vq->index); } const QVirtioBus qvirtio_pci = { @@ -305,8 +315,8 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci, control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT); qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index); - qpci_io_writew(d->pdev, d->addr + QVIRTIO_MSIX_QUEUE_VECTOR, entry); - vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_MSIX_QUEUE_VECTOR); + qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR, entry); + vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR); g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR); } @@ -337,7 +347,7 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d, qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL, control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT); - qpci_io_writew(d->pdev, d->addr + QVIRTIO_MSIX_CONF_VECTOR, entry); - vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_MSIX_CONF_VECTOR); + qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR, entry); + vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR); g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR); } diff --git a/tests/libqos/virtio-pci.h b/tests/libqos/virtio-pci.h index 883f7ff..8f0e52a 100644 --- a/tests/libqos/virtio-pci.h +++ b/tests/libqos/virtio-pci.h @@ -13,18 +13,18 @@ #include "libqos/virtio.h" #include "libqos/pci.h" -#define QVIRTIO_DEVICE_FEATURES 0x00 -#define QVIRTIO_GUEST_FEATURES 0x04 -#define QVIRTIO_QUEUE_ADDRESS 0x08 -#define QVIRTIO_QUEUE_SIZE 0x0C -#define QVIRTIO_QUEUE_SELECT 0x0E -#define QVIRTIO_QUEUE_NOTIFY 0x10 -#define QVIRTIO_DEVICE_STATUS 0x12 -#define QVIRTIO_ISR_STATUS 0x13 -#define QVIRTIO_MSIX_CONF_VECTOR 0x14 -#define QVIRTIO_MSIX_QUEUE_VECTOR 0x16 -#define QVIRTIO_DEVICE_SPECIFIC_MSIX 0x18 -#define QVIRTIO_DEVICE_SPECIFIC_NO_MSIX 0x14 +#define QVIRTIO_PCI_DEVICE_FEATURES 0x00 +#define QVIRTIO_PCI_GUEST_FEATURES 0x04 +#define QVIRTIO_PCI_QUEUE_ADDRESS 0x08 +#define QVIRTIO_PCI_QUEUE_SIZE 0x0C +#define QVIRTIO_PCI_QUEUE_SELECT 0x0E +#define QVIRTIO_PCI_QUEUE_NOTIFY 0x10 +#define QVIRTIO_PCI_DEVICE_STATUS 0x12 +#define QVIRTIO_PCI_ISR_STATUS 0x13 +#define QVIRTIO_PCI_MSIX_CONF_VECTOR 0x14 +#define QVIRTIO_PCI_MSIX_QUEUE_VECTOR 0x16 +#define QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX 0x18 +#define QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX 0x14 #define QVIRTIO_PCI_ALIGN 4096 diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c index a061289..3205b88 100644 --- a/tests/libqos/virtio.c +++ b/tests/libqos/virtio.c @@ -12,25 +12,25 @@ #include "libqos/virtio.h" uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d, - void *addr) + uint64_t addr) { return bus->config_readb(d, addr); } uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d, - void *addr) + uint64_t addr) { return bus->config_readw(d, addr); } uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d, - void *addr) + uint64_t addr) { return bus->config_readl(d, addr); } uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d, - void *addr) + uint64_t addr) { return bus->config_readq(d, addr); } diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h index 29fbacb..2449fee 100644 --- a/tests/libqos/virtio.h +++ b/tests/libqos/virtio.h @@ -93,10 +93,10 @@ typedef struct QVRingIndirectDesc { } QVRingIndirectDesc; typedef struct QVirtioBus { - uint8_t (*config_readb)(QVirtioDevice *d, void *addr); - uint16_t (*config_readw)(QVirtioDevice *d, void *addr); - uint32_t (*config_readl)(QVirtioDevice *d, void *addr); - uint64_t (*config_readq)(QVirtioDevice *d, void *addr); + uint8_t (*config_readb)(QVirtioDevice *d, uint64_t addr); + uint16_t (*config_readw)(QVirtioDevice *d, uint64_t addr); + uint32_t (*config_readl)(QVirtioDevice *d, uint64_t addr); + uint64_t (*config_readq)(QVirtioDevice *d, uint64_t addr); /* Get features of the device */ uint32_t (*get_features)(QVirtioDevice *d); @@ -144,13 +144,13 @@ static inline uint32_t qvring_size(uint32_t num, uint32_t align) } uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d, - void *addr); + uint64_t addr); uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d, - void *addr); + uint64_t addr); uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d, - void *addr); + uint64_t addr); uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d, - void *addr); + uint64_t addr); uint32_t qvirtio_get_features(const QVirtioBus *bus, QVirtioDevice *d); void qvirtio_set_features(const QVirtioBus *bus, QVirtioDevice *d, uint32_t features); diff --git a/tests/qemu-iotests/004 b/tests/qemu-iotests/004 index 651072e..2ad77ed 100755 --- a/tests/qemu-iotests/004 +++ b/tests/qemu-iotests/004 @@ -38,7 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx _supported_proto generic _supported_os Linux diff --git a/tests/qemu-iotests/006.out b/tests/qemu-iotests/006.out deleted file mode 100644 index d135841..0000000 --- a/tests/qemu-iotests/006.out +++ /dev/null @@ -1,6 +0,0 @@ -QA output created by 006 - -creating 128GB image -qemu-img: The image size is too large for file format 'vpc' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=137438953472 -*** done diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007 index fe1a743..7b5aff5 100755 --- a/tests/qemu-iotests/007 +++ b/tests/qemu-iotests/007 @@ -43,6 +43,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +# refcount_bits must be at least 4 so we can create ten internal snapshots +# (1 bit supports none, 2 bits support two, 4 bits support 14) +_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]' echo echo "creating image" diff --git a/tests/qemu-iotests/015 b/tests/qemu-iotests/015 index 099d757..6f26095 100755 --- a/tests/qemu-iotests/015 +++ b/tests/qemu-iotests/015 @@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +# Internal snapshots are (currently) impossible with refcount_bits=1 +_unsupported_imgopts 'refcount_bits=1[^0-9]' echo echo "creating image" diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026 index df2884b..0fc3244 100755 --- a/tests/qemu-iotests/026 +++ b/tests/qemu-iotests/026 @@ -46,6 +46,13 @@ _supported_proto file _supported_os Linux _default_cache_mode "writethrough" _supported_cache_modes "writethrough" "none" +# The refcount table tests expect a certain minimum width for refcount entries +# (so that the refcount table actually needs to grow); that minimum is 16 bits, +# being the default refcount entry width. +# 32 and 64 bits do not work either, however, due to different leaked cluster +# count on error. +# Thus, the only remaining option is refcount_bits=16. +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' echo "Errors while writing 128 kB" echo diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index 524f7ee..5e964fb 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -140,19 +140,13 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: on; write -Failed to flush the L2 table cache: Input/output error write failed: Input/output error - -127 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: on; write -b -Failed to flush the L2 table cache: Input/output error write failed: Input/output error - -127 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write @@ -174,19 +168,13 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: on; write -Failed to flush the L2 table cache: No space left on device write failed: No space left on device - -127 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: on; write -b -Failed to flush the L2 table cache: No space left on device write failed: No space left on device - -127 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write @@ -356,13 +344,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: on; write -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: on; write -b -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -382,13 +368,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: on; write -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: on; write -b -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029 index fa46ace..b9cd826 100755 --- a/tests/qemu-iotests/029 +++ b/tests/qemu-iotests/029 @@ -44,6 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +# Internal snapshots are (currently) impossible with refcount_bits=1 +_unsupported_imgopts 'refcount_bits=1[^0-9]' offset_size=24 offset_l1_size=36 diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index b6311b0..765afdd 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -4,90 +4,90 @@ QA output created by 049 == 1. Traditional size parameter == qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 == 2. Specifying size via -o == qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 == 3. Invalid sizes == @@ -97,7 +97,7 @@ qemu-img: Image size must be less than 8 EiB! qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 qemu-img: qcow2 doesn't support shrinking images yet qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k qemu-img: Image size must be less than 8 EiB! @@ -105,14 +105,14 @@ qemu-img: Image size must be less than 8 EiB! qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 qemu-img: qcow2 doesn't support shrinking images yet qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for @@ -125,84 +125,84 @@ qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2' == Check correct interpretation of suffixes for cluster size == qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off refcount_bits=16 == Check compat level option == qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 == Check preallocation option == qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='off' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='off' lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off refcount_bits=16 == Check encryption option == qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16 == Check lazy_refcounts option (only with v3) == qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16 *** done diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 27138a2..0360f37 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -41,6 +41,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +# A compat=0.10 image is created in this test which does not support anything +# other than refcount_bits=16 +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' function do_run_qemu() { @@ -96,6 +99,12 @@ run_qemu -drive file="$TEST_IMG",driver=raw,format=qcow2 run_qemu -drive file="$TEST_IMG",driver=qcow2,format=qcow2 echo +echo === Device without drive === +echo + +run_qemu -device virtio-scsi-pci -device scsi-hd + +echo echo === Overriding backing file === echo diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index bf52bf0..09895e6 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -47,6 +47,14 @@ Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specify both 'driver' and 'format' +=== Device without drive === + +Testing: -device virtio-scsi-pci -device scsi-hd +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd: drive property not set +QEMU_PROG: -device scsi-hd: Device 'scsi-hd' could not be initialized + + === Overriding backing file === Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults @@ -115,8 +123,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive if=ide QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: Device needs media, but drive is empty -QEMU_PROG: Device initialization failed. -QEMU_PROG: Initialization of device ide-hd failed +QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. Testing: -drive if=virtio QEMU X.Y.Z monitor - type 'help' for more information @@ -127,8 +134,7 @@ QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized Testing: -drive if=scsi QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty -QEMU_PROG: Device initialization failed. -QEMU_PROG: Initialization of device lsi53c895a failed +QEMU_PROG: Initialization of device lsi53c895a failed: Device initialization failed. Testing: -drive if=none,id=disk -device ide-cd,drive=disk QEMU X.Y.Z monitor - type 'help' for more information @@ -178,8 +184,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: Can't use a read-only drive -QEMU_PROG: Device initialization failed. -QEMU_PROG: Initialization of device ide-hd failed +QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on QEMU X.Y.Z monitor - type 'help' for more information diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058 index a60b34b..f2bdd0b 100755 --- a/tests/qemu-iotests/058 +++ b/tests/qemu-iotests/058 @@ -89,6 +89,8 @@ _supported_fmt qcow2 _supported_proto file _supported_os Linux _require_command QEMU_NBD +# Internal snapshots are (currently) impossible with refcount_bits=1 +_unsupported_imgopts 'refcount_bits=1[^0-9]' # Use -f raw instead of -f $IMGFMT for the NBD connection QEMU_IO_NBD="$QEMU_IO -f raw --cache=$CACHEMODE" diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index dc9f6b7..7511189 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -18,6 +18,7 @@ cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false + refcount bits: 16 corrupt: true qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write read 512/512 bytes at offset 0 diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065 index 8d3a9c9..72aa970 100755 --- a/tests/qemu-iotests/065 +++ b/tests/qemu-iotests/065 @@ -88,34 +88,41 @@ class TestQMP(TestImageInfoSpecific): class TestQCow2(TestQemuImgInfo): '''Testing a qcow2 version 2 image''' img_options = 'compat=0.10' - json_compare = { 'compat': '0.10' } - human_compare = [ 'compat: 0.10' ] + json_compare = { 'compat': '0.10', 'refcount-bits': 16 } + human_compare = [ 'compat: 0.10', 'refcount bits: 16' ] class TestQCow3NotLazy(TestQemuImgInfo): '''Testing a qcow2 version 3 image with lazy refcounts disabled''' img_options = 'compat=1.1,lazy_refcounts=off' - json_compare = { 'compat': '1.1', 'lazy-refcounts': False, 'corrupt': False } - human_compare = [ 'compat: 1.1', 'lazy refcounts: false', 'corrupt: false' ] + json_compare = { 'compat': '1.1', 'lazy-refcounts': False, + 'refcount-bits': 16, 'corrupt': False } + human_compare = [ 'compat: 1.1', 'lazy refcounts: false', + 'refcount bits: 16', 'corrupt: false' ] class TestQCow3Lazy(TestQemuImgInfo): '''Testing a qcow2 version 3 image with lazy refcounts enabled''' img_options = 'compat=1.1,lazy_refcounts=on' - json_compare = { 'compat': '1.1', 'lazy-refcounts': True, 'corrupt': False } - human_compare = [ 'compat: 1.1', 'lazy refcounts: true', 'corrupt: false' ] + json_compare = { 'compat': '1.1', 'lazy-refcounts': True, + 'refcount-bits': 16, 'corrupt': False } + human_compare = [ 'compat: 1.1', 'lazy refcounts: true', + 'refcount bits: 16', 'corrupt: false' ] class TestQCow3NotLazyQMP(TestQMP): '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening with lazy refcounts enabled''' img_options = 'compat=1.1,lazy_refcounts=off' qemu_options = 'lazy-refcounts=on' - compare = { 'compat': '1.1', 'lazy-refcounts': False, 'corrupt': False } + compare = { 'compat': '1.1', 'lazy-refcounts': False, + 'refcount-bits': 16, 'corrupt': False } + class TestQCow3LazyQMP(TestQMP): '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening with lazy refcounts disabled''' img_options = 'compat=1.1,lazy_refcounts=on' qemu_options = 'lazy-refcounts=off' - compare = { 'compat': '1.1', 'lazy-refcounts': True, 'corrupt': False } + compare = { 'compat': '1.1', 'lazy-refcounts': True, + 'refcount-bits': 16, 'corrupt': False } TestImageInfoSpecific = None TestQemuImgInfo = None diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index 0508c69..83eefa3 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -35,6 +35,8 @@ status=1 # failure is the default! _supported_fmt qcow2 _supported_proto file _supported_os Linux +# Because anything other than 16 would change the output of query-block +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' function do_run_qemu() { diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 00b3eae..6ff41bc 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -32,6 +32,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti "data": { "compat": "1.1", "lazy-refcounts": false, + "refcount-bits": 16, "corrupt": false } }, @@ -208,6 +209,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk "data": { "compat": "1.1", "lazy-refcounts": false, + "refcount-bits": 16, "corrupt": false } }, @@ -414,6 +416,7 @@ Testing: "data": { "compat": "1.1", "lazy-refcounts": false, + "refcount-bits": 16, "corrupt": false } }, @@ -599,6 +602,7 @@ Testing: "data": { "compat": "1.1", "lazy-refcounts": false, + "refcount-bits": 16, "corrupt": false } }, @@ -710,6 +714,7 @@ Testing: "data": { "compat": "1.1", "lazy-refcounts": false, + "refcount-bits": 16, "corrupt": false } }, diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079 index 6613cfb..ade6efa 100755 --- a/tests/qemu-iotests/079 +++ b/tests/qemu-iotests/079 @@ -42,19 +42,13 @@ _supported_fmt qcow2 _supported_proto file nfs _supported_os Linux -function test_qemu_img() -{ - echo qemu-img "$@" | _filter_testdir - $QEMU_IMG "$@" 2>&1 | _filter_testdir - echo -} - echo "=== Check option preallocation and cluster_size ===" echo cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304" for s in $cluster_sizes; do - test_qemu_img create -f $IMGFMT -o preallocation=metadata,cluster_size=$s "$TEST_IMG" 4G + IMGOPTS=$(_optstr_add "$IMGOPTS" "preallocation=metadata,cluster_size=$s") \ + _make_test_img 4G done # success, all done diff --git a/tests/qemu-iotests/079.out b/tests/qemu-iotests/079.out index ef4b8c9..6dc5d57 100644 --- a/tests/qemu-iotests/079.out +++ b/tests/qemu-iotests/079.out @@ -1,32 +1,14 @@ QA output created by 079 === Check option preallocation and cluster_size === -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=16384 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=16384 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=32768 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=32768 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=65536 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=131072 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=131072 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=262144 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=262144 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=524288 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=524288 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=1048576 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=1048576 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=2097152 TEST_DIR/t.qcow2 4G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=2097152 preallocation='metadata' lazy_refcounts=off - -qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=4194304 TEST_DIR/t.qcow2 4G -qemu-img: TEST_DIR/t.qcow2: Cluster size must be a power of two between 512 and 2048k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=4194304 preallocation='metadata' lazy_refcounts=off - +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' +qemu-img: TEST_DIR/t.IMGFMT: Cluster size must be a power of two between 512 and 2048k +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata' *** done diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 73795f1..a2c58ae 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -42,6 +42,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +# Internal snapshots are (currently) impossible with refcount_bits=1 +_unsupported_imgopts 'refcount_bits=1[^0-9]' header_size=104 diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out index d0234e6..3a749b8 100644 --- a/tests/qemu-iotests/082.out +++ b/tests/qemu-iotests/082.out @@ -3,14 +3,14 @@ QA output created by 082 === create: Options specified more than once === Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) cluster_size: 65536 Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -18,10 +18,11 @@ cluster_size: 4096 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -29,10 +30,11 @@ cluster_size: 8192 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -50,6 +52,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M @@ -62,6 +65,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M @@ -74,6 +78,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M @@ -86,6 +91,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M @@ -98,6 +104,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M @@ -110,6 +117,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M @@ -122,6 +130,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M @@ -134,13 +143,14 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,?' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,?' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, @@ -161,6 +171,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits Testing: create -o help Supported options: @@ -169,7 +180,7 @@ size Virtual disk size === convert: Options specified more than once === Testing: create -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -190,6 +201,7 @@ cluster_size: 4096 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -200,6 +212,7 @@ cluster_size: 8192 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: convert -O qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -220,6 +233,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -232,6 +246,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -244,6 +259,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -256,6 +272,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -268,6 +285,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -280,6 +298,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -292,6 +311,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -304,6 +324,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -331,6 +352,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits Testing: convert -o help Supported options: @@ -346,6 +368,7 @@ cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2 @@ -356,6 +379,7 @@ cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false + refcount bits: 16 corrupt: false Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2 @@ -366,6 +390,7 @@ cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: true + refcount bits: 16 corrupt: false Testing: amend -f qcow2 -o size=4M,size=148M TEST_DIR/t.qcow2 @@ -386,6 +411,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2 @@ -398,6 +424,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 @@ -410,6 +437,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 @@ -422,6 +450,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 @@ -434,6 +463,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 @@ -446,6 +476,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 @@ -458,6 +489,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 @@ -470,6 +502,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 @@ -499,6 +532,7 @@ encryption Encrypt the image cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates +refcount_bits Width of a reference count entry in bits Testing: convert -o help Supported options: diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out index 0f2b17f..5eb8b94 100644 --- a/tests/qemu-iotests/085.out +++ b/tests/qemu-iotests/085.out @@ -11,7 +11,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === Create a single snapshot on virtio0 === -Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2.orig' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2.orig' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} === Invalid command - missing device and nodename === @@ -25,31 +25,31 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file === Create several transactional group snapshots === -Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/1-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/1-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off -Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} *** done diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index 6f74cec..3e0038d 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -41,6 +41,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +# Because anything other than 16 would change the output of qemu_io -c info +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' # Using an image filename containing quotation marks will render the JSON data # below invalid. In that case, we have little choice but simply not to run this diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index a6d3711..5b541a3 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -43,6 +43,7 @@ vm state offset: 512 MiB Format specific information: compat: 1.1 lazy refcounts: false + refcount bits: 16 corrupt: false format name: IMGFMT cluster size: 64 KiB @@ -50,5 +51,6 @@ vm state offset: 512 MiB Format specific information: compat: 1.1 lazy refcounts: false + refcount bits: 16 corrupt: false *** done diff --git a/tests/qemu-iotests/104 b/tests/qemu-iotests/104 index f32752b..2e35ea8 100755 --- a/tests/qemu-iotests/104 +++ b/tests/qemu-iotests/104 @@ -34,7 +34,7 @@ trap "exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx _supported_proto generic _supported_os Linux diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108 index 12fc92a..ce44749 100755 --- a/tests/qemu-iotests/108 +++ b/tests/qemu-iotests/108 @@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +# This test directly modifies a refblock so it relies on refcount_bits being 16 +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' echo echo '=== Repairing an image without any refcount table ===' diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112 new file mode 100755 index 0000000..3f054a3 --- /dev/null +++ b/tests/qemu-iotests/112 @@ -0,0 +1,187 @@ +#!/bin/bash +# +# Test cases for different refcount_bits values +# +# Copyright (C) 2015 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +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 file +_supported_os Linux +# This test will set refcount_bits on its own which would conflict with the +# manual setting; compat will be overridden as well +_unsupported_imgopts refcount_bits 'compat=0.10' + +function print_refcount_bits() +{ + $QEMU_IMG info "$TEST_IMG" | sed -n '/refcount bits:/ s/^ *//p' +} + +echo +echo '=== refcount_bits limits ===' +echo + +# Must be positive (non-zero) +IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M +# Must be positive (non-negative) +IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M +# May not exceed 64 +IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M +# Must be a power of two +IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M + +# 1 is the minimum +IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M +print_refcount_bits + +# 64 is the maximum +IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M +print_refcount_bits + +# 16 is the default +_make_test_img 64M +print_refcount_bits + +echo +echo '=== refcount_bits and compat=0.10 ===' +echo + +# Should work +IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M +print_refcount_bits + +# Should not work +IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M +IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M + + +echo +echo '=== Snapshot limit on refcount_bits=1 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M +print_refcount_bits + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Should fail for now; in the future, this might be supported by automatically +# copying all clusters with overflowing refcount +$QEMU_IMG snapshot -c foo "$TEST_IMG" + +# The new L1 table could/should be leaked +_check_test_img + +echo +echo '=== Snapshot limit on refcount_bits=2 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M +print_refcount_bits + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Should succeed +$QEMU_IMG snapshot -c foo "$TEST_IMG" +$QEMU_IMG snapshot -c bar "$TEST_IMG" +# Should fail (4th reference) +$QEMU_IMG snapshot -c baz "$TEST_IMG" + +# The new L1 table could/should be leaked +_check_test_img + +echo +echo '=== Compressed clusters with refcount_bits=1 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M +print_refcount_bits + +# Both should fit into a single host cluster; instead of failing to increase the +# refcount of that cluster, qemu should just allocate a new cluster and make +# this operation succeed +$QEMU_IO -c 'write -P 0 -c 0 64k' \ + -c 'write -P 1 -c 64k 64k' \ + "$TEST_IMG" | _filter_qemu_io + +_check_test_img + +echo +echo '=== MSb set in 64 bit refcount ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M +print_refcount_bits + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Set the MSb in the refblock entry of the data cluster +poke_file "$TEST_IMG" $((0x20028)) "\x80\x00\x00\x00\x00\x00\x00\x00" + +# Clear OFLAG_COPIED in the L2 entry of the data cluster +poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00" + +# Try to write to that cluster (should work, even though the MSb is set) +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +echo +echo '=== Snapshot on maximum 64 bit refcount value ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M +print_refcount_bits + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Set the refblock entry to the maximum value possible +poke_file "$TEST_IMG" $((0x20028)) "\xff\xff\xff\xff\xff\xff\xff\xff" + +# Clear OFLAG_COPIED in the L2 entry of the data cluster +poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00" + +# Try a snapshot (should correctly identify the overflow; may work in the future +# by falling back to COW) +$QEMU_IMG snapshot -c foo "$TEST_IMG" + +# The new L1 table could/should be leaked; and obviously the data cluster is +# leaked (refcount=UINT64_MAX reference=1) +_check_test_img + + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out new file mode 100644 index 0000000..9a98633 --- /dev/null +++ b/tests/qemu-iotests/112.out @@ -0,0 +1,84 @@ +QA output created by 112 + +=== refcount_bits limits === + +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount_bits=-1 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 1 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 64 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 16 + +=== refcount_bits and compat=0.10 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 16 +qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + +=== Snapshot limit on refcount_bits=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 1 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'foo': -22 (Invalid argument) +Leaked cluster 6 refcount=1 reference=0 + +1 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. + +=== Snapshot limit on refcount_bits=2 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 2 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'baz': -22 (Invalid argument) +Leaked cluster 7 refcount=1 reference=0 + +1 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. + +=== Compressed clusters with refcount_bits=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 1 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. + +=== MSb set in 64 bit refcount === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 64 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Snapshot on maximum 64 bit refcount value === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 64 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'foo': -22 (Invalid argument) +Leaked cluster 5 refcount=18446744073709551615 reference=1 +Leaked cluster 6 refcount=1 reference=0 + +2 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. +*** done diff --git a/tests/qemu-iotests/006 b/tests/qemu-iotests/128 index 0c0cf5d..249a865 100755 --- a/tests/qemu-iotests/006 +++ b/tests/qemu-iotests/128 @@ -1,9 +1,8 @@ #!/bin/bash # -# Make sure qemu-img rejects > 127GB images for the vpc format as the format -# doesn't support this. +# Test that opening O_DIRECT succeeds when image file I/O produces EIO # -# Copyright (C) 2009 Red Hat, Inc. +# Copyright (C) 2015 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 @@ -20,7 +19,7 @@ # # creator -owner=hch@lst.de +owner=stefanha@redhat.com seq=`basename $0` echo "QA output created by $seq" @@ -29,9 +28,34 @@ here=`pwd` tmp=/tmp/$$ status=1 # failure is the default! +devname="eiodev$$" + +_setup_eiodev() +{ + # This test should either be run as root or with passwordless sudo + for cmd in "" "sudo -n"; do + echo "0 $((1024 * 1024 * 1024 / 512)) error" | \ + $cmd dmsetup create "$devname" 2>/dev/null + if [ "$?" -eq 0 ]; then + return + fi + done + _notrun "root privileges required to run dmsetup" +} + +_cleanup_eiodev() +{ + for cmd in "" "sudo -n"; do + $cmd dmsetup remove "$devname" 2>/dev/null + if [ "$?" -eq 0 ]; then + return + fi + done +} + _cleanup() { - _cleanup_test_img + _cleanup_eiodev } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -39,14 +63,18 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt vpc -_supported_proto generic +_supported_fmt raw +_supported_proto file _supported_os Linux +_setup_eiodev + +TEST_IMG="/dev/mapper/$devname" echo -echo "creating 128GB image" -_make_test_img 128G +echo "== reading from error device ==" +# Opening image should succeed but the read operation should fail +$QEMU_IO --format "$IMGFMT" --nocache -c "read 0 65536" "$TEST_IMG" | _filter_qemu_io # success, all done echo "*** done" diff --git a/tests/qemu-iotests/128.out b/tests/qemu-iotests/128.out new file mode 100644 index 0000000..4e43f5f --- /dev/null +++ b/tests/qemu-iotests/128.out @@ -0,0 +1,5 @@ +QA output created by 128 + +== reading from error device == +read failed: Input/output error +*** done diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 06e1bb0..012a812 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -192,7 +192,8 @@ _filter_img_create() -e "s# block_size=[0-9]\\+##g" \ -e "s# block_state_zero=\\(on\\|off\\)##g" \ -e "s# log_size=[0-9]\\+##g" \ - -e "s/archipelago:a/TEST_DIR\//g" + -e "s/archipelago:a/TEST_DIR\//g" \ + -e "s# refcount_bits=[0-9]\\+##g" } _filter_img_info() diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 0d3b95c..71f19d4 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -12,7 +12,7 @@ 003 rw auto 004 rw auto quick 005 img auto quick -006 img auto +# 006 was removed, do not reuse 007 snapshot auto 008 rw auto quick 009 rw auto quick @@ -116,7 +116,9 @@ 109 rw auto 110 rw auto backing quick 111 rw auto quick +112 rw auto 113 rw auto quick 114 rw auto quick 116 rw auto quick 123 rw auto quick +128 rw auto quick diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c index 27d1b6f..b552d9f 100644 --- a/tests/test-coroutine.c +++ b/tests/test-coroutine.c @@ -13,6 +13,7 @@ #include <glib.h> #include "block/coroutine.h" +#include "block/coroutine_int.h" /* * Check that qemu_in_coroutine() works @@ -122,6 +123,30 @@ static void test_yield(void) g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */ } +static void coroutine_fn c2_fn(void *opaque) +{ + qemu_coroutine_yield(); +} + +static void coroutine_fn c1_fn(void *opaque) +{ + Coroutine *c2 = opaque; + qemu_coroutine_enter(c2, NULL); +} + +static void test_co_queue(void) +{ + Coroutine *c1; + Coroutine *c2; + + c1 = qemu_coroutine_create(c1_fn); + c2 = qemu_coroutine_create(c2_fn); + + qemu_coroutine_enter(c1, c2); + memset(c1, 0xff, sizeof(Coroutine)); + qemu_coroutine_enter(c2, NULL); +} + /* * Check that creation, enter, and return work */ @@ -343,6 +368,7 @@ static void perf_cost(void) int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); + g_test_add_func("/basic/co_queue", test_co_queue); g_test_add_func("/basic/lifecycle", test_lifecycle); g_test_add_func("/basic/yield", test_yield); g_test_add_func("/basic/nesting", test_nesting); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 89d7cbf..4078321 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -16,9 +16,11 @@ #include "libqtest.h" #include "libqos/virtio.h" #include "libqos/virtio-pci.h" +#include "libqos/virtio-mmio.h" #include "libqos/pci-pc.h" #include "libqos/malloc.h" #include "libqos/malloc-pc.h" +#include "libqos/malloc-generic.h" #include "qemu/bswap.h" #define QVIRTIO_BLK_F_BARRIER 0x00000001 @@ -42,10 +44,14 @@ #define TEST_IMAGE_SIZE (64 * 1024 * 1024) #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000) +#define PCI_SLOT_HP 0x06 #define PCI_SLOT 0x04 #define PCI_FN 0x00 -#define PCI_SLOT_HP 0x06 +#define MMIO_PAGE_SIZE 4096 +#define MMIO_DEV_BASE_ADDR 0x0A003E00 +#define MMIO_RAM_ADDR 0x40000000 +#define MMIO_RAM_SIZE 0x20000000 typedef struct QVirtioBlkReq { uint32_t type; @@ -55,11 +61,10 @@ typedef struct QVirtioBlkReq { uint8_t status; } QVirtioBlkReq; -static QPCIBus *test_start(void) +static char *drive_create(void) { - char *cmdline; - char tmp_path[] = "/tmp/qtest.XXXXXX"; int fd, ret; + char *tmp_path = g_strdup("/tmp/qtest.XXXXXX"); /* Create a temporary raw image */ fd = mkstemp(tmp_path); @@ -68,24 +73,52 @@ static QPCIBus *test_start(void) g_assert_cmpint(ret, ==, 0); close(fd); + return tmp_path; +} + +static QPCIBus *pci_test_start(void) +{ + char *cmdline; + char *tmp_path; + + tmp_path = drive_create(); + cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw " - "-drive if=none,id=drive1,file=/dev/null,format=raw " - "-device virtio-blk-pci,id=drv0,drive=drive0," - "addr=%x.%x", - tmp_path, PCI_SLOT, PCI_FN); + "-drive if=none,id=drive1,file=/dev/null,format=raw " + "-device virtio-blk-pci,id=drv0,drive=drive0," + "addr=%x.%x", + tmp_path, PCI_SLOT, PCI_FN); qtest_start(cmdline); unlink(tmp_path); + g_free(tmp_path); g_free(cmdline); return qpci_init_pc(); } +static void arm_test_start(void) +{ + char *cmdline; + char *tmp_path; + + tmp_path = drive_create(); + + cmdline = g_strdup_printf("-machine virt " + "-drive if=none,id=drive0,file=%s,format=raw " + "-device virtio-blk-device,drive=drive0", + tmp_path); + qtest_start(cmdline); + unlink(tmp_path); + g_free(tmp_path); + g_free(cmdline); +} + static void test_end(void) { qtest_end(); } -static QVirtioPCIDevice *virtio_blk_init(QPCIBus *bus, int slot) +static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot) { QVirtioPCIDevice *dev; @@ -135,14 +168,10 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req, return addr; } -static void pci_basic(void) +static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev, + QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific) { - QVirtioPCIDevice *dev; - QPCIBus *bus; - QVirtQueuePCI *vqpci; - QGuestAllocator *alloc; QVirtioBlkReq req; - void *addr; uint64_t req_addr; uint64_t capacity; uint32_t features; @@ -150,29 +179,19 @@ static void pci_basic(void) uint8_t status; char *data; - bus = test_start(); + capacity = qvirtio_config_readq(bus, dev, device_specific); - dev = virtio_blk_init(bus, PCI_SLOT); - - /* MSI-X is not enabled */ - addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; - - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); - features = qvirtio_get_features(&qvirtio_pci, &dev->vdev); + features = qvirtio_get_features(bus, dev); features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_INDIRECT_DESC | QVIRTIO_F_RING_EVENT_IDX | QVIRTIO_BLK_F_SCSI); - qvirtio_set_features(&qvirtio_pci, &dev->vdev, features); - - alloc = pc_alloc_init(); - vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev, - alloc, 0); + qvirtio_set_features(bus, dev, features); - qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev); + qvirtio_set_driver_ok(bus, dev); - /* Write and read with 2 descriptor layout */ + /* Write and read with 3 descriptor layout */ /* Write request */ req.type = QVIRTIO_BLK_T_OUT; req.ioprio = 1; @@ -184,12 +203,13 @@ static void pci_basic(void) g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, false, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); - qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq, - QVIRTIO_BLK_TIMEOUT_US); + qvirtqueue_kick(bus, dev, vq, free_head); + + qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); @@ -205,13 +225,13 @@ static void pci_basic(void) g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 513, true, false); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, true, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); + qvirtqueue_kick(bus, dev, vq, free_head); - qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq, - QVIRTIO_BLK_TIMEOUT_US); + qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); @@ -222,61 +242,84 @@ static void pci_basic(void) guest_free(alloc, req_addr); - /* Write and read with 3 descriptor layout */ - /* Write request */ - req.type = QVIRTIO_BLK_T_OUT; - req.ioprio = 1; - req.sector = 1; - req.data = g_malloc0(512); - strcpy(req.data, "TEST"); + if (features & QVIRTIO_F_ANY_LAYOUT) { + /* Write and read with 2 descriptor layout */ + /* Write request */ + req.type = QVIRTIO_BLK_T_OUT; + req.ioprio = 1; + req.sector = 1; + req.data = g_malloc0(512); + strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(alloc, &req, 512); + req_addr = virtio_blk_request(alloc, &req, 512); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); + g_free(req.data); - qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add(vq, req_addr, 528, false, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); + qvirtqueue_kick(bus, dev, vq, free_head); - qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq, - QVIRTIO_BLK_TIMEOUT_US); - status = readb(req_addr + 528); - g_assert_cmpint(status, ==, 0); + qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US); + status = readb(req_addr + 528); + g_assert_cmpint(status, ==, 0); - guest_free(alloc, req_addr); + guest_free(alloc, req_addr); - /* Read request */ - req.type = QVIRTIO_BLK_T_IN; - req.ioprio = 1; - req.sector = 1; - req.data = g_malloc0(512); + /* Read request */ + req.type = QVIRTIO_BLK_T_IN; + req.ioprio = 1; + req.sector = 1; + req.data = g_malloc0(512); - req_addr = virtio_blk_request(alloc, &req, 512); + req_addr = virtio_blk_request(alloc, &req, 512); - g_free(req.data); + g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 513, true, false); - qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); + qvirtqueue_kick(bus, dev, vq, free_head); - qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq, - QVIRTIO_BLK_TIMEOUT_US); - status = readb(req_addr + 528); - g_assert_cmpint(status, ==, 0); + qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US); + status = readb(req_addr + 528); + g_assert_cmpint(status, ==, 0); - data = g_malloc0(512); - memread(req_addr + 16, data, 512); - g_assert_cmpstr(data, ==, "TEST"); - g_free(data); + data = g_malloc0(512); + memread(req_addr + 16, data, 512); + g_assert_cmpstr(data, ==, "TEST"); + g_free(data); - guest_free(alloc, req_addr); + guest_free(alloc, req_addr); + } +} + +static void pci_basic(void) +{ + QVirtioPCIDevice *dev; + QPCIBus *bus; + QVirtQueuePCI *vqpci; + QGuestAllocator *alloc; + void *addr; + + bus = pci_test_start(); + dev = virtio_blk_pci_init(bus, PCI_SLOT); + + alloc = pc_alloc_init(); + vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev, + alloc, 0); + + /* MSI-X is not enabled */ + addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX; + + test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq, + (uint64_t)(uintptr_t)addr); /* End test */ guest_free(alloc, vqpci->vq.desc); + pc_alloc_uninit(alloc); qvirtio_pci_device_disable(dev); g_free(dev); + qpci_free_pc(bus); test_end(); } @@ -296,14 +339,15 @@ static void pci_indirect(void) uint8_t status; char *data; - bus = test_start(); + bus = pci_test_start(); - dev = virtio_blk_init(bus, PCI_SLOT); + dev = virtio_blk_pci_init(bus, PCI_SLOT); /* MSI-X is not enabled */ - addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; + addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX; - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); features = qvirtio_get_features(&qvirtio_pci, &dev->vdev); @@ -374,8 +418,10 @@ static void pci_indirect(void) /* End test */ guest_free(alloc, vqpci->vq.desc); + pc_alloc_uninit(alloc); qvirtio_pci_device_disable(dev); g_free(dev); + qpci_free_pc(bus); test_end(); } @@ -387,14 +433,15 @@ static void pci_config(void) void *addr; uint64_t capacity; - bus = test_start(); + bus = pci_test_start(); - dev = virtio_blk_init(bus, PCI_SLOT); + dev = virtio_blk_pci_init(bus, PCI_SLOT); /* MSI-X is not enabled */ - addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; + addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX; - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev); @@ -403,11 +450,13 @@ static void pci_config(void) " 'size': %d } }", n_size); qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US); - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, n_size / 512); qvirtio_pci_device_disable(dev); g_free(dev); + qpci_free_pc(bus); test_end(); } @@ -427,18 +476,19 @@ static void pci_msix(void) uint8_t status; char *data; - bus = test_start(); + bus = pci_test_start(); alloc = pc_alloc_init(); - dev = virtio_blk_init(bus, PCI_SLOT); + dev = virtio_blk_pci_init(bus, PCI_SLOT); qpci_msix_enable(dev->pdev); qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0); /* MSI-X is enabled */ - addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_MSIX; + addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX; - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); features = qvirtio_get_features(&qvirtio_pci, &dev->vdev); @@ -458,7 +508,8 @@ static void pci_msix(void) qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US); - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, n_size / 512); /* Write request */ @@ -472,7 +523,8 @@ static void pci_msix(void) g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true); + free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); + qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); @@ -495,7 +547,8 @@ static void pci_msix(void) g_free(req.data); free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 513, true, false); + qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true); + qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); @@ -514,10 +567,12 @@ static void pci_msix(void) guest_free(alloc, req_addr); /* End test */ - guest_free(alloc, (uint64_t)vqpci->vq.desc); + guest_free(alloc, vqpci->vq.desc); + pc_alloc_uninit(alloc); qpci_msix_disable(dev->pdev); qvirtio_pci_device_disable(dev); g_free(dev); + qpci_free_pc(bus); test_end(); } @@ -536,18 +591,19 @@ static void pci_idx(void) uint8_t status; char *data; - bus = test_start(); + bus = pci_test_start(); alloc = pc_alloc_init(); - dev = virtio_blk_init(bus, PCI_SLOT); + dev = virtio_blk_pci_init(bus, PCI_SLOT); qpci_msix_enable(dev->pdev); qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0); /* MSI-X is enabled */ - addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_MSIX; + addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX; - capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr); + capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, + (uint64_t)(uintptr_t)addr); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); features = qvirtio_get_features(&qvirtio_pci, &dev->vdev); @@ -573,7 +629,8 @@ static void pci_idx(void) g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true); + free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); + qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); @@ -593,7 +650,8 @@ static void pci_idx(void) /* Notify after processing the third request */ qvirtqueue_set_used_event(&vqpci->vq, 2); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true); + free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); + qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); @@ -616,11 +674,11 @@ static void pci_idx(void) g_free(req.data); free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 513, true, false); + qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true); + qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); - qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq, QVIRTIO_BLK_TIMEOUT_US); @@ -636,45 +694,94 @@ static void pci_idx(void) /* End test */ guest_free(alloc, vqpci->vq.desc); + pc_alloc_uninit(alloc); qpci_msix_disable(dev->pdev); qvirtio_pci_device_disable(dev); g_free(dev); + qpci_free_pc(bus); test_end(); } -static void hotplug(void) +static void pci_hotplug(void) { QPCIBus *bus; QVirtioPCIDevice *dev; - bus = test_start(); + bus = pci_test_start(); /* plug secondary disk */ qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP, "'drive': 'drive1'"); - dev = virtio_blk_init(bus, PCI_SLOT_HP); + dev = virtio_blk_pci_init(bus, PCI_SLOT_HP); g_assert(dev); qvirtio_pci_device_disable(dev); g_free(dev); /* unplug secondary disk */ qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP); + qpci_free_pc(bus); + test_end(); +} + +static void mmio_basic(void) +{ + QVirtioMMIODevice *dev; + QVirtQueue *vq; + QGuestAllocator *alloc; + int n_size = TEST_IMAGE_SIZE / 2; + uint64_t capacity; + + arm_test_start(); + + dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE); + g_assert(dev != NULL); + g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID); + + qvirtio_reset(&qvirtio_mmio, &dev->vdev); + qvirtio_set_acknowledge(&qvirtio_mmio, &dev->vdev); + qvirtio_set_driver(&qvirtio_mmio, &dev->vdev); + + alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE); + vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0); + + test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq, + QVIRTIO_MMIO_DEVICE_SPECIFIC); + + qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', " + " 'size': %d } }", n_size); + + qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq, + QVIRTIO_BLK_TIMEOUT_US); + + capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev, + QVIRTIO_MMIO_DEVICE_SPECIFIC); + g_assert_cmpint(capacity, ==, n_size / 512); + + /* End test */ + guest_free(alloc, vq->desc); + generic_alloc_uninit(alloc); + g_free(dev); test_end(); } int main(int argc, char **argv) { int ret; + const char *arch = qtest_get_arch(); g_test_init(&argc, &argv, NULL); - g_test_add_func("/virtio/blk/pci/basic", pci_basic); - g_test_add_func("/virtio/blk/pci/indirect", pci_indirect); - g_test_add_func("/virtio/blk/pci/config", pci_config); - g_test_add_func("/virtio/blk/pci/msix", pci_msix); - g_test_add_func("/virtio/blk/pci/idx", pci_idx); - g_test_add_func("/virtio/blk/pci/hotplug", hotplug); + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("/virtio/blk/pci/basic", pci_basic); + qtest_add_func("/virtio/blk/pci/indirect", pci_indirect); + qtest_add_func("/virtio/blk/pci/config", pci_config); + qtest_add_func("/virtio/blk/pci/msix", pci_msix); + qtest_add_func("/virtio/blk/pci/idx", pci_idx); + qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug); + } else if (strcmp(arch, "arm") == 0) { + qtest_add_func("/virtio/blk/mmio/basic", mmio_basic); + } ret = g_test_run(); |