diff options
-rw-r--r-- | block.c | 4 | ||||
-rw-r--r-- | block/bochs.c | 22 | ||||
-rw-r--r-- | block/cloop.c | 29 | ||||
-rw-r--r-- | block/dmg.c | 153 | ||||
-rw-r--r-- | block/parallels.c | 23 | ||||
-rw-r--r-- | block/raw-posix.c | 11 | ||||
-rw-r--r-- | block/sheepdog.c | 5 | ||||
-rw-r--r-- | block/vmdk.c | 41 | ||||
-rw-r--r-- | block/vpc.c | 42 | ||||
-rw-r--r-- | include/block/block_int.h | 1 | ||||
-rwxr-xr-x | tests/qemu-iotests/041 | 48 | ||||
-rw-r--r-- | tests/qemu-iotests/041.out | 4 | ||||
-rwxr-xr-x | tests/qemu-iotests/047 | 75 | ||||
-rw-r--r-- | tests/qemu-iotests/047.out | 22 | ||||
-rw-r--r-- | tests/qemu-iotests/group | 1 |
15 files changed, 379 insertions, 102 deletions
@@ -2800,7 +2800,9 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, * * [sector_num+x, nr_sectors] allocated. */ - if (n > pnum_inter) { + if (n > pnum_inter && + (intermediate == top || + sector_num + pnum_inter < intermediate->total_sectors)) { n = pnum_inter; } diff --git a/block/bochs.c b/block/bochs.c index 37375834e9..a6eb33da42 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -114,11 +114,13 @@ static int bochs_open(BlockDriverState *bs, int flags) int i; struct bochs_header bochs; struct bochs_header_v1 header_v1; + int ret; bs->read_only = 1; // no write support yet - if (bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)) != sizeof(bochs)) { - goto fail; + ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)); + if (ret < 0) { + return ret; } if (strcmp(bochs.magic, HEADER_MAGIC) || @@ -138,9 +140,13 @@ static int bochs_open(BlockDriverState *bs, int flags) s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog); s->catalog_bitmap = g_malloc(s->catalog_size * 4); - if (bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap, - s->catalog_size * 4) != s->catalog_size * 4) - goto fail; + + ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap, + s->catalog_size * 4); + if (ret < 0) { + goto fail; + } + for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); @@ -153,8 +159,10 @@ static int bochs_open(BlockDriverState *bs, int flags) qemu_co_mutex_init(&s->lock); return 0; - fail: - return -1; + +fail: + g_free(s->catalog_bitmap); + return ret; } static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) diff --git a/block/cloop.c b/block/cloop.c index 5a0d0d805f..8fe13e92a1 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -57,27 +57,32 @@ static int cloop_open(BlockDriverState *bs, int flags) { BDRVCloopState *s = bs->opaque; uint32_t offsets_size, max_compressed_block_size = 1, i; + int ret; bs->read_only = 1; /* read header */ - if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) { - goto cloop_close; + ret = bdrv_pread(bs->file, 128, &s->block_size, 4); + if (ret < 0) { + return ret; } s->block_size = be32_to_cpu(s->block_size); - if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) { - goto cloop_close; + ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4); + if (ret < 0) { + return ret; } s->n_blocks = be32_to_cpu(s->n_blocks); /* read offsets */ offsets_size = s->n_blocks * sizeof(uint64_t); s->offsets = g_malloc(offsets_size); - if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) < - offsets_size) { - goto cloop_close; + + ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size); + if (ret < 0) { + goto fail; } + for(i=0;i<s->n_blocks;i++) { s->offsets[i] = be64_to_cpu(s->offsets[i]); if (i > 0) { @@ -92,7 +97,8 @@ static int cloop_open(BlockDriverState *bs, int flags) s->compressed_block = g_malloc(max_compressed_block_size + 1); s->uncompressed_block = g_malloc(s->block_size); if (inflateInit(&s->zstream) != Z_OK) { - goto cloop_close; + ret = -EINVAL; + goto fail; } s->current_block = s->n_blocks; @@ -101,8 +107,11 @@ static int cloop_open(BlockDriverState *bs, int flags) qemu_co_mutex_init(&s->lock); return 0; -cloop_close: - return -1; +fail: + g_free(s->offsets); + g_free(s->compressed_block); + g_free(s->uncompressed_block); + return ret; } static inline int cloop_read_block(BlockDriverState *bs, int block_num) diff --git a/block/dmg.c b/block/dmg.c index ac397dc8f7..6d85801a84 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -57,29 +57,42 @@ static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename) return 0; } -static off_t read_off(BlockDriverState *bs, int64_t offset) +static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result) { - uint64_t buffer; - if (bdrv_pread(bs->file, offset, &buffer, 8) < 8) - return 0; - return be64_to_cpu(buffer); + uint64_t buffer; + int ret; + + ret = bdrv_pread(bs->file, offset, &buffer, 8); + if (ret < 0) { + return ret; + } + + *result = be64_to_cpu(buffer); + return 0; } -static off_t read_uint32(BlockDriverState *bs, int64_t offset) +static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result) { - uint32_t buffer; - if (bdrv_pread(bs->file, offset, &buffer, 4) < 4) - return 0; - return be32_to_cpu(buffer); + uint32_t buffer; + int ret; + + ret = bdrv_pread(bs->file, offset, &buffer, 4); + if (ret < 0) { + return ret; + } + + *result = be32_to_cpu(buffer); + return 0; } static int dmg_open(BlockDriverState *bs, int flags) { BDRVDMGState *s = bs->opaque; - off_t info_begin,info_end,last_in_offset,last_out_offset; - uint32_t count; + uint64_t info_begin,info_end,last_in_offset,last_out_offset; + uint32_t count, tmp; uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i; int64_t offset; + int ret; bs->read_only = 1; s->n_chunks = 0; @@ -88,21 +101,32 @@ static int dmg_open(BlockDriverState *bs, int flags) /* read offset of info blocks */ offset = bdrv_getlength(bs->file); if (offset < 0) { + ret = offset; goto fail; } offset -= 0x1d8; - info_begin = read_off(bs, offset); - if (info_begin == 0) { - goto fail; + ret = read_uint64(bs, offset, &info_begin); + if (ret < 0) { + goto fail; + } else if (info_begin == 0) { + ret = -EINVAL; + goto fail; } - if (read_uint32(bs, info_begin) != 0x100) { + ret = read_uint32(bs, info_begin, &tmp); + if (ret < 0) { + goto fail; + } else if (tmp != 0x100) { + ret = -EINVAL; goto fail; } - count = read_uint32(bs, info_begin + 4); - if (count == 0) { + ret = read_uint32(bs, info_begin + 4, &count); + if (ret < 0) { + goto fail; + } else if (count == 0) { + ret = -EINVAL; goto fail; } info_end = info_begin + count; @@ -114,12 +138,20 @@ static int dmg_open(BlockDriverState *bs, int flags) while (offset < info_end) { uint32_t type; - count = read_uint32(bs, offset); - if(count==0) - goto fail; + ret = read_uint32(bs, offset, &count); + if (ret < 0) { + goto fail; + } else if (count == 0) { + ret = -EINVAL; + goto fail; + } offset += 4; - type = read_uint32(bs, offset); + ret = read_uint32(bs, offset, &type); + if (ret < 0) { + goto fail; + } + if (type == 0x6d697368 && count >= 244) { int new_size, chunk_count; @@ -134,8 +166,11 @@ static int dmg_open(BlockDriverState *bs, int flags) s->sectors = g_realloc(s->sectors, new_size); s->sectorcounts = g_realloc(s->sectorcounts, new_size); - for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) { - s->types[i] = read_uint32(bs, offset); + for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) { + ret = read_uint32(bs, offset, &s->types[i]); + if (ret < 0) { + goto fail; + } offset += 4; if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) { if(s->types[i]==0xffffffff) { @@ -149,17 +184,31 @@ static int dmg_open(BlockDriverState *bs, int flags) } offset += 4; - s->sectors[i] = last_out_offset+read_off(bs, offset); - offset += 8; - - s->sectorcounts[i] = read_off(bs, offset); - offset += 8; - - s->offsets[i] = last_in_offset+read_off(bs, offset); - offset += 8; - - s->lengths[i] = read_off(bs, offset); - offset += 8; + ret = read_uint64(bs, offset, &s->sectors[i]); + if (ret < 0) { + goto fail; + } + s->sectors[i] += last_out_offset; + offset += 8; + + ret = read_uint64(bs, offset, &s->sectorcounts[i]); + if (ret < 0) { + goto fail; + } + offset += 8; + + ret = read_uint64(bs, offset, &s->offsets[i]); + if (ret < 0) { + goto fail; + } + s->offsets[i] += last_in_offset; + offset += 8; + + ret = read_uint64(bs, offset, &s->lengths[i]); + if (ret < 0) { + goto fail; + } + offset += 8; if(s->lengths[i]>max_compressed_size) max_compressed_size = s->lengths[i]; @@ -173,15 +222,25 @@ static int dmg_open(BlockDriverState *bs, int flags) /* initialize zlib engine */ s->compressed_chunk = g_malloc(max_compressed_size+1); s->uncompressed_chunk = g_malloc(512*max_sectors_per_chunk); - if(inflateInit(&s->zstream) != Z_OK) - goto fail; + if(inflateInit(&s->zstream) != Z_OK) { + ret = -EINVAL; + goto fail; + } s->current_chunk = s->n_chunks; qemu_co_mutex_init(&s->lock); return 0; + fail: - return -1; + g_free(s->types); + g_free(s->offsets); + g_free(s->lengths); + g_free(s->sectors); + g_free(s->sectorcounts); + g_free(s->compressed_chunk); + g_free(s->uncompressed_chunk); + return ret; } static inline int is_sector_in_chunk(BDRVDMGState* s, @@ -296,15 +355,15 @@ static coroutine_fn int dmg_co_read(BlockDriverState *bs, int64_t sector_num, static void dmg_close(BlockDriverState *bs) { BDRVDMGState *s = bs->opaque; - if(s->n_chunks>0) { - free(s->types); - free(s->offsets); - free(s->lengths); - free(s->sectors); - free(s->sectorcounts); - } - free(s->compressed_chunk); - free(s->uncompressed_chunk); + + g_free(s->types); + g_free(s->offsets); + g_free(s->lengths); + g_free(s->sectors); + g_free(s->sectorcounts); + g_free(s->compressed_chunk); + g_free(s->uncompressed_chunk); + inflateEnd(&s->zstream); } diff --git a/block/parallels.c b/block/parallels.c index 377375046f..8688f6ca4c 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -73,14 +73,18 @@ static int parallels_open(BlockDriverState *bs, int flags) BDRVParallelsState *s = bs->opaque; int i; struct parallels_header ph; + int ret; bs->read_only = 1; // no write support yet - if (bdrv_pread(bs->file, 0, &ph, sizeof(ph)) != sizeof(ph)) + ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); + if (ret < 0) { goto fail; + } if (memcmp(ph.magic, HEADER_MAGIC, 16) || - (le32_to_cpu(ph.version) != HEADER_VERSION)) { + (le32_to_cpu(ph.version) != HEADER_VERSION)) { + ret = -EMEDIUMTYPE; goto fail; } @@ -90,18 +94,21 @@ static int parallels_open(BlockDriverState *bs, int flags) s->catalog_size = le32_to_cpu(ph.catalog_entries); s->catalog_bitmap = g_malloc(s->catalog_size * 4); - if (bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4) != - s->catalog_size * 4) - goto fail; + + ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4); + if (ret < 0) { + goto fail; + } + for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); qemu_co_mutex_init(&s->lock); return 0; + fail: - if (s->catalog_bitmap) - g_free(s->catalog_bitmap); - return -1; + g_free(s->catalog_bitmap); + return ret; } static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) diff --git a/block/raw-posix.c b/block/raw-posix.c index 657af95637..8b6b92608b 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -345,11 +345,20 @@ static int raw_reopen_prepare(BDRVReopenState *state, raw_s->fd = -1; - int fcntl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; + int fcntl_flags = O_APPEND | O_NONBLOCK; #ifdef O_NOATIME fcntl_flags |= O_NOATIME; #endif +#ifdef O_ASYNC + /* Not all operating systems have O_ASYNC, and those that don't + * will not let us track the state into raw_s->open_flags (typically + * you achieve the same effect with an ioctl, for example I_SETSIG + * on Solaris). But we do not use O_ASYNC, so that's fine. + */ + assert((s->open_flags & O_ASYNC) == 0); +#endif + if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) { /* dup the original fd */ /* TODO: use qemu fcntl wrapper */ diff --git a/block/sheepdog.c b/block/sheepdog.c index 3e49bb83bb..d466b232d7 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -145,7 +145,7 @@ typedef struct SheepdogVdiReq { uint32_t id; uint32_t data_length; uint64_t vdi_size; - uint32_t base_vdi_id; + uint32_t vdi_id; uint32_t copies; uint32_t snapid; uint32_t pad[3]; @@ -1201,7 +1201,7 @@ static int do_sd_create(char *filename, int64_t vdi_size, memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_NEW_VDI; - hdr.base_vdi_id = base_vid; + hdr.vdi_id = base_vid; wlen = SD_MAX_VDI_LEN; @@ -1384,6 +1384,7 @@ static void sd_close(BlockDriverState *bs) memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_RELEASE_VDI; + hdr.vdi_id = s->inode.vdi_id; wlen = strlen(s->name) + 1; hdr.data_length = wlen; hdr.flags = SD_FLAG_CMD_WRITE; diff --git a/block/vmdk.c b/block/vmdk.c index 8333afb5e3..aef1abcb4f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -641,7 +641,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, * RW [size in sectors] SPARSE "file-name.vmdk" */ flat_offset = -1; - ret = sscanf(p, "%10s %" SCNd64 " %10s %511s %" SCNd64, + ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64, access, §ors, type, fname, &flat_offset); if (ret < 4 || strcmp(access, "RW")) { goto next_line; @@ -653,14 +653,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, return -EINVAL; } - /* trim the quotation marks around */ - if (fname[0] == '"') { - memmove(fname, fname + 1, strlen(fname)); - if (strlen(fname) <= 1 || fname[strlen(fname) - 1] != '"') { - return -EINVAL; - } - fname[strlen(fname) - 1] = '\0'; - } if (sectors <= 0 || (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) || (strcmp(access, "RW"))) { @@ -1442,6 +1434,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) int fd, idx = 0; char desc[BUF_SIZE]; int64_t total_size = 0, filesize; + const char *adapter_type = NULL; const char *backing_file = NULL; const char *fmt = NULL; int flags = 0; @@ -1453,6 +1446,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) const char *desc_extent_line; char parent_desc_line[BUF_SIZE] = ""; uint32_t parent_cid = 0xffffffff; + uint32_t number_heads = 16; const char desc_template[] = "# Disk DescriptorFile\n" "version=1\n" @@ -1469,9 +1463,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) "\n" "ddb.virtualHWVersion = \"%d\"\n" "ddb.geometry.cylinders = \"%" PRId64 "\"\n" - "ddb.geometry.heads = \"16\"\n" + "ddb.geometry.heads = \"%d\"\n" "ddb.geometry.sectors = \"63\"\n" - "ddb.adapterType = \"ide\"\n"; + "ddb.adapterType = \"%s\"\n"; if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { return -EINVAL; @@ -1480,6 +1474,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { total_size = options->value.n; + } else if (!strcmp(options->name, BLOCK_OPT_ADAPTER_TYPE)) { + adapter_type = options->value.s; } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { backing_file = options->value.s; } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { @@ -1489,6 +1485,20 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) } options++; } + if (!adapter_type) { + adapter_type = "ide"; + } else if (strcmp(adapter_type, "ide") && + strcmp(adapter_type, "buslogic") && + strcmp(adapter_type, "lsilogic") && + strcmp(adapter_type, "legacyESX")) { + fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", adapter_type); + return -EINVAL; + } + if (strcmp(adapter_type, "ide") != 0) { + /* that's the number of heads with which vmware operates when + creating, exporting, etc. vmdk files with a non-ide adapter type */ + number_heads = 255; + } if (!fmt) { /* Default format to monolithicSparse */ fmt = "monolithicSparse"; @@ -1576,7 +1586,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) parent_desc_line, ext_desc_lines, (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), - total_size / (int64_t)(63 * 16 * 512)); + total_size / (int64_t)(63 * number_heads * 512), number_heads, + adapter_type); if (split || flat) { fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, @@ -1661,6 +1672,12 @@ static QEMUOptionParameter vmdk_create_options[] = { .help = "Virtual disk size" }, { + .name = BLOCK_OPT_ADAPTER_TYPE, + .type = OPT_STRING, + .help = "Virtual adapter type, can be one of " + "ide (default), lsilogic, buslogic or legacyESX" + }, + { .name = BLOCK_OPT_BACKING_FILE, .type = OPT_STRING, .help = "File name of a base image" diff --git a/block/vpc.c b/block/vpc.c index 7948609e50..82229ef5a0 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -163,24 +163,33 @@ static int vpc_open(BlockDriverState *bs, int flags) struct vhd_dyndisk_header* dyndisk_header; uint8_t buf[HEADER_SIZE]; uint32_t checksum; - int err = -1; int disk_type = VHD_DYNAMIC; + int ret; - if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE) + ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE); + if (ret < 0) { goto fail; + } footer = (struct vhd_footer*) s->footer_buf; if (strncmp(footer->creator, "conectix", 8)) { int64_t offset = bdrv_getlength(bs->file); - if (offset < HEADER_SIZE) { + if (offset < 0) { + ret = offset; + goto fail; + } else if (offset < HEADER_SIZE) { + ret = -EINVAL; goto fail; } + /* If a fixed disk, the footer is found only at the end of the file */ - if (bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, HEADER_SIZE) - != HEADER_SIZE) { + ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, + HEADER_SIZE); + if (ret < 0) { goto fail; } if (strncmp(footer->creator, "conectix", 8)) { + ret = -EMEDIUMTYPE; goto fail; } disk_type = VHD_FIXED; @@ -203,19 +212,21 @@ static int vpc_open(BlockDriverState *bs, int flags) /* Allow a maximum disk size of approximately 2 TB */ if (bs->total_sectors >= 65535LL * 255 * 255) { - err = -EFBIG; + ret = -EFBIG; goto fail; } if (disk_type == VHD_DYNAMIC) { - if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, - HEADER_SIZE) != HEADER_SIZE) { + ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, + HEADER_SIZE); + if (ret < 0) { goto fail; } dyndisk_header = (struct vhd_dyndisk_header *) buf; if (strncmp(dyndisk_header->magic, "cxsparse", 8)) { + ret = -EINVAL; goto fail; } @@ -226,8 +237,10 @@ static int vpc_open(BlockDriverState *bs, int flags) s->pagetable = g_malloc(s->max_table_entries * 4); s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); - if (bdrv_pread(bs->file, s->bat_offset, s->pagetable, - s->max_table_entries * 4) != s->max_table_entries * 4) { + + ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, + s->max_table_entries * 4); + if (ret < 0) { goto fail; } @@ -265,8 +278,13 @@ static int vpc_open(BlockDriverState *bs, int flags) migrate_add_blocker(s->migration_blocker); return 0; - fail: - return err; + +fail: + g_free(s->pagetable); +#ifdef CACHE + g_free(s->pageentry_u8); +#endif + return ret; } static int vpc_reopen_prepare(BDRVReopenState *state, diff --git a/include/block/block_int.h b/include/block/block_int.h index f7279b978a..eaad53e426 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -56,6 +56,7 @@ #define BLOCK_OPT_SUBFMT "subformat" #define BLOCK_OPT_COMPAT_LEVEL "compat" #define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts" +#define BLOCK_OPT_ADAPTER_TYPE "adapter_type" typedef struct BdrvTrackedRequest BdrvTrackedRequest; diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index b040820c51..720eeff921 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -344,6 +344,54 @@ class TestMirrorNoBacking(ImageMirroringTestCase): self.assertTrue(self.compare_images(test_img, target_img), 'target image does not match source after mirroring') +class TestMirrorResized(ImageMirroringTestCase): + backing_len = 1 * 1024 * 1024 # MB + image_len = 2 * 1024 * 1024 # MB + + def setUp(self): + self.create_image(backing_img, TestMirrorResized.backing_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('resize', test_img, '2M') + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + try: + os.remove(target_img) + except OSError: + pass + + def test_complete_top(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='top', + target=target_img) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', target_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_complete_full(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', target_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + class TestReadErrors(ImageMirroringTestCase): image_len = 2 * 1024 * 1024 # MB diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out index 84bfd63fba..42314e9c00 100644 --- a/tests/qemu-iotests/041.out +++ b/tests/qemu-iotests/041.out @@ -1,5 +1,5 @@ -...................... +........................ ---------------------------------------------------------------------- -Ran 22 tests +Ran 24 tests OK diff --git a/tests/qemu-iotests/047 b/tests/qemu-iotests/047 new file mode 100755 index 0000000000..0cf36b434f --- /dev/null +++ b/tests/qemu-iotests/047 @@ -0,0 +1,75 @@ +#!/bin/bash +# +# Regression test for commit b7ab0fea (which was a corruption fix, +# despite the commit message claiming otherwise) +# +# 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=kwolf@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 + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +size=128M + +_make_test_img $size + +function qemu_io_cmds() +{ +cat <<EOF +write -P 0x66 0 320k +write 320k 128k +write -P 0x55 1M 128k +write -P 0x88 448k 128k +discard 320k 128k +aio_flush + +write -P 0x77 0 480k +aio_flush + +read -P 0x77 0 480k +read -P 0x88 480k 96k +read -P 0x55 1M 128k +EOF +} + +qemu_io_cmds | $QEMU_IO $TEST_IMG | _filter_qemu_io +_check_test_img + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/047.out b/tests/qemu-iotests/047.out new file mode 100644 index 0000000000..81b2ff73b8 --- /dev/null +++ b/tests/qemu-iotests/047.out @@ -0,0 +1,22 @@ +QA output created by 047 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +qemu-io> wrote 327680/327680 bytes at offset 0 +320 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> wrote 131072/131072 bytes at offset 327680 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> wrote 131072/131072 bytes at offset 1048576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> wrote 131072/131072 bytes at offset 458752 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> discard 131072/131072 bytes at offset 327680 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> qemu-io> qemu-io> wrote 491520/491520 bytes at offset 0 +480 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> qemu-io> qemu-io> read 491520/491520 bytes at offset 0 +480 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> read 98304/98304 bytes at offset 491520 +96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> read 131072/131072 bytes at offset 1048576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io> No errors were found on the image. +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index a0307de06b..1bbd2bf929 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -53,3 +53,4 @@ 044 rw auto 045 rw auto 046 rw auto aio +047 rw auto |