static void virDomainObjDispose(void *obj);
static void virDomainXMLOptionDispose(void *obj);
+
+static void
+virDomainChrSourceDefFormat(virBufferPtr buf,
+ virDomainChrSourceDefPtr def,
+ unsigned int flags);
+
+
+static int
+virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt);
+
+
static int virDomainObjOnceInit(void)
{
if (!VIR_CLASS_NEW(virDomainObj, virClassForObjectLockable()))
disk->src->nvme->managed = VIR_TRISTATE_BOOL_YES;
}
+ /* vhost-user doesn't allow us to snapshot, disable snapshots by default */
+ if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER &&
+ disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT) {
+ disk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
+ }
+
if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
virDomainDiskDefAssignAddress(xmlopt, disk, def) < 0) {
return -1;
}
+static int
+virDomainDiskSourceVHostUserParse(xmlNodePtr node,
+ virStorageSourcePtr src,
+ virDomainXMLOptionPtr xmlopt,
+ xmlXPathContextPtr ctxt)
+{
+ g_autofree char *type = virXMLPropString(node, "type");
+ g_autofree char *path = virXMLPropString(node, "path");
+
+ if (!type) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing 'type' attribute for vhostuser disk source"));
+ return -1;
+ }
+
+ if (STRNEQ(type, "unix")) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("invalid 'type' attribute for vhostuser disk source"));
+ return -1;
+ }
+
+ if (!path) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing 'path' attribute for vhostuser disk source"));
+ return -1;
+ }
+
+ if (!(src->vhostuser = virDomainChrSourceDefNew(xmlopt)))
+ return -1;
+
+ src->vhostuser->type = virDomainChrTypeFromString(type);
+ src->vhostuser->data.nix.path = g_steal_pointer(&path);
+
+ if (virDomainChrSourceReconnectDefParseXML(&src->vhostuser->data.nix.reconnect,
+ node,
+ ctxt) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainDiskSourcePRParse(xmlNodePtr node,
xmlXPathContextPtr ctxt,
if (virDomainDiskSourceNVMeParse(node, ctxt, src) < 0)
return -1;
break;
+ case VIR_STORAGE_TYPE_VHOST_USER:
+ if (virDomainDiskSourceVHostUserParse(node, src, xmlopt, ctxt) < 0)
+ return -1;
+ break;
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
}
+static void
+virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
+ virDomainChrSourceReconnectDefPtr def);
+
+
+static void
+virDomainDiskSourceVhostuserFormat(virBufferPtr attrBuf,
+ virBufferPtr childBuf,
+ virDomainChrSourceDefPtr vhostuser)
+{
+ virBufferAddLit(attrBuf, " type='unix'");
+ virBufferAsprintf(attrBuf, " path='%s'", vhostuser->data.nix.path);
+
+ virDomainChrSourceReconnectDefFormat(childBuf, &vhostuser->data.nix.reconnect);
+}
+
+
static int
virDomainDiskSourceFormatPrivateData(virBufferPtr buf,
virStorageSourcePtr src,
virDomainDiskSourceNVMeFormat(&attrBuf, &childBuf, src->nvme);
break;
+ case VIR_STORAGE_TYPE_VHOST_USER:
+ virDomainDiskSourceVhostuserFormat(&attrBuf, &childBuf, src->vhostuser);
+ break;
+
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
#include "domain_validate.h"
#include "domain_conf.h"
+#include "snapshot_conf.h"
#include "virconftypes.h"
#include "virlog.h"
#include "virutil.h"
}
+static int
+virDomainDiskVhostUserValidate(const virDomainDiskDef *disk)
+{
+ if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("vhostuser disk supports only virtio bus"));
+ return -1;
+ }
+
+ if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("only snapshot=no is supported with vhostuser disk"));
+ return -1;
+ }
+
+ /* Unsupported driver attributes */
+
+ if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("cache is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->error_policy || disk->rerror_policy) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("error_policy is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->iomode) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("io is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->ioeventfd != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("ioeventfd is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->copy_on_read) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("copy_on_read is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->discard) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("discard is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->iothread) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("iothread is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->detect_zeroes) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("detect_zeroes is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ /* Unsupported driver elements */
+
+ if (disk->virtio) {
+ if (disk->virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("iommu is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("ats is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->virtio->packed != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("packed is not supported with vhostuser disk"));
+ return -1;
+ }
+ }
+
+ if (disk->src->metadataCacheMaxSize > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("metadata_cache is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ /* Unsupported disk elements */
+
+ if (disk->blkdeviotune.group_name ||
+ virDomainBlockIoTuneInfoHasAny(&disk->blkdeviotune)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("iotune is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->src->backingStore) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("backingStore is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->src->encryption) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("encryption is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->src->readonly) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("readonly is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->src->shared) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("shareable is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->transient) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("transient is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->serial) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("serial is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->wwn) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("wwn is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->vendor) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("vendor is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->product) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("product is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->src->auth) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("auth is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->geometry.cylinders > 0 ||
+ disk->geometry.heads > 0 ||
+ disk->geometry.sectors > 0 ||
+ disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("geometry is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ if (disk->blockio.logical_block_size > 0 ||
+ disk->blockio.physical_block_size > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("blockio is not supported with vhostuser disk"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
#define VENDOR_LEN 8
#define PRODUCT_LEN 16
}
}
+ if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER &&
+ virDomainDiskVhostUserValidate(disk) < 0) {
+ return -1;
+ }
+
for (next = disk->src; next; next = next->backingStore) {
if (virSecurityDeviceLabelDefValidate(next->seclabels,
next->nseclabels,
"network",
"volume",
"nvme",
+ "vhostuser"
);
/* While NVMe disks are local, they are not accessible via src->path.
* Therefore, we have to return false here. */
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_LAST:
case VIR_STORAGE_TYPE_NONE:
return false;
case VIR_STORAGE_TYPE_NETWORK:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
return false;
#include "storage_encryption_conf.h"
#include "virbitmap.h"
+#include "virconftypes.h"
#include "virenum.h"
#include "virobject.h"
#include "virpci.h"
VIR_STORAGE_TYPE_NETWORK,
VIR_STORAGE_TYPE_VOLUME,
VIR_STORAGE_TYPE_NVME,
+ VIR_STORAGE_TYPE_VHOST_USER,
VIR_STORAGE_TYPE_LAST
} virStorageType;
virStorageSourceNVMeDefPtr nvme; /* type == VIR_STORAGE_TYPE_NVME */
+ virDomainChrSourceDefPtr vhostuser; /* type == VIR_STORAGE_TYPE_VHOST_USER */
+
virStorageSourceInitiatorDef initiator;
virObjectPtr privateData;
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
break;
return NULL;
break;
+ case VIR_STORAGE_TYPE_VHOST_USER:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unable to create blockdev props for vhostuser disk type"));
+ return NULL;
+
case VIR_STORAGE_TYPE_VOLUME:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("storage source pool '%s' volume '%s' is not translated"),
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
return 0;
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
break;
case VIR_STORAGE_TYPE_BLOCK:
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
unsafe = true;
break;
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_BLOCK:
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
case VIR_STORAGE_TYPE_DIR:
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
/* We shouldn't get VOLUME, but the switch requires all cases */
case VIR_STORAGE_TYPE_VOLUME:
case VIR_STORAGE_TYPE_NVME:
+ case VIR_STORAGE_TYPE_VHOST_USER:
case VIR_STORAGE_TYPE_NONE:
case VIR_STORAGE_TYPE_LAST:
return -1;
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <memoryBacking>
+ <source type='memfd'/>
+ <access mode='shared'/>
+ </memoryBacking>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ </os>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='vhostuser' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source type='unix' path='/tmp/vhost1.sock'/>
+ <target dev='vda' bus='virtio'/>
+ <boot order='1'/>
+ </disk>
+ <disk type='vhostuser' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source type='unix' path='/tmp/vhost1.sock'>
+ <reconnect enabled='yes' timeout='10'/>
+ </source>
+ <target dev='vdb' bus='virtio'/>
+ </disk>
+ </devices>
+</domain>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <memoryBacking>
+ <source type='memfd'/>
+ <access mode='shared'/>
+ </memoryBacking>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='vhostuser' device='disk' snapshot='no'>
+ <driver name='qemu' type='raw'/>
+ <source type='unix' path='/tmp/vhost1.sock'/>
+ <target dev='vda' bus='virtio'/>
+ <boot order='1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </disk>
+ <disk type='vhostuser' device='disk' snapshot='no'>
+ <driver name='qemu' type='raw'/>
+ <source type='unix' path='/tmp/vhost1.sock'>
+ <reconnect enabled='yes' timeout='10'/>
+ </source>
+ <target dev='vdb' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </disk>
+ <controller type='usb' index='0' model='piix3-uhci'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
DO_TEST("disk-network-tlsx509-nbd", NONE);
DO_TEST("disk-network-tlsx509-vxhs", NONE);
DO_TEST("disk-nvme", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_QCOW2_LUKS);
+ DO_TEST_CAPS_LATEST("disk-vhostuser");
DO_TEST_CAPS_LATEST("disk-scsi");
DO_TEST("disk-virtio-scsi-reservations",
QEMU_CAPS_VIRTIO_SCSI,