diff --git a/block/sheepdog.c b/block/sheepdog.c index a506137bb8..afe053376c 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 e6c50b1e35..346bb5cad9 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 c55ca5c557..b9a848db74 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 cb9def50e6..d54dc86921 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 9588d0c977..5582ed3655 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 0000000000..b03429dd01 --- /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 . +# + +# 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 0000000000..9e715e5a95 --- /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 9dbcae8d8c..97a31ff0b1 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 e9ba3586b5..5e077c3573 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 69e208c709..43c05d6f5c 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 cc6e837c83..f705586808 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;