aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-08-07 12:43:27 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-08-07 12:43:27 -0500
commitcafffa545420a2c6dc33f9cb58401c606af59572 (patch)
treef992e52ba0a368f2dcc13a5edf60e73293eeb547
parenta1fc6246b3964e74ddb3a7e0b8bba03af1c6ac38 (diff)
parentca8804ced9fdba7a1925ed81084dfb7a5b6ffa9f (diff)
downloadqemu-cafffa545420a2c6dc33f9cb58401c606af59572.zip
qemu-cafffa545420a2c6dc33f9cb58401c606af59572.tar.gz
qemu-cafffa545420a2c6dc33f9cb58401c606af59572.tar.bz2
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>
-rw-r--r--block/sheepdog.c2
-rw-r--r--block/vmdk.c115
-rw-r--r--qemu-img.c21
-rw-r--r--qemu-io.c4
-rw-r--r--tests/qemu-iotests/051.out64
-rwxr-xr-xtests/qemu-iotests/05972
-rw-r--r--tests/qemu-iotests/059.out20
-rw-r--r--tests/qemu-iotests/common.filter3
-rw-r--r--tests/qemu-iotests/common.rc6
-rw-r--r--tests/qemu-iotests/group1
-rw-r--r--util/iov.c6
11 files changed, 237 insertions, 77 deletions
diff --git a/block/sheepdog.c b/block/sheepdog.c
index a506137..afe0533 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -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,
diff --git a/block/vmdk.c b/block/vmdk.c
index e6c50b1..346bb5c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -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);
diff --git a/qemu-img.c b/qemu-img.c
index c55ca5c..b9a848d 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -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();
diff --git a/qemu-io.c b/qemu-io.c
index cb9def5..d54dc86 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -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) {
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 9588d0c..5582ed3 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -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
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
new file mode 100755
index 0000000..b03429d
--- /dev/null
+++ b/tests/qemu-iotests/059
@@ -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
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
new file mode 100644
index 0000000..9e715e5
--- /dev/null
+++ b/tests/qemu-iotests/059.out
@@ -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
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 9dbcae8..97a31ff 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -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
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index e9ba358..5e077c3 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -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
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 69e208c..43c05d6 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -63,3 +63,4 @@
054 rw auto
055 rw auto
056 rw auto backing
+059 rw auto
diff --git a/util/iov.c b/util/iov.c
index cc6e837..f705586 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -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;