mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request # gpg: Signature made Fri 09 May 2014 19:57:53 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: glib: fix g_poll early timeout on windows block: qemu-iotests - test for live migration block: qemu-iotests - update 085 to use common.qemu block: qemu-iotests - add common.qemu, for bash-controlled qemu tests block/raw-posix: Try both FIEMAP and SEEK_HOLE gluster: Correctly propagate errors when volume isn't accessible vl.c: remove init_clocks call from main block: Fix open flags with BDRV_O_SNAPSHOT qemu-iotests: Test converting to streamOptimized from small cluster size vmdk: Implement .bdrv_get_info() vmdk: Implement .bdrv_write_compressed qemu-img: Convert by cluster size if target is compressed block/iscsi: bump year in copyright notice block/nfs: Check for NULL server part qemu-img: sort block formats in help message iotests: Use configured python qcow2: Fix alloc_clusters_noref() overflow detection Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -774,6 +774,16 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
||||
bs->copy_on_read--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the flags that a temporary snapshot should get, based on the
|
||||
* originally requested flags (the originally requested image will have flags
|
||||
* like a backing file)
|
||||
*/
|
||||
static int bdrv_temp_snapshot_flags(int flags)
|
||||
{
|
||||
return (flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the flags that bs->file should get, based on the given flags for
|
||||
* the parent BDS
|
||||
@@ -787,11 +797,6 @@ static int bdrv_inherited_flags(int flags)
|
||||
* so we can enable both unconditionally on lower layers. */
|
||||
flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP;
|
||||
|
||||
/* The backing file of a temporary snapshot is read-only */
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
flags &= ~BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
/* Clear flags that only apply to the top layer */
|
||||
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
|
||||
|
||||
@@ -817,11 +822,6 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
{
|
||||
int open_flags = flags | BDRV_O_CACHE_WB;
|
||||
|
||||
/* The backing file of a temporary snapshot is read-only */
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
open_flags &= ~BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear flags that are internal to the block layer before opening the
|
||||
* image.
|
||||
@@ -1206,7 +1206,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
|
||||
{
|
||||
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
||||
char *tmp_filename = g_malloc0(PATH_MAX + 1);
|
||||
@@ -1262,8 +1262,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
bs_snapshot = bdrv_new("", &error_abort);
|
||||
|
||||
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
|
||||
(bs->open_flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY,
|
||||
bdrv_qcow2, &local_err);
|
||||
flags, bdrv_qcow2, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
@@ -1298,6 +1297,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
BlockDriverState *file = NULL, *bs;
|
||||
const char *drvname;
|
||||
Error *local_err = NULL;
|
||||
int snapshot_flags = 0;
|
||||
|
||||
assert(pbs);
|
||||
|
||||
@@ -1358,6 +1358,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
if (flags & BDRV_O_RDWR) {
|
||||
flags |= BDRV_O_ALLOW_RDWR;
|
||||
}
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
snapshot_flags = bdrv_temp_snapshot_flags(flags);
|
||||
flags = bdrv_backing_flags(flags);
|
||||
}
|
||||
|
||||
assert(file == NULL);
|
||||
ret = bdrv_open_image(&file, filename, options, "file",
|
||||
@@ -1417,8 +1421,8 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
|
||||
/* For snapshot=on, create a temporary qcow2 overlay. bs points to the
|
||||
* temporary snapshot afterwards. */
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
bdrv_append_temp_snapshot(bs, &local_err);
|
||||
if (snapshot_flags) {
|
||||
bdrv_append_temp_snapshot(bs, snapshot_flags, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto close_and_fail;
|
||||
|
||||
+6
-1
@@ -207,6 +207,11 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
|
||||
"volume=%s image=%s transport=%s", gconf->server,
|
||||
gconf->port, gconf->volname, gconf->image,
|
||||
gconf->transport);
|
||||
|
||||
/* glfs_init sometimes doesn't set errno although docs suggest that */
|
||||
if (errno == 0)
|
||||
errno = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
return glfs;
|
||||
@@ -482,7 +487,7 @@ static int qemu_gluster_create(const char *filename,
|
||||
|
||||
glfs = qemu_gluster_init(gconf, filename, errp);
|
||||
if (!glfs) {
|
||||
ret = -EINVAL;
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* QEMU Block driver for iSCSI images
|
||||
*
|
||||
* Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
* Copyright (c) 2012-2013 Peter Lieven <pl@kamp.de>
|
||||
* Copyright (c) 2012-2014 Peter Lieven <pl@kamp.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -256,6 +256,10 @@ static int64_t nfs_client_open(NFSClient *client, const char *filename,
|
||||
error_setg(errp, "Invalid URL specified");
|
||||
goto fail;
|
||||
}
|
||||
if (!uri->server) {
|
||||
error_setg(errp, "Invalid URL specified");
|
||||
goto fail;
|
||||
}
|
||||
strp = strrchr(uri->path, '/');
|
||||
if (strp == NULL) {
|
||||
error_setg(errp, "Invalid URL specified");
|
||||
|
||||
@@ -656,7 +656,9 @@ retry:
|
||||
|
||||
/* Make sure that all offsets in the "allocated" range are representable
|
||||
* in an int64_t */
|
||||
if (s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits)) {
|
||||
if (s->free_cluster_index > 0 &&
|
||||
s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits))
|
||||
{
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
|
||||
+91
-64
@@ -146,6 +146,9 @@ typedef struct BDRVRawState {
|
||||
bool has_discard:1;
|
||||
bool has_write_zeroes:1;
|
||||
bool discard_zeroes:1;
|
||||
#ifdef CONFIG_FIEMAP
|
||||
bool skip_fiemap;
|
||||
#endif
|
||||
} BDRVRawState;
|
||||
|
||||
typedef struct BDRVRawReopenState {
|
||||
@@ -1272,6 +1275,83 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
return result;
|
||||
}
|
||||
|
||||
static int64_t try_fiemap(BlockDriverState *bs, off_t start, off_t *data,
|
||||
off_t *hole, int nb_sectors, int *pnum)
|
||||
{
|
||||
#ifdef CONFIG_FIEMAP
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
struct {
|
||||
struct fiemap fm;
|
||||
struct fiemap_extent fe;
|
||||
} f;
|
||||
|
||||
if (s->skip_fiemap) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
f.fm.fm_start = start;
|
||||
f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
|
||||
f.fm.fm_flags = 0;
|
||||
f.fm.fm_extent_count = 1;
|
||||
f.fm.fm_reserved = 0;
|
||||
if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
|
||||
s->skip_fiemap = true;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (f.fm.fm_mapped_extents == 0) {
|
||||
/* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
|
||||
* f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
|
||||
*/
|
||||
off_t length = lseek(s->fd, 0, SEEK_END);
|
||||
*hole = f.fm.fm_start;
|
||||
*data = MIN(f.fm.fm_start + f.fm.fm_length, length);
|
||||
} else {
|
||||
*data = f.fe.fe_logical;
|
||||
*hole = f.fe.fe_logical + f.fe.fe_length;
|
||||
if (f.fe.fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int64_t try_seek_hole(BlockDriverState *bs, off_t start, off_t *data,
|
||||
off_t *hole, int *pnum)
|
||||
{
|
||||
#if defined SEEK_HOLE && defined SEEK_DATA
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
*hole = lseek(s->fd, start, SEEK_HOLE);
|
||||
if (*hole == -1) {
|
||||
/* -ENXIO indicates that sector_num was past the end of the file.
|
||||
* There is a virtual hole there. */
|
||||
assert(errno != -ENXIO);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (*hole > start) {
|
||||
*data = start;
|
||||
} else {
|
||||
/* On a hole. We need another syscall to find its end. */
|
||||
*data = lseek(s->fd, start, SEEK_DATA);
|
||||
if (*data == -1) {
|
||||
*data = lseek(s->fd, 0, SEEK_END);
|
||||
}
|
||||
}
|
||||
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true iff the specified sector is present in the disk image. Drivers
|
||||
* not implementing the functionality are assumed to not support backing files,
|
||||
@@ -1288,10 +1368,10 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
* beyond the end of the disk image it will be clamped.
|
||||
*/
|
||||
static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum)
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum)
|
||||
{
|
||||
off_t start, data, hole;
|
||||
off_t start, data = 0, hole = 0;
|
||||
int64_t ret;
|
||||
|
||||
ret = fd_open(bs);
|
||||
@@ -1300,71 +1380,18 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
start = sector_num * BDRV_SECTOR_SIZE;
|
||||
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
|
||||
#ifdef CONFIG_FIEMAP
|
||||
|
||||
BDRVRawState *s = bs->opaque;
|
||||
struct {
|
||||
struct fiemap fm;
|
||||
struct fiemap_extent fe;
|
||||
} f;
|
||||
|
||||
f.fm.fm_start = start;
|
||||
f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
|
||||
f.fm.fm_flags = 0;
|
||||
f.fm.fm_extent_count = 1;
|
||||
f.fm.fm_reserved = 0;
|
||||
if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
|
||||
/* Assume everything is allocated. */
|
||||
*pnum = nb_sectors;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (f.fm.fm_mapped_extents == 0) {
|
||||
/* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
|
||||
* f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
|
||||
*/
|
||||
off_t length = lseek(s->fd, 0, SEEK_END);
|
||||
hole = f.fm.fm_start;
|
||||
data = MIN(f.fm.fm_start + f.fm.fm_length, length);
|
||||
} else {
|
||||
data = f.fe.fe_logical;
|
||||
hole = f.fe.fe_logical + f.fe.fe_length;
|
||||
if (f.fe.fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum);
|
||||
if (ret < 0) {
|
||||
ret = try_seek_hole(bs, start, &data, &hole, pnum);
|
||||
if (ret < 0) {
|
||||
/* Assume everything is allocated. */
|
||||
data = 0;
|
||||
hole = start + nb_sectors * BDRV_SECTOR_SIZE;
|
||||
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SEEK_HOLE && defined SEEK_DATA
|
||||
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
hole = lseek(s->fd, start, SEEK_HOLE);
|
||||
if (hole == -1) {
|
||||
/* -ENXIO indicates that sector_num was past the end of the file.
|
||||
* There is a virtual hole there. */
|
||||
assert(errno != -ENXIO);
|
||||
|
||||
/* Most likely EINVAL. Assume everything is allocated. */
|
||||
*pnum = nb_sectors;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (hole > start) {
|
||||
data = start;
|
||||
} else {
|
||||
/* On a hole. We need another syscall to find its end. */
|
||||
data = lseek(s->fd, start, SEEK_DATA);
|
||||
if (data == -1) {
|
||||
data = lseek(s->fd, 0, SEEK_END);
|
||||
}
|
||||
}
|
||||
#else
|
||||
data = 0;
|
||||
hole = start + nb_sectors * BDRV_SECTOR_SIZE;
|
||||
#endif
|
||||
|
||||
if (data <= start) {
|
||||
/* On a data extent, compute sectors to the end of the extent. */
|
||||
*pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
|
||||
|
||||
@@ -1496,6 +1496,19 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vmdk_write_compressed(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
const uint8_t *buf,
|
||||
int nb_sectors)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
if (s->num_extents == 1 && s->extents[0].compressed) {
|
||||
return vmdk_write(bs, sector_num, buf, nb_sectors, false, false);
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors,
|
||||
@@ -2063,6 +2076,26 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
|
||||
return spec_info;
|
||||
}
|
||||
|
||||
static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
int i;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
assert(s->num_extents);
|
||||
bdi->needs_compressed_writes = s->extents[0].compressed;
|
||||
if (!s->extents[0].flat) {
|
||||
bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
|
||||
}
|
||||
/* See if we have multiple extents but they have different cases */
|
||||
for (i = 1; i < s->num_extents; i++) {
|
||||
if (bdi->needs_compressed_writes != s->extents[i].compressed ||
|
||||
(bdi->cluster_size && bdi->cluster_size !=
|
||||
s->extents[i].cluster_sectors << BDRV_SECTOR_BITS)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vmdk_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
@@ -2109,6 +2142,7 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_reopen_prepare = vmdk_reopen_prepare,
|
||||
.bdrv_read = vmdk_co_read,
|
||||
.bdrv_write = vmdk_co_write,
|
||||
.bdrv_write_compressed = vmdk_write_compressed,
|
||||
.bdrv_co_write_zeroes = vmdk_co_write_zeroes,
|
||||
.bdrv_close = vmdk_close,
|
||||
.bdrv_create = vmdk_create,
|
||||
@@ -2118,6 +2152,7 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_has_zero_init = vmdk_has_zero_init,
|
||||
.bdrv_get_specific_info = vmdk_get_specific_info,
|
||||
.bdrv_refresh_limits = vmdk_refresh_limits,
|
||||
.bdrv_get_info = vmdk_get_info,
|
||||
|
||||
.create_options = vmdk_create_options,
|
||||
};
|
||||
|
||||
@@ -4771,6 +4771,12 @@ if test "$gcov" = "yes" ; then
|
||||
echo "GCOV=$gcov_tool" >> $config_host_mak
|
||||
fi
|
||||
|
||||
iotests_common_env="tests/qemu-iotests/common.env"
|
||||
|
||||
echo "# Automatically generated by configure - do not modify" > $iotests_common_env
|
||||
echo >> $iotests_common_env
|
||||
echo "PYTHON='$python'" >> $iotests_common_env
|
||||
|
||||
# use included Linux headers
|
||||
if test "$linux" = "yes" ; then
|
||||
mkdir -p linux-headers
|
||||
|
||||
@@ -34,6 +34,10 @@ typedef struct BlockDriverInfo {
|
||||
* opened with BDRV_O_UNMAP flag for this to work.
|
||||
*/
|
||||
bool can_write_zeroes_with_unmap;
|
||||
/*
|
||||
* True if this block driver only supports compressed writes
|
||||
*/
|
||||
bool needs_compressed_writes;
|
||||
} BlockDriverInfo;
|
||||
|
||||
typedef struct BlockFragInfo {
|
||||
@@ -191,7 +195,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
QDict *options, const char *bdref_key, int flags,
|
||||
bool allow_none, Error **errp);
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
|
||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp);
|
||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
|
||||
int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
const char *reference, QDict *options, int flags,
|
||||
BlockDriver *drv, Error **errp);
|
||||
|
||||
@@ -24,7 +24,14 @@ static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 20, 0)
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* g_poll has a problem on Windows when using
|
||||
* timeouts < 10ms, so use wrapper.
|
||||
*/
|
||||
#define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout)
|
||||
gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
|
||||
#elif !GLIB_CHECK_VERSION(2, 20, 0)
|
||||
/*
|
||||
* Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly
|
||||
* on older systems.
|
||||
|
||||
+26
-3
@@ -32,6 +32,7 @@
|
||||
#include "block/block_int.h"
|
||||
#include "block/qapi.h"
|
||||
#include <getopt.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
|
||||
", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
@@ -55,9 +56,25 @@ typedef enum OutputFormat {
|
||||
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
|
||||
#define BDRV_DEFAULT_CACHE "writeback"
|
||||
|
||||
static void format_print(void *opaque, const char *name)
|
||||
static gint compare_data(gconstpointer a, gconstpointer b, gpointer user)
|
||||
{
|
||||
printf(" %s", name);
|
||||
return g_strcmp0(a, b);
|
||||
}
|
||||
|
||||
static void print_format(gpointer data, gpointer user)
|
||||
{
|
||||
printf(" %s", (char *)data);
|
||||
}
|
||||
|
||||
static void add_format_to_seq(void *opaque, const char *fmt_name)
|
||||
{
|
||||
GSequence *seq = opaque;
|
||||
|
||||
if (!g_sequence_lookup(seq, (gpointer)fmt_name,
|
||||
compare_data, NULL)) {
|
||||
g_sequence_insert_sorted(seq, (gpointer)fmt_name,
|
||||
compare_data, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
|
||||
@@ -142,10 +159,15 @@ static void QEMU_NORETURN help(void)
|
||||
" '-f' first image format\n"
|
||||
" '-F' second image format\n"
|
||||
" '-s' run in Strict mode - fail on different image size or sector allocation\n";
|
||||
GSequence *seq;
|
||||
|
||||
printf("%s\nSupported formats:", help_msg);
|
||||
bdrv_iterate_format(format_print, NULL);
|
||||
seq = g_sequence_new(NULL);
|
||||
bdrv_iterate_format(add_format_to_seq, seq);
|
||||
g_sequence_foreach(seq, print_format, NULL);
|
||||
printf("\n");
|
||||
g_sequence_free(seq);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1480,6 +1502,7 @@ static int img_convert(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
compress = compress || bdi.needs_compressed_writes;
|
||||
cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,9 @@ static void qemu_clock_init(QEMUClockType type)
|
||||
{
|
||||
QEMUClock *clock = qemu_clock_ptr(type);
|
||||
|
||||
/* Assert that the clock of type TYPE has not been initialized yet. */
|
||||
assert(main_loop_tlg.tl[type] == NULL);
|
||||
|
||||
clock->type = type;
|
||||
clock->enabled = true;
|
||||
clock->last = INT64_MIN;
|
||||
|
||||
@@ -35,6 +35,7 @@ _cleanup()
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.env
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.pattern
|
||||
@@ -56,22 +57,22 @@ for IMGOPTS in "compat=0.10" "compat=1.1"; do
|
||||
echo === Create image with unknown header extension ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
./qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
|
||||
./qcow2.py "$TEST_IMG" dump-header
|
||||
$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo === Rewrite header with no backing file ===
|
||||
echo
|
||||
$QEMU_IMG rebase -u -b "" "$TEST_IMG"
|
||||
./qcow2.py "$TEST_IMG" dump-header
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo === Add a backing file and format ===
|
||||
echo
|
||||
$QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device "$TEST_IMG"
|
||||
./qcow2.py "$TEST_IMG" dump-header
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
done
|
||||
|
||||
# success, all done
|
||||
|
||||
@@ -38,6 +38,7 @@ _cleanup()
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.env
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.pattern
|
||||
@@ -53,15 +54,15 @@ IMGOPTS="compat=1.1"
|
||||
echo === Create image with unknown autoclear feature bit ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
./qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
|
||||
./qcow2.py "$TEST_IMG" dump-header
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
|
||||
echo
|
||||
echo === Repair image ===
|
||||
echo
|
||||
_check_test_img -r all
|
||||
|
||||
./qcow2.py "$TEST_IMG" dump-header
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
|
||||
+10
-9
@@ -38,6 +38,7 @@ _cleanup()
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.env
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
@@ -58,7 +59,7 @@ _make_test_img $size
|
||||
$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# The dirty bit must not be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
@@ -73,7 +74,7 @@ $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
|
||||
ulimit -c "$old_ulimit"
|
||||
|
||||
# The dirty bit must be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
@@ -82,7 +83,7 @@ echo "== Read-only access must still work =="
|
||||
$QEMU_IO -r -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# The dirty bit must be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
|
||||
echo
|
||||
echo "== Repairing the image file must succeed =="
|
||||
@@ -90,7 +91,7 @@ echo "== Repairing the image file must succeed =="
|
||||
_check_test_img -r all
|
||||
|
||||
# The dirty bit must not be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
|
||||
echo
|
||||
echo "== Data should still be accessible after repair =="
|
||||
@@ -109,12 +110,12 @@ $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
|
||||
ulimit -c "$old_ulimit"
|
||||
|
||||
# The dirty bit must be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
|
||||
$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# The dirty bit must not be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
|
||||
echo
|
||||
echo "== Creating an image file with lazy_refcounts=off =="
|
||||
@@ -128,7 +129,7 @@ $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
|
||||
ulimit -c "$old_ulimit"
|
||||
|
||||
# The dirty bit must not be set since lazy_refcounts=off
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
@@ -144,8 +145,8 @@ $QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IMG commit "$TEST_IMG"
|
||||
|
||||
# The dirty bit must not be set
|
||||
./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
./qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
|
||||
$PYTHON qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
|
||||
|
||||
_check_test_img
|
||||
TEST_IMG="$TEST_IMG".base _check_test_img
|
||||
|
||||
@@ -233,6 +233,10 @@ echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",
|
||||
|
||||
$QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo -e 'qemu-io ide0-hd0 "write -P 0x33 0 4k"\ncommit ide0-hd0' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
|
||||
|
||||
$QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -35,6 +35,7 @@ _cleanup()
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.env
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
@@ -49,7 +50,7 @@ _make_test_img $((1024*1024))T
|
||||
echo
|
||||
echo "creating too large image (1 EB) using qcow2.py"
|
||||
_make_test_img 4G
|
||||
./qcow2.py "$TEST_IMG" set-header size $((1024 ** 6))
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-header size $((1024 ** 6))
|
||||
_check_test_img
|
||||
|
||||
# success, all done
|
||||
|
||||
@@ -103,6 +103,13 @@ IMGOPTS="subformat=monolithicSparse" _make_test_img 100G
|
||||
truncate -s 10M $TEST_IMG
|
||||
_img_info
|
||||
|
||||
echo
|
||||
echo "=== Converting to streamOptimized from image with small cluster size==="
|
||||
TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
|
||||
$QEMU_IO -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
|
||||
$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
|
||||
|
||||
echo
|
||||
echo "=== Testing version 3 ==="
|
||||
_use_sample_img iotest-version3.vmdk.bz2
|
||||
|
||||
@@ -2046,10 +2046,18 @@ RW 12582912 VMFS "dummy.IMGFMT" 1
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': File truncated, expecting at least 13172736 bytes
|
||||
|
||||
=== Converting to streamOptimized from image with small cluster size===
|
||||
Formatting 'TEST_DIR/t.vmdk.IMGFMT', fmt=IMGFMT size=1073741824
|
||||
wrote 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 10240
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Testing version 3 ===
|
||||
image: TEST_DIR/iotest-version3.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 1.0G (1073741824 bytes)
|
||||
cluster_size: 65536
|
||||
|
||||
=== Testing 4TB monolithicFlat creation and IO ===
|
||||
Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user