Block patches for 2.8

-----BEGIN PGP SIGNATURE-----
 
 iQEvBAABCAAZBQJX4ZxBEhxtcmVpdHpAcmVkaGF0LmNvbQAKCRD0B9sAYdXPQAW7
 CACiTqooe3QwyBigm4aOFeK0tELz6osng35k9fBycxMCjJKzt/8d/InN7SeN1XPV
 YJm7TSoienqHTJgGPvrl6k2gnRD6uy0ECyu6AYqvTDV0vEimFetTnT3511+eYFNk
 2f65mnvH1C6zgntRN8TzfyO+viWUuC9nG831jzIS7mIDeh8K+S4NhaGx8K5IHWb0
 1Hl1HOoPr9qbZcNbcEmg0My/9iOpAuDuVVf0kGIqUy0JOyFlJO7BHv5flVE5SPRf
 E1eC1h6fbpak1nXkZDr0BfyW7VY5ouwnvOa7it0lb5RWcSvWnFpV0dS/9F826UHZ
 MSstX5Fw8U5MQac4O/eY6fCo
 =tEbN
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2016-09-20' into staging

Block patches for 2.8

# gpg: Signature made Tue 20 Sep 2016 21:29:53 BST
# gpg:                using RSA key 0xF407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2016-09-20:
  iotest 055: refactor and speed up
  commit: get the overlay node before manipulating the backing chain
  blockdev: Modularize nfs block driver
  blockdev: Add dynamic module loading for block drivers
  blockdev: Add dynamic generation of module_block.h
  blockdev: prepare iSCSI block driver for dynamic loading
  qemu-img: add skip option to dd
  qemu-img: add the 'dd' subcommand

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-09-22 12:16:51 +01:00
commit ffd455ae41
23 changed files with 997 additions and 118 deletions

View File

@ -76,6 +76,8 @@ GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c GENERATED_SOURCES += trace/generated-ust.c
endif endif
GENERATED_HEADERS += module_block.h
# Don't try to regenerate Makefile or configure # Don't try to regenerate Makefile or configure
# We don't generate any of them # We don't generate any of them
Makefile: ; Makefile: ;
@ -245,9 +247,6 @@ Makefile: $(version-obj-y) $(version-lobj-y)
libqemustub.a: $(stub-obj-y) libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y) libqemuutil.a: $(util-obj-y)
block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
###################################################################### ######################################################################
qemu-img.o: qemu-img-cmds.h qemu-img.o: qemu-img-cmds.h
@ -352,6 +351,11 @@ ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) libqemuutil.a libqemustub.a
ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
$(call LINK, $^) $(call LINK, $^)
module_block.h: $(SRC_PATH)/scripts/modules/module_block.py config-host.mak
$(call quiet-command,$(PYTHON) $< $@ \
$(addprefix $(SRC_PATH)/,$(patsubst %.mo,%.c,$(block-obj-m))), \
" GEN $@")
clean: clean:
# avoid old build problems by removing potentially incorrect old files # avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h

62
block.c
View File

@ -27,6 +27,7 @@
#include "block/blockjob.h" #include "block/blockjob.h"
#include "block/nbd.h" #include "block/nbd.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "module_block.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
@ -242,17 +243,40 @@ BlockDriverState *bdrv_new(void)
return bs; return bs;
} }
BlockDriver *bdrv_find_format(const char *format_name) static BlockDriver *bdrv_do_find_format(const char *format_name)
{ {
BlockDriver *drv1; BlockDriver *drv1;
QLIST_FOREACH(drv1, &bdrv_drivers, list) { QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (!strcmp(drv1->format_name, format_name)) { if (!strcmp(drv1->format_name, format_name)) {
return drv1; return drv1;
} }
} }
return NULL; return NULL;
} }
BlockDriver *bdrv_find_format(const char *format_name)
{
BlockDriver *drv1;
int i;
drv1 = bdrv_do_find_format(format_name);
if (drv1) {
return drv1;
}
/* The driver isn't registered, maybe we need to load a module */
for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) {
if (!strcmp(block_driver_modules[i].format_name, format_name)) {
block_module_load_one(block_driver_modules[i].library_name);
break;
}
}
return bdrv_do_find_format(format_name);
}
static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only) static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
{ {
static const char *whitelist_rw[] = { static const char *whitelist_rw[] = {
@ -461,6 +485,19 @@ static BlockDriver *find_hdev_driver(const char *filename)
return drv; return drv;
} }
static BlockDriver *bdrv_do_find_protocol(const char *protocol)
{
BlockDriver *drv1;
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (drv1->protocol_name && !strcmp(drv1->protocol_name, protocol)) {
return drv1;
}
}
return NULL;
}
BlockDriver *bdrv_find_protocol(const char *filename, BlockDriver *bdrv_find_protocol(const char *filename,
bool allow_protocol_prefix, bool allow_protocol_prefix,
Error **errp) Error **errp)
@ -469,6 +506,7 @@ BlockDriver *bdrv_find_protocol(const char *filename,
char protocol[128]; char protocol[128];
int len; int len;
const char *p; const char *p;
int i;
/* TODO Drivers without bdrv_file_open must be specified explicitly */ /* TODO Drivers without bdrv_file_open must be specified explicitly */
@ -495,15 +533,25 @@ BlockDriver *bdrv_find_protocol(const char *filename,
len = sizeof(protocol) - 1; len = sizeof(protocol) - 1;
memcpy(protocol, filename, len); memcpy(protocol, filename, len);
protocol[len] = '\0'; protocol[len] = '\0';
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (drv1->protocol_name && drv1 = bdrv_do_find_protocol(protocol);
!strcmp(drv1->protocol_name, protocol)) { if (drv1) {
return drv1; return drv1;
}
for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) {
if (block_driver_modules[i].protocol_name &&
!strcmp(block_driver_modules[i].protocol_name, protocol)) {
block_module_load_one(block_driver_modules[i].library_name);
break;
} }
} }
error_setg(errp, "Unknown protocol '%s'", protocol); drv1 = bdrv_do_find_protocol(protocol);
return NULL; if (!drv1) {
error_setg(errp, "Unknown protocol '%s'", protocol);
}
return drv1;
} }
/* /*

View File

@ -1,4 +1,4 @@
block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o block-obj-y += qed-check.o
@ -29,6 +29,7 @@ block-obj-y += crypto.o
common-obj-y += stream.o common-obj-y += stream.o
nfs.o-libs := $(LIBNFS_LIBS)
iscsi.o-cflags := $(LIBISCSI_CFLAGS) iscsi.o-cflags := $(LIBISCSI_CFLAGS)
iscsi.o-libs := $(LIBISCSI_LIBS) iscsi.o-libs := $(LIBISCSI_LIBS)
curl.o-cflags := $(CURL_CFLAGS) curl.o-cflags := $(CURL_CFLAGS)
@ -40,7 +41,6 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS) ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS) ssh.o-libs := $(LIBSSH2_LIBS)
archipelago.o-libs := $(ARCHIPELAGO_LIBS) archipelago.o-libs := $(ARCHIPELAGO_LIBS)
block-obj-m += dmg.o
dmg.o-libs := $(BZIP2_LIBS) dmg.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz qcow.o-libs := -lz
linux-aio.o-libs := -laio linux-aio.o-libs := -laio

View File

@ -83,7 +83,7 @@ static void commit_complete(BlockJob *job, void *opaque)
BlockDriverState *active = s->active; BlockDriverState *active = s->active;
BlockDriverState *top = blk_bs(s->top); BlockDriverState *top = blk_bs(s->top);
BlockDriverState *base = blk_bs(s->base); BlockDriverState *base = blk_bs(s->base);
BlockDriverState *overlay_bs; BlockDriverState *overlay_bs = bdrv_find_overlay(active, top);
int ret = data->ret; int ret = data->ret;
if (!block_job_is_cancelled(&s->common) && ret == 0) { if (!block_job_is_cancelled(&s->common) && ret == 0) {
@ -97,7 +97,6 @@ static void commit_complete(BlockJob *job, void *opaque)
if (s->base_flags != bdrv_get_flags(base)) { if (s->base_flags != bdrv_get_flags(base)) {
bdrv_reopen(base, s->base_flags, NULL); bdrv_reopen(base, s->base_flags, NULL);
} }
overlay_bs = bdrv_find_overlay(active, top);
if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) { if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) {
bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
} }

View File

@ -2010,45 +2010,9 @@ static BlockDriver bdrv_iscsi = {
.bdrv_attach_aio_context = iscsi_attach_aio_context, .bdrv_attach_aio_context = iscsi_attach_aio_context,
}; };
static QemuOptsList qemu_iscsi_opts = {
.name = "iscsi",
.head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
.desc = {
{
.name = "user",
.type = QEMU_OPT_STRING,
.help = "username for CHAP authentication to target",
},{
.name = "password",
.type = QEMU_OPT_STRING,
.help = "password for CHAP authentication to target",
},{
.name = "password-secret",
.type = QEMU_OPT_STRING,
.help = "ID of the secret providing password for CHAP "
"authentication to target",
},{
.name = "header-digest",
.type = QEMU_OPT_STRING,
.help = "HeaderDigest setting. "
"{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
},{
.name = "initiator-name",
.type = QEMU_OPT_STRING,
.help = "Initiator iqn name to use when connecting",
},{
.name = "timeout",
.type = QEMU_OPT_NUMBER,
.help = "Request timeout in seconds (default 0 = no timeout)",
},
{ /* end of list */ }
},
};
static void iscsi_block_init(void) static void iscsi_block_init(void)
{ {
bdrv_register(&bdrv_iscsi); bdrv_register(&bdrv_iscsi);
qemu_add_opts(&qemu_iscsi_opts);
} }
block_init(iscsi_block_init); block_init(iscsi_block_init);

4
configure vendored
View File

@ -4578,7 +4578,6 @@ if test "$libnfs" != "no" ; then
if $pkg_config --atleast-version=1.9.3 libnfs; then if $pkg_config --atleast-version=1.9.3 libnfs; then
libnfs="yes" libnfs="yes"
libnfs_libs=$($pkg_config --libs libnfs) libnfs_libs=$($pkg_config --libs libnfs)
LIBS="$LIBS $libnfs_libs"
else else
if test "$libnfs" = "yes" ; then if test "$libnfs" = "yes" ; then
feature_not_found "libnfs" "Install libnfs devel >= 1.9.3" feature_not_found "libnfs" "Install libnfs devel >= 1.9.3"
@ -5351,7 +5350,8 @@ if test "$libiscsi" = "yes" ; then
fi fi
if test "$libnfs" = "yes" ; then if test "$libnfs" = "yes" ; then
echo "CONFIG_LIBNFS=y" >> $config_host_mak echo "CONFIG_LIBNFS=m" >> $config_host_mak
echo "LIBNFS_LIBS=$libnfs_libs" >> $config_host_mak
fi fi
if test "$seccomp" = "yes"; then if test "$seccomp" = "yes"; then

View File

@ -52,9 +52,12 @@ typedef enum {
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI) #define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
#define type_init(function) module_init(function, MODULE_INIT_QOM) #define type_init(function) module_init(function, MODULE_INIT_QOM)
#define block_module_load_one(lib) module_load_one("block-", lib)
void register_module_init(void (*fn)(void), module_init_type type); void register_module_init(void (*fn)(void), module_init_type type);
void register_dso_module_init(void (*fn)(void), module_init_type type); void register_dso_module_init(void (*fn)(void), module_init_type type);
void module_call_init(module_init_type type); void module_call_init(module_init_type type);
void module_load_one(const char *prefix, const char *lib_name);
#endif #endif

View File

@ -45,6 +45,12 @@ STEXI
@item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} @item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
ETEXI ETEXI
DEF("dd", img_dd,
"dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
STEXI
@item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
ETEXI
DEF("info", img_info, DEF("info", img_info,
"info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename") "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename")
STEXI STEXI

View File

@ -166,7 +166,15 @@ static void QEMU_NORETURN help(void)
"Parameters to compare subcommand:\n" "Parameters to compare subcommand:\n"
" '-f' first image format\n" " '-f' first image format\n"
" '-F' second image format\n" " '-F' second image format\n"
" '-s' run in Strict mode - fail on different image size or sector allocation\n"; " '-s' run in Strict mode - fail on different image size or sector allocation\n"
"\n"
"Parameters to dd subcommand:\n"
" 'bs=BYTES' read and write up to BYTES bytes at a time "
"(default: 512)\n"
" 'count=N' copy only N input blocks\n"
" 'if=FILE' read from FILE\n"
" 'of=FILE' write to FILE\n"
" 'skip=N' skip N bs-sized blocks at the start of input\n";
printf("%s\nSupported formats:", help_msg); printf("%s\nSupported formats:", help_msg);
bdrv_iterate_format(format_print, NULL); bdrv_iterate_format(format_print, NULL);
@ -3796,6 +3804,339 @@ out:
return 0; return 0;
} }
#define C_BS 01
#define C_COUNT 02
#define C_IF 04
#define C_OF 010
#define C_SKIP 020
struct DdInfo {
unsigned int flags;
int64_t count;
};
struct DdIo {
int bsz; /* Block size */
char *filename;
uint8_t *buf;
int64_t offset;
};
struct DdOpts {
const char *name;
int (*f)(const char *, struct DdIo *, struct DdIo *, struct DdInfo *);
unsigned int flag;
};
static int img_dd_bs(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
char *end;
int64_t res;
res = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
if (res <= 0 || res > INT_MAX || *end) {
error_report("invalid number: '%s'", arg);
return 1;
}
in->bsz = out->bsz = res;
return 0;
}
static int img_dd_count(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
char *end;
dd->count = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
if (dd->count < 0 || *end) {
error_report("invalid number: '%s'", arg);
return 1;
}
return 0;
}
static int img_dd_if(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
in->filename = g_strdup(arg);
return 0;
}
static int img_dd_of(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
out->filename = g_strdup(arg);
return 0;
}
static int img_dd_skip(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
char *end;
in->offset = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
if (in->offset < 0 || *end) {
error_report("invalid number: '%s'", arg);
return 1;
}
return 0;
}
static int img_dd(int argc, char **argv)
{
int ret = 0;
char *arg = NULL;
char *tmp;
BlockDriver *drv = NULL, *proto_drv = NULL;
BlockBackend *blk1 = NULL, *blk2 = NULL;
QemuOpts *opts = NULL;
QemuOptsList *create_opts = NULL;
Error *local_err = NULL;
bool image_opts = false;
int c, i;
const char *out_fmt = "raw";
const char *fmt = NULL;
int64_t size = 0;
int64_t block_count = 0, out_pos, in_pos;
struct DdInfo dd = {
.flags = 0,
.count = 0,
};
struct DdIo in = {
.bsz = 512, /* Block size is by default 512 bytes */
.filename = NULL,
.buf = NULL,
.offset = 0
};
struct DdIo out = {
.bsz = 512,
.filename = NULL,
.buf = NULL,
.offset = 0
};
const struct DdOpts options[] = {
{ "bs", img_dd_bs, C_BS },
{ "count", img_dd_count, C_COUNT },
{ "if", img_dd_if, C_IF },
{ "of", img_dd_of, C_OF },
{ "skip", img_dd_skip, C_SKIP },
{ NULL, NULL, 0 }
};
const struct option long_options[] = {
{ "help", no_argument, 0, 'h'},
{ "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{ 0, 0, 0, 0 }
};
while ((c = getopt_long(argc, argv, "hf:O:", long_options, NULL))) {
if (c == EOF) {
break;
}
switch (c) {
case 'O':
out_fmt = optarg;
break;
case 'f':
fmt = optarg;
break;
case '?':
error_report("Try 'qemu-img --help' for more information.");
ret = -1;
goto out;
case 'h':
help();
break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
}
}
for (i = optind; i < argc; i++) {
int j;
arg = g_strdup(argv[i]);
tmp = strchr(arg, '=');
if (tmp == NULL) {
error_report("unrecognized operand %s", arg);
ret = -1;
goto out;
}
*tmp++ = '\0';
for (j = 0; options[j].name != NULL; j++) {
if (!strcmp(arg, options[j].name)) {
break;
}
}
if (options[j].name == NULL) {
error_report("unrecognized operand %s", arg);
ret = -1;
goto out;
}
if (options[j].f(tmp, &in, &out, &dd) != 0) {
ret = -1;
goto out;
}
dd.flags |= options[j].flag;
g_free(arg);
arg = NULL;
}
if (!(dd.flags & C_IF && dd.flags & C_OF)) {
error_report("Must specify both input and output files");
ret = -1;
goto out;
}
blk1 = img_open(image_opts, in.filename, fmt, 0, false, false);
if (!blk1) {
ret = -1;
goto out;
}
drv = bdrv_find_format(out_fmt);
if (!drv) {
error_report("Unknown file format");
ret = -1;
goto out;
}
proto_drv = bdrv_find_protocol(out.filename, true, &local_err);
if (!proto_drv) {
error_report_err(local_err);
ret = -1;
goto out;
}
if (!drv->create_opts) {
error_report("Format driver '%s' does not support image creation",
drv->format_name);
ret = -1;
goto out;
}
if (!proto_drv->create_opts) {
error_report("Protocol driver '%s' does not support image creation",
proto_drv->format_name);
ret = -1;
goto out;
}
create_opts = qemu_opts_append(create_opts, drv->create_opts);
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
size = blk_getlength(blk1);
if (size < 0) {
error_report("Failed to get size for '%s'", in.filename);
ret = -1;
goto out;
}
if (dd.flags & C_COUNT && dd.count <= INT64_MAX / in.bsz &&
dd.count * in.bsz < size) {
size = dd.count * in.bsz;
}
/* Overflow means the specified offset is beyond input image's size */
if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
size < in.bsz * in.offset)) {
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort);
} else {
qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
size - in.bsz * in.offset, &error_abort);
}
ret = bdrv_create(drv, out.filename, opts, &local_err);
if (ret < 0) {
error_reportf_err(local_err,
"%s: error while creating output image: ",
out.filename);
ret = -1;
goto out;
}
blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
false, false);
if (!blk2) {
ret = -1;
goto out;
}
if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
size < in.offset * in.bsz)) {
/* We give a warning if the skip option is bigger than the input
* size and create an empty output disk image (i.e. like dd(1)).
*/
error_report("%s: cannot skip to specified offset", in.filename);
in_pos = size;
} else {
in_pos = in.offset * in.bsz;
}
in.buf = g_new(uint8_t, in.bsz);
for (out_pos = 0; in_pos < size; block_count++) {
int in_ret, out_ret;
if (in_pos + in.bsz > size) {
in_ret = blk_pread(blk1, in_pos, in.buf, size - in_pos);
} else {
in_ret = blk_pread(blk1, in_pos, in.buf, in.bsz);
}
if (in_ret < 0) {
error_report("error while reading from input image file: %s",
strerror(-in_ret));
ret = -1;
goto out;
}
in_pos += in_ret;
out_ret = blk_pwrite(blk2, out_pos, in.buf, in_ret, 0);
if (out_ret < 0) {
error_report("error while writing to output image file: %s",
strerror(-out_ret));
ret = -1;
goto out;
}
out_pos += out_ret;
}
out:
g_free(arg);
qemu_opts_del(opts);
qemu_opts_free(create_opts);
blk_unref(blk1);
blk_unref(blk2);
g_free(in.filename);
g_free(out.filename);
g_free(in.buf);
g_free(out.buf);
if (ret) {
return 1;
}
return 0;
}
static const img_cmd_t img_cmds[] = { static const img_cmd_t img_cmds[] = {
#define DEF(option, callback, arg_string) \ #define DEF(option, callback, arg_string) \

View File

@ -139,6 +139,22 @@ Parameters to convert subcommand:
Skip the creation of the target volume Skip the creation of the target volume
@end table @end table
Parameters to dd subcommand:
@table @option
@item bs=@var{block_size}
defines the block size
@item count=@var{blocks}
sets the number of input blocks to copy
@item if=@var{input}
sets the input file
@item of=@var{output}
sets the output file
@item skip=@var{blocks}
sets the number of input blocks to skip
@end table
Command description: Command description:
@table @option @table @option
@ -310,6 +326,17 @@ skipped. This is useful for formats such as @code{rbd} if the target
volume has already been created with site specific options that cannot volume has already been created with site specific options that cannot
be supplied through qemu-img. be supplied through qemu-img.
@item dd [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
Dd copies from @var{input} file to @var{output} file converting it from
@var{fmt} format to @var{output_fmt} format.
The data is by default read and written using blocks of 512 bytes but can be
modified by specifying @var{block_size}. If count=@var{blocks} is specified
dd will stop reading input after reading @var{blocks} input blocks.
The size syntax is similar to dd(1)'s size syntax.
@item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} @item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
Give information about the disk image @var{filename}. Use it in Give information about the disk image @var{filename}. Use it in

View File

@ -0,0 +1,108 @@
#!/usr/bin/python
#
# Module information generator
#
# Copyright Red Hat, Inc. 2015 - 2016
#
# Authors:
# Marc Mari <markmb@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from __future__ import print_function
import sys
import os
def get_string_struct(line):
data = line.split()
# data[0] -> struct element name
# data[1] -> =
# data[2] -> value
return data[2].replace('"', '')[:-1]
def add_module(fheader, library, format_name, protocol_name):
lines = []
lines.append('.library_name = "' + library + '",')
if format_name != "":
lines.append('.format_name = "' + format_name + '",')
if protocol_name != "":
lines.append('.protocol_name = "' + protocol_name + '",')
text = '\n '.join(lines)
fheader.write('\n {\n ' + text + '\n },')
def process_file(fheader, filename):
# This parser assumes the coding style rules are being followed
with open(filename, "r") as cfile:
found_something = False
found_start = False
library, _ = os.path.splitext(os.path.basename(filename))
for line in cfile:
if found_start:
line = line.replace('\n', '')
if line.find(".format_name") != -1:
format_name = get_string_struct(line)
elif line.find(".protocol_name") != -1:
protocol_name = get_string_struct(line)
elif line == "};":
add_module(fheader, library, format_name, protocol_name)
found_start = False
elif line.find("static BlockDriver") != -1:
found_something = True
found_start = True
format_name = ""
protocol_name = ""
if not found_something:
print("No BlockDriver struct found in " + filename + ". \
Is this really a module?", file=sys.stderr)
sys.exit(1)
def print_top(fheader):
fheader.write('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
* QEMU Block Module Infrastructure
*
* Authors:
* Marc Mari <markmb@redhat.com>
*/
''')
fheader.write('''#ifndef QEMU_MODULE_BLOCK_H
#define QEMU_MODULE_BLOCK_H
#include "qemu-common.h"
static const struct {
const char *format_name;
const char *protocol_name;
const char *library_name;
} block_driver_modules[] = {''')
def print_bottom(fheader):
fheader.write('''
};
#endif
''')
# First argument: output file
# All other arguments: modules source files (.c)
output_file = sys.argv[1]
with open(output_file, 'w') as fheader:
print_top(fheader)
for filename in sys.argv[2:]:
if os.path.isfile(filename):
process_file(fheader, filename)
else:
print("File " + filename + " does not exist.", file=sys.stderr)
sys.exit(1)
print_bottom(fheader)
sys.exit(0)

View File

@ -29,17 +29,24 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
target_img = os.path.join(iotests.test_dir, 'target.img') target_img = os.path.join(iotests.test_dir, 'target.img')
blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img') blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img')
class TestSingleDrive(iotests.QMPTestCase): image_len = 64 * 1024 * 1024 # MB
image_len = 64 * 1024 * 1024 # MB
def setUpModule():
qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
def tearDownModule():
os.remove(test_img)
class TestSingleDrive(iotests.QMPTestCase):
def setUp(self): def setUp(self):
# Write data to the image so we can compare later qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img)
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img) self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
if iotests.qemu_default_machine == 'pc': if iotests.qemu_default_machine == 'pc':
@ -48,7 +55,6 @@ class TestSingleDrive(iotests.QMPTestCase):
def tearDown(self): def tearDown(self):
self.vm.shutdown() self.vm.shutdown()
os.remove(test_img)
os.remove(blockdev_target_img) os.remove(blockdev_target_img)
try: try:
os.remove(target_img) os.remove(target_img)
@ -155,19 +161,14 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/class', 'GenericError')
class TestSetSpeed(iotests.QMPTestCase): class TestSetSpeed(iotests.QMPTestCase):
image_len = 80 * 1024 * 1024 # MB
def setUp(self): def setUp(self):
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len)) qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img)
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img) self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
self.vm.launch() self.vm.launch()
def tearDown(self): def tearDown(self):
self.vm.shutdown() self.vm.shutdown()
os.remove(test_img)
os.remove(blockdev_target_img) os.remove(blockdev_target_img)
try: try:
os.remove(target_img) os.remove(target_img)
@ -243,15 +244,8 @@ class TestSetSpeed(iotests.QMPTestCase):
self.do_test_set_speed_invalid('blockdev-backup', 'drive1') self.do_test_set_speed_invalid('blockdev-backup', 'drive1')
class TestSingleTransaction(iotests.QMPTestCase): class TestSingleTransaction(iotests.QMPTestCase):
image_len = 64 * 1024 * 1024 # MB
def setUp(self): def setUp(self):
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len)) qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img)
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img) self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
if iotests.qemu_default_machine == 'pc': if iotests.qemu_default_machine == 'pc':
@ -260,7 +254,6 @@ class TestSingleTransaction(iotests.QMPTestCase):
def tearDown(self): def tearDown(self):
self.vm.shutdown() self.vm.shutdown()
os.remove(test_img)
os.remove(blockdev_target_img) os.remove(blockdev_target_img)
try: try:
os.remove(target_img) os.remove(target_img)
@ -454,17 +447,8 @@ class TestDriveCompression(iotests.QMPTestCase):
fmt_supports_compression = [{'type': 'qcow2', 'args': ()}, fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
{'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}] {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
def setUp(self):
# Write data to the image so we can compare later
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestDriveCompression.image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
def tearDown(self): def tearDown(self):
self.vm.shutdown() self.vm.shutdown()
os.remove(test_img)
os.remove(blockdev_target_img) os.remove(blockdev_target_img)
try: try:
os.remove(target_img) os.remove(target_img)

70
tests/qemu-iotests/159 Executable file
View File

@ -0,0 +1,70 @@
#! /bin/bash
#
# qemu-img dd test with different block sizes
#
# Copyright (C) 2016 Reda Sallahi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
owner=fullmanet@gmail.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
status=1
_cleanup()
{
_cleanup_test_img
rm -f "$TEST_IMG.out"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
_supported_fmt generic
_supported_proto file
_supported_os Linux
TEST_SIZES="5 512 1024 1999 1K 64K 1M"
for bs in $TEST_SIZES; do
echo
echo "== Creating image =="
size=1M
_make_test_img $size
_check_test_img
$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
echo
echo "== Converting the image with dd with a block size of $bs =="
$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" bs=$bs -O "$IMGFMT"
TEST_IMG="$TEST_IMG.out" _check_test_img
echo
echo "== Compare the images with qemu-img compare =="
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.out"
done
echo
echo "*** done"
rm -f "$seq.full"
status=0

View File

@ -0,0 +1,87 @@
QA output created by 159
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 5 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 512 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 1024 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 1999 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 1K ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 64K ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with a block size of 1M ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
*** done

72
tests/qemu-iotests/160 Executable file
View File

@ -0,0 +1,72 @@
#! /bin/bash
#
# qemu-img dd test for the skip option
#
# Copyright (C) 2016 Reda Sallahi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
owner=fullmanet@gmail.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
status=1
_cleanup()
{
_cleanup_test_img
rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
_supported_fmt raw
_supported_proto file
_supported_os Linux
TEST_SKIP_BLOCKS="1 2 30 30K"
for skip in $TEST_SKIP_BLOCKS; do
echo
echo "== Creating image =="
size=1M
_make_test_img $size
_check_test_img
$QEMU_IO -c "write -P 0xa 24 512k" "$TEST_IMG" | _filter_qemu_io
echo
echo "== Converting the image with dd with skip=$skip =="
$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" skip="$skip" -O "$IMGFMT" \
2> /dev/null
TEST_IMG="$TEST_IMG.out" _check_test_img
dd if="$TEST_IMG" of="$TEST_IMG.out.dd" skip="$skip" status=none
echo
echo "== Compare the images with qemu-img compare =="
$QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
done
echo
echo "*** done"
rm -f "$seq.full"
status=0

View File

@ -0,0 +1,51 @@
QA output created by 160
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=1 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=2 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=30 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=30K ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
*** done

67
tests/qemu-iotests/170 Executable file
View File

@ -0,0 +1,67 @@
#! /bin/bash
#
# qemu-img dd test
#
# Copyright (C) 2016 Reda Sallahi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
owner=fullmanet@gmail.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
status=1
_cleanup()
{
_cleanup_test_img
rm -f "$TEST_IMG.out"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
_supported_fmt generic
_supported_proto file
_supported_os Linux
echo
echo "== Creating image =="
size=1M
_make_test_img $size
_check_test_img
$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
echo
echo "== Converting the image with dd =="
$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" -O "$IMGFMT"
TEST_IMG="$TEST_IMG.out" _check_test_img
echo
echo "== Compare the images with qemu-img compare =="
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.out"
echo
echo "*** done"
rm -f "$seq.full"
status=0

View File

@ -0,0 +1,15 @@
QA output created by 170
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
*** done

View File

@ -44,6 +44,15 @@ _filter_imgfmt()
sed -e "s#$IMGFMT#IMGFMT#g" sed -e "s#$IMGFMT#IMGFMT#g"
} }
# Replace error message when the format is not supported and delete
# the output lines after the first one
_filter_qemu_img_check()
{
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'
}
# Removes \r from messages # Removes \r from messages
_filter_win32() _filter_win32()
{ {

View File

@ -234,10 +234,7 @@ _check_test_img()
else else
$QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
fi fi
) | _filter_testdir | \ ) | _filter_testdir | _filter_qemu_img_check
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'
} }
_img_info() _img_info()

View File

@ -157,4 +157,7 @@
155 rw auto 155 rw auto
156 rw auto quick 156 rw auto quick
157 auto 157 auto
159 rw auto quick
160 rw auto quick
162 auto quick 162 auto quick
170 rw auto quick

View File

@ -87,14 +87,11 @@ void register_dso_module_init(void (*fn)(void), module_init_type type)
QTAILQ_INSERT_TAIL(&dso_init_list, e, node); QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
} }
static void module_load(module_init_type type);
void module_call_init(module_init_type type) void module_call_init(module_init_type type)
{ {
ModuleTypeList *l; ModuleTypeList *l;
ModuleEntry *e; ModuleEntry *e;
module_load(type);
l = find_type(type); l = find_type(type);
QTAILQ_FOREACH(e, l, node) { QTAILQ_FOREACH(e, l, node) {
@ -145,6 +142,7 @@ static int module_load_file(const char *fname)
ret = -EINVAL; ret = -EINVAL;
} else { } else {
QTAILQ_FOREACH(e, &dso_init_list, node) { QTAILQ_FOREACH(e, &dso_init_list, node) {
e->init();
register_module_init(e->init, e->type); register_module_init(e->init, e->type);
} }
ret = 0; ret = 0;
@ -159,14 +157,10 @@ out:
} }
#endif #endif
static void module_load(module_init_type type) void module_load_one(const char *prefix, const char *lib_name)
{ {
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
char *fname = NULL; char *fname = NULL;
const char **mp;
static const char *block_modules[] = {
CONFIG_BLOCK_MODULES
};
char *exec_dir; char *exec_dir;
char *dirs[3]; char *dirs[3];
int i = 0; int i = 0;
@ -177,15 +171,6 @@ static void module_load(module_init_type type)
return; return;
} }
switch (type) {
case MODULE_INIT_BLOCK:
mp = block_modules;
break;
default:
/* no other types have dynamic modules for now*/
return;
}
exec_dir = qemu_get_exec_dir(); exec_dir = qemu_get_exec_dir();
dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR); dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : ""); dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
@ -194,16 +179,15 @@ static void module_load(module_init_type type)
g_free(exec_dir); g_free(exec_dir);
exec_dir = NULL; exec_dir = NULL;
for ( ; *mp; mp++) { for (i = 0; i < ARRAY_SIZE(dirs); i++) {
for (i = 0; i < ARRAY_SIZE(dirs); i++) { fname = g_strdup_printf("%s/%s%s%s",
fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF); dirs[i], prefix, lib_name, HOST_DSOSUF);
ret = module_load_file(fname); ret = module_load_file(fname);
g_free(fname); g_free(fname);
fname = NULL; fname = NULL;
/* Try loading until loaded a module file */ /* Try loading until loaded a module file */
if (!ret) { if (!ret) {
break; break;
}
} }
} }

40
vl.c
View File

@ -507,6 +507,43 @@ static QemuOptsList qemu_fw_cfg_opts = {
}, },
}; };
#ifdef CONFIG_LIBISCSI
static QemuOptsList qemu_iscsi_opts = {
.name = "iscsi",
.head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
.desc = {
{
.name = "user",
.type = QEMU_OPT_STRING,
.help = "username for CHAP authentication to target",
},{
.name = "password",
.type = QEMU_OPT_STRING,
.help = "password for CHAP authentication to target",
},{
.name = "password-secret",
.type = QEMU_OPT_STRING,
.help = "ID of the secret providing password for CHAP "
"authentication to target",
},{
.name = "header-digest",
.type = QEMU_OPT_STRING,
.help = "HeaderDigest setting. "
"{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
},{
.name = "initiator-name",
.type = QEMU_OPT_STRING,
.help = "Initiator iqn name to use when connecting",
},{
.name = "timeout",
.type = QEMU_OPT_NUMBER,
.help = "Request timeout in seconds (default 0 = no timeout)",
},
{ /* end of list */ }
},
};
#endif
/** /**
* Get machine options * Get machine options
* *
@ -3017,6 +3054,9 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_icount_opts); qemu_add_opts(&qemu_icount_opts);
qemu_add_opts(&qemu_semihosting_config_opts); qemu_add_opts(&qemu_semihosting_config_opts);
qemu_add_opts(&qemu_fw_cfg_opts); qemu_add_opts(&qemu_fw_cfg_opts);
#ifdef CONFIG_LIBISCSI
qemu_add_opts(&qemu_iscsi_opts);
#endif
module_call_init(MODULE_INIT_OPTS); module_call_init(MODULE_INIT_OPTS);
runstate_init(); runstate_init();