fsdev: Error out when unsupported option is passed

Each fsdriver only supports a subset of the options that can be passed
to -fsdev. Unsupported options are simply ignored. This could cause the
user to erroneously think QEMU has a bug.

Enforce strict checking of supported options for all fsdrivers. This
shouldn't impact libvirt, since it doesn't know about the synth and
proxy fsdrivers.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Greg Kurz 2019-05-17 17:34:48 +02:00
parent 2023243573
commit aee7f3ecd8

View File

@ -34,6 +34,7 @@
typedef struct FsDriverTable { typedef struct FsDriverTable {
const char *name; const char *name;
FileOperations *ops; FileOperations *ops;
const char **opts;
} FsDriverTable; } FsDriverTable;
typedef struct FsDriverListEntry { typedef struct FsDriverListEntry {
@ -44,12 +45,75 @@ typedef struct FsDriverListEntry {
static QTAILQ_HEAD(, FsDriverListEntry) fsdriver_entries = static QTAILQ_HEAD(, FsDriverListEntry) fsdriver_entries =
QTAILQ_HEAD_INITIALIZER(fsdriver_entries); QTAILQ_HEAD_INITIALIZER(fsdriver_entries);
#define COMMON_FS_DRIVER_OPTIONS "id", "fsdriver", "readonly"
static FsDriverTable FsDrivers[] = { static FsDriverTable FsDrivers[] = {
{ .name = "local", .ops = &local_ops}, {
{ .name = "synth", .ops = &synth_ops}, .name = "local",
{ .name = "proxy", .ops = &proxy_ops}, .ops = &local_ops,
.opts = (const char * []) {
COMMON_FS_DRIVER_OPTIONS,
"security_model",
"path",
"writeout",
"fmode",
"dmode",
"throttling.bps-total",
"throttling.bps-read",
"throttling.bps-write",
"throttling.iops-total",
"throttling.iops-read",
"throttling.iops-write",
"throttling.bps-total-max",
"throttling.bps-read-max",
"throttling.bps-write-max",
"throttling.iops-total-max",
"throttling.iops-read-max",
"throttling.iops-write-max",
"throttling.bps-total-max-length",
"throttling.bps-read-max-length",
"throttling.bps-write-max-length",
"throttling.iops-total-max-length",
"throttling.iops-read-max-length",
"throttling.iops-write-max-length",
"throttling.iops-size",
},
},
{
.name = "synth",
.ops = &synth_ops,
.opts = (const char * []) {
COMMON_FS_DRIVER_OPTIONS,
},
},
{
.name = "proxy",
.ops = &proxy_ops,
.opts = (const char * []) {
COMMON_FS_DRIVER_OPTIONS,
"socket",
"sock_fd",
"writeout",
},
},
}; };
static int validate_opt(void *opaque, const char *name, const char *value,
Error **errp)
{
FsDriverTable *drv = opaque;
const char **opt;
for (opt = drv->opts; *opt; opt++) {
if (!strcmp(*opt, name)) {
return 0;
}
}
error_setg(errp, "'%s' is invalid for fsdriver '%s'", name, drv->name);
return -1;
}
int qemu_fsdev_add(QemuOpts *opts, Error **errp) int qemu_fsdev_add(QemuOpts *opts, Error **errp)
{ {
int i; int i;
@ -80,6 +144,10 @@ int qemu_fsdev_add(QemuOpts *opts, Error **errp)
return -1; return -1;
} }
if (qemu_opt_foreach(opts, validate_opt, &FsDrivers[i], errp)) {
return -1;
}
fsle = g_malloc0(sizeof(*fsle)); fsle = g_malloc0(sizeof(*fsle));
fsle->fse.fsdev_id = g_strdup(fsdev_id); fsle->fse.fsdev_id = g_strdup(fsdev_id);
fsle->fse.ops = FsDrivers[i].ops; fsle->fse.ops = FsDrivers[i].ops;