QEMU APIs: introduction to QemuOpts
This post is a short introduction to the QemuOpts API inside QEMU. This is part of a series, see the introduction for other pointers and additional information.
QemuOpts was introduced in 2009. It is a simple abstraction that handles two tasks:
- Parsing of config files and command-line options
- Storage of configuration options
Data structures
The QemuOpts data model is pretty simple:
-
QemuOptsList
carries the list of all options belonging to a given config group. Each entity is represented by aQemuOpts
struct. -
QemuOpts
represents a set of key-value pairs. (Some of the code refers to that as a config group, but to avoid confusion withQemuOptsList
, I will call them config sections). -
QemuOpt
is a single key=value pair.
Some config groups have multiple QemuOpts
structs (e.g.
“drive”, “object”, “device”, that represent multiple drives,
multiple objects, and multiple devices, respectively), while
others always have only one QemuOpts
struct (e.g. the “machine”
config group).
For example, the following command-line options:
-drive id=disk1,file=disk.raw,format=raw,if=ide \
-drive id=disk2,file=disk.qcow2,format=qcow2,if=virtio \
-machine usb=on -machine accel=kvm
are represented internally as:
Data Types
QemuOpts supports a limited number of data types for option values:
- Strings
- Boolean options
- Numbers (integers)
- Sizes
Strings
Strings are just used as-is, after the command-line or config file is parsed.
Note: On the command-line, options are separated by commas, but
commas inside option values can be escaped as ,,
.
Boolean options
The QemuOpt parser accepts only “on” and “off” as values for this option.
Warning: note that this behavior is different from the QOM property parser. I plan to explore this in future posts.
Numbers (integers)
Numbers are supposed to be unsigned 64-bit integers. However, the
code relies on the behavior of strtoull()
and does not
reject negative numbers. That means the parsed uint64_t
value
might be converted to a signed integer later. For example, the
following command-line is not rejected by QEMU:
$ qemu-system-x86_64 -smp cpus=-18446744073709551615,cores=1,threads=1
I don’t know if there is existing code that requires negative numbers to be accepted by the QemuOpts parser. I assume it exists, so we couldn’t easily change the existing parsing rules without breaking existing code.
Sizes
Sizes are represented internally as integers, but the parser accept suffixes like K, M, G, T.
qemu-system-x86_64 -m size=2G
is equivalent to:
qemu-system-x86_64 -m size=2048M
Note: there are two different size-suffix parsers inside QEMU: one at util/cutils.c and another at util/qemu-option.c. Figuring out which one is going to be used is left as an exercise to the reader.
Working around the QemuOpts parsers
QEMU code sometimes uses tricks to avoid or work around the QemuOpts option value parsers:
Example 1: using the raw option value
It is possible to get the original raw option value as a string
using qemu_opt_get()
, even after it was already parsed. For
example, the code that handles memory options in QEMU does that,
to ensure a suffix-less number is interpreted as Mebibytes, not
bytes:
Example 2: empty option name list
Some options do not use the QemuOpts value parsers at all, by not defining any option names in the QemuOptsList struct. In those cases, the option values are parsed and validated using different methods. Some examples:
This is a common pattern when options are translated to other data representations: mostly QOM properties or QAPI structs. I plan to explore this in a future blog post.
The following config groups use this method and do their own parsing/validation of config options: acpi, device, drive, machine, net, netdev, numa, object, smbios, tpmdev
-writeconfig
The QemuOpts code is responsible for two tasks:
- Parsing command-line options and config files
- Storage of configuration options
This means sometimes config options are parsed by custom code and
converted to QemuOpts data structures. Storage of config options
inside QemuOpts allow the existing QEMU configuration to be
written to a file using the -writeconfig
command-line option.
The original commit introducing
-writeconfig
describes it this way:
In theory you should be able to do:
qemu < machine config cmd line switches here > -writeconfig vm.cfg qemu -readconfig vm.cfg
In practice it will not work. Not all command line switches are converted to QemuOpts, so you’ll have to keep the not-yet converted ones on the second line. Also there might be bugs lurking which prevent even the converted ones from working correctly.
This has improved over the years, but the comment still applies today: most command-line options are converted to QemuOpts options, but not all of them.
Further reading
- Main QemuOptsList registration code
- QemuOpts code: qemu-option.c, qemu-config.c
- opts-visitor.c: used when converting QemuOpts to QOM properties or QAPI structures