Skip to content

kvm: make the virtio-blk disk controller usable - #10

Closed
calvix wants to merge 2 commits into
mainfrom
feature/kvm-virtio-blk-controller-main
Closed

calvix wants to merge 2 commits into
mainfrom
feature/kvm-virtio-blk-controller-main

Conversation

@calvix

@calvix calvix commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

When the VM setting rootDiskController=virtio-blk is set, there is an error that blocks the start of a VM.
DiskBus renders its own value into the libvirt disk XML, and virtio-blk is not one of libvirt's target buses (ide, scsi, virtio, xen, usb, sata, sd, fdc, uml), so libvirt rejects the domain and the start fails on every host.

We wanted to use virtio-vlk in order to get virtio disk with discard='unmap', plain virtio disks keep libvirt's default discard='ignore', so a guest's TRIM never reaches the storage. On Ceph RBD that means deleted data keeps occupying the pool.

Reproduction

Any KVM host and template will do:

cmk deploy virtualmachine zoneid=<zone> serviceofferingid=<offering> \
    templateid=<any KVM template> networkids=<network> \
    'details[0].rootDiskController=virtio-blk'

The deploy job fails with errorcode 530, "Unable to orchestrate the start of VM instance", and the instance is left in the Error state. The planner retries on every host in the zone, and each agent logs:

WARN  [resource.wrapper.LibvirtStartCommandWrapper] ... LibvirtException
org.libvirt.LibvirtException: XML error: Invalid value for attribute 'bus' in
element 'target': 'virtio-blk'.

It is not version specific: the bus name is rejected by libvirt's own schema, so it fails the same way on libvirt 10.0.0 / QEMU 8.2.2 and on libvirt 12.0.0 / QEMU 10.2.1.

virtio-blk is also offered as a supported value: for a KVM resource, listDetailOptions returns it for both controller details, so the UI and API advertise a value that cannot start a VM:

$ cmk list detailoptions resourcetype=Template resourceid=<KVM template>
{
  "detailoptions": {
    "details": {
      ...
      "dataDiskController": [
        "osdefault",
        "ide",
        "scsi",
        "virtio",
        "virtio-blk"
      ],
      ...
      "rootDiskController": [
        "osdefault",
        "ide",
        "scsi",
        "virtio",
        "virtio-blk"
      ],
      ...
    }
  }
}

The list comes from QueryManagerImpl.fillVMOrTemplateDetailOptions, which adds these KVM-only options when the resource's hypervisor is KVM; without a resourceid the controller keys are not returned at all.

Changes

  • Render the libvirt bus name instead of the enum value.

  • Label virtio-blk disks vd*, as virtio disks are labelled. They previously fell through to the hd* branch, so even a valid bus would have produced an IDE-style target name.

  • Data disks follow a virtio-blk root, as they already follow a SCSI one, so a VM that opts in gets discard on all of its disks.

  • A data disk with no controller of its own follows the root detail when attaching. The attach path cannot recover the controller from the running domain XML, where a virtio-blk disk is indistinguishable from a virtio one; without this a hot-plugged disk silently loses discard until the next stop/start. The scan of the running disks still runs first, so a VM started on SCSI whose rootDiskController detail was later changed to virtio-blk keeps getting SCSI disks instead of a virtio disk next to its sd* ones.

  • Virtio-blk disks get the iothread= binding when the VM has iothreads enabled, as virtio disks do. It was gated on the VIRTIO enum value only, so a virtio-blk VM ran with io='threads' but no iothread on any disk.

The VM detail rootDiskController=virtio-blk has never been able to start a VM.
DiskBus renders its own value into the libvirt disk XML, and 'virtio-blk' is
not one of libvirt's target buses (ide, scsi, virtio, xen, usb, sata, sd, fdc,
uml), so libvirt rejects the domain and every host fails the start with:

  XML error: Invalid value for attribute 'bus' in element 'target': 'virtio-blk'

The point of the controller was a virtio disk with discard='unmap', so that
combination has been unreachable: only SCSI disks get discard on KVM today,
and plain virtio disks keep libvirt's default discard='ignore', which drops a
guest's TRIM before it reaches the storage.

Render the libvirt bus name rather than the enum value, leaving toString() and
fromValue() alone so the detail keeps parsing, and label virtio-blk disks vd*
as virtio disks are labelled. Data disks now follow a virtio-blk root as they
already follow a SCSI one, so a VM that opts in gets discard on all its disks,
and the second attach path gives a hot-plugged disk the same discard the
volume-attach path does.

A disk being attached cannot recover the controller from the running domain
XML, where a virtio-blk disk is indistinguishable from a virtio one, so a data
disk with no controller of its own follows the root detail; without that a
hot-plugged disk silently loses discard until the next stop/start.

Verified on a KVM host with Ceph RBD primary storage: the VM starts, every
disk is bus='virtio' with discard='unmap', guest device names are stable
across reboot and stop/start, and after an fstrim in the guest 700 MiB of the
728 MiB written was returned to the pool.
… win on attach

A disk with iothreads enabled got its iothread= binding only when its bus was
VIRTIO, although a virtio-blk disk is rendered with the same libvirt bus. A
virtio-blk VM with the iothreads detail therefore ran every disk with
io='threads' but no iothread, and data disks following a virtio-blk root now
lost it as well. Treat VIRTIOBLK like VIRTIO there.

When a data disk is attached without a controller of its own, the virtio-blk
root fallback ran before the scan of the running domain. The root detail can
be changed on a running VM, so a VM started on SCSI whose detail was later set
to virtio-blk would get a virtio disk hot-plugged next to its sd* ones. Scan
the running disks first and use the fallback only when no SCSI disk is there.
@calvix calvix closed this Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant