mirror of https://gitee.com/openkylin/qemu.git
Block pull request
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTyRWPAAoJEJykq7OBq3PI5uYIALvrix8BJs+gyIBbOkXwAcVt fO1zMb+YjfCNZBjn05bw0uCkr3RcF4/I5VhV8MUvEvGtltnO9NVnZe9aXWt8z0mQ mcw8B63lW93xBRN1tfkdfHxN8bwwhmdfBo900MOKq1O0AftQr7o1UQnMk7O/THl4 GQjFnA+TKPzt6TWn+xfPDVkXr4lf4bOd+LKs8JU1u4LhUR5VdOlBzsVGsWfUJo/e jUnXBM2epIiWjz4iDadmXmupaGEJn4WMwtEVgMaBpDQsp5LSvRgKYfuoT9U1qqAw 4cDH5hIfCc5/L9PSIk3VJiB6CyOUSLKcjdfzEpmUdisJfZfyHpzsTPp7wc8OlMM= =Q2gD -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging Block pull request # gpg: Signature made Fri 18 Jul 2014 13:39:43 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: qemu-iotests: fix 028 failure due to disk image path raw-posix: Fail gracefully if no working alignment is found block: Add Error argument to bdrv_refresh_limits() qcow2: Fix error path for unknown incompatible features Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e0097ea371
33
block.c
33
block.c
|
@ -508,19 +508,24 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_refresh_limits(BlockDriverState *bs)
|
||||
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
Error *local_err = NULL;
|
||||
|
||||
memset(&bs->bl, 0, sizeof(bs->bl));
|
||||
|
||||
if (!drv) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Take some limits from the children as a default */
|
||||
if (bs->file) {
|
||||
bdrv_refresh_limits(bs->file);
|
||||
bdrv_refresh_limits(bs->file, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
|
||||
bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
|
||||
} else {
|
||||
|
@ -528,7 +533,11 @@ int bdrv_refresh_limits(BlockDriverState *bs)
|
|||
}
|
||||
|
||||
if (bs->backing_hd) {
|
||||
bdrv_refresh_limits(bs->backing_hd);
|
||||
bdrv_refresh_limits(bs->backing_hd, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
bs->bl.opt_transfer_length =
|
||||
MAX(bs->bl.opt_transfer_length,
|
||||
bs->backing_hd->bl.opt_transfer_length);
|
||||
|
@ -539,10 +548,8 @@ int bdrv_refresh_limits(BlockDriverState *bs)
|
|||
|
||||
/* Then let the driver override it */
|
||||
if (drv->bdrv_refresh_limits) {
|
||||
return drv->bdrv_refresh_limits(bs);
|
||||
drv->bdrv_refresh_limits(bs, errp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -993,7 +1000,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||
goto free_and_fail;
|
||||
}
|
||||
|
||||
bdrv_refresh_limits(bs);
|
||||
bdrv_refresh_limits(bs, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto free_and_fail;
|
||||
}
|
||||
|
||||
assert(bdrv_opt_mem_align(bs) != 0);
|
||||
assert((bs->request_alignment != 0) || bs->sg);
|
||||
return 0;
|
||||
|
@ -1154,7 +1167,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
|
|||
bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
|
||||
bs->backing_blocker);
|
||||
out:
|
||||
bdrv_refresh_limits(bs);
|
||||
bdrv_refresh_limits(bs, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1778,7 +1791,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
|||
BDRV_O_CACHE_WB);
|
||||
reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
|
||||
|
||||
bdrv_refresh_limits(reopen_state->bs);
|
||||
bdrv_refresh_limits(reopen_state->bs, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1450,7 +1450,7 @@ static void iscsi_close(BlockDriverState *bs)
|
|||
memset(iscsilun, 0, sizeof(IscsiLun));
|
||||
}
|
||||
|
||||
static int iscsi_refresh_limits(BlockDriverState *bs)
|
||||
static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
|
||||
|
@ -1475,7 +1475,6 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
|
|||
}
|
||||
bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
|
||||
iscsilun);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
|
||||
|
|
|
@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
|
|||
static void report_unsupported_feature(BlockDriverState *bs,
|
||||
Error **errp, Qcow2Feature *table, uint64_t mask)
|
||||
{
|
||||
char *features = g_strdup("");
|
||||
char *old;
|
||||
|
||||
while (table && table->name[0] != '\0') {
|
||||
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
|
||||
if (mask & (1 << table->bit)) {
|
||||
report_unsupported(bs, errp, "%.46s", table->name);
|
||||
mask &= ~(1 << table->bit);
|
||||
if (mask & (1ULL << table->bit)) {
|
||||
old = features;
|
||||
features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
|
||||
table->name);
|
||||
g_free(old);
|
||||
mask &= ~(1ULL << table->bit);
|
||||
}
|
||||
}
|
||||
table++;
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
|
||||
mask);
|
||||
old = features;
|
||||
features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
|
||||
old, *old ? ", " : "", mask);
|
||||
g_free(old);
|
||||
}
|
||||
|
||||
report_unsupported(bs, errp, "%s", features);
|
||||
g_free(features);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -855,13 +866,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_refresh_limits(BlockDriverState *bs)
|
||||
static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
bs->bl.write_zeroes_alignment = s->cluster_sectors;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
||||
|
|
|
@ -528,13 +528,11 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int bdrv_qed_refresh_limits(BlockDriverState *bs)
|
||||
static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have nothing to do for QED reopen, stubs just return
|
||||
|
|
|
@ -221,7 +221,7 @@ static int raw_normalize_devicepath(const char **filename)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void raw_probe_alignment(BlockDriverState *bs)
|
||||
static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
char *buf;
|
||||
|
@ -240,24 +240,24 @@ static void raw_probe_alignment(BlockDriverState *bs)
|
|||
s->buf_align = 0;
|
||||
|
||||
#ifdef BLKSSZGET
|
||||
if (ioctl(s->fd, BLKSSZGET, §or_size) >= 0) {
|
||||
if (ioctl(fd, BLKSSZGET, §or_size) >= 0) {
|
||||
bs->request_alignment = sector_size;
|
||||
}
|
||||
#endif
|
||||
#ifdef DKIOCGETBLOCKSIZE
|
||||
if (ioctl(s->fd, DKIOCGETBLOCKSIZE, §or_size) >= 0) {
|
||||
if (ioctl(fd, DKIOCGETBLOCKSIZE, §or_size) >= 0) {
|
||||
bs->request_alignment = sector_size;
|
||||
}
|
||||
#endif
|
||||
#ifdef DIOCGSECTORSIZE
|
||||
if (ioctl(s->fd, DIOCGSECTORSIZE, §or_size) >= 0) {
|
||||
if (ioctl(fd, DIOCGSECTORSIZE, §or_size) >= 0) {
|
||||
bs->request_alignment = sector_size;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_XFS
|
||||
if (s->is_xfs) {
|
||||
struct dioattr da;
|
||||
if (xfsctl(NULL, s->fd, XFS_IOC_DIOINFO, &da) >= 0) {
|
||||
if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
|
||||
bs->request_alignment = da.d_miniosz;
|
||||
/* The kernel returns wrong information for d_mem */
|
||||
/* s->buf_align = da.d_mem; */
|
||||
|
@ -270,7 +270,7 @@ static void raw_probe_alignment(BlockDriverState *bs)
|
|||
size_t align;
|
||||
buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
|
||||
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
|
||||
if (pread(s->fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
|
||||
if (pread(fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
|
||||
s->buf_align = align;
|
||||
break;
|
||||
}
|
||||
|
@ -282,13 +282,18 @@ static void raw_probe_alignment(BlockDriverState *bs)
|
|||
size_t align;
|
||||
buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE);
|
||||
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
|
||||
if (pread(s->fd, buf, align, 0) >= 0) {
|
||||
if (pread(fd, buf, align, 0) >= 0) {
|
||||
bs->request_alignment = align;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qemu_vfree(buf);
|
||||
}
|
||||
|
||||
if (!s->buf_align || !bs->request_alignment) {
|
||||
error_setg(errp, "Could not find working O_DIRECT alignment. "
|
||||
"Try cache.direct=off.");
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_parse_flags(int bdrv_flags, int *open_flags)
|
||||
|
@ -505,6 +510,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
|
|||
BDRVRawState *s;
|
||||
BDRVRawReopenState *raw_s;
|
||||
int ret = 0;
|
||||
Error *local_err = NULL;
|
||||
|
||||
assert(state != NULL);
|
||||
assert(state->bs != NULL);
|
||||
|
@ -577,6 +583,19 @@ static int raw_reopen_prepare(BDRVReopenState *state,
|
|||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fail already reopen_prepare() if we can't get a working O_DIRECT
|
||||
* alignment with the new fd. */
|
||||
if (raw_s->fd != -1) {
|
||||
raw_probe_alignment(state->bs, raw_s->fd, &local_err);
|
||||
if (local_err) {
|
||||
qemu_close(raw_s->fd);
|
||||
raw_s->fd = -1;
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -615,14 +634,12 @@ static void raw_reopen_abort(BDRVReopenState *state)
|
|||
state->opaque = NULL;
|
||||
}
|
||||
|
||||
static int raw_refresh_limits(BlockDriverState *bs)
|
||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
raw_probe_alignment(bs);
|
||||
raw_probe_alignment(bs, s->fd, errp);
|
||||
bs->bl.opt_mem_alignment = s->buf_align;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
|
||||
|
|
|
@ -94,10 +94,9 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||
return bdrv_get_info(bs->file, bdi);
|
||||
}
|
||||
|
||||
static int raw_refresh_limits(BlockDriverState *bs)
|
||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl = bs->file->bl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
|
|
@ -76,7 +76,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
|
|||
bdrv_unref(unused);
|
||||
}
|
||||
|
||||
bdrv_refresh_limits(top);
|
||||
bdrv_refresh_limits(top, NULL);
|
||||
}
|
||||
|
||||
static void coroutine_fn stream_run(void *opaque)
|
||||
|
|
|
@ -938,7 +938,7 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static int vmdk_refresh_limits(BlockDriverState *bs)
|
||||
static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int i;
|
||||
|
@ -950,8 +950,6 @@ static int vmdk_refresh_limits(BlockDriverState *bs)
|
|||
s->extents[i].cluster_sectors);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_whole_cluster(BlockDriverState *bs,
|
||||
|
|
|
@ -278,7 +278,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
|
|||
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
|
||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
|
||||
int bdrv_refresh_limits(BlockDriverState *bs);
|
||||
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
|
||||
int bdrv_commit(BlockDriverState *bs);
|
||||
int bdrv_commit_all(void);
|
||||
int bdrv_change_backing_file(BlockDriverState *bs,
|
||||
|
|
|
@ -240,7 +240,7 @@ struct BlockDriver {
|
|||
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
|
||||
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
|
||||
|
||||
int (*bdrv_refresh_limits)(BlockDriverState *bs);
|
||||
void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);
|
||||
|
||||
/*
|
||||
* Returns 1 if newly created images are guaranteed to contain only
|
||||
|
|
|
@ -110,7 +110,9 @@ _launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
|
|||
h=$QEMU_HANDLE
|
||||
QEMU_COMM_TIMEOUT=1
|
||||
|
||||
_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
|
||||
# Silence output since it contains the disk image path and QEMU's readline
|
||||
# character echoing makes it very hard to filter the output
|
||||
_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
|
||||
qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
|
||||
_send_qemu_cmd $h 'quit' ""
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Test that qcow2 unknown autoclear feature bits are cleared
|
||||
# Test qcow2 feature bits
|
||||
#
|
||||
# Copyright (C) 2011 Red Hat, Inc.
|
||||
# Copyright IBM, Corp. 2010
|
||||
|
@ -50,6 +50,56 @@ _supported_os Linux
|
|||
# Only qcow2v3 and later supports feature bits
|
||||
IMGOPTS="compat=1.1"
|
||||
|
||||
echo
|
||||
echo === Image with unknown incompatible feature bit ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
|
||||
|
||||
# Without feature table
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 63
|
||||
printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
echo
|
||||
echo === Image with multiple incompatible feature bits ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 61
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
|
||||
|
||||
# Without feature table
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 63
|
||||
printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 61
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing bits 61 and 62
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s" "test1" "" "test2" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing all bits
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s\x00\x3f%s\x00%40s" "test1" "" "test2" "" "test3" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing unrelated bits, including compatible/autoclear
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x01\x3d%s\x00%40s\x00\x3e%s\x00%40s\x02\x3f%s\x00%40s\x00\x3c%s\x00%40s" "test1" "" "test2" "" "test3" "" "test4" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
|
||||
echo === Create image with unknown autoclear feature bit ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
|
|
|
@ -1,4 +1,39 @@
|
|||
QA output created by 036
|
||||
|
||||
=== Image with unknown incompatible feature bit ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
backing_file_offset 0x0
|
||||
backing_file_size 0x0
|
||||
cluster_bits 16
|
||||
size 67108864
|
||||
crypt_method 0
|
||||
l1_size 1
|
||||
l1_table_offset 0x30000
|
||||
refcount_table_offset 0x10000
|
||||
refcount_table_clusters 1
|
||||
nb_snapshots 0
|
||||
snapshot_offset 0x0
|
||||
incompatible_features 0x8000000000000000
|
||||
compatible_features 0x0
|
||||
autoclear_features 0x0
|
||||
refcount_order 4
|
||||
header_length 104
|
||||
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: 8000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature
|
||||
|
||||
=== Image with multiple incompatible feature bits ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, Unknown incompatible feature: 8000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, test3
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000
|
||||
=== Create image with unknown autoclear feature bit ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
|
|
@ -176,6 +176,10 @@ def cmd_add_header_ext(fd, magic, data):
|
|||
h.extensions.append(QcowHeaderExtension.create(magic, data))
|
||||
h.update(fd)
|
||||
|
||||
def cmd_add_header_ext_stdio(fd, magic):
|
||||
data = sys.stdin.read()
|
||||
cmd_add_header_ext(fd, magic, data)
|
||||
|
||||
def cmd_del_header_ext(fd, magic):
|
||||
try:
|
||||
magic = int(magic, 0)
|
||||
|
@ -223,6 +227,7 @@ def cmd_set_feature_bit(fd, group, bit):
|
|||
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
|
||||
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
|
||||
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
|
||||
[ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
|
||||
[ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
|
||||
[ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue