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: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-08-07 12:43:27 -05:00
commit cafffa5454
11 changed files with 237 additions and 77 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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();

View file

@ -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) {

View file

@ -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

72
tests/qemu-iotests/059 Executable file
View file

@ -0,0 +1,72 @@
#!/bin/bash
#
# Test case for vmdk
#
# Copyright (C) 2013 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=famz@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 vmdk-specific low-level functionality
_supported_fmt vmdk
_supported_proto generic
_supported_os Linux
capacity_offset=16
granularity_offset=20
grain_table_size_offset=44
echo "=== Testing invalid granularity ==="
echo
_make_test_img 64M
poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff"
{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
echo "=== Testing too big L2 table size ==="
echo
_make_test_img 64M
poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff"
{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
echo "=== Testing too big L1 table size ==="
echo
_make_test_img 64M
poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff"
poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View file

@ -0,0 +1,20 @@
QA output created by 059
=== Testing invalid granularity ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
invalid granularity, image may be corrupt
qemu-io: can't open device TEST_DIR/t.vmdk
no file open, try 'help open'
=== Testing too big L2 table size ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
L2 table size too big
qemu-io: can't open device TEST_DIR/t.vmdk
no file open, try 'help open'
=== Testing too big L1 table size ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
L1 size too big
qemu-io: can't open device TEST_DIR/t.vmdk
no file open, try 'help open'
*** done

View file

@ -155,7 +155,8 @@ _filter_qemu_io()
# replace occurrences of QEMU_PROG with "qemu"
_filter_qemu()
{
sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#"
sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
-e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#'
}
# make sure this script returns success

View file

@ -34,6 +34,12 @@ dd()
fi
}
# poke_file 'test.img' 512 '\xff\xfe'
poke_file()
{
printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null
}
# we need common.config
if [ "$iam" != "check" ]
then

View file

@ -63,3 +63,4 @@
054 rw auto
055 rw auto
056 rw auto backing
059 rw auto

View file

@ -202,6 +202,12 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
return -1;
}
if (ret == 0 && !do_send) {
/* recv returns 0 when the peer has performed an orderly
* shutdown. */
break;
}
/* Prepare for the next iteration */
offset += ret;
total += ret;