v3: We don't agree on what "protocol" and "format" mean, even less on how they stack, dumb down accordingly Human monitor syntax
v2: Cover protocols Split blockdev_change into media_insert and media_remove Option syntax list TODOs Rationale: Why new commands for block devices? ============================================== We want a clean separation between host part and guest part. Existing -drive and drive_add don't provide that; they were designed to specify both parts together. Moreover, drive_add is limited to adding virtio drives (with pci_add's help) and SCSI drives. We already have commands to specify the guest part: -device and device_add. Support for defining just a host part for use with -device and device_add was grafted onto -drive and drive_add (if=none), but it's a mess. Some parts are redundant, other parts are broken. For instance, unit, bus, index, addr are redundant: -device/device_add don't use them. They provide their own parameters to specify bus and bus-specific address. The checks whether rerror, werror, readonly, cyls, heads, secs are sane for a particular guest device model are broken. The checks are in the -drive code, which used to know what the guest device model supports, but can't with if=none. Moreover, -drive/drive_add have several flaws: * Many parameters set with -drive/drive_add silently revert to defaults on media change. * There are two ways to specify protocol, and both are flawed: you either use parameter format (then you can neither specify a non-default format, nor supply protocol options), or encode it in parameter file (yet another ad hoc mini-language, breaks filenames with ':'). * Behavior when format= is missing is insecure. My proposed solution is a new option -blockdev and monitor command blockdev_add. These specify only the host drive. Guest drive properties are left to -device/device_add. We keep -drive for backwards compatibility and command line convenience. Except we get rid of if=none (may need a grace period). New monitor command blockdev_del works regardless of how the host block device was created. New monitor commands media_insert, media_remove provide full control over the host part, unlike the existing change command. Unfortunately, there's a thorny problem: format and protocol. Right now, our code is consistent with the following structure: * Format + protocols form a tree. * The tree root is the format, and it has exactly one child. * All the other tree nodes are protocols, with a variable number of children. No current protocol has more than one child, though. However, the code has changed quite a bit recently, and it may well change some more. It's not just -drive that is confused about format and protocol, even our block hackers can't quite agree on what they are and how they should play together. Designing a stable, general interface to something we don't understand is hopeless. Instead, we codify existing usage in the simplest imaginable way. Generality has to wait for understanding. If we come up with a more general interface later, that interface will probably do format and protocol differently. We either ditch the current interface then, or keep it as syntactic sugar. Summary of the host / guest split: -drive options host or guest? bus, unit, if, index, addr guest, already covered by qdev cyls, heads, secs, trans guest, new qdev properties (but defaults depend on image) media guest FIXME snapshot, cache, aio host, blockdev_add options file, format host, blockdev_add options separate options for protocol format is just that, not protocol file is just a filename, no protocol rerror, werror host, guest device models will reject values they don't support serial guest, new qdev properties readonly both host & guest, qdev will refuse to connect readonly host to read/write guest QMP command docs ================ blockdev_add ------------ Add host block device. Arguments: - "id": the host block device's ID, must be unique (json-string) - "format": image format (json-string, optional) - Possible values: "raw", "qcow2", ... - "protocol": image access protocol (json-string, optional) - Possible values: "auto", "file", "nbd", ... - Additional members depending on "protocol" - For "protocol": "file", [...] - "file": name of image file (json-string) - For "protocol": "nbd": - "domain": address family (json-string, optional) - Possible values: "inet" (default), "unix" - "file": name of socket file (json-string), only with "domain": "unix" - "host": host name (json-string), only with "domain": "inet" - "port": port (json-int), only with "domain": "inet" [...] - "blkdebug": name of blkdebug config file (json-string, optional) - "aio": host AIO (json-string, optional) - Possible values: "threads" (default), "native" - "cache": host cache usage (json-string, optional) - Possible values: "writethrough" (default), "writeback", "unsafe", "none" - "readonly": open image read-only (json-bool, optional, default false) - "rerror": what to do on read error (json-string, optional) - Possible values: "report" (default), "ignore", "stop" - "werror": what to do on write error (json-string, optional) - Possible values: "enospc" (default), "report", "ignore", "stop" - "snapshot": enable snapshot (json-bool, optional, default false) Example: -> { "execute": "blockdev_add", "arguments": { "id": "blk1", "format": "raw", "protocol": "file", "file": "fedora.img" } } <- { "return": {} } -> { "execute": "blockdev_add", "arguments": { "id": "blk2", "format": "qcow2", "blkdebug": "test.blkdebug", "protocol": "file", "file": "test.qcow2" } } <- { "return": {} } -> { "execute": "blockdev_add", "arguments": { "id": "blk3" } } <- { "return": {} } Notes: (1) If argument "protocol" is missing, all other optional arguments must be missing as well. This defines a block device with no media inserted. (2) It's possible to list supported disk formats and protocols by running QEMU with arguments "-blockdev_add \?". blockdev_del ------------ Remove a host block device. Arguments: - "id": the host block device's ID (json-string) Example: -> { "execute": "blockdev_del", "arguments": { "id": "blk1" } } <- { "return": {} } media_insert ------------ Insert media into an empty host block device. Arguments are exactly like blockdev_add, except "protocol" is mandatory. media_remove ------------ Remove media from a host block device. Arguments: - "id": the host block device's ID (json-string) Example: -> { "execute": "media_remove", "arguments": { "id": "blk1" } } <- { "return": {} } Command line syntax =================== -blockdev syntax corresponds 1:1 to QMP blockdev_add: the members of QMP's argument object become -blockdev's QemuOpts options. Example: -blockdev id=blk1,format=raw,protocol=file,file=fedora.img -blockdev id=blk2,format=qcow2,blkdebug=test.blkdebug,\ protocol=file,file=test.qcow2 -blockdev id=blk3 Sensible defaults are important for usability: * The default format is derived from the image file name: if it ends with .F, where F is a format name, that format is the default, else "raw". * The default protocol depends on the image file type: if it is a special file, it defaults to the protocol appropriate for that special file ("host_cdrom" for CD-ROM, ...). Else it defaults to "file". This permits shortening the first two examples: -blockdev id=blk1,file=fedora.img -blockdev id=blk2,blkdebug=test.blkdebug,file=test.qcow2 Human monitor syntax ==================== blockdev_add ------------ Single argument, which is exactly like -blockdev's argument (args_type is "blockdev:O", where "blockdev" is the name of -blockdev's QemuOptsList). blockdev_del ------------ blockdev_del ID media_insert ------------ Argument are exactly like blockdev_add, except either "protocol" or "file" must be given. media_remove ------------ media_remove ID