aboutsummaryrefslogtreecommitdiff
path: root/block/blkdebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blkdebug.c')
-rw-r--r--block/blkdebug.c114
1 files changed, 82 insertions, 32 deletions
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 37cfbc7fc8..3d03fcb637 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -273,11 +273,6 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)
int ret;
struct add_rule_data d;
- /* Allow usage without config file */
- if (!*filename) {
- return 0;
- }
-
f = fopen(filename, "r");
if (f == NULL) {
return -errno;
@@ -304,44 +299,99 @@ fail:
}
/* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
-static int blkdebug_open(BlockDriverState *bs, const char *filename,
- QDict *options, int flags)
+static void blkdebug_parse_filename(const char *filename, QDict *options,
+ Error **errp)
{
- BDRVBlkdebugState *s = bs->opaque;
- int ret;
- char *config, *c;
+ const char *c;
/* Parse the blkdebug: prefix */
- if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) {
- return -EINVAL;
+ if (!strstart(filename, "blkdebug:", &filename)) {
+ error_setg(errp, "File name string must start with 'blkdebug:'");
+ return;
}
- filename += strlen("blkdebug:");
- /* Read rules from config file */
+ /* Parse config file path */
c = strchr(filename, ':');
if (c == NULL) {
- return -EINVAL;
+ error_setg(errp, "blkdebug requires both config file and image path");
+ return;
}
- config = g_strdup(filename);
- config[c - filename] = '\0';
- ret = read_config(s, config);
- g_free(config);
- if (ret < 0) {
- return ret;
+ if (c != filename) {
+ QString *config_path;
+ config_path = qstring_from_substr(filename, 0, c - filename - 1);
+ qdict_put(options, "config", config_path);
}
+
+ /* TODO Allow multi-level nesting and set file.filename here */
filename = c + 1;
+ qdict_put(options, "x-image", qstring_from_str(filename));
+}
+
+static QemuOptsList runtime_opts = {
+ .name = "blkdebug",
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
+ .desc = {
+ {
+ .name = "config",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to the configuration file",
+ },
+ {
+ .name = "x-image",
+ .type = QEMU_OPT_STRING,
+ .help = "[internal use only, will be removed]",
+ },
+ { /* end of list */ }
+ },
+};
+
+static int blkdebug_open(BlockDriverState *bs, const char *dummy,
+ QDict *options, int flags)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ QemuOpts *opts;
+ Error *local_err = NULL;
+ const char *filename, *config;
+ int ret;
+
+ opts = qemu_opts_create_nofail(&runtime_opts);
+ qemu_opts_absorb_qdict(opts, options, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* Read rules from config file */
+ config = qemu_opt_get(opts, "config");
+ if (config) {
+ ret = read_config(s, config);
+ if (ret < 0) {
+ goto fail;
+ }
+ }
/* Set initial state */
s->state = 1;
/* Open the backing file */
+ filename = qemu_opt_get(opts, "x-image");
+ if (filename == NULL) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
ret = bdrv_file_open(&bs->file, filename, NULL, flags);
if (ret < 0) {
- return ret;
+ goto fail;
}
- return 0;
+ ret = 0;
+fail:
+ qemu_opts_del(opts);
+ return ret;
}
static void error_callback_bh(void *opaque)
@@ -569,17 +619,17 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
}
static BlockDriver bdrv_blkdebug = {
- .format_name = "blkdebug",
- .protocol_name = "blkdebug",
-
- .instance_size = sizeof(BDRVBlkdebugState),
+ .format_name = "blkdebug",
+ .protocol_name = "blkdebug",
+ .instance_size = sizeof(BDRVBlkdebugState),
- .bdrv_file_open = blkdebug_open,
- .bdrv_close = blkdebug_close,
- .bdrv_getlength = blkdebug_getlength,
+ .bdrv_parse_filename = blkdebug_parse_filename,
+ .bdrv_file_open = blkdebug_open,
+ .bdrv_close = blkdebug_close,
+ .bdrv_getlength = blkdebug_getlength,
- .bdrv_aio_readv = blkdebug_aio_readv,
- .bdrv_aio_writev = blkdebug_aio_writev,
+ .bdrv_aio_readv = blkdebug_aio_readv,
+ .bdrv_aio_writev = blkdebug_aio_writev,
.bdrv_debug_event = blkdebug_debug_event,
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,