Commit cafffa54 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'kwolf/for-anthony' into staging



# By Fam Zheng (8) and others
# Via Kevin Wolf
* kwolf/for-anthony:
  vmdk: rename num_gtes_per_gte to num_gtes_per_gt
  vmdk: use heap allocation for whole_grain
  vmdk: check l1 size before opening image
  vmdk: check l2 table size when opening
  vmdk: check granularity field in opening
  qemu-iotests: add empty test case for vmdk
  qemu-iotests: add poke_file utility function
  vmdk: use unsigned values for on disk header fields
  vmdk: Make VMDK3Header and VmdkGrainMarker QEMU_PACKED
  sheepdog: add missing .bdrv_has_zero_init
  qemu-iotests: filter QEMU version in monitor banner
  iov: handle EOF in iov_send_recv
  ignore SIGPIPE in qemu-img and qemu-io
  qemu-img: Error out for excess arguments

Message-id: 1375799990-995-1-git-send-email-kwolf@redhat.com
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents a1fc6246 ca8804ce
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2347,6 +2347,7 @@ static BlockDriver bdrv_sheepdog = {
    .bdrv_file_open = sd_open,
    .bdrv_close     = sd_close,
    .bdrv_create    = sd_create,
    .bdrv_has_zero_init = bdrv_has_zero_init_1,
    .bdrv_getlength = sd_getlength,
    .bdrv_truncate  = sd_truncate,

@@ -2374,6 +2375,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
    .bdrv_file_open = sd_open,
    .bdrv_close     = sd_close,
    .bdrv_create    = sd_create,
    .bdrv_has_zero_init = bdrv_has_zero_init_1,
    .bdrv_getlength = sd_getlength,
    .bdrv_truncate  = sd_truncate,

+78 −37
Original line number Diff line number Diff line
@@ -62,19 +62,20 @@ typedef struct {
    uint32_t cylinders;
    uint32_t heads;
    uint32_t sectors_per_track;
} VMDK3Header;
} QEMU_PACKED VMDK3Header;

typedef struct {
    uint32_t version;
    uint32_t flags;
    int64_t capacity;
    int64_t granularity;
    int64_t desc_offset;
    int64_t desc_size;
    int32_t num_gtes_per_gte;
    int64_t rgd_offset;
    int64_t gd_offset;
    int64_t grain_offset;
    uint64_t capacity;
    uint64_t granularity;
    uint64_t desc_offset;
    uint64_t desc_size;
    /* Number of GrainTableEntries per GrainTable */
    uint32_t num_gtes_per_gt;
    uint64_t rgd_offset;
    uint64_t gd_offset;
    uint64_t grain_offset;
    char filler[1];
    char check_bytes[4];
    uint16_t compressAlgorithm;
@@ -109,7 +110,7 @@ typedef struct VmdkExtent {

typedef struct BDRVVmdkState {
    CoMutex lock;
    int desc_offset;
    uint64_t desc_offset;
    bool cid_updated;
    uint32_t parent_cid;
    int num_extents;
@@ -131,7 +132,7 @@ typedef struct VmdkGrainMarker {
    uint64_t lba;
    uint32_t size;
    uint8_t  data[0];
} VmdkGrainMarker;
} QEMU_PACKED VmdkGrainMarker;

enum {
    MARKER_END_OF_STREAM    = 0,
@@ -385,15 +386,22 @@ static int vmdk_parent_open(BlockDriverState *bs)

/* Create and append extent to the extent array. Return the added VmdkExtent
 * address. return NULL if allocation failed. */
static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
static int vmdk_add_extent(BlockDriverState *bs,
                           BlockDriverState *file, bool flat, int64_t sectors,
                           int64_t l1_offset, int64_t l1_backup_offset,
                           uint32_t l1_size,
                           int l2_size, unsigned int cluster_sectors)
                           int l2_size, uint64_t cluster_sectors,
                           VmdkExtent **new_extent)
{
    VmdkExtent *extent;
    BDRVVmdkState *s = bs->opaque;

    if (cluster_sectors > 0x200000) {
        /* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */
        error_report("invalid granularity, image may be corrupt");
        return -EINVAL;
    }

    s->extents = g_realloc(s->extents,
                              (s->num_extents + 1) * sizeof(VmdkExtent));
    extent = &s->extents[s->num_extents];
@@ -416,7 +424,10 @@ static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
        extent->end_sector = extent->sectors;
    }
    bs->total_sectors = extent->end_sector;
    return extent;
    if (new_extent) {
        *new_extent = extent;
    }
    return 0;
}

static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
@@ -475,12 +486,17 @@ static int vmdk_open_vmdk3(BlockDriverState *bs,
    if (ret < 0) {
        return ret;
    }
    extent = vmdk_add_extent(bs,

    ret = vmdk_add_extent(bs,
                             bs->file, false,
                             le32_to_cpu(header.disk_sectors),
                             le32_to_cpu(header.l1dir_offset) << 9,
                             0, 1 << 6, 1 << 9,
                             le32_to_cpu(header.granularity));
                             le32_to_cpu(header.granularity),
                             &extent);
    if (ret < 0) {
        return ret;
    }
    ret = vmdk_init_tables(bs, extent);
    if (ret) {
        /* free extent allocated by vmdk_add_extent */
@@ -490,7 +506,7 @@ static int vmdk_open_vmdk3(BlockDriverState *bs,
}

static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
                               int64_t desc_offset);
                               uint64_t desc_offset);

static int vmdk_open_vmdk4(BlockDriverState *bs,
                           BlockDriverState *file,
@@ -508,7 +524,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
        return ret;
    }
    if (header.capacity == 0) {
        int64_t desc_offset = le64_to_cpu(header.desc_offset);
        uint64_t desc_offset = le64_to_cpu(header.desc_offset);
        if (desc_offset) {
            return vmdk_open_desc_file(bs, flags, desc_offset << 9);
        }
@@ -570,23 +586,40 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
        return -ENOTSUP;
    }

    l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
    if (le32_to_cpu(header.num_gtes_per_gt) > 512) {
        error_report("L2 table size too big");
        return -EINVAL;
    }

    l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt)
                        * le64_to_cpu(header.granularity);
    if (l1_entry_sectors == 0) {
        return -EINVAL;
    }
    l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
                / l1_entry_sectors;
    if (l1_size > 512 * 1024 * 1024) {
        /* although with big capacity and small l1_entry_sectors, we can get a
         * big l1_size, we don't want unbounded value to allocate the table.
         * Limit it to 512M, which is 16PB for default cluster and L2 table
         * size */
        error_report("L1 size too big");
        return -EFBIG;
    }
    if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
        l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
    }
    extent = vmdk_add_extent(bs, file, false,
    ret = vmdk_add_extent(bs, file, false,
                          le64_to_cpu(header.capacity),
                          le64_to_cpu(header.gd_offset) << 9,
                          l1_backup_offset,
                          l1_size,
                          le32_to_cpu(header.num_gtes_per_gte),
                          le64_to_cpu(header.granularity));
                          le32_to_cpu(header.num_gtes_per_gt),
                          le64_to_cpu(header.granularity),
                          &extent);
    if (ret < 0) {
        return ret;
    }
    extent->compressed =
        le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
    extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
@@ -702,8 +735,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
            /* FLAT extent */
            VmdkExtent *extent;

            extent = vmdk_add_extent(bs, extent_file, true, sectors,
                            0, 0, 0, 0, sectors);
            ret = vmdk_add_extent(bs, extent_file, true, sectors,
                            0, 0, 0, 0, sectors, &extent);
            if (ret < 0) {
                return ret;
            }
            extent->flat_start_offset = flat_offset << 9;
        } else if (!strcmp(type, "SPARSE")) {
            /* SPARSE extent */
@@ -728,7 +764,7 @@ next_line:
}

static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
                               int64_t desc_offset)
                               uint64_t desc_offset)
{
    int ret;
    char *buf = NULL;
@@ -807,16 +843,17 @@ static int get_whole_cluster(BlockDriverState *bs,
                uint64_t offset,
                bool allocate)
{
    /* 128 sectors * 512 bytes each = grain size 64KB */
    uint8_t  whole_grain[extent->cluster_sectors * 512];
    int ret = VMDK_OK;
    uint8_t *whole_grain = NULL;

    /* we will be here if it's first write on non-exist grain(cluster).
     * try to read from parent image, if exist */
    if (bs->backing_hd) {
        int ret;

        whole_grain =
            qemu_blockalign(bs, extent->cluster_sectors << BDRV_SECTOR_BITS);
        if (!vmdk_is_cid_valid(bs)) {
            return VMDK_ERROR;
            ret = VMDK_ERROR;
            goto exit;
        }

        /* floor offset to cluster */
@@ -824,17 +861,21 @@ static int get_whole_cluster(BlockDriverState *bs,
        ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
                extent->cluster_sectors);
        if (ret < 0) {
            return VMDK_ERROR;
            ret = VMDK_ERROR;
            goto exit;
        }

        /* Write grain only into the active image */
        ret = bdrv_write(extent->file, cluster_offset, whole_grain,
                extent->cluster_sectors);
        if (ret < 0) {
            return VMDK_ERROR;
            ret = VMDK_ERROR;
            goto exit;
        }
    }
    return VMDK_OK;
exit:
    qemu_vfree(whole_grain);
    return ret;
}

static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
@@ -1371,12 +1412,12 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
    header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
    header.capacity = filesize / 512;
    header.granularity = 128;
    header.num_gtes_per_gte = 512;
    header.num_gtes_per_gt = 512;

    grains = (filesize / 512 + header.granularity - 1) / header.granularity;
    gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
    gt_size = ((header.num_gtes_per_gt * sizeof(uint32_t)) + 511) >> 9;
    gt_count =
        (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
        (grains + header.num_gtes_per_gt - 1) / header.num_gtes_per_gt;
    gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;

    header.desc_offset = 1;
@@ -1392,7 +1433,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
    header.flags = cpu_to_le32(header.flags);
    header.capacity = cpu_to_le64(header.capacity);
    header.granularity = cpu_to_le64(header.granularity);
    header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
    header.num_gtes_per_gt = cpu_to_le32(header.num_gtes_per_gt);
    header.desc_offset = cpu_to_le64(header.desc_offset);
    header.desc_size = cpu_to_le64(header.desc_size);
    header.rgd_offset = cpu_to_le64(header.rgd_offset);
+14 −7
Original line number Diff line number Diff line
@@ -396,6 +396,9 @@ static int img_create(int argc, char **argv)
        }
        img_size = (uint64_t)sval;
    }
    if (optind != argc) {
        help();
    }

    if (options && is_help_option(options)) {
        return print_block_option_help(filename, fmt);
@@ -573,7 +576,7 @@ static int img_check(int argc, char **argv)
            break;
        }
    }
    if (optind >= argc) {
    if (optind != argc - 1) {
        help();
    }
    filename = argv[optind++];
@@ -684,7 +687,7 @@ static int img_commit(int argc, char **argv)
            break;
        }
    }
    if (optind >= argc) {
    if (optind != argc - 1) {
        help();
    }
    filename = argv[optind++];
@@ -930,7 +933,7 @@ static int img_compare(int argc, char **argv)
    }


    if (optind > argc - 2) {
    if (optind != argc - 2) {
        help();
    }
    filename1 = argv[optind++];
@@ -1741,7 +1744,7 @@ static int img_info(int argc, char **argv)
            break;
        }
    }
    if (optind >= argc) {
    if (optind != argc - 1) {
        help();
    }
    filename = argv[optind++];
@@ -1842,7 +1845,7 @@ static int img_snapshot(int argc, char **argv)
        }
    }

    if (optind >= argc) {
    if (optind != argc - 1) {
        help();
    }
    filename = argv[optind++];
@@ -1953,7 +1956,7 @@ static int img_rebase(int argc, char **argv)
        progress = 0;
    }

    if ((optind >= argc) || (!unsafe && !out_baseimg)) {
    if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
        help();
    }
    filename = argv[optind++];
@@ -2232,7 +2235,7 @@ static int img_resize(int argc, char **argv)
            break;
        }
    }
    if (optind >= argc) {
    if (optind != argc - 1) {
        help();
    }
    filename = argv[optind++];
@@ -2319,6 +2322,10 @@ int main(int argc, char **argv)
    const img_cmd_t *cmd;
    const char *cmdname;

#ifdef CONFIG_POSIX
    signal(SIGPIPE, SIG_IGN);
#endif

    error_set_progname(argv[0]);

    qemu_init_main_loop();
+4 −0
Original line number Diff line number Diff line
@@ -335,6 +335,10 @@ int main(int argc, char **argv)
    int opt_index = 0;
    int flags = BDRV_O_UNMAP;

#ifdef CONFIG_POSIX
    signal(SIGPIPE, SIG_IGN);
#endif

    progname = basename(argv[0]);

    while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
+32 −32
Original line number Diff line number Diff line
@@ -23,11 +23,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===

Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
@@ -51,72 +51,72 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy ref
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument

Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit


=== No medium ===

Testing: -drive if=floppy
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive if=ide,media=cdrom
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive if=scsi,media=cdrom
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive if=ide
QEMU 1.5.50 monitor - type 'help' for more information
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

Testing: -drive if=virtio
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
QEMU_PROG: -drive if=virtio: Device initialization failed.
QEMU_PROG: -drive if=virtio: Device initialization failed.
QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized

Testing: -drive if=scsi
QEMU 1.5.50 monitor - type 'help' for more information
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: -drive if=scsi: Device initialization failed.
QEMU_PROG: Device initialization failed.
QEMU_PROG: Initialization of device lsi53c895a failed

Testing: -drive if=none,id=disk -device ide-cd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive if=none,id=disk -device ide-drive,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized

Testing: -drive if=none,id=disk -device ide-hd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized

Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed.
QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized

Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
@@ -125,77 +125,77 @@ QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
=== Read-only ===

Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type

Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit


=== Cache modes ===

Testing: -drive media=cdrom,cache=none
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive media=cdrom,cache=directsync
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive media=cdrom,cache=writeback
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive media=cdrom,cache=writethrough
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive media=cdrom,cache=unsafe
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive media=cdrom,cache=invalid_value
@@ -205,7 +205,7 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
=== Specifying the protocol layer ===

Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
QEMU 1.5.50 monitor - type 'help' for more information
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit

Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
Loading