提交 a126050a 编写于 作者: A Anthony Liguori

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

Block patches for 1.7.0-rc0 (v2)

# gpg: Signature made Thu 31 Oct 2013 04:44:39 PM CET using RSA key ID C88F2FD6
# gpg: Can't check signature: public key not found

* kwolf/tags/for-anthony: (30 commits)
  vmdk: Implment bdrv_get_specific_info
  qapi: Add optional field 'compressed' to ImageInfo
  qemu-iotests: prefill some data to test image
  sheepdog: check simultaneous create in resend_aioreq
  sheepdog: cancel aio requests if possible
  sheepdog: make add_aio_request and send_aioreq void functions
  sheepdog: try to reconnect to sheepdog after network error
  coroutine: add co_aio_sleep_ns() to allow sleep in block drivers
  sheepdog: reload inode outside of resend_aioreq
  sheepdog: handle vdi objects in resend_aio_req
  sheepdog: check return values of qemu_co_recv/send correctly
  qemu-iotests: Test case for backing file deletion
  qemu-iotests: drop duplicated "create_image"
  qemu-iotests: Fix 051 reference output
  block: Avoid unecessary drv->bdrv_getlength() calls
  block: Disable BDRV_O_COPY_ON_READ for the backing file
  ahci: fix win7 hang on boot
  sheepdog: pass copy_policy in the request
  sheepdog: explicitly set copies as type uint8_t
  block: Don't copy backing file name on error
  ...

Message-id: 1383064269-27720-1-git-send-email-kwolf@redhat.com
Signed-off-by: NAnthony Liguori <anthony@codemonkey.ws>
......@@ -999,13 +999,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
}
/* backing files always opened read-only */
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
BDRV_O_COPY_ON_READ);
ret = bdrv_open(bs->backing_hd,
*backing_filename ? backing_filename : NULL, options,
back_flags, back_drv, &local_err);
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
bs->backing_hd->file->filename);
if (ret < 0) {
bdrv_unref(bs->backing_hd);
bs->backing_hd = NULL;
......@@ -1013,6 +1012,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
error_propagate(errp, local_err);
return ret;
}
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
bs->backing_hd->file->filename);
return 0;
}
......@@ -2868,9 +2869,10 @@ int64_t bdrv_getlength(BlockDriverState *bs)
if (!drv)
return -ENOMEDIUM;
if (bdrv_dev_has_removable_media(bs)) {
if (drv->bdrv_getlength) {
return drv->bdrv_getlength(bs);
if (drv->has_variable_length) {
int ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
return ret;
}
}
return bs->total_sectors * BDRV_SECTOR_SIZE;
......
......@@ -1584,6 +1584,16 @@ static int qcow2_create2(const char *filename, int64_t total_size,
}
}
bdrv_close(bs);
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
ret = bdrv_open(bs, filename, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB, drv, &local_err);
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
goto out;
}
ret = 0;
out:
bdrv_unref(bs);
......@@ -1939,13 +1949,22 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos)
{
BDRVQcowState *s = bs->opaque;
int64_t total_sectors = bs->total_sectors;
int growable = bs->growable;
bool zero_beyond_eof = bs->zero_beyond_eof;
int ret;
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
bs->growable = 1;
bs->zero_beyond_eof = false;
ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov);
bs->growable = growable;
bs->zero_beyond_eof = zero_beyond_eof;
/* bdrv_co_do_writev will have increased the total_sectors value to include
* the VM state - the VM state is however not an actual part of the block
* device, therefore, we need to restore the old value. */
bs->total_sectors = total_sectors;
return ret;
}
......
......@@ -1715,7 +1715,8 @@ static BlockDriver bdrv_host_floppy = {
.bdrv_aio_flush = raw_aio_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
......@@ -1824,7 +1825,8 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_aio_flush = raw_aio_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
......@@ -1951,7 +1953,8 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_aio_flush = raw_aio_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
......
......@@ -616,7 +616,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_getlength = raw_getlength,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
};
......
......@@ -178,6 +178,7 @@ static BlockDriver bdrv_raw = {
.bdrv_co_get_block_status = &raw_co_get_block_status,
.bdrv_truncate = &raw_truncate,
.bdrv_getlength = &raw_getlength,
.has_variable_length = true,
.bdrv_get_info = &raw_get_info,
.bdrv_is_inserted = &raw_is_inserted,
.bdrv_media_changed = &raw_media_changed,
......
此差异已折叠。
......@@ -106,6 +106,7 @@ typedef struct VmdkExtent {
uint32_t l2_cache_counts[L2_CACHE_SIZE];
int64_t cluster_sectors;
char *type;
} VmdkExtent;
typedef struct BDRVVmdkState {
......@@ -113,11 +114,13 @@ typedef struct BDRVVmdkState {
uint64_t desc_offset;
bool cid_updated;
bool cid_checked;
uint32_t cid;
uint32_t parent_cid;
int num_extents;
/* Extent array with num_extents entries, ascend ordered by address */
VmdkExtent *extents;
Error *migration_blocker;
char *create_type;
} BDRVVmdkState;
typedef struct VmdkMetaData {
......@@ -214,6 +217,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
g_free(e->l1_table);
g_free(e->l2_cache);
g_free(e->l1_backup_table);
g_free(e->type);
if (e->file != bs->file) {
bdrv_unref(e->file);
}
......@@ -534,6 +538,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
uint32_t l1_size, l1_entry_sectors;
VMDK4Header header;
VmdkExtent *extent;
BDRVVmdkState *s = bs->opaque;
int64_t l1_backup_offset = 0;
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
......@@ -549,6 +554,10 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
}
}
if (!s->create_type) {
s->create_type = g_strdup("monolithicSparse");
}
if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
/*
* The footer takes precedence over the header, so read it in. The
......@@ -709,6 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
int64_t flat_offset;
char extent_path[PATH_MAX];
BlockDriverState *extent_file;
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent;
while (*p) {
/* parse extent line:
......@@ -751,7 +762,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
/* save to extents array */
if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {
/* FLAT extent */
VmdkExtent *extent;
ret = vmdk_add_extent(bs, extent_file, true, sectors,
0, 0, 0, 0, 0, &extent, errp);
......@@ -766,10 +776,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
bdrv_unref(extent_file);
return ret;
}
extent = &s->extents[s->num_extents - 1];
} else {
error_setg(errp, "Unsupported extent type '%s'", type);
return -ENOTSUP;
}
extent->type = g_strdup(type);
next_line:
/* move to next line */
while (*p) {
......@@ -817,6 +829,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
ret = -ENOTSUP;
goto exit;
}
s->create_type = g_strdup(ct);
s->desc_offset = 0;
ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp);
exit:
......@@ -843,6 +856,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
if (ret) {
goto fail;
}
s->cid = vmdk_read_cid(bs, 0);
s->parent_cid = vmdk_read_cid(bs, 1);
qemu_co_mutex_init(&s->lock);
......@@ -855,6 +869,8 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
return 0;
fail:
g_free(s->create_type);
s->create_type = NULL;
vmdk_free_extents(bs);
return ret;
}
......@@ -1766,6 +1782,7 @@ static void vmdk_close(BlockDriverState *bs)
BDRVVmdkState *s = bs->opaque;
vmdk_free_extents(bs);
g_free(s->create_type);
migrate_del_blocker(s->migration_blocker);
error_free(s->migration_blocker);
......@@ -1827,6 +1844,54 @@ static int vmdk_has_zero_init(BlockDriverState *bs)
return 1;
}
static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
{
ImageInfo *info = g_new0(ImageInfo, 1);
*info = (ImageInfo){
.filename = g_strdup(extent->file->filename),
.format = g_strdup(extent->type),
.virtual_size = extent->sectors * BDRV_SECTOR_SIZE,
.compressed = extent->compressed,
.has_compressed = extent->compressed,
.cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE,
.has_cluster_size = !extent->flat,
};
return info;
}
static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
{
int i;
BDRVVmdkState *s = bs->opaque;
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
ImageInfoList **next;
*spec_info = (ImageInfoSpecific){
.kind = IMAGE_INFO_SPECIFIC_KIND_VMDK,
{
.vmdk = g_new0(ImageInfoSpecificVmdk, 1),
},
};
*spec_info->vmdk = (ImageInfoSpecificVmdk) {
.create_type = g_strdup(s->create_type),
.cid = s->cid,
.parent_cid = s->parent_cid,
};
next = &spec_info->vmdk->extents;
for (i = 0; i < s->num_extents; i++) {
*next = g_new0(ImageInfoList, 1);
(*next)->value = vmdk_get_extent_info(&s->extents[i]);
(*next)->next = NULL;
next = &(*next)->next;
}
return spec_info;
}
static QEMUOptionParameter vmdk_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
......@@ -1879,6 +1944,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_co_get_block_status = vmdk_co_get_block_status,
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
.bdrv_has_zero_init = vmdk_has_zero_init,
.bdrv_get_specific_info = vmdk_get_specific_info,
.create_options = vmdk_create_options,
};
......
......@@ -260,6 +260,13 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
}
if (s->free_data_block_offset > bdrv_getlength(bs->file)) {
error_setg(errp, "block-vpc: free_data_block_offset points after "
"the end of file. The image has been truncated.");
ret = -EINVAL;
goto fail;
}
s->last_bitmap_offset = (int64_t) -1;
#ifdef CACHE
......
......@@ -2099,7 +2099,9 @@ void *address_space_map(AddressSpace *as,
if (bounce.buffer) {
return NULL;
}
bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
/* Avoid unbounded allocations */
l = MIN(l, TARGET_PAGE_SIZE);
bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l);
bounce.addr = addr;
bounce.len = l;
......
......@@ -961,7 +961,8 @@ static int handle_cmd(AHCIState *s, int port, int slot)
/* We're ready to process the command in FIS byte 2. */
ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
if (s->dev[port].port.ifs[0].status & READY_STAT) {
if ((s->dev[port].port.ifs[0].status & (READY_STAT|DRQ_STAT|BUSY_STAT)) ==
READY_STAT) {
ahci_write_fis_d2h(&s->dev[port], cmd_fis);
}
}
......
......@@ -156,8 +156,11 @@ struct BlockDriver {
const char *protocol_name;
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
bool has_variable_length;
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
......
......@@ -215,6 +215,15 @@ void qemu_co_rwlock_unlock(CoRwlock *lock);
*/
void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns);
/**
* Yield the coroutine for a given duration
*
* Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
* resumed when using qemu_aio_wait().
*/
void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
int64_t ns);
/**
* Yield until a file descriptor becomes readable
*
......
......@@ -224,6 +224,27 @@
'*lazy-refcounts': 'bool'
} }
##
# @ImageInfoSpecificVmdk:
#
# @create_type: The create type of VMDK image
#
# @cid: Content id of image
#
# @parent-cid: Parent VMDK image's cid
#
# @extents: List of extent files
#
# Since: 1.7
##
{ 'type': 'ImageInfoSpecificVmdk',
'data': {
'create-type': 'str',
'cid': 'int',
'parent-cid': 'int',
'extents': ['ImageInfo']
} }
##
# @ImageInfoSpecific:
#
......@@ -234,7 +255,8 @@
{ 'union': 'ImageInfoSpecific',
'data': {
'qcow2': 'ImageInfoSpecificQCow2'
'qcow2': 'ImageInfoSpecificQCow2',
'vmdk': 'ImageInfoSpecificVmdk'
} }
##
......@@ -256,6 +278,8 @@
#
# @encrypted: #optional true if the image is encrypted
#
# @compressed: #optional true if the image is compressed (Since 1.7)
#
# @backing-filename: #optional name of the backing file
#
# @full-backing-filename: #optional full path of the backing file
......@@ -276,7 +300,7 @@
{ 'type': 'ImageInfo',
'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
'*actual-size': 'int', 'virtual-size': 'int',
'*cluster-size': 'int', '*encrypted': 'bool',
'*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
'*backing-filename': 'str', '*full-backing-filename': 'str',
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
'*backing-image': 'ImageInfo',
......
......@@ -13,6 +13,7 @@
#include "block/coroutine.h"
#include "qemu/timer.h"
#include "block/aio.h"
typedef struct CoSleepCB {
QEMUTimer *ts;
......@@ -37,3 +38,16 @@ void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns)
timer_del(sleep_cb.ts);
timer_free(sleep_cb.ts);
}
void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
int64_t ns)
{
CoSleepCB sleep_cb = {
.co = qemu_coroutine_self(),
};
sleep_cb.ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &sleep_cb);
timer_mod(sleep_cb.ts, qemu_clock_get_ns(type) + ns);
qemu_coroutine_yield();
timer_del(sleep_cb.ts);
timer_free(sleep_cb.ts);
}
......@@ -607,7 +607,7 @@ static int img_check(int argc, char **argv)
if (output_format == OFORMAT_HUMAN) {
error_report("This image format does not support checks");
}
ret = 1;
ret = 63;
goto fail;
}
......
......@@ -81,6 +81,7 @@ enum {
CMD_IDENTIFY = 0xec,
CMDF_ABORT = 0x100,
CMDF_NO_BM = 0x200,
};
enum {
......@@ -192,6 +193,11 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
g_assert_not_reached();
}
if (flags & CMDF_NO_BM) {
qpci_config_writew(dev, PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
}
/* Select device 0 */
outb(IDE_BASE + reg_device, 0 | LBA);
......@@ -352,6 +358,25 @@ static void test_bmdma_long_prdt(void)
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
}
static void test_bmdma_no_busmaster(void)
{
uint8_t status;
/* No PRDT_EOT, each entry addr 0/size 64k, and in theory qemu shouldn't be
* able to access it anyway because the Bus Master bit in the PCI command
* register isn't set. This is complete nonsense, but it used to be pretty
* good at confusing and occasionally crashing qemu. */
PrdtEntry prdt[4096] = { };
status = send_dma_request(CMD_READ_DMA | CMDF_NO_BM, 0, 512,
prdt, ARRAY_SIZE(prdt));
/* Not entirely clear what the expected result is, but this is what we get
* in practice. At least we want to be aware of any changes. */
g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
}
static void test_bmdma_setup(void)
{
ide_test_start(
......@@ -493,6 +518,7 @@ int main(int argc, char **argv)
qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
qtest_add_func("/ide/bmdma/short_prdt", test_bmdma_short_prdt);
qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
qtest_add_func("/ide/bmdma/no_busmaster", test_bmdma_no_busmaster);
qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
qtest_add_func("/ide/flush", test_flush);
......
CC=gcc
CCFLAGS=-m32 -Wall -Wextra -Werror -fno-stack-protector -nostdinc -fno-builtin
ASFLAGS=-m32
LD=ld
LDFLAGS=-melf_i386 -T link.ld
LIBS=$(shell $(CC) $(CCFLAGS) -print-libgcc-file-name)
all: mmap.elf
mmap.elf: start.o mmap.o libc.o
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
%.o: %.c
$(CC) $(CCFLAGS) -c -o $@ $^
%.o: %.S
$(CC) $(ASFLAGS) -c -o $@ $^
/*
* Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "libc.h"
static void print_char(char c)
{
outb(0xe9, c);
}
static void print_str(char *s)
{
while (*s) {
print_char(*s++);
}
}
static void print_num(uint64_t value, int base)
{
char digits[] = "0123456789abcdef";
char buf[32] = { 0 };
int i = sizeof(buf) - 2;
do {
buf[i--] = digits[value % base];
value /= base;
} while (value);
print_str(&buf[i + 1]);
}
void printf(const char *fmt, ...)
{
va_list ap;
uint64_t val;
char *str;
int base;
int has_long;
int alt_form;
va_start(ap, fmt);
for (; *fmt; fmt++) {
if (*fmt != '%') {
print_char(*fmt);
continue;
}
fmt++;
if (*fmt == '#') {
fmt++;
alt_form = 1;
} else {
alt_form = 0;
}
if (*fmt == 'l') {
fmt++;
if (*fmt == 'l') {
fmt++;
has_long = 2;
} else {
has_long = 1;
}
} else {
has_long = 0;
}
switch (*fmt) {
case 'x':
case 'p':
base = 16;
goto convert_number;
case 'd':
case 'i':
case 'u':
base = 10;
goto convert_number;
case 'o':
base = 8;
goto convert_number;
convert_number:
switch (has_long) {
case 0:
val = va_arg(ap, unsigned int);
break;
case 1:
val = va_arg(ap, unsigned long);
break;
case 2:
val = va_arg(ap, unsigned long long);
break;
}
if (alt_form && base == 16) {
print_str("0x");
}
print_num(val, base);
break;
case 's':
str = va_arg(ap, char*);
print_str(str);
break;
case '%':
print_char(*fmt);
break;
default:
print_char('%');
print_char(*fmt);
break;
}
}
va_end(ap);
}
/*
* Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIBC_H
#define LIBC_H
/* Integer types */
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef signed long long int64_t;
typedef signed int int32_t;
typedef signed short int16_t;
typedef signed char int8_t;
typedef uint32_t uintptr_t;
/* stdarg.h */
typedef __builtin_va_list va_list;
#define va_start(ap, X) __builtin_va_start(ap, X)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
/* Port I/O functions */
static inline void outb(uint16_t port, uint8_t data)
{
asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}
/* Misc functions */
void printf(const char *fmt, ...);
#endif
ENTRY(_start)
SECTIONS
{
. = 0x100000;
.text : {
*(multiboot)
*(.text)
}
.data ALIGN(4096) : {
*(.data)
}
.rodata ALIGN(4096) : {
*(.rodata)
}
.bss ALIGN(4096) : {
*(.bss)
}
}
/*
* Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "libc.h"
#include "multiboot.h"
int test_main(uint32_t magic, struct mb_info *mbi)
{
uintptr_t entry_addr;
struct mb_mmap_entry *entry;
(void) magic;
printf("Lower memory: %dk\n", mbi->mem_lower);
printf("Upper memory: %dk\n", mbi->mem_upper);
printf("\ne820 memory map:\n");
for (entry_addr = mbi->mmap_addr;
entry_addr < mbi->mmap_addr + mbi->mmap_length;
entry_addr += entry->size + 4)
{
entry = (struct mb_mmap_entry*) entry_addr;
printf("%#llx - %#llx: type %d [entry size: %d]\n",
entry->base_addr,
entry->base_addr + entry->length,
entry->type,
entry->size);
}
printf("\nmmap start: %#x\n", mbi->mmap_addr);
printf("mmap end: %#x\n", mbi->mmap_addr + mbi->mmap_length);
printf("real mmap end: %#x\n", entry_addr);
return 0;
}
=== Running test case: mmap.elf ===
Lower memory: 639k
Upper memory: 130040k
e820 memory map:
0x0 - 0x9fc00: type 1 [entry size: 20]
0x9fc00 - 0xa0000: type 2 [entry size: 20]
0xf0000 - 0x100000: type 2 [entry size: 20]
0x100000 - 0x7ffe000: type 1 [entry size: 20]
0x7ffe000 - 0x8000000: type 2 [entry size: 20]
0xfffc0000 - 0x100000000: type 2 [entry size: 20]
mmap start: 0x9000
mmap end: 0x9090
real mmap end: 0x9090
=== Running test case: mmap.elf -m 1.1M ===
Lower memory: 639k
Upper memory: 96k
e820 memory map:
0x0 - 0x9fc00: type 1 [entry size: 20]
0x9fc00 - 0xa0000: type 2 [entry size: 20]
0xf0000 - 0x100000: type 2 [entry size: 20]
0x100000 - 0x118000: type 1 [entry size: 20]
0x118000 - 0x11a000: type 2 [entry size: 20]
0xfffc0000 - 0x100000000: type 2 [entry size: 20]
mmap start: 0x9000
mmap end: 0x9090
real mmap end: 0x9090
=== Running test case: mmap.elf -m 2G ===
Lower memory: 639k
Upper memory: 2096120k
e820 memory map:
0x0 - 0x9fc00: type 1 [entry size: 20]
0x9fc00 - 0xa0000: type 2 [entry size: 20]
0xf0000 - 0x100000: type 2 [entry size: 20]
0x100000 - 0x7fffe000: type 1 [entry size: 20]
0x7fffe000 - 0x80000000: type 2 [entry size: 20]
0xfffc0000 - 0x100000000: type 2 [entry size: 20]
mmap start: 0x9000
mmap end: 0x9090
real mmap end: 0x9090
=== Running test case: mmap.elf -m 4G ===
Lower memory: 639k
Upper memory: 3668984k
e820 memory map:
0x0 - 0x9fc00: type 1 [entry size: 20]
0x9fc00 - 0xa0000: type 2 [entry size: 20]
0xf0000 - 0x100000: type 2 [entry size: 20]
0x100000 - 0xdfffe000: type 1 [entry size: 20]
0xdfffe000 - 0xe0000000: type 2 [entry size: 20]
0xfffc0000 - 0x100000000: type 2 [entry size: 20]
0x100000000 - 0x120000000: type 1 [entry size: 20]
mmap start: 0x9000
mmap end: 0x90a8
real mmap end: 0x90a8
=== Running test case: mmap.elf -m 8G ===
Lower memory: 639k
Upper memory: 3668984k
e820 memory map:
0x0 - 0x9fc00: type 1 [entry size: 20]
0x9fc00 - 0xa0000: type 2 [entry size: 20]
0xf0000 - 0x100000: type 2 [entry size: 20]
0x100000 - 0xdfffe000: type 1 [entry size: 20]
0xdfffe000 - 0xe0000000: type 2 [entry size: 20]
0xfffc0000 - 0x100000000: type 2 [entry size: 20]
0x100000000 - 0x220000000: type 1 [entry size: 20]
mmap start: 0x9000
mmap end: 0x90a8
real mmap end: 0x90a8
/*
* Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MULTIBOOT_H
#define MULTIBOOT_H
#include "libc.h"
struct mb_info {
uint32_t flags;
uint32_t mem_lower;
uint32_t mem_upper;
uint32_t boot_device;
uint32_t cmdline;
uint32_t mods_count;
uint32_t mods_addr;
char syms[16];
uint32_t mmap_length;
uint32_t mmap_addr;
uint32_t drives_length;
uint32_t drives_addr;
uint32_t config_table;
uint32_t boot_loader_name;
uint32_t apm_table;
uint32_t vbe_control_info;
uint32_t vbe_mode_info;
uint16_t vbe_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
} __attribute__((packed));
struct mb_module {
uint32_t mod_start;
uint32_t mod_end;
uint32_t string;
uint32_t reserved;
} __attribute__((packed));
struct mb_mmap_entry {
uint32_t size;
uint64_t base_addr;
uint64_t length;
uint32_t type;
} __attribute__((packed));
#endif
#!/bin/bash
# Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
QEMU=${QEMU:-"../../x86_64-softmmu/qemu-system-x86_64"}
run_qemu() {
local kernel=$1
shift
echo -e "\n\n=== Running test case: $kernel $@ ===\n" >> test.log
$QEMU \
-kernel $kernel \
-display none \
-device isa-debugcon,chardev=stdio \
-chardev file,path=test.out,id=stdio \
-device isa-debug-exit,iobase=0xf4,iosize=0x4 \
"$@"
ret=$?
cat test.out >> test.log
}
mmap() {
run_qemu mmap.elf
run_qemu mmap.elf -m 1.1M
run_qemu mmap.elf -m 2G
run_qemu mmap.elf -m 4G
run_qemu mmap.elf -m 8G
}
make all
for t in mmap; do
echo > test.log
$t
debugexit=$((ret & 0x1))
ret=$((ret >> 1))
pass=1
if [ $debugexit != 1 ]; then
echo -e "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)"
pass=0
elif [ $ret != 0 ]; then
echo -e "\e[31mFAIL\e[0m $t (exit code $ret)"
pass=0
fi
if ! diff $t.out test.log > /dev/null 2>&1; then
echo -e "\e[31mFAIL\e[0m $t (output difference)"
diff -u $t.out test.log
pass=0
fi
if [ $pass == 1 ]; then
echo -e "\e[32mPASS\e[0m $t"
fi
done
/*
* Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x0
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)
.align 4
.int MB_MAGIC
.int MB_FLAGS
.int MB_CHECKSUM
.section .text
.global _start
_start:
mov $stack, %esp
push %ebx
push %eax
call test_main
/* Test device exit */
outl %eax, $0xf4
cli
hlt
jmp .
.section bss
.space 8192
stack:
......@@ -388,7 +388,9 @@ class TestStreamStop(iotests.QMPTestCase):
def setUp(self):
qemu_img('create', backing_img, str(TestStreamStop.image_len))
qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
self.vm = iotests.VM().add_drive(test_img)
self.vm.launch()
......@@ -414,7 +416,9 @@ class TestSetSpeed(iotests.QMPTestCase):
def setUp(self):
qemu_img('create', backing_img, str(TestSetSpeed.image_len))
qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
self.vm = iotests.VM().add_drive(test_img)
self.vm.launch()
......
......@@ -54,22 +54,12 @@ class ImageCommitTestCase(iotests.QMPTestCase):
self.assert_no_active_commit()
def create_image(self, name, size):
file = open(name, 'w')
i = 0
while i < size:
sector = struct.pack('>l504xl', i / 512, i / 512)
file.write(sector)
i = i + 512
file.close()
class TestSingleDrive(ImageCommitTestCase):
image_len = 1 * 1024 * 1024
test_len = 1 * 1024 * 256
def setUp(self):
self.create_image(backing_img, TestSingleDrive.image_len)
iotests.create_image(backing_img, TestSingleDrive.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
qemu_io('-c', 'write -P 0xab 0 524288', backing_img)
......@@ -167,7 +157,7 @@ class TestRelativePaths(ImageCommitTestCase):
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
self.create_image(self.backing_img_abs, TestRelativePaths.image_len)
iotests.create_image(self.backing_img_abs, TestRelativePaths.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.backing_img_abs, self.mid_img_abs)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img)
qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs)
......
......@@ -24,7 +24,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
[not inserted](qemu) qququiquit
(qemu) qququiquit
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
......
......@@ -69,7 +69,7 @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
echo
echo "=== Testing monolithicFlat creation and opening ==="
IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
$QEMU_IMG info $TEST_IMG | _filter_testdir
_img_info
echo
echo "=== Testing monolithicFlat with zeroed_grain ==="
......
......@@ -18,10 +18,9 @@ no file open, try 'help open'
=== Testing monolithicFlat creation and opening ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
image: TEST_DIR/t.vmdk
file format: vmdk
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 2.0G (2147483648 bytes)
disk size: 4.0K
=== Testing monolithicFlat with zeroed_grain ===
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
......
#!/bin/bash
#
# Test case for loading a saved VM state from a qcow2 image
#
# 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=mreitz@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 qocw2-specific low-level functionality
_supported_fmt qcow2
_supported_proto generic
_supported_os Linux
IMGOPTS="compat=1.1"
IMG_SIZE=128K
echo
echo "=== Saving and reloading a VM state to/from a qcow2 image ==="
echo
_make_test_img $IMG_SIZE
# Give qemu some time to boot before saving the VM state
bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\
$QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\
_filter_qemu
# Now try to continue from that VM state (this should just work)
echo quit |\
$QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\
_filter_qemu
# success, all done
echo "*** done"
rm -f $seq.full
status=0
QA output created by 068
=== Saving and reloading a VM state to/from a qcow2 image ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) ssasavsavesavevsavevmsavevm savevm 0
(qemu) qququiquit
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
*** done
#!/bin/bash
#
# Test case for deleting a backing file
#
# 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=mreitz@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 cow qed qcow qcow2 vmdk
_supported_proto generic
_supported_os Linux
IMG_SIZE=128K
echo
echo "=== Creating an image with a backing file and deleting that file ==="
echo
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
rm -f "$TEST_IMG.base"
# Just open the image and close it right again (this should print an error message)
$QEMU_IO -c quit "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
# success, all done
echo "*** done"
rm -f $seq.full
status=0
QA output created by 069
=== Creating an image with a backing file and deleting that file ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base'
qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open file: No such file or directory
*** done
......@@ -73,3 +73,5 @@
065 rw auto
066 rw auto
067 rw auto
068 rw auto
069 rw auto
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册