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
57
block.c
57
block.c
@ -1174,10 +1174,10 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
||||
return child;
|
||||
}
|
||||
|
||||
static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
const BdrvChildRole *child_role)
|
||||
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
const BdrvChildRole *child_role)
|
||||
{
|
||||
BdrvChild *child = bdrv_root_attach_child(child_bs, child_name, child_role);
|
||||
QLIST_INSERT_HEAD(&parent_bs->children, child, next);
|
||||
@ -4011,3 +4011,52 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
||||
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/cutils.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
@ -67,6 +68,9 @@ typedef struct QuorumVotes {
|
||||
typedef struct BDRVQuorumState {
|
||||
BdrvChild **children; /* children BlockDriverStates */
|
||||
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
|
||||
* same result a quorum error occurs.
|
||||
*/
|
||||
@ -883,9 +887,9 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (s->num_children < 2) {
|
||||
if (s->num_children < 1) {
|
||||
error_setg(&local_err,
|
||||
"Number of provided children must be greater than 1");
|
||||
"Number of provided children must be 1 or more");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@ -949,6 +953,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
opened[i] = true;
|
||||
}
|
||||
s->next_child_index = s->num_children;
|
||||
|
||||
g_free(opened);
|
||||
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)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
@ -1059,6 +1130,9 @@ static BlockDriver bdrv_quorum = {
|
||||
.bdrv_detach_aio_context = quorum_detach_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,
|
||||
.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);
|
||||
}
|
||||
|
||||
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 *head = NULL, **p_next = &head;
|
||||
|
@ -476,6 +476,10 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs);
|
||||
void bdrv_ref(BlockDriverState *bs);
|
||||
void bdrv_unref(BlockDriverState *bs);
|
||||
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);
|
||||
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_add_child(BlockDriverState *parent, BlockDriverState *child,
|
||||
Error **errp);
|
||||
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
|
||||
|
||||
#endif
|
||||
|
@ -314,6 +314,11 @@ struct BlockDriver {
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -2556,3 +2556,35 @@
|
||||
##
|
||||
{ 'command': 'block-set-write-threshold',
|
||||
'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' } }
|
||||
|
15
qemu-img.c
15
qemu-img.c
@ -1475,10 +1475,21 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
||||
} else if (!s->target_has_backing) {
|
||||
/* Without a target backing file we must copy over the contents of
|
||||
* 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
|
||||
* buffer size */
|
||||
s->status = BLK_DATA;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
s->status = BLK_BACKING_FILE;
|
||||
}
|
||||
|
228
qemu-io-cmds.c
228
qemu-io-cmds.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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,
|
||||
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];
|
||||
|
||||
@ -395,12 +395,6 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (len & 0x1ff) {
|
||||
printf("length argument %" PRId64
|
||||
" is not sector aligned\n", len);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sizes[i] = 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,
|
||||
int64_t count, int64_t *total)
|
||||
int64_t count, int flags, int64_t *total)
|
||||
{
|
||||
if (count > INT_MAX) {
|
||||
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) {
|
||||
return *total;
|
||||
}
|
||||
@ -452,6 +446,7 @@ typedef struct {
|
||||
int64_t offset;
|
||||
int64_t count;
|
||||
int64_t *total;
|
||||
int flags;
|
||||
int ret;
|
||||
bool done;
|
||||
} CoWriteZeroes;
|
||||
@ -460,7 +455,8 @@ static void coroutine_fn co_write_zeroes_entry(void *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;
|
||||
if (data->ret < 0) {
|
||||
*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,
|
||||
int64_t *total)
|
||||
int flags, int64_t *total)
|
||||
{
|
||||
Coroutine *co;
|
||||
CoWriteZeroes data = {
|
||||
@ -479,6 +475,7 @@ static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count,
|
||||
.offset = offset,
|
||||
.count = count,
|
||||
.total = total,
|
||||
.flags = flags,
|
||||
.done = false,
|
||||
};
|
||||
|
||||
@ -564,11 +561,11 @@ static int do_aio_readv(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;
|
||||
|
||||
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) {
|
||||
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"
|
||||
" -C, -- report statistics in a machine parsable format\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"
|
||||
" -q, -- quiet mode, do not show I/O statistics\n"
|
||||
" -s, -- start offset for pattern verification (only with -P)\n"
|
||||
@ -650,7 +647,7 @@ static const cmdinfo_t read_cmd = {
|
||||
.cfunc = read_f,
|
||||
.argmin = 2,
|
||||
.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",
|
||||
.help = read_help,
|
||||
};
|
||||
@ -658,8 +655,8 @@ static const cmdinfo_t read_cmd = {
|
||||
static int read_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
|
||||
int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
|
||||
bool Cflag = false, qflag = false, vflag = false;
|
||||
bool Pflag = false, sflag = false, lflag = false, bflag = false;
|
||||
int c, cnt;
|
||||
char *buf;
|
||||
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) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
bflag = 1;
|
||||
bflag = true;
|
||||
break;
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
lflag = true;
|
||||
pattern_count = cvtnum(optarg);
|
||||
if (pattern_count < 0) {
|
||||
print_cvtnum_err(pattern_count, optarg);
|
||||
@ -686,20 +683,20 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
/* Ignored for backwards compatibility */
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
Pflag = true;
|
||||
pattern = parse_pattern(optarg);
|
||||
if (pattern < 0) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
sflag = true;
|
||||
pattern_offset = cvtnum(optarg);
|
||||
if (pattern_offset < 0) {
|
||||
print_cvtnum_err(pattern_offset, optarg);
|
||||
@ -707,7 +704,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
vflag = true;
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
if (bflag && pflag) {
|
||||
printf("-b and -p cannot be specified at the same time\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = cvtnum(argv[optind]);
|
||||
if (offset < 0) {
|
||||
print_cvtnum_err(offset, argv[optind]);
|
||||
@ -753,7 +745,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pflag) {
|
||||
if (bflag) {
|
||||
if (offset & 0x1ff) {
|
||||
printf("offset %" PRId64 " is not sector aligned\n",
|
||||
offset);
|
||||
@ -836,7 +828,7 @@ static const cmdinfo_t readv_cmd = {
|
||||
.cfunc = readv_f,
|
||||
.argmin = 2,
|
||||
.argmax = -1,
|
||||
.args = "[-Cqv] [-P pattern ] off len [len..]",
|
||||
.args = "[-Cqv] [-P pattern] off len [len..]",
|
||||
.oneline = "reads a number of bytes at a specified offset",
|
||||
.help = readv_help,
|
||||
};
|
||||
@ -844,7 +836,7 @@ static const cmdinfo_t readv_cmd = {
|
||||
static int readv_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, qflag = 0, vflag = 0;
|
||||
bool Cflag = false, qflag = false, vflag = false;
|
||||
int c, cnt;
|
||||
char *buf;
|
||||
int64_t offset;
|
||||
@ -853,25 +845,25 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
|
||||
int nr_iov;
|
||||
QEMUIOVector qiov;
|
||||
int pattern = 0;
|
||||
int Pflag = 0;
|
||||
bool Pflag = false;
|
||||
|
||||
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
Pflag = true;
|
||||
pattern = parse_pattern(optarg);
|
||||
if (pattern < 0) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
vflag = true;
|
||||
break;
|
||||
default:
|
||||
return qemuio_command_usage(&readv_cmd);
|
||||
@ -890,12 +882,6 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
optind++;
|
||||
|
||||
if (offset & 0x1ff) {
|
||||
printf("offset %" PRId64 " is not sector aligned\n",
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nr_iov = argc - optind;
|
||||
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
|
||||
if (buf == NULL) {
|
||||
@ -952,10 +938,12 @@ static void write_help(void)
|
||||
" filled with a set pattern (0xcdcdcdcd).\n"
|
||||
" -b, -- write to the VM state rather than the virtual disk\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"
|
||||
" -C, -- report statistics in a machine parsable format\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"
|
||||
"\n");
|
||||
}
|
||||
@ -968,7 +956,7 @@ static const cmdinfo_t write_cmd = {
|
||||
.cfunc = write_f,
|
||||
.argmin = 2,
|
||||
.argmax = -1,
|
||||
.args = "[-bcCpqz] [-P pattern ] off len",
|
||||
.args = "[-bcCfquz] [-P pattern] off len",
|
||||
.oneline = "writes a number of bytes at a specified offset",
|
||||
.help = write_help,
|
||||
};
|
||||
@ -976,8 +964,9 @@ static const cmdinfo_t write_cmd = {
|
||||
static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
|
||||
int cflag = 0;
|
||||
bool Cflag = false, qflag = false, bflag = false;
|
||||
bool Pflag = false, zflag = false, cflag = false;
|
||||
int flags = 0;
|
||||
int c, cnt;
|
||||
char *buf = NULL;
|
||||
int64_t offset;
|
||||
@ -986,32 +975,38 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||
int64_t total = 0;
|
||||
int pattern = 0xcd;
|
||||
|
||||
while ((c = getopt(argc, argv, "bcCpP:qz")) != -1) {
|
||||
while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
bflag = 1;
|
||||
bflag = true;
|
||||
break;
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
cflag = true;
|
||||
break;
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'f':
|
||||
flags |= BDRV_REQ_FUA;
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
/* Ignored for backwards compatibility */
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
Pflag = true;
|
||||
pattern = parse_pattern(optarg);
|
||||
if (pattern < 0) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
case 'u':
|
||||
flags |= BDRV_REQ_MAY_UNMAP;
|
||||
break;
|
||||
case 'z':
|
||||
zflag = 1;
|
||||
zflag = true;
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
if (bflag + pflag + zflag > 1) {
|
||||
printf("-b, -p, or -z cannot be specified at the same time\n");
|
||||
if (bflag && zflag) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1049,7 +1054,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pflag) {
|
||||
if (bflag || cflag) {
|
||||
if (offset & 0x1ff) {
|
||||
printf("offset %" PRId64 " is not sector aligned\n",
|
||||
offset);
|
||||
@ -1071,11 +1076,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||
if (bflag) {
|
||||
cnt = do_save_vmstate(blk, buf, offset, count, &total);
|
||||
} 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) {
|
||||
cnt = do_write_compressed(blk, buf, offset, count, &total);
|
||||
} else {
|
||||
cnt = do_pwrite(blk, buf, offset, count, &total);
|
||||
cnt = do_pwrite(blk, buf, offset, count, flags, &total);
|
||||
}
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
@ -1114,6 +1119,7 @@ writev_help(void)
|
||||
" filled with a set pattern (0xcdcdcdcd).\n"
|
||||
" -P, -- use different pattern to fill file\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"
|
||||
"\n");
|
||||
}
|
||||
@ -1125,7 +1131,7 @@ static const cmdinfo_t writev_cmd = {
|
||||
.cfunc = writev_f,
|
||||
.argmin = 2,
|
||||
.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",
|
||||
.help = writev_help,
|
||||
};
|
||||
@ -1133,7 +1139,8 @@ static const cmdinfo_t writev_cmd = {
|
||||
static int writev_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, qflag = 0;
|
||||
bool Cflag = false, qflag = false;
|
||||
int flags = 0;
|
||||
int c, cnt;
|
||||
char *buf;
|
||||
int64_t offset;
|
||||
@ -1146,10 +1153,13 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
||||
while ((c = getopt(argc, argv, "CqP:")) != -1) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'f':
|
||||
flags |= BDRV_REQ_FUA;
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
case 'P':
|
||||
pattern = parse_pattern(optarg);
|
||||
@ -1173,12 +1183,6 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
optind++;
|
||||
|
||||
if (offset & 0x1ff) {
|
||||
printf("offset %" PRId64 " is not sector aligned\n",
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nr_iov = argc - optind;
|
||||
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
|
||||
if (buf == NULL) {
|
||||
@ -1186,7 +1190,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
|
||||
gettimeofday(&t1, NULL);
|
||||
cnt = do_aio_writev(blk, &qiov, offset, &total);
|
||||
cnt = do_aio_writev(blk, &qiov, offset, flags, &total);
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
if (cnt < 0) {
|
||||
@ -1242,7 +1246,7 @@ static const cmdinfo_t multiwrite_cmd = {
|
||||
static int multiwrite_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, qflag = 0;
|
||||
bool Cflag = false, qflag = false;
|
||||
int c, cnt;
|
||||
char **buf;
|
||||
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) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
case 'P':
|
||||
pattern = parse_pattern(optarg);
|
||||
@ -1371,11 +1375,11 @@ struct aio_ctx {
|
||||
QEMUIOVector qiov;
|
||||
int64_t offset;
|
||||
char *buf;
|
||||
int qflag;
|
||||
int vflag;
|
||||
int Cflag;
|
||||
int Pflag;
|
||||
int zflag;
|
||||
bool qflag;
|
||||
bool vflag;
|
||||
bool Cflag;
|
||||
bool Pflag;
|
||||
bool zflag;
|
||||
BlockAcctCookie acct;
|
||||
int pattern;
|
||||
struct timeval t1;
|
||||
@ -1484,7 +1488,7 @@ static const cmdinfo_t aio_read_cmd = {
|
||||
.cfunc = aio_read_f,
|
||||
.argmin = 2,
|
||||
.argmax = -1,
|
||||
.args = "[-Cqv] [-P pattern ] off len [len..]",
|
||||
.args = "[-Cqv] [-P pattern] off len [len..]",
|
||||
.oneline = "asynchronously reads a number of bytes",
|
||||
.help = aio_read_help,
|
||||
};
|
||||
@ -1498,10 +1502,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
||||
while ((c = getopt(argc, argv, "CP:qv")) != -1) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
ctx->Cflag = 1;
|
||||
ctx->Cflag = true;
|
||||
break;
|
||||
case 'P':
|
||||
ctx->Pflag = 1;
|
||||
ctx->Pflag = true;
|
||||
ctx->pattern = parse_pattern(optarg);
|
||||
if (ctx->pattern < 0) {
|
||||
g_free(ctx);
|
||||
@ -1509,10 +1513,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
ctx->qflag = 1;
|
||||
ctx->qflag = true;
|
||||
break;
|
||||
case 'v':
|
||||
ctx->vflag = 1;
|
||||
ctx->vflag = true;
|
||||
break;
|
||||
default:
|
||||
g_free(ctx);
|
||||
@ -1533,14 +1537,6 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
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;
|
||||
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
|
||||
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"
|
||||
" -P, -- use different pattern to fill file\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"
|
||||
" -u, -- with -z, allow unmapping\n"
|
||||
" -z, -- write zeroes using blk_aio_write_zeroes\n"
|
||||
"\n");
|
||||
}
|
||||
@ -1584,7 +1582,7 @@ static const cmdinfo_t aio_write_cmd = {
|
||||
.cfunc = aio_write_f,
|
||||
.argmin = 2,
|
||||
.argmax = -1,
|
||||
.args = "[-Cqz] [-P pattern ] off len [len..]",
|
||||
.args = "[-Cfquz] [-P pattern] off len [len..]",
|
||||
.oneline = "asynchronously writes a number of bytes",
|
||||
.help = aio_write_help,
|
||||
};
|
||||
@ -1594,15 +1592,22 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
||||
int nr_iov, c;
|
||||
int pattern = 0xcd;
|
||||
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
|
||||
int flags = 0;
|
||||
|
||||
ctx->blk = blk;
|
||||
while ((c = getopt(argc, argv, "CqP:z")) != -1) {
|
||||
while ((c = getopt(argc, argv, "CfqP:z")) != -1) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
ctx->Cflag = 1;
|
||||
ctx->Cflag = true;
|
||||
break;
|
||||
case 'f':
|
||||
flags |= BDRV_REQ_FUA;
|
||||
break;
|
||||
case 'q':
|
||||
ctx->qflag = 1;
|
||||
ctx->qflag = true;
|
||||
break;
|
||||
case 'u':
|
||||
flags |= BDRV_REQ_MAY_UNMAP;
|
||||
break;
|
||||
case 'P':
|
||||
pattern = parse_pattern(optarg);
|
||||
@ -1612,7 +1617,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
ctx->zflag = 1;
|
||||
ctx->zflag = true;
|
||||
break;
|
||||
default:
|
||||
g_free(ctx);
|
||||
@ -1631,6 +1636,11 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
||||
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) {
|
||||
printf("-z and -P cannot be specified at the same time\n");
|
||||
g_free(ctx);
|
||||
@ -1645,14 +1655,6 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
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) {
|
||||
int64_t count = cvtnum(argv[optind]);
|
||||
if (count < 0) {
|
||||
@ -1662,7 +1664,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
|
||||
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 {
|
||||
nr_iov = argc - optind;
|
||||
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_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;
|
||||
}
|
||||
@ -1841,17 +1845,17 @@ static const cmdinfo_t discard_cmd = {
|
||||
static int discard_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
int Cflag = 0, qflag = 0;
|
||||
bool Cflag = false, qflag = false;
|
||||
int c, ret;
|
||||
int64_t offset, count;
|
||||
|
||||
while ((c = getopt(argc, argv, "Cq")) != -1) {
|
||||
switch (c) {
|
||||
case 'C':
|
||||
Cflag = 1;
|
||||
Cflag = true;
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
qflag = true;
|
||||
break;
|
||||
default:
|
||||
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"
|
||||
"\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"
|
||||
" Opens a file for subsequent use by all of the other qemu-io commands.\n"
|
||||
" -r, -- open file read-only\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"
|
||||
"\n");
|
||||
}
|
||||
@ -120,7 +123,7 @@ static const cmdinfo_t open_cmd = {
|
||||
.argmin = 1,
|
||||
.argmax = -1,
|
||||
.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",
|
||||
.help = open_help,
|
||||
};
|
||||
@ -137,14 +140,14 @@ static QemuOptsList empty_opts = {
|
||||
|
||||
static int open_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
int flags = 0;
|
||||
int flags = BDRV_O_UNMAP;
|
||||
int readonly = 0;
|
||||
bool writethrough = true;
|
||||
int c;
|
||||
QemuOpts *qopts;
|
||||
QDict *opts;
|
||||
|
||||
while ((c = getopt(argc, argv, "snrgo:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "snro:kt:d:")) != -1) {
|
||||
switch (c) {
|
||||
case 's':
|
||||
flags |= BDRV_O_SNAPSHOT;
|
||||
@ -156,9 +159,27 @@ static int open_f(BlockBackend *blk, int argc, char **argv)
|
||||
case 'r':
|
||||
readonly = 1;
|
||||
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':
|
||||
if (imageOpts) {
|
||||
printf("--image-opts and 'open -o' are mutually exclusive\n");
|
||||
qemu_opts_reset(&empty_opts);
|
||||
return 0;
|
||||
}
|
||||
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)
|
||||
{
|
||||
printf(
|
||||
"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n"
|
||||
"Usage: %s [OPTIONS]... [-c STRING]... [file]\n"
|
||||
"QEMU Disk exerciser\n"
|
||||
"\n"
|
||||
" --object OBJECTDEF define an object such as 'secret' for\n"
|
||||
" passwords and/or encryption keys\n"
|
||||
" --image-opts treat file as option string\n"
|
||||
" -c, --cmd STRING execute command with its arguments\n"
|
||||
" from the given string\n"
|
||||
" -f, --format FMT specifies the block driver to use\n"
|
||||
" -r, --read-only export read-only\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"
|
||||
" -k, --native-aio use kernel AIO implementation (on Linux only)\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"
|
||||
" -h, --help display this help 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 readonly = 0;
|
||||
const char *sopt = "hVc:d:f:rsnmgkt:T:";
|
||||
const char *sopt = "hVc:d:f:rsnmkt:T:";
|
||||
const struct option lopt[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "offset", required_argument, NULL, 'o' },
|
||||
{ "cmd", required_argument, NULL, 'c' },
|
||||
{ "format", required_argument, NULL, 'f' },
|
||||
{ "read-only", no_argument, NULL, 'r' },
|
||||
|
@ -4395,6 +4395,59 @@ Example:
|
||||
|
||||
<- { "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
|
||||
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.rc
|
||||
. ./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_os Linux
|
||||
|
||||
|
@ -43,13 +43,16 @@ _supported_fmt generic
|
||||
_supported_proto file
|
||||
_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
|
||||
_make_test_img $size
|
||||
|
||||
echo
|
||||
echo "== mark image read-only"
|
||||
chmod a-w "$TEST_IMG"
|
||||
chmod a-w "$TEST_IMG_FILE"
|
||||
|
||||
echo
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x1
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x1
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x0
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x1
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x0
|
||||
No errors were found on the image.
|
||||
|
@ -31,13 +31,13 @@ _cleanup()
|
||||
{
|
||||
echo "Cleanup"
|
||||
_cleanup_test_img
|
||||
rm "${TEST_IMG2}"
|
||||
rm "${TEST_IMG_FILE2}"
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
_compare()
|
||||
{
|
||||
$QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}"
|
||||
$QEMU_IMG compare $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" "${TEST_IMG2}"
|
||||
echo $?
|
||||
}
|
||||
|
||||
@ -46,25 +46,37 @@ _compare()
|
||||
. ./common.filter
|
||||
. ./common.pattern
|
||||
|
||||
_supported_fmt raw qcow qcow2 qed
|
||||
_supported_fmt raw qcow qcow2 qed luks
|
||||
_supported_proto file
|
||||
_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
|
||||
TEST_IMG2=$TEST_IMG.2
|
||||
TEST_IMG_FILE2=$TEST_IMG_FILE.2
|
||||
CLUSTER_SIZE=4096
|
||||
size=1024M
|
||||
size=128M
|
||||
|
||||
_make_test_img $size
|
||||
io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45
|
||||
|
||||
# Compare identical images
|
||||
cp "$TEST_IMG" "${TEST_IMG2}"
|
||||
cp "$TEST_IMG_FILE" "${TEST_IMG_FILE2}"
|
||||
_compare
|
||||
_compare -q
|
||||
|
||||
# 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 -s
|
||||
|
||||
@ -77,7 +89,7 @@ _compare
|
||||
# Test unaligned case of mismatch offsets in allocated clusters
|
||||
_make_test_img $size
|
||||
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
|
||||
_compare
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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
|
||||
wrote 4096/4096 bytes at offset 524288
|
||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
@ -13,6 +13,8 @@ Images are identical.
|
||||
0
|
||||
0
|
||||
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!
|
||||
Images are identical.
|
||||
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)
|
||||
Content mismatch at offset 0!
|
||||
1
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
=== IO: pattern 100
|
||||
wrote 512/512 bytes at offset 0
|
||||
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
|
||||
_make_test_img $size
|
||||
|
||||
echo
|
||||
echo "== initializing whole image =="
|
||||
$QEMU_IO -c "write -z 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== reading whole image =="
|
||||
$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
|
@ -1,6 +1,10 @@
|
||||
QA output created by 052
|
||||
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 ==
|
||||
read 134217728/134217728 bytes at offset 0
|
||||
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
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
@ -220,9 +220,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 131072/131072 bytes at offset 0
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
|
@ -43,7 +43,7 @@ choose_tcp_port() {
|
||||
|
||||
wait_for_tcp_port() {
|
||||
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
|
||||
done
|
||||
}
|
||||
@ -70,7 +70,7 @@ EOF
|
||||
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
|
||||
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"
|
||||
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
|
||||
|
||||
|
@ -47,6 +47,7 @@ size=128M
|
||||
echo
|
||||
echo "== Single request =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -59,6 +60,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Sequential requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -72,6 +74,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Superset overlapping requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -87,6 +90,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Subset overlapping requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -102,6 +106,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Head overlapping requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -116,6 +121,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Tail overlapping requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
@ -130,6 +136,7 @@ _cleanup_test_img
|
||||
echo
|
||||
echo "== Disjoint requests =="
|
||||
_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
|
||||
|
||||
echo
|
||||
|
@ -2,6 +2,8 @@ QA output created by 100
|
||||
|
||||
== Single request ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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 ==
|
||||
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
|
||||
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
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
./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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
|
||||
fi )
|
||||
incompatible_features 0x0
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
@ -53,6 +53,8 @@ export QEMU_IO_OPTIONS=""
|
||||
export CACHEMODE_IS_DEFAULT=true
|
||||
export QEMU_OPTIONS="-nodefaults"
|
||||
export VALGRIND_QEMU=
|
||||
export IMGKEYSECRET=
|
||||
export IMGOPTSSYNTAX=false
|
||||
|
||||
for r
|
||||
do
|
||||
@ -207,6 +209,13 @@ testlist options
|
||||
xpand=false
|
||||
;;
|
||||
|
||||
-luks)
|
||||
IMGOPTSSYNTAX=true
|
||||
IMGFMT=luks
|
||||
IMGKEYSECRET=123456
|
||||
xpand=false
|
||||
;;
|
||||
|
||||
-qed)
|
||||
IMGFMT=qed
|
||||
xpand=false
|
||||
@ -399,7 +408,11 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
|
||||
done
|
||||
|
||||
# Set qemu-io cache mode with $CACHEMODE we have
|
||||
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
|
||||
if [ "$IMGOPTSSYNTAX" = "true" ]; then
|
||||
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
|
||||
else
|
||||
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_imgopts
|
||||
|
@ -123,12 +123,19 @@ _qemu_img_wrapper()
|
||||
_qemu_io_wrapper()
|
||||
{
|
||||
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
|
||||
(
|
||||
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
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
|
||||
exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
|
||||
fi
|
||||
)
|
||||
RETVAL=$?
|
||||
@ -154,6 +161,16 @@ export QEMU_IMG=_qemu_img_wrapper
|
||||
export QEMU_IO=_qemu_io_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_alias_machine=$($QEMU -machine help | \
|
||||
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# log_size=[0-9]\\+##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()
|
||||
|
@ -53,21 +53,45 @@ fi
|
||||
# make sure we have a standard umask
|
||||
umask 022
|
||||
|
||||
if [ "$IMGPROTO" = "file" ]; then
|
||||
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
||||
elif [ "$IMGPROTO" = "nbd" ]; then
|
||||
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||
TEST_IMG="nbd:127.0.0.1:10810"
|
||||
elif [ "$IMGPROTO" = "ssh" ]; then
|
||||
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
|
||||
elif [ "$IMGPROTO" = "nfs" ]; then
|
||||
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
|
||||
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
||||
elif [ "$IMGPROTO" = "archipelago" ]; then
|
||||
TEST_IMG="archipelago:at.$IMGFMT"
|
||||
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
|
||||
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
||||
if [ "$IMGPROTO" = "file" ]; then
|
||||
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
||||
elif [ "$IMGPROTO" = "nbd" ]; then
|
||||
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||
TEST_IMG="nbd:127.0.0.1:10810"
|
||||
elif [ "$IMGPROTO" = "ssh" ]; then
|
||||
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
|
||||
elif [ "$IMGPROTO" = "nfs" ]; then
|
||||
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
|
||||
TEST_IMG=$TEST_DIR/t.$IMGFMT
|
||||
elif [ "$IMGPROTO" = "archipelago" ]; then
|
||||
TEST_IMG="archipelago:at.$IMGFMT"
|
||||
else
|
||||
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
||||
fi
|
||||
fi
|
||||
|
||||
_optstr_add()
|
||||
@ -108,6 +132,7 @@ _make_test_img()
|
||||
local img_name=""
|
||||
local use_backing=0
|
||||
local backing_file=""
|
||||
local object_options=""
|
||||
|
||||
if [ -n "$TEST_IMG_FILE" ]; then
|
||||
img_name=$TEST_IMG_FILE
|
||||
@ -118,6 +143,10 @@ _make_test_img()
|
||||
if [ -n "$IMGOPTS" ]; then
|
||||
optstr=$(_optstr_add "$optstr" "$IMGOPTS")
|
||||
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
|
||||
use_backing=1
|
||||
@ -135,9 +164,9 @@ _make_test_img()
|
||||
# XXX(hch): have global image options?
|
||||
(
|
||||
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
|
||||
$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
|
||||
) | _filter_img_create
|
||||
|
||||
@ -199,7 +228,13 @@ _cleanup_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' \
|
||||
-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'
|
||||
|
@ -47,7 +47,7 @@ if os.environ.get('QEMU_OPTIONS'):
|
||||
|
||||
imgfmt = os.environ.get('IMGFMT', 'raw')
|
||||
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', '.')
|
||||
cachemode = os.environ.get('CACHEMODE')
|
||||
qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
|
||||
@ -461,6 +461,14 @@ def verify_quorum():
|
||||
def main(supported_fmts=[], supported_oses=['linux']):
|
||||
'''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
|
||||
verbosity = 1
|
||||
verify_image_format(supported_fmts)
|
||||
|
Loading…
Reference in New Issue
Block a user