Block patches for 2.7
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJXNIZVAAoJEDuxQgLoOKytrQcH/1PleLZ6jzu1ZQLmrCx73OBf B8pLjSNvGxGQaFfc0SZi4kLhsVtk5s7CZwwY2i0xSnYetcrOa/w9ioLj4j9CkSpb zU80k+HeYagLGpF5TbVbMaBcZK0UAu0ti4eWGcbwN5rdpmO4sdpTrR5rx8n0dziW qj20p7Z9NfDPEQfMJ45Aco0cQ//NsAh4FaPCHdJvgIsrL7uoD9dQ6CN+DrstXQsq GRSS/doWCxohtdX01C5OLATvTKkEO10hrO9INo27Db/XC0PovaELZTa5lfQgYBlD zx4Xv2ga/dEf3pYWTj2/wPmBa06GUV3xts3WpWJqjbXkYbczWllYoqA4z7R0/lw= =A6+m -----END PGP SIGNATURE----- Merge remote-tracking branch 'mreitz/tags/pull-block-for-kevin-2016-05-12' into queue-block Block patches for 2.7 # gpg: Signature made Thu May 12 15:34:13 2016 CEST using RSA key ID E838ACAD # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" * mreitz/tags/pull-block-for-kevin-2016-05-12: qemu-iotests: iotests: fail hard if not run via "check" block: enable testing of LUKS driver with block I/O tests block: add support for encryption secrets in block I/O tests block: add support for --image-opts in block I/O tests qemu-io: Add 'write -z -u' to test MAY_UNMAP flag qemu-io: Add 'write -f' to test FUA flag qemu-io: Allow unaligned access by default qemu-io: Use bool for command line flags qemu-io: Make 'open' subcommand more like command line qemu-io: Add missing option documentation qmp: add monitor command to add/remove a child quorum: implement bdrv_add_child() and bdrv_del_child() Add new block driver interface to add/delete a BDS's child qemu-img: check block status of backing file when converting. iotests: fix the redirection order in 083 Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
commit
efc2645f71
51
block.c
51
block.c
@ -1174,7 +1174,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||||
BlockDriverState *child_bs,
|
BlockDriverState *child_bs,
|
||||||
const char *child_name,
|
const char *child_name,
|
||||||
const BdrvChildRole *child_role)
|
const BdrvChildRole *child_role)
|
||||||
@ -4011,3 +4011,52 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
|||||||
QDECREF(json);
|
QDECREF(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hot add/remove a BDS's child. So the user can take a child offline when
|
||||||
|
* it is broken and take a new child online
|
||||||
|
*/
|
||||||
|
void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!parent_bs->drv || !parent_bs->drv->bdrv_add_child) {
|
||||||
|
error_setg(errp, "The node %s does not support adding a child",
|
||||||
|
bdrv_get_device_or_node_name(parent_bs));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QLIST_EMPTY(&child_bs->parents)) {
|
||||||
|
error_setg(errp, "The node %s already has a parent",
|
||||||
|
child_bs->node_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_bs->drv->bdrv_add_child(parent_bs, child_bs, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
|
||||||
|
{
|
||||||
|
BdrvChild *tmp;
|
||||||
|
|
||||||
|
if (!parent_bs->drv || !parent_bs->drv->bdrv_del_child) {
|
||||||
|
error_setg(errp, "The node %s does not support removing a child",
|
||||||
|
bdrv_get_device_or_node_name(parent_bs));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLIST_FOREACH(tmp, &parent_bs->children, next) {
|
||||||
|
if (tmp == child) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tmp) {
|
||||||
|
error_setg(errp, "The node %s does not have a child named %s",
|
||||||
|
bdrv_get_device_or_node_name(parent_bs),
|
||||||
|
bdrv_get_device_or_node_name(child->bs));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "qapi/qmp/qbool.h"
|
#include "qapi/qmp/qbool.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
@ -67,6 +68,9 @@ typedef struct QuorumVotes {
|
|||||||
typedef struct BDRVQuorumState {
|
typedef struct BDRVQuorumState {
|
||||||
BdrvChild **children; /* children BlockDriverStates */
|
BdrvChild **children; /* children BlockDriverStates */
|
||||||
int num_children; /* children count */
|
int num_children; /* children count */
|
||||||
|
unsigned next_child_index; /* the index of the next child that should
|
||||||
|
* be added
|
||||||
|
*/
|
||||||
int threshold; /* if less than threshold children reads gave the
|
int threshold; /* if less than threshold children reads gave the
|
||||||
* same result a quorum error occurs.
|
* same result a quorum error occurs.
|
||||||
*/
|
*/
|
||||||
@ -883,9 +887,9 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (s->num_children < 2) {
|
if (s->num_children < 1) {
|
||||||
error_setg(&local_err,
|
error_setg(&local_err,
|
||||||
"Number of provided children must be greater than 1");
|
"Number of provided children must be 1 or more");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -949,6 +953,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
opened[i] = true;
|
opened[i] = true;
|
||||||
}
|
}
|
||||||
|
s->next_child_index = s->num_children;
|
||||||
|
|
||||||
g_free(opened);
|
g_free(opened);
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -1005,6 +1010,72 @@ static void quorum_attach_aio_context(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BDRVQuorumState *s = bs->opaque;
|
||||||
|
BdrvChild *child;
|
||||||
|
char indexstr[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
|
||||||
|
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
|
||||||
|
s->next_child_index == UINT_MAX) {
|
||||||
|
error_setg(errp, "Too many children");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snprintf(indexstr, 32, "children.%u", s->next_child_index);
|
||||||
|
if (ret < 0 || ret >= 32) {
|
||||||
|
error_setg(errp, "cannot generate child name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->next_child_index++;
|
||||||
|
|
||||||
|
bdrv_drained_begin(bs);
|
||||||
|
|
||||||
|
/* We can safely add the child now */
|
||||||
|
bdrv_ref(child_bs);
|
||||||
|
child = bdrv_attach_child(bs, child_bs, indexstr, &child_format);
|
||||||
|
s->children = g_renew(BdrvChild *, s->children, s->num_children + 1);
|
||||||
|
s->children[s->num_children++] = child;
|
||||||
|
|
||||||
|
bdrv_drained_end(bs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BDRVQuorumState *s = bs->opaque;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < s->num_children; i++) {
|
||||||
|
if (s->children[i] == child) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have checked it in bdrv_del_child() */
|
||||||
|
assert(i < s->num_children);
|
||||||
|
|
||||||
|
if (s->num_children <= s->threshold) {
|
||||||
|
error_setg(errp,
|
||||||
|
"The number of children cannot be lower than the vote threshold %d",
|
||||||
|
s->threshold);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_drained_begin(bs);
|
||||||
|
|
||||||
|
/* We can safely remove this child now */
|
||||||
|
memmove(&s->children[i], &s->children[i + 1],
|
||||||
|
(s->num_children - i - 1) * sizeof(BdrvChild *));
|
||||||
|
s->children = g_renew(BdrvChild *, s->children, --s->num_children);
|
||||||
|
bdrv_unref_child(bs, child);
|
||||||
|
|
||||||
|
bdrv_drained_end(bs);
|
||||||
|
}
|
||||||
|
|
||||||
static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
|
static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||||
{
|
{
|
||||||
BDRVQuorumState *s = bs->opaque;
|
BDRVQuorumState *s = bs->opaque;
|
||||||
@ -1059,6 +1130,9 @@ static BlockDriver bdrv_quorum = {
|
|||||||
.bdrv_detach_aio_context = quorum_detach_aio_context,
|
.bdrv_detach_aio_context = quorum_detach_aio_context,
|
||||||
.bdrv_attach_aio_context = quorum_attach_aio_context,
|
.bdrv_attach_aio_context = quorum_attach_aio_context,
|
||||||
|
|
||||||
|
.bdrv_add_child = quorum_add_child,
|
||||||
|
.bdrv_del_child = quorum_del_child,
|
||||||
|
|
||||||
.is_filter = true,
|
.is_filter = true,
|
||||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||||
};
|
};
|
||||||
|
55
blockdev.c
55
blockdev.c
@ -4092,6 +4092,61 @@ out:
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BdrvChild *bdrv_find_child(BlockDriverState *parent_bs,
|
||||||
|
const char *child_name)
|
||||||
|
{
|
||||||
|
BdrvChild *child;
|
||||||
|
|
||||||
|
QLIST_FOREACH(child, &parent_bs->children, next) {
|
||||||
|
if (strcmp(child->name, child_name) == 0) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qmp_x_blockdev_change(const char *parent, bool has_child,
|
||||||
|
const char *child, bool has_node,
|
||||||
|
const char *node, Error **errp)
|
||||||
|
{
|
||||||
|
BlockDriverState *parent_bs, *new_bs = NULL;
|
||||||
|
BdrvChild *p_child;
|
||||||
|
|
||||||
|
parent_bs = bdrv_lookup_bs(parent, parent, errp);
|
||||||
|
if (!parent_bs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_child == has_node) {
|
||||||
|
if (has_child) {
|
||||||
|
error_setg(errp, "The parameters child and node are in conflict");
|
||||||
|
} else {
|
||||||
|
error_setg(errp, "Either child or node must be specified");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_child) {
|
||||||
|
p_child = bdrv_find_child(parent_bs, child);
|
||||||
|
if (!p_child) {
|
||||||
|
error_setg(errp, "Node '%s' does not have child '%s'",
|
||||||
|
parent, child);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bdrv_del_child(parent_bs, p_child, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_node) {
|
||||||
|
new_bs = bdrv_find_node(node);
|
||||||
|
if (!new_bs) {
|
||||||
|
error_setg(errp, "Node '%s' not found", node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bdrv_add_child(parent_bs, new_bs, errp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
||||||
{
|
{
|
||||||
BlockJobInfoList *head = NULL, **p_next = &head;
|
BlockJobInfoList *head = NULL, **p_next = &head;
|
||||||
|
@ -476,6 +476,10 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs);
|
|||||||
void bdrv_ref(BlockDriverState *bs);
|
void bdrv_ref(BlockDriverState *bs);
|
||||||
void bdrv_unref(BlockDriverState *bs);
|
void bdrv_unref(BlockDriverState *bs);
|
||||||
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
|
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
|
||||||
|
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||||
|
BlockDriverState *child_bs,
|
||||||
|
const char *child_name,
|
||||||
|
const BdrvChildRole *child_role);
|
||||||
|
|
||||||
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
|
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
|
||||||
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
|
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
|
||||||
@ -542,4 +546,8 @@ void bdrv_drained_begin(BlockDriverState *bs);
|
|||||||
*/
|
*/
|
||||||
void bdrv_drained_end(BlockDriverState *bs);
|
void bdrv_drained_end(BlockDriverState *bs);
|
||||||
|
|
||||||
|
void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child,
|
||||||
|
Error **errp);
|
||||||
|
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -314,6 +314,11 @@ struct BlockDriver {
|
|||||||
*/
|
*/
|
||||||
void (*bdrv_drain)(BlockDriverState *bs);
|
void (*bdrv_drain)(BlockDriverState *bs);
|
||||||
|
|
||||||
|
void (*bdrv_add_child)(BlockDriverState *parent, BlockDriverState *child,
|
||||||
|
Error **errp);
|
||||||
|
void (*bdrv_del_child)(BlockDriverState *parent, BdrvChild *child,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
QLIST_ENTRY(BlockDriver) list;
|
QLIST_ENTRY(BlockDriver) list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2556,3 +2556,35 @@
|
|||||||
##
|
##
|
||||||
{ 'command': 'block-set-write-threshold',
|
{ 'command': 'block-set-write-threshold',
|
||||||
'data': { 'node-name': 'str', 'write-threshold': 'uint64' } }
|
'data': { 'node-name': 'str', 'write-threshold': 'uint64' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @x-blockdev-change
|
||||||
|
#
|
||||||
|
# Dynamically reconfigure the block driver state graph. It can be used
|
||||||
|
# to add, remove, insert or replace a graph node. Currently only the
|
||||||
|
# Quorum driver implements this feature to add or remove its child. This
|
||||||
|
# is useful to fix a broken quorum child.
|
||||||
|
#
|
||||||
|
# If @node is specified, it will be inserted under @parent. @child
|
||||||
|
# may not be specified in this case. If both @parent and @child are
|
||||||
|
# specified but @node is not, @child will be detached from @parent.
|
||||||
|
#
|
||||||
|
# @parent: the id or name of the parent node.
|
||||||
|
#
|
||||||
|
# @child: #optional the name of a child under the given parent node.
|
||||||
|
#
|
||||||
|
# @node: #optional the name of the node that will be added.
|
||||||
|
#
|
||||||
|
# Note: this command is experimental, and its API is not stable. It
|
||||||
|
# does not support all kinds of operations, all kinds of children, nor
|
||||||
|
# all block drivers.
|
||||||
|
#
|
||||||
|
# Warning: The data in a new quorum child MUST be consistent with that of
|
||||||
|
# the rest of the array.
|
||||||
|
#
|
||||||
|
# Since: 2.7
|
||||||
|
##
|
||||||
|
{ 'command': 'x-blockdev-change',
|
||||||
|
'data' : { 'parent': 'str',
|
||||||
|
'*child': 'str',
|
||||||
|
'*node': 'str' } }
|
||||||
|
13
qemu-img.c
13
qemu-img.c
@ -1475,10 +1475,21 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
|||||||
} else if (!s->target_has_backing) {
|
} else if (!s->target_has_backing) {
|
||||||
/* Without a target backing file we must copy over the contents of
|
/* Without a target backing file we must copy over the contents of
|
||||||
* the backing file as well. */
|
* the backing file as well. */
|
||||||
/* TODO Check block status of the backing file chain to avoid
|
/* Check block status of the backing file chain to avoid
|
||||||
* needlessly reading zeroes and limiting the iteration to the
|
* needlessly reading zeroes and limiting the iteration to the
|
||||||
* buffer size */
|
* buffer size */
|
||||||
|
ret = bdrv_get_block_status_above(blk_bs(s->src[s->src_cur]), NULL,
|
||||||
|
sector_num - s->src_cur_offset,
|
||||||
|
n, &n, &file);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret & BDRV_BLOCK_ZERO) {
|
||||||
|
s->status = BLK_ZERO;
|
||||||
|
} else {
|
||||||
s->status = BLK_DATA;
|
s->status = BLK_DATA;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s->status = BLK_BACKING_FILE;
|
s->status = BLK_BACKING_FILE;
|
||||||
}
|
}
|
||||||
|
224
qemu-io-cmds.c
224
qemu-io-cmds.c
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Command line utility to exercise the QEMU I/O path.
|
* Command line utility to exercise the QEMU I/O path.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Red Hat, Inc.
|
* Copyright (C) 2009-2016 Red Hat, Inc.
|
||||||
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
|
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
|
||||||
*
|
*
|
||||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
@ -345,7 +345,7 @@ static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void print_report(const char *op, struct timeval *t, int64_t offset,
|
static void print_report(const char *op, struct timeval *t, int64_t offset,
|
||||||
int64_t count, int64_t total, int cnt, int Cflag)
|
int64_t count, int64_t total, int cnt, bool Cflag)
|
||||||
{
|
{
|
||||||
char s1[64], s2[64], ts[64];
|
char s1[64], s2[64], ts[64];
|
||||||
|
|
||||||
@ -395,12 +395,6 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len & 0x1ff) {
|
|
||||||
printf("length argument %" PRId64
|
|
||||||
" is not sector aligned\n", len);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
sizes[i] = len;
|
sizes[i] = len;
|
||||||
count += len;
|
count += len;
|
||||||
}
|
}
|
||||||
@ -434,13 +428,13 @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
|
static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
|
||||||
int64_t count, int64_t *total)
|
int64_t count, int flags, int64_t *total)
|
||||||
{
|
{
|
||||||
if (count > INT_MAX) {
|
if (count > INT_MAX) {
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*total = blk_pwrite(blk, offset, (uint8_t *)buf, count, 0);
|
*total = blk_pwrite(blk, offset, (uint8_t *)buf, count, flags);
|
||||||
if (*total < 0) {
|
if (*total < 0) {
|
||||||
return *total;
|
return *total;
|
||||||
}
|
}
|
||||||
@ -452,6 +446,7 @@ typedef struct {
|
|||||||
int64_t offset;
|
int64_t offset;
|
||||||
int64_t count;
|
int64_t count;
|
||||||
int64_t *total;
|
int64_t *total;
|
||||||
|
int flags;
|
||||||
int ret;
|
int ret;
|
||||||
bool done;
|
bool done;
|
||||||
} CoWriteZeroes;
|
} CoWriteZeroes;
|
||||||
@ -460,7 +455,8 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
|
|||||||
{
|
{
|
||||||
CoWriteZeroes *data = opaque;
|
CoWriteZeroes *data = opaque;
|
||||||
|
|
||||||
data->ret = blk_co_write_zeroes(data->blk, data->offset, data->count, 0);
|
data->ret = blk_co_write_zeroes(data->blk, data->offset, data->count,
|
||||||
|
data->flags);
|
||||||
data->done = true;
|
data->done = true;
|
||||||
if (data->ret < 0) {
|
if (data->ret < 0) {
|
||||||
*data->total = data->ret;
|
*data->total = data->ret;
|
||||||
@ -471,7 +467,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count,
|
static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count,
|
||||||
int64_t *total)
|
int flags, int64_t *total)
|
||||||
{
|
{
|
||||||
Coroutine *co;
|
Coroutine *co;
|
||||||
CoWriteZeroes data = {
|
CoWriteZeroes data = {
|
||||||
@ -479,6 +475,7 @@ static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count,
|
|||||||
.offset = offset,
|
.offset = offset,
|
||||||
.count = count,
|
.count = count,
|
||||||
.total = total,
|
.total = total,
|
||||||
|
.flags = flags,
|
||||||
.done = false,
|
.done = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -564,11 +561,11 @@ static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
|
static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
|
||||||
int64_t offset, int *total)
|
int64_t offset, int flags, int *total)
|
||||||
{
|
{
|
||||||
int async_ret = NOT_DONE;
|
int async_ret = NOT_DONE;
|
||||||
|
|
||||||
blk_aio_pwritev(blk, offset, qiov, 0, aio_rw_done, &async_ret);
|
blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
|
||||||
while (async_ret == NOT_DONE) {
|
while (async_ret == NOT_DONE) {
|
||||||
main_loop_wait(false);
|
main_loop_wait(false);
|
||||||
}
|
}
|
||||||
@ -634,7 +631,7 @@ static void read_help(void)
|
|||||||
" -b, -- read from the VM state rather than the virtual disk\n"
|
" -b, -- read from the VM state rather than the virtual disk\n"
|
||||||
" -C, -- report statistics in a machine parsable format\n"
|
" -C, -- report statistics in a machine parsable format\n"
|
||||||
" -l, -- length for pattern verification (only with -P)\n"
|
" -l, -- length for pattern verification (only with -P)\n"
|
||||||
" -p, -- allow unaligned access\n"
|
" -p, -- ignored for backwards compatibility\n"
|
||||||
" -P, -- use a pattern to verify read data\n"
|
" -P, -- use a pattern to verify read data\n"
|
||||||
" -q, -- quiet mode, do not show I/O statistics\n"
|
" -q, -- quiet mode, do not show I/O statistics\n"
|
||||||
" -s, -- start offset for pattern verification (only with -P)\n"
|
" -s, -- start offset for pattern verification (only with -P)\n"
|
||||||
@ -650,7 +647,7 @@ static const cmdinfo_t read_cmd = {
|
|||||||
.cfunc = read_f,
|
.cfunc = read_f,
|
||||||
.argmin = 2,
|
.argmin = 2,
|
||||||
.argmax = -1,
|
.argmax = -1,
|
||||||
.args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
|
.args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
|
||||||
.oneline = "reads a number of bytes at a specified offset",
|
.oneline = "reads a number of bytes at a specified offset",
|
||||||
.help = read_help,
|
.help = read_help,
|
||||||
};
|
};
|
||||||
@ -658,8 +655,8 @@ static const cmdinfo_t read_cmd = {
|
|||||||
static int read_f(BlockBackend *blk, int argc, char **argv)
|
static int read_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
|
bool Cflag = false, qflag = false, vflag = false;
|
||||||
int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
|
bool Pflag = false, sflag = false, lflag = false, bflag = false;
|
||||||
int c, cnt;
|
int c, cnt;
|
||||||
char *buf;
|
char *buf;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
@ -672,13 +669,13 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
|
while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
bflag = 1;
|
bflag = true;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
lflag = 1;
|
lflag = true;
|
||||||
pattern_count = cvtnum(optarg);
|
pattern_count = cvtnum(optarg);
|
||||||
if (pattern_count < 0) {
|
if (pattern_count < 0) {
|
||||||
print_cvtnum_err(pattern_count, optarg);
|
print_cvtnum_err(pattern_count, optarg);
|
||||||
@ -686,20 +683,20 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
pflag = 1;
|
/* Ignored for backwards compatibility */
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
Pflag = 1;
|
Pflag = true;
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
if (pattern < 0) {
|
if (pattern < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
sflag = 1;
|
sflag = true;
|
||||||
pattern_offset = cvtnum(optarg);
|
pattern_offset = cvtnum(optarg);
|
||||||
if (pattern_offset < 0) {
|
if (pattern_offset < 0) {
|
||||||
print_cvtnum_err(pattern_offset, optarg);
|
print_cvtnum_err(pattern_offset, optarg);
|
||||||
@ -707,7 +704,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
vflag = 1;
|
vflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return qemuio_command_usage(&read_cmd);
|
return qemuio_command_usage(&read_cmd);
|
||||||
@ -718,11 +715,6 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
return qemuio_command_usage(&read_cmd);
|
return qemuio_command_usage(&read_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bflag && pflag) {
|
|
||||||
printf("-b and -p cannot be specified at the same time\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = cvtnum(argv[optind]);
|
offset = cvtnum(argv[optind]);
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
print_cvtnum_err(offset, argv[optind]);
|
print_cvtnum_err(offset, argv[optind]);
|
||||||
@ -753,7 +745,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pflag) {
|
if (bflag) {
|
||||||
if (offset & 0x1ff) {
|
if (offset & 0x1ff) {
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
printf("offset %" PRId64 " is not sector aligned\n",
|
||||||
offset);
|
offset);
|
||||||
@ -844,7 +836,7 @@ static const cmdinfo_t readv_cmd = {
|
|||||||
static int readv_f(BlockBackend *blk, int argc, char **argv)
|
static int readv_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, qflag = 0, vflag = 0;
|
bool Cflag = false, qflag = false, vflag = false;
|
||||||
int c, cnt;
|
int c, cnt;
|
||||||
char *buf;
|
char *buf;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
@ -853,25 +845,25 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
int nr_iov;
|
int nr_iov;
|
||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
int pattern = 0;
|
int pattern = 0;
|
||||||
int Pflag = 0;
|
bool Pflag = false;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
Pflag = 1;
|
Pflag = true;
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
if (pattern < 0) {
|
if (pattern < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
vflag = 1;
|
vflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return qemuio_command_usage(&readv_cmd);
|
return qemuio_command_usage(&readv_cmd);
|
||||||
@ -890,12 +882,6 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if (offset & 0x1ff) {
|
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
|
||||||
offset);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr_iov = argc - optind;
|
nr_iov = argc - optind;
|
||||||
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
|
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
@ -952,10 +938,12 @@ static void write_help(void)
|
|||||||
" filled with a set pattern (0xcdcdcdcd).\n"
|
" filled with a set pattern (0xcdcdcdcd).\n"
|
||||||
" -b, -- write to the VM state rather than the virtual disk\n"
|
" -b, -- write to the VM state rather than the virtual disk\n"
|
||||||
" -c, -- write compressed data with blk_write_compressed\n"
|
" -c, -- write compressed data with blk_write_compressed\n"
|
||||||
" -p, -- allow unaligned access\n"
|
" -f, -- use Force Unit Access semantics\n"
|
||||||
|
" -p, -- ignored for backwards compatibility\n"
|
||||||
" -P, -- use different pattern to fill file\n"
|
" -P, -- use different pattern to fill file\n"
|
||||||
" -C, -- report statistics in a machine parsable format\n"
|
" -C, -- report statistics in a machine parsable format\n"
|
||||||
" -q, -- quiet mode, do not show I/O statistics\n"
|
" -q, -- quiet mode, do not show I/O statistics\n"
|
||||||
|
" -u, -- with -z, allow unmapping\n"
|
||||||
" -z, -- write zeroes using blk_co_write_zeroes\n"
|
" -z, -- write zeroes using blk_co_write_zeroes\n"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
@ -968,7 +956,7 @@ static const cmdinfo_t write_cmd = {
|
|||||||
.cfunc = write_f,
|
.cfunc = write_f,
|
||||||
.argmin = 2,
|
.argmin = 2,
|
||||||
.argmax = -1,
|
.argmax = -1,
|
||||||
.args = "[-bcCpqz] [-P pattern ] off len",
|
.args = "[-bcCfquz] [-P pattern] off len",
|
||||||
.oneline = "writes a number of bytes at a specified offset",
|
.oneline = "writes a number of bytes at a specified offset",
|
||||||
.help = write_help,
|
.help = write_help,
|
||||||
};
|
};
|
||||||
@ -976,8 +964,9 @@ static const cmdinfo_t write_cmd = {
|
|||||||
static int write_f(BlockBackend *blk, int argc, char **argv)
|
static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
|
bool Cflag = false, qflag = false, bflag = false;
|
||||||
int cflag = 0;
|
bool Pflag = false, zflag = false, cflag = false;
|
||||||
|
int flags = 0;
|
||||||
int c, cnt;
|
int c, cnt;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
@ -986,32 +975,38 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
int64_t total = 0;
|
int64_t total = 0;
|
||||||
int pattern = 0xcd;
|
int pattern = 0xcd;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "bcCpP:qz")) != -1) {
|
while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
bflag = 1;
|
bflag = true;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
cflag = 1;
|
cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
flags |= BDRV_REQ_FUA;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
pflag = 1;
|
/* Ignored for backwards compatibility */
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
Pflag = 1;
|
Pflag = true;
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
if (pattern < 0) {
|
if (pattern < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
flags |= BDRV_REQ_MAY_UNMAP;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
zflag = 1;
|
zflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return qemuio_command_usage(&write_cmd);
|
return qemuio_command_usage(&write_cmd);
|
||||||
@ -1022,8 +1017,18 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
return qemuio_command_usage(&write_cmd);
|
return qemuio_command_usage(&write_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bflag + pflag + zflag > 1) {
|
if (bflag && zflag) {
|
||||||
printf("-b, -p, or -z cannot be specified at the same time\n");
|
printf("-b and -z cannot be specified at the same time\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
|
||||||
|
printf("-f and -b or -c cannot be specified at the same time\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
|
||||||
|
printf("-u requires -z to be specified\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,7 +1054,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pflag) {
|
if (bflag || cflag) {
|
||||||
if (offset & 0x1ff) {
|
if (offset & 0x1ff) {
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
printf("offset %" PRId64 " is not sector aligned\n",
|
||||||
offset);
|
offset);
|
||||||
@ -1071,11 +1076,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
if (bflag) {
|
if (bflag) {
|
||||||
cnt = do_save_vmstate(blk, buf, offset, count, &total);
|
cnt = do_save_vmstate(blk, buf, offset, count, &total);
|
||||||
} else if (zflag) {
|
} else if (zflag) {
|
||||||
cnt = do_co_write_zeroes(blk, offset, count, &total);
|
cnt = do_co_write_zeroes(blk, offset, count, flags, &total);
|
||||||
} else if (cflag) {
|
} else if (cflag) {
|
||||||
cnt = do_write_compressed(blk, buf, offset, count, &total);
|
cnt = do_write_compressed(blk, buf, offset, count, &total);
|
||||||
} else {
|
} else {
|
||||||
cnt = do_pwrite(blk, buf, offset, count, &total);
|
cnt = do_pwrite(blk, buf, offset, count, flags, &total);
|
||||||
}
|
}
|
||||||
gettimeofday(&t2, NULL);
|
gettimeofday(&t2, NULL);
|
||||||
|
|
||||||
@ -1114,6 +1119,7 @@ writev_help(void)
|
|||||||
" filled with a set pattern (0xcdcdcdcd).\n"
|
" filled with a set pattern (0xcdcdcdcd).\n"
|
||||||
" -P, -- use different pattern to fill file\n"
|
" -P, -- use different pattern to fill file\n"
|
||||||
" -C, -- report statistics in a machine parsable format\n"
|
" -C, -- report statistics in a machine parsable format\n"
|
||||||
|
" -f, -- use Force Unit Access semantics\n"
|
||||||
" -q, -- quiet mode, do not show I/O statistics\n"
|
" -q, -- quiet mode, do not show I/O statistics\n"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
@ -1125,7 +1131,7 @@ static const cmdinfo_t writev_cmd = {
|
|||||||
.cfunc = writev_f,
|
.cfunc = writev_f,
|
||||||
.argmin = 2,
|
.argmin = 2,
|
||||||
.argmax = -1,
|
.argmax = -1,
|
||||||
.args = "[-Cq] [-P pattern ] off len [len..]",
|
.args = "[-Cfq] [-P pattern] off len [len..]",
|
||||||
.oneline = "writes a number of bytes at a specified offset",
|
.oneline = "writes a number of bytes at a specified offset",
|
||||||
.help = writev_help,
|
.help = writev_help,
|
||||||
};
|
};
|
||||||
@ -1133,7 +1139,8 @@ static const cmdinfo_t writev_cmd = {
|
|||||||
static int writev_f(BlockBackend *blk, int argc, char **argv)
|
static int writev_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, qflag = 0;
|
bool Cflag = false, qflag = false;
|
||||||
|
int flags = 0;
|
||||||
int c, cnt;
|
int c, cnt;
|
||||||
char *buf;
|
char *buf;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
@ -1146,10 +1153,13 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
while ((c = getopt(argc, argv, "CqP:")) != -1) {
|
while ((c = getopt(argc, argv, "CqP:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
flags |= BDRV_REQ_FUA;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
@ -1173,12 +1183,6 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if (offset & 0x1ff) {
|
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
|
||||||
offset);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr_iov = argc - optind;
|
nr_iov = argc - optind;
|
||||||
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
|
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
@ -1186,7 +1190,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday(&t1, NULL);
|
gettimeofday(&t1, NULL);
|
||||||
cnt = do_aio_writev(blk, &qiov, offset, &total);
|
cnt = do_aio_writev(blk, &qiov, offset, flags, &total);
|
||||||
gettimeofday(&t2, NULL);
|
gettimeofday(&t2, NULL);
|
||||||
|
|
||||||
if (cnt < 0) {
|
if (cnt < 0) {
|
||||||
@ -1242,7 +1246,7 @@ static const cmdinfo_t multiwrite_cmd = {
|
|||||||
static int multiwrite_f(BlockBackend *blk, int argc, char **argv)
|
static int multiwrite_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, qflag = 0;
|
bool Cflag = false, qflag = false;
|
||||||
int c, cnt;
|
int c, cnt;
|
||||||
char **buf;
|
char **buf;
|
||||||
int64_t offset, first_offset = 0;
|
int64_t offset, first_offset = 0;
|
||||||
@ -1258,10 +1262,10 @@ static int multiwrite_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
while ((c = getopt(argc, argv, "CqP:")) != -1) {
|
while ((c = getopt(argc, argv, "CqP:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
@ -1371,11 +1375,11 @@ struct aio_ctx {
|
|||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
char *buf;
|
char *buf;
|
||||||
int qflag;
|
bool qflag;
|
||||||
int vflag;
|
bool vflag;
|
||||||
int Cflag;
|
bool Cflag;
|
||||||
int Pflag;
|
bool Pflag;
|
||||||
int zflag;
|
bool zflag;
|
||||||
BlockAcctCookie acct;
|
BlockAcctCookie acct;
|
||||||
int pattern;
|
int pattern;
|
||||||
struct timeval t1;
|
struct timeval t1;
|
||||||
@ -1498,10 +1502,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
ctx->Cflag = 1;
|
ctx->Cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
ctx->Pflag = 1;
|
ctx->Pflag = true;
|
||||||
ctx->pattern = parse_pattern(optarg);
|
ctx->pattern = parse_pattern(optarg);
|
||||||
if (ctx->pattern < 0) {
|
if (ctx->pattern < 0) {
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
@ -1509,10 +1513,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
ctx->qflag = 1;
|
ctx->qflag = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
ctx->vflag = 1;
|
ctx->vflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
@ -1533,14 +1537,6 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if (ctx->offset & 0x1ff) {
|
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
|
||||||
ctx->offset);
|
|
||||||
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
|
|
||||||
g_free(ctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr_iov = argc - optind;
|
nr_iov = argc - optind;
|
||||||
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
|
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
|
||||||
if (ctx->buf == NULL) {
|
if (ctx->buf == NULL) {
|
||||||
@ -1572,7 +1568,9 @@ static void aio_write_help(void)
|
|||||||
" used to ensure all outstanding aio requests have been completed.\n"
|
" used to ensure all outstanding aio requests have been completed.\n"
|
||||||
" -P, -- use different pattern to fill file\n"
|
" -P, -- use different pattern to fill file\n"
|
||||||
" -C, -- report statistics in a machine parsable format\n"
|
" -C, -- report statistics in a machine parsable format\n"
|
||||||
|
" -f, -- use Force Unit Access semantics\n"
|
||||||
" -q, -- quiet mode, do not show I/O statistics\n"
|
" -q, -- quiet mode, do not show I/O statistics\n"
|
||||||
|
" -u, -- with -z, allow unmapping\n"
|
||||||
" -z, -- write zeroes using blk_aio_write_zeroes\n"
|
" -z, -- write zeroes using blk_aio_write_zeroes\n"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
@ -1584,7 +1582,7 @@ static const cmdinfo_t aio_write_cmd = {
|
|||||||
.cfunc = aio_write_f,
|
.cfunc = aio_write_f,
|
||||||
.argmin = 2,
|
.argmin = 2,
|
||||||
.argmax = -1,
|
.argmax = -1,
|
||||||
.args = "[-Cqz] [-P pattern ] off len [len..]",
|
.args = "[-Cfquz] [-P pattern] off len [len..]",
|
||||||
.oneline = "asynchronously writes a number of bytes",
|
.oneline = "asynchronously writes a number of bytes",
|
||||||
.help = aio_write_help,
|
.help = aio_write_help,
|
||||||
};
|
};
|
||||||
@ -1594,15 +1592,22 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
int nr_iov, c;
|
int nr_iov, c;
|
||||||
int pattern = 0xcd;
|
int pattern = 0xcd;
|
||||||
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
|
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
ctx->blk = blk;
|
ctx->blk = blk;
|
||||||
while ((c = getopt(argc, argv, "CqP:z")) != -1) {
|
while ((c = getopt(argc, argv, "CfqP:z")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
ctx->Cflag = 1;
|
ctx->Cflag = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
flags |= BDRV_REQ_FUA;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
ctx->qflag = 1;
|
ctx->qflag = true;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
flags |= BDRV_REQ_MAY_UNMAP;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
pattern = parse_pattern(optarg);
|
pattern = parse_pattern(optarg);
|
||||||
@ -1612,7 +1617,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
ctx->zflag = 1;
|
ctx->zflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
@ -1631,6 +1636,11 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
|
||||||
|
printf("-u requires -z to be specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->zflag && ctx->Pflag) {
|
if (ctx->zflag && ctx->Pflag) {
|
||||||
printf("-z and -P cannot be specified at the same time\n");
|
printf("-z and -P cannot be specified at the same time\n");
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
@ -1645,14 +1655,6 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if (ctx->offset & 0x1ff) {
|
|
||||||
printf("offset %" PRId64 " is not sector aligned\n",
|
|
||||||
ctx->offset);
|
|
||||||
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
|
|
||||||
g_free(ctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->zflag) {
|
if (ctx->zflag) {
|
||||||
int64_t count = cvtnum(argv[optind]);
|
int64_t count = cvtnum(argv[optind]);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
@ -1662,7 +1664,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->qiov.size = count;
|
ctx->qiov.size = count;
|
||||||
blk_aio_write_zeroes(blk, ctx->offset, count, 0, aio_write_done, ctx);
|
blk_aio_write_zeroes(blk, ctx->offset, count, flags, aio_write_done,
|
||||||
|
ctx);
|
||||||
} else {
|
} else {
|
||||||
nr_iov = argc - optind;
|
nr_iov = argc - optind;
|
||||||
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
|
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
|
||||||
@ -1677,7 +1680,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
|
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
|
||||||
BLOCK_ACCT_WRITE);
|
BLOCK_ACCT_WRITE);
|
||||||
|
|
||||||
blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, 0, aio_write_done, ctx);
|
blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
|
||||||
|
ctx);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1841,17 +1845,17 @@ static const cmdinfo_t discard_cmd = {
|
|||||||
static int discard_f(BlockBackend *blk, int argc, char **argv)
|
static int discard_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
int Cflag = 0, qflag = 0;
|
bool Cflag = false, qflag = false;
|
||||||
int c, ret;
|
int c, ret;
|
||||||
int64_t offset, count;
|
int64_t offset, count;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "Cq")) != -1) {
|
while ((c = getopt(argc, argv, "Cq")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
Cflag = 1;
|
Cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return qemuio_command_usage(&discard_cmd);
|
return qemuio_command_usage(&discard_cmd);
|
||||||
|
40
qemu-io.c
40
qemu-io.c
@ -101,12 +101,15 @@ static void open_help(void)
|
|||||||
" opens a new file in the requested mode\n"
|
" opens a new file in the requested mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Example:\n"
|
" Example:\n"
|
||||||
" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
|
" 'open -n -o driver=raw /tmp/data' - opens raw data file read-write, uncached\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Opens a file for subsequent use by all of the other qemu-io commands.\n"
|
" Opens a file for subsequent use by all of the other qemu-io commands.\n"
|
||||||
" -r, -- open file read-only\n"
|
" -r, -- open file read-only\n"
|
||||||
" -s, -- use snapshot file\n"
|
" -s, -- use snapshot file\n"
|
||||||
" -n, -- disable host cache\n"
|
" -n, -- disable host cache, short for -t none\n"
|
||||||
|
" -k, -- use kernel AIO implementation (on Linux only)\n"
|
||||||
|
" -t, -- use the given cache mode for the image\n"
|
||||||
|
" -d, -- use the given discard mode for the image\n"
|
||||||
" -o, -- options to be given to the block driver"
|
" -o, -- options to be given to the block driver"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
@ -120,7 +123,7 @@ static const cmdinfo_t open_cmd = {
|
|||||||
.argmin = 1,
|
.argmin = 1,
|
||||||
.argmax = -1,
|
.argmax = -1,
|
||||||
.flags = CMD_NOFILE_OK,
|
.flags = CMD_NOFILE_OK,
|
||||||
.args = "[-Crsn] [-o options] [path]",
|
.args = "[-rsnk] [-t cache] [-d discard] [-o options] [path]",
|
||||||
.oneline = "open the file specified by path",
|
.oneline = "open the file specified by path",
|
||||||
.help = open_help,
|
.help = open_help,
|
||||||
};
|
};
|
||||||
@ -137,14 +140,14 @@ static QemuOptsList empty_opts = {
|
|||||||
|
|
||||||
static int open_f(BlockBackend *blk, int argc, char **argv)
|
static int open_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = BDRV_O_UNMAP;
|
||||||
int readonly = 0;
|
int readonly = 0;
|
||||||
bool writethrough = true;
|
bool writethrough = true;
|
||||||
int c;
|
int c;
|
||||||
QemuOpts *qopts;
|
QemuOpts *qopts;
|
||||||
QDict *opts;
|
QDict *opts;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "snrgo:")) != -1) {
|
while ((c = getopt(argc, argv, "snro:kt:d:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 's':
|
case 's':
|
||||||
flags |= BDRV_O_SNAPSHOT;
|
flags |= BDRV_O_SNAPSHOT;
|
||||||
@ -156,9 +159,27 @@ static int open_f(BlockBackend *blk, int argc, char **argv)
|
|||||||
case 'r':
|
case 'r':
|
||||||
readonly = 1;
|
readonly = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'k':
|
||||||
|
flags |= BDRV_O_NATIVE_AIO;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
|
||||||
|
error_report("Invalid cache option: %s", optarg);
|
||||||
|
qemu_opts_reset(&empty_opts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (bdrv_parse_discard_flags(optarg, &flags) < 0) {
|
||||||
|
error_report("Invalid discard option: %s", optarg);
|
||||||
|
qemu_opts_reset(&empty_opts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (imageOpts) {
|
if (imageOpts) {
|
||||||
printf("--image-opts and 'open -o' are mutually exclusive\n");
|
printf("--image-opts and 'open -o' are mutually exclusive\n");
|
||||||
|
qemu_opts_reset(&empty_opts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) {
|
if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) {
|
||||||
@ -216,20 +237,22 @@ static const cmdinfo_t quit_cmd = {
|
|||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n"
|
"Usage: %s [OPTIONS]... [-c STRING]... [file]\n"
|
||||||
"QEMU Disk exerciser\n"
|
"QEMU Disk exerciser\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --object OBJECTDEF define an object such as 'secret' for\n"
|
" --object OBJECTDEF define an object such as 'secret' for\n"
|
||||||
" passwords and/or encryption keys\n"
|
" passwords and/or encryption keys\n"
|
||||||
|
" --image-opts treat file as option string\n"
|
||||||
" -c, --cmd STRING execute command with its arguments\n"
|
" -c, --cmd STRING execute command with its arguments\n"
|
||||||
" from the given string\n"
|
" from the given string\n"
|
||||||
" -f, --format FMT specifies the block driver to use\n"
|
" -f, --format FMT specifies the block driver to use\n"
|
||||||
" -r, --read-only export read-only\n"
|
" -r, --read-only export read-only\n"
|
||||||
" -s, --snapshot use snapshot file\n"
|
" -s, --snapshot use snapshot file\n"
|
||||||
" -n, --nocache disable host cache\n"
|
" -n, --nocache disable host cache, short for -t none\n"
|
||||||
" -m, --misalign misalign allocations for O_DIRECT\n"
|
" -m, --misalign misalign allocations for O_DIRECT\n"
|
||||||
" -k, --native-aio use kernel AIO implementation (on Linux only)\n"
|
" -k, --native-aio use kernel AIO implementation (on Linux only)\n"
|
||||||
" -t, --cache=MODE use the given cache mode for the image\n"
|
" -t, --cache=MODE use the given cache mode for the image\n"
|
||||||
|
" -d, --discard=MODE use the given discard mode for the image\n"
|
||||||
" -T, --trace FILE enable trace events listed in the given file\n"
|
" -T, --trace FILE enable trace events listed in the given file\n"
|
||||||
" -h, --help display this help and exit\n"
|
" -h, --help display this help and exit\n"
|
||||||
" -V, --version output version information and exit\n"
|
" -V, --version output version information and exit\n"
|
||||||
@ -410,11 +433,10 @@ static QemuOptsList file_opts = {
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int readonly = 0;
|
int readonly = 0;
|
||||||
const char *sopt = "hVc:d:f:rsnmgkt:T:";
|
const char *sopt = "hVc:d:f:rsnmkt:T:";
|
||||||
const struct option lopt[] = {
|
const struct option lopt[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
{ "offset", required_argument, NULL, 'o' },
|
|
||||||
{ "cmd", required_argument, NULL, 'c' },
|
{ "cmd", required_argument, NULL, 'c' },
|
||||||
{ "format", required_argument, NULL, 'f' },
|
{ "format", required_argument, NULL, 'f' },
|
||||||
{ "read-only", no_argument, NULL, 'r' },
|
{ "read-only", no_argument, NULL, 'r' },
|
||||||
|
@ -4395,6 +4395,59 @@ Example:
|
|||||||
|
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "x-blockdev-change",
|
||||||
|
.args_type = "parent:B,child:B?,node:B?",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_x_blockdev_change,
|
||||||
|
},
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
x-blockdev-change
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Dynamically reconfigure the block driver state graph. It can be used
|
||||||
|
to add, remove, insert or replace a graph node. Currently only the
|
||||||
|
Quorum driver implements this feature to add or remove its child. This
|
||||||
|
is useful to fix a broken quorum child.
|
||||||
|
|
||||||
|
If @node is specified, it will be inserted under @parent. @child
|
||||||
|
may not be specified in this case. If both @parent and @child are
|
||||||
|
specified but @node is not, @child will be detached from @parent.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- "parent": the id or name of the parent node (json-string)
|
||||||
|
- "child": the name of a child under the given parent node (json-string, optional)
|
||||||
|
- "node": the name of the node that will be added (json-string, optional)
|
||||||
|
|
||||||
|
Note: this command is experimental, and not a stable API. It doesn't
|
||||||
|
support all kinds of operations, all kinds of children, nor all block
|
||||||
|
drivers.
|
||||||
|
|
||||||
|
Warning: The data in a new quorum child MUST be consistent with that of
|
||||||
|
the rest of the array.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Add a new node to a quorum
|
||||||
|
-> { "execute": "blockdev-add",
|
||||||
|
"arguments": { "options": { "driver": "raw",
|
||||||
|
"node-name": "new_node",
|
||||||
|
"file": { "driver": "file",
|
||||||
|
"filename": "test.raw" } } } }
|
||||||
|
<- { "return": {} }
|
||||||
|
-> { "execute": "x-blockdev-change",
|
||||||
|
"arguments": { "parent": "disk1",
|
||||||
|
"node": "new_node" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
|
Delete a quorum's node
|
||||||
|
-> { "execute": "x-blockdev-change",
|
||||||
|
"arguments": { "parent": "disk1",
|
||||||
|
"child": "children.1" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
. ./common.rc
|
. ./common.rc
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx
|
_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx luks
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
@ -43,13 +43,16 @@ _supported_fmt generic
|
|||||||
_supported_proto file
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
# Remove once all tests are fixed to use TEST_IMG_FILE
|
||||||
|
# correctly and common.rc sets it unconditionally
|
||||||
|
test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG
|
||||||
|
|
||||||
size=128M
|
size=128M
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== mark image read-only"
|
echo "== mark image read-only"
|
||||||
chmod a-w "$TEST_IMG"
|
chmod a-w "$TEST_IMG_FILE"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== read from read-only image"
|
echo "== read from read-only image"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,9 +12,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x1
|
incompatible_features 0x1
|
||||||
ERROR cluster 5 refcount=0 reference=1
|
ERROR cluster 5 refcount=0 reference=1
|
||||||
@ -51,9 +51,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x1
|
incompatible_features 0x1
|
||||||
ERROR cluster 5 refcount=0 reference=1
|
ERROR cluster 5 refcount=0 reference=1
|
||||||
@ -69,9 +69,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x0
|
incompatible_features 0x0
|
||||||
No errors were found on the image.
|
No errors were found on the image.
|
||||||
@ -92,9 +92,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x1
|
incompatible_features 0x1
|
||||||
ERROR cluster 5 refcount=0 reference=1
|
ERROR cluster 5 refcount=0 reference=1
|
||||||
@ -106,9 +106,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x0
|
incompatible_features 0x0
|
||||||
No errors were found on the image.
|
No errors were found on the image.
|
||||||
|
@ -31,13 +31,13 @@ _cleanup()
|
|||||||
{
|
{
|
||||||
echo "Cleanup"
|
echo "Cleanup"
|
||||||
_cleanup_test_img
|
_cleanup_test_img
|
||||||
rm "${TEST_IMG2}"
|
rm "${TEST_IMG_FILE2}"
|
||||||
}
|
}
|
||||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
_compare()
|
_compare()
|
||||||
{
|
{
|
||||||
$QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}"
|
$QEMU_IMG compare $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" "${TEST_IMG2}"
|
||||||
echo $?
|
echo $?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,25 +46,37 @@ _compare()
|
|||||||
. ./common.filter
|
. ./common.filter
|
||||||
. ./common.pattern
|
. ./common.pattern
|
||||||
|
|
||||||
_supported_fmt raw qcow qcow2 qed
|
_supported_fmt raw qcow qcow2 qed luks
|
||||||
_supported_proto file
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
# Remove once all tests are fixed to use TEST_IMG_FILE
|
||||||
|
# correctly and common.rc sets it unconditionally
|
||||||
|
test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG
|
||||||
|
|
||||||
# Setup test basic parameters
|
# Setup test basic parameters
|
||||||
TEST_IMG2=$TEST_IMG.2
|
TEST_IMG2=$TEST_IMG.2
|
||||||
|
TEST_IMG_FILE2=$TEST_IMG_FILE.2
|
||||||
CLUSTER_SIZE=4096
|
CLUSTER_SIZE=4096
|
||||||
size=1024M
|
size=128M
|
||||||
|
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45
|
io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45
|
||||||
|
|
||||||
# Compare identical images
|
# Compare identical images
|
||||||
cp "$TEST_IMG" "${TEST_IMG2}"
|
cp "$TEST_IMG_FILE" "${TEST_IMG_FILE2}"
|
||||||
_compare
|
_compare
|
||||||
_compare -q
|
_compare -q
|
||||||
|
|
||||||
# Compare images with different size
|
# Compare images with different size
|
||||||
$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +512M
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
$QEMU_IMG resize $QEMU_IMG_EXTRA_ARGS "$TEST_IMG" +32M
|
||||||
|
else
|
||||||
|
$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +32M
|
||||||
|
fi
|
||||||
|
# Ensure extended space is zero-initialized
|
||||||
|
$QEMU_IO "$TEST_IMG" -c "write -z $size 32M" | _filter_qemu_io
|
||||||
|
|
||||||
_compare
|
_compare
|
||||||
_compare -s
|
_compare -s
|
||||||
|
|
||||||
@ -77,7 +89,7 @@ _compare
|
|||||||
# Test unaligned case of mismatch offsets in allocated clusters
|
# Test unaligned case of mismatch offsets in allocated clusters
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
io_pattern write 0 512 0 1 100
|
io_pattern write 0 512 0 1 100
|
||||||
cp "$TEST_IMG" "$TEST_IMG2"
|
cp "$TEST_IMG_FILE" "$TEST_IMG_FILE2"
|
||||||
io_pattern write 512 512 0 1 101
|
io_pattern write 512 512 0 1 101
|
||||||
_compare
|
_compare
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
QA output created by 048
|
QA output created by 048
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
=== IO: pattern 45
|
=== IO: pattern 45
|
||||||
wrote 4096/4096 bytes at offset 524288
|
wrote 4096/4096 bytes at offset 524288
|
||||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -13,6 +13,8 @@ Images are identical.
|
|||||||
0
|
0
|
||||||
0
|
0
|
||||||
Image resized.
|
Image resized.
|
||||||
|
wrote 33554432/33554432 bytes at offset 134217728
|
||||||
|
32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
Warning: Image size mismatch!
|
Warning: Image size mismatch!
|
||||||
Images are identical.
|
Images are identical.
|
||||||
0
|
0
|
||||||
@ -28,7 +30,7 @@ wrote 4096/4096 bytes at offset 0
|
|||||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
Content mismatch at offset 0!
|
Content mismatch at offset 0!
|
||||||
1
|
1
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
=== IO: pattern 100
|
=== IO: pattern 100
|
||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
@ -47,6 +47,10 @@ _supported_cache_modes "writeback" "writethrough" "unsafe"
|
|||||||
size=128M
|
size=128M
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== initializing whole image =="
|
||||||
|
$QEMU_IO -c "write -z 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== reading whole image =="
|
echo "== reading whole image =="
|
||||||
$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
QA output created by 052
|
QA output created by 052
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
|
||||||
|
== initializing whole image ==
|
||||||
|
wrote 134217728/134217728 bytes at offset 0
|
||||||
|
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
== reading whole image ==
|
== reading whole image ==
|
||||||
read 134217728/134217728 bytes at offset 0
|
read 134217728/134217728 bytes at offset 0
|
||||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
@ -58,9 +58,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
|||||||
wrote 131072/131072 bytes at offset 0
|
wrote 131072/131072 bytes at offset 0
|
||||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
magic 0x514649fb
|
magic 0x514649fb
|
||||||
version 3
|
version 3
|
||||||
@ -220,9 +220,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
|||||||
wrote 131072/131072 bytes at offset 0
|
wrote 131072/131072 bytes at offset 0
|
||||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
magic 0x514649fb
|
magic 0x514649fb
|
||||||
version 3
|
version 3
|
||||||
|
@ -43,7 +43,7 @@ choose_tcp_port() {
|
|||||||
|
|
||||||
wait_for_tcp_port() {
|
wait_for_tcp_port() {
|
||||||
while ! (netstat --tcp --listening --numeric | \
|
while ! (netstat --tcp --listening --numeric | \
|
||||||
grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") 2>&1 >/dev/null; do
|
grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") >/dev/null 2>&1; do
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ EOF
|
|||||||
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
|
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null &
|
$PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" >/dev/null 2>&1 &
|
||||||
wait_for_tcp_port "127\\.0\\.0\\.1:$port"
|
wait_for_tcp_port "127\\.0\\.0\\.1:$port"
|
||||||
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
|
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ size=128M
|
|||||||
echo
|
echo
|
||||||
echo "== Single request =="
|
echo "== Single request =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 0 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 0 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -59,6 +60,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Sequential requests =="
|
echo "== Sequential requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 12k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 0 4k ; 4k 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 0 4k ; 4k 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -72,6 +74,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Superset overlapping requests =="
|
echo "== Superset overlapping requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 0 4k ; 1k 2k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 0 4k ; 1k 2k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -87,6 +90,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Subset overlapping requests =="
|
echo "== Subset overlapping requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 1k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 1k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -102,6 +106,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Head overlapping requests =="
|
echo "== Head overlapping requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 0k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 0k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -116,6 +121,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Tail overlapping requests =="
|
echo "== Tail overlapping requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 2k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 2k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -130,6 +136,7 @@ _cleanup_test_img
|
|||||||
echo
|
echo
|
||||||
echo "== Disjoint requests =="
|
echo "== Disjoint requests =="
|
||||||
_make_test_img $size
|
_make_test_img $size
|
||||||
|
$QEMU_IO -c "write -z 0 72k" "$TEST_IMG" | _filter_qemu_io
|
||||||
$QEMU_IO -c "multiwrite 0 4k ; 64k 4k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "multiwrite 0 4k ; 64k 4k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
@ -2,6 +2,8 @@ QA output created by 100
|
|||||||
|
|
||||||
== Single request ==
|
== Single request ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 8192/8192 bytes at offset 0
|
||||||
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 4096/4096 bytes at offset 0
|
wrote 4096/4096 bytes at offset 0
|
||||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -13,6 +15,8 @@ read 4096/4096 bytes at offset 4096
|
|||||||
|
|
||||||
== Sequential requests ==
|
== Sequential requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 12288/12288 bytes at offset 0
|
||||||
|
12 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 8192/8192 bytes at offset 0
|
wrote 8192/8192 bytes at offset 0
|
||||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -26,6 +30,8 @@ read 4096/4096 bytes at offset 8192
|
|||||||
|
|
||||||
== Superset overlapping requests ==
|
== Superset overlapping requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 8192/8192 bytes at offset 0
|
||||||
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 6144/6144 bytes at offset 0
|
wrote 6144/6144 bytes at offset 0
|
||||||
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -39,6 +45,8 @@ read 4096/4096 bytes at offset 4096
|
|||||||
|
|
||||||
== Subset overlapping requests ==
|
== Subset overlapping requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 8192/8192 bytes at offset 0
|
||||||
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 6144/6144 bytes at offset 1024
|
wrote 6144/6144 bytes at offset 1024
|
||||||
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -52,6 +60,8 @@ read 4096/4096 bytes at offset 4096
|
|||||||
|
|
||||||
== Head overlapping requests ==
|
== Head overlapping requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 8192/8192 bytes at offset 0
|
||||||
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 6144/6144 bytes at offset 0
|
wrote 6144/6144 bytes at offset 0
|
||||||
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -63,6 +73,8 @@ read 4096/4096 bytes at offset 4096
|
|||||||
|
|
||||||
== Tail overlapping requests ==
|
== Tail overlapping requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 8192/8192 bytes at offset 0
|
||||||
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 6144/6144 bytes at offset 2048
|
wrote 6144/6144 bytes at offset 2048
|
||||||
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
@ -74,6 +86,8 @@ read 4096/4096 bytes at offset 4096
|
|||||||
|
|
||||||
== Disjoint requests ==
|
== Disjoint requests ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
|
wrote 73728/73728 bytes at offset 0
|
||||||
|
72 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 8192/8192 bytes at offset 0
|
wrote 8192/8192 bytes at offset 0
|
||||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
@ -32,9 +32,9 @@ Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of t
|
|||||||
wrote 512/512 bytes at offset 0
|
wrote 512/512 bytes at offset 0
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||||
fi )
|
fi )
|
||||||
incompatible_features 0x0
|
incompatible_features 0x0
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
|
@ -53,6 +53,8 @@ export QEMU_IO_OPTIONS=""
|
|||||||
export CACHEMODE_IS_DEFAULT=true
|
export CACHEMODE_IS_DEFAULT=true
|
||||||
export QEMU_OPTIONS="-nodefaults"
|
export QEMU_OPTIONS="-nodefaults"
|
||||||
export VALGRIND_QEMU=
|
export VALGRIND_QEMU=
|
||||||
|
export IMGKEYSECRET=
|
||||||
|
export IMGOPTSSYNTAX=false
|
||||||
|
|
||||||
for r
|
for r
|
||||||
do
|
do
|
||||||
@ -207,6 +209,13 @@ testlist options
|
|||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-luks)
|
||||||
|
IMGOPTSSYNTAX=true
|
||||||
|
IMGFMT=luks
|
||||||
|
IMGKEYSECRET=123456
|
||||||
|
xpand=false
|
||||||
|
;;
|
||||||
|
|
||||||
-qed)
|
-qed)
|
||||||
IMGFMT=qed
|
IMGFMT=qed
|
||||||
xpand=false
|
xpand=false
|
||||||
@ -399,7 +408,11 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Set qemu-io cache mode with $CACHEMODE we have
|
# Set qemu-io cache mode with $CACHEMODE we have
|
||||||
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
|
||||||
|
else
|
||||||
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
|
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
|
||||||
|
fi
|
||||||
|
|
||||||
# Set default options for qemu-img create -o if they were not specified
|
# Set default options for qemu-img create -o if they were not specified
|
||||||
_set_default_imgopts
|
_set_default_imgopts
|
||||||
|
@ -123,12 +123,19 @@ _qemu_img_wrapper()
|
|||||||
_qemu_io_wrapper()
|
_qemu_io_wrapper()
|
||||||
{
|
{
|
||||||
local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
|
local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
|
||||||
|
local QEMU_IO_ARGS="$QEMU_IO_OPTIONS"
|
||||||
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS"
|
||||||
|
if [ -n "$IMGKEYSECRET" ]; then
|
||||||
|
QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
local RETVAL
|
local RETVAL
|
||||||
(
|
(
|
||||||
if [ "${VALGRIND_QEMU}" == "y" ]; then
|
if [ "${VALGRIND_QEMU}" == "y" ]; then
|
||||||
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
|
exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
|
||||||
else
|
else
|
||||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
|
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
|
||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
@ -154,6 +161,16 @@ export QEMU_IMG=_qemu_img_wrapper
|
|||||||
export QEMU_IO=_qemu_io_wrapper
|
export QEMU_IO=_qemu_io_wrapper
|
||||||
export QEMU_NBD=_qemu_nbd_wrapper
|
export QEMU_NBD=_qemu_nbd_wrapper
|
||||||
|
|
||||||
|
QEMU_IMG_EXTRA_ARGS=
|
||||||
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS"
|
||||||
|
if [ -n "$IMGKEYSECRET" ]; then
|
||||||
|
QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
export QEMU_IMG_EXTRA_ARGS
|
||||||
|
|
||||||
|
|
||||||
default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p')
|
default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p')
|
||||||
default_alias_machine=$($QEMU -machine help | \
|
default_alias_machine=$($QEMU -machine help | \
|
||||||
sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }")
|
sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }")
|
||||||
|
@ -98,7 +98,8 @@ _filter_img_create()
|
|||||||
-e "s# block_state_zero=\\(on\\|off\\)##g" \
|
-e "s# block_state_zero=\\(on\\|off\\)##g" \
|
||||||
-e "s# log_size=[0-9]\\+##g" \
|
-e "s# log_size=[0-9]\\+##g" \
|
||||||
-e "s/archipelago:a/TEST_DIR\//g" \
|
-e "s/archipelago:a/TEST_DIR\//g" \
|
||||||
-e "s# refcount_bits=[0-9]\\+##g"
|
-e "s# refcount_bits=[0-9]\\+##g" \
|
||||||
|
-e "s# key-secret=[a-zA-Z0-9]\\+##g"
|
||||||
}
|
}
|
||||||
|
|
||||||
_filter_img_info()
|
_filter_img_info()
|
||||||
|
@ -53,6 +53,29 @@ fi
|
|||||||
# make sure we have a standard umask
|
# make sure we have a standard umask
|
||||||
umask 022
|
umask 022
|
||||||
|
|
||||||
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
DRIVER="driver=$IMGFMT"
|
||||||
|
if [ "$IMGFMT" = "luks" ]; then
|
||||||
|
DRIVER="$DRIVER,key-secret=keysec0"
|
||||||
|
fi
|
||||||
|
if [ "$IMGPROTO" = "file" ]; then
|
||||||
|
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||||
|
TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT"
|
||||||
|
elif [ "$IMGPROTO" = "nbd" ]; then
|
||||||
|
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||||
|
TEST_IMG="$DRIVER,file.driver=nbd,file.host=127.0.0.1,file.port=10810"
|
||||||
|
elif [ "$IMGPROTO" = "ssh" ]; then
|
||||||
|
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||||
|
TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE"
|
||||||
|
elif [ "$IMGPROTO" = "nfs" ]; then
|
||||||
|
TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR"
|
||||||
|
TEST_IMG=$TEST_DIR_OPTS/t.$IMGFMT
|
||||||
|
elif [ "$IMGPROTO" = "archipelago" ]; then
|
||||||
|
TEST_IMG="$DRIVER,file.driver=archipelago,file.volume=:at.$IMGFMT"
|
||||||
|
else
|
||||||
|
TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT"
|
||||||
|
fi
|
||||||
|
else
|
||||||
if [ "$IMGPROTO" = "file" ]; then
|
if [ "$IMGPROTO" = "file" ]; then
|
||||||
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
||||||
elif [ "$IMGPROTO" = "nbd" ]; then
|
elif [ "$IMGPROTO" = "nbd" ]; then
|
||||||
@ -69,6 +92,7 @@ elif [ "$IMGPROTO" = "archipelago" ]; then
|
|||||||
else
|
else
|
||||||
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
_optstr_add()
|
_optstr_add()
|
||||||
{
|
{
|
||||||
@ -108,6 +132,7 @@ _make_test_img()
|
|||||||
local img_name=""
|
local img_name=""
|
||||||
local use_backing=0
|
local use_backing=0
|
||||||
local backing_file=""
|
local backing_file=""
|
||||||
|
local object_options=""
|
||||||
|
|
||||||
if [ -n "$TEST_IMG_FILE" ]; then
|
if [ -n "$TEST_IMG_FILE" ]; then
|
||||||
img_name=$TEST_IMG_FILE
|
img_name=$TEST_IMG_FILE
|
||||||
@ -118,6 +143,10 @@ _make_test_img()
|
|||||||
if [ -n "$IMGOPTS" ]; then
|
if [ -n "$IMGOPTS" ]; then
|
||||||
optstr=$(_optstr_add "$optstr" "$IMGOPTS")
|
optstr=$(_optstr_add "$optstr" "$IMGOPTS")
|
||||||
fi
|
fi
|
||||||
|
if [ -n "$IMGKEYSECRET" ]; then
|
||||||
|
object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
|
||||||
|
optstr=$(_optstr_add "$optstr" "key-secret=keysec0")
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$1" = "-b" ]; then
|
if [ "$1" = "-b" ]; then
|
||||||
use_backing=1
|
use_backing=1
|
||||||
@ -135,9 +164,9 @@ _make_test_img()
|
|||||||
# XXX(hch): have global image options?
|
# XXX(hch): have global image options?
|
||||||
(
|
(
|
||||||
if [ $use_backing = 1 ]; then
|
if [ $use_backing = 1 ]; then
|
||||||
$QEMU_IMG create -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
|
$QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
|
||||||
else
|
else
|
||||||
$QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
|
$QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
|
||||||
fi
|
fi
|
||||||
) | _filter_img_create
|
) | _filter_img_create
|
||||||
|
|
||||||
@ -199,7 +228,13 @@ _cleanup_test_img()
|
|||||||
|
|
||||||
_check_test_img()
|
_check_test_img()
|
||||||
{
|
{
|
||||||
$QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \
|
(
|
||||||
|
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||||
|
$QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1
|
||||||
|
else
|
||||||
|
$QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
|
||||||
|
fi
|
||||||
|
) | _filter_testdir | \
|
||||||
sed -e '/allocated.*fragmented.*compressed clusters/d' \
|
sed -e '/allocated.*fragmented.*compressed clusters/d' \
|
||||||
-e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
|
-e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
|
||||||
-e '/Image end offset: [0-9]\+/d'
|
-e '/Image end offset: [0-9]\+/d'
|
||||||
|
@ -47,7 +47,7 @@ if os.environ.get('QEMU_OPTIONS'):
|
|||||||
|
|
||||||
imgfmt = os.environ.get('IMGFMT', 'raw')
|
imgfmt = os.environ.get('IMGFMT', 'raw')
|
||||||
imgproto = os.environ.get('IMGPROTO', 'file')
|
imgproto = os.environ.get('IMGPROTO', 'file')
|
||||||
test_dir = os.environ.get('TEST_DIR', '/var/tmp')
|
test_dir = os.environ.get('TEST_DIR')
|
||||||
output_dir = os.environ.get('OUTPUT_DIR', '.')
|
output_dir = os.environ.get('OUTPUT_DIR', '.')
|
||||||
cachemode = os.environ.get('CACHEMODE')
|
cachemode = os.environ.get('CACHEMODE')
|
||||||
qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
|
qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
|
||||||
@ -461,6 +461,14 @@ def verify_quorum():
|
|||||||
def main(supported_fmts=[], supported_oses=['linux']):
|
def main(supported_fmts=[], supported_oses=['linux']):
|
||||||
'''Run tests'''
|
'''Run tests'''
|
||||||
|
|
||||||
|
# We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
|
||||||
|
# indicate that we're not being run via "check". There may be
|
||||||
|
# other things set up by "check" that individual test cases rely
|
||||||
|
# on.
|
||||||
|
if test_dir is None or qemu_default_machine is None:
|
||||||
|
sys.stderr.write('Please run this test via the "check" script\n')
|
||||||
|
sys.exit(os.EX_USAGE)
|
||||||
|
|
||||||
debug = '-d' in sys.argv
|
debug = '-d' in sys.argv
|
||||||
verbosity = 1
|
verbosity = 1
|
||||||
verify_image_format(supported_fmts)
|
verify_image_format(supported_fmts)
|
||||||
|
Loading…
Reference in New Issue
Block a user