mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
qemu: implement vhost-user-blk support
Implements QEMU support for vhost-user-blk together with live hotplug/unplug. Signed-off-by: Pavel Hrdina <phrdina@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
c8b0d5b0ad
commit
d763466edc
@ -1642,6 +1642,8 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
|
|||||||
VIR_FREE(data->httpcookiesecretAlias);
|
VIR_FREE(data->httpcookiesecretAlias);
|
||||||
VIR_FREE(data->driveCmd);
|
VIR_FREE(data->driveCmd);
|
||||||
VIR_FREE(data->driveAlias);
|
VIR_FREE(data->driveAlias);
|
||||||
|
VIR_FREE(data->chardevAlias);
|
||||||
|
VIR_FREE(data->chardevCmd);
|
||||||
VIR_FREE(data);
|
VIR_FREE(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1815,6 +1817,13 @@ qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
|
|||||||
data->driveAdded = true;
|
data->driveAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->chardevDef) {
|
||||||
|
if (qemuMonitorAttachCharDev(mon, data->chardevAlias, data->chardevDef) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
data->chardevAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1837,6 +1846,13 @@ qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
virErrorPreserveLast(&orig_err);
|
virErrorPreserveLast(&orig_err);
|
||||||
|
|
||||||
|
if (data->chardevAdded) {
|
||||||
|
if (qemuMonitorDetachCharDev(mon, data->chardevAlias) < 0) {
|
||||||
|
VIR_WARN("Unable to remove chardev %s after failed " "qemuMonitorAddDevice",
|
||||||
|
data->chardevAlias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (data->driveAdded) {
|
if (data->driveAdded) {
|
||||||
if (qemuMonitorDriveDel(mon, data->driveAlias) < 0)
|
if (qemuMonitorDriveDel(mon, data->driveAlias) < 0)
|
||||||
VIR_WARN("Unable to remove drive %s (%s) after failed "
|
VIR_WARN("Unable to remove drive %s (%s) after failed "
|
||||||
@ -2004,6 +2020,32 @@ qemuBlockStorageSourceChainDetachPrepareDrive(virStorageSourcePtr src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBlockStorageSourceChainDetachPrepareChardev
|
||||||
|
* @src: storage source chain to remove
|
||||||
|
*
|
||||||
|
* Prepares qemuBlockStorageSourceChainDataPtr for detaching @src and its
|
||||||
|
* backingStore if -chardev was used.
|
||||||
|
*/
|
||||||
|
qemuBlockStorageSourceChainDataPtr
|
||||||
|
qemuBlockStorageSourceChainDetachPrepareChardev(char *chardevAlias)
|
||||||
|
{
|
||||||
|
g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL;
|
||||||
|
g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
|
||||||
|
|
||||||
|
data = g_new0(qemuBlockStorageSourceChainData, 1);
|
||||||
|
backend = g_new0(qemuBlockStorageSourceAttachData, 1);
|
||||||
|
|
||||||
|
backend->chardevAlias = chardevAlias;
|
||||||
|
backend->chardevAdded = true;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, backend) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemuBlockStorageSourceChainAttach:
|
* qemuBlockStorageSourceChainAttach:
|
||||||
* @mon: monitor object
|
* @mon: monitor object
|
||||||
|
@ -99,6 +99,11 @@ struct qemuBlockStorageSourceAttachData {
|
|||||||
char *driveAlias;
|
char *driveAlias;
|
||||||
bool driveAdded;
|
bool driveAdded;
|
||||||
|
|
||||||
|
virDomainChrSourceDefPtr chardevDef;
|
||||||
|
char *chardevAlias;
|
||||||
|
char *chardevCmd;
|
||||||
|
bool chardevAdded;
|
||||||
|
|
||||||
virJSONValuePtr authsecretProps;
|
virJSONValuePtr authsecretProps;
|
||||||
char *authsecretAlias;
|
char *authsecretAlias;
|
||||||
|
|
||||||
@ -160,6 +165,8 @@ qemuBlockStorageSourceChainDetachPrepareBlockdev(virStorageSourcePtr src);
|
|||||||
qemuBlockStorageSourceChainDataPtr
|
qemuBlockStorageSourceChainDataPtr
|
||||||
qemuBlockStorageSourceChainDetachPrepareDrive(virStorageSourcePtr src,
|
qemuBlockStorageSourceChainDetachPrepareDrive(virStorageSourcePtr src,
|
||||||
char *driveAlias);
|
char *driveAlias);
|
||||||
|
qemuBlockStorageSourceChainDataPtr
|
||||||
|
qemuBlockStorageSourceChainDetachPrepareChardev(char *chardevAlias);
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuBlockStorageSourceChainAttach(qemuMonitorPtr mon,
|
qemuBlockStorageSourceChainAttach(qemuMonitorPtr mon,
|
||||||
|
@ -1714,9 +1714,16 @@ qemuBuildDiskDeviceStr(const virDomainDef *def,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
||||||
if (qemuBuildVirtioDevStr(&opt, "virtio-blk", qemuCaps,
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
VIR_DOMAIN_DEVICE_DISK, disk) < 0) {
|
if (qemuBuildVirtioDevStr(&opt, "vhost-user-blk", qemuCaps,
|
||||||
return NULL;
|
VIR_DOMAIN_DEVICE_DISK, disk) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (qemuBuildVirtioDevStr(&opt, "virtio-blk", qemuCaps,
|
||||||
|
VIR_DOMAIN_DEVICE_DISK, disk) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->iothread)
|
if (disk->iothread)
|
||||||
@ -1775,11 +1782,17 @@ qemuBuildDiskDeviceStr(const virDomainDef *def,
|
|||||||
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
|
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
|
||||||
virBufferAddLit(&opt, ",share-rw=on");
|
virBufferAddLit(&opt, ",share-rw=on");
|
||||||
|
|
||||||
if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
return NULL;
|
backendAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
||||||
|
|
||||||
if (backendAlias)
|
virBufferAsprintf(&opt, ",chardev=%s", backendAlias);
|
||||||
virBufferAsprintf(&opt, ",drive=%s", backendAlias);
|
} else {
|
||||||
|
if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (backendAlias)
|
||||||
|
virBufferAsprintf(&opt, ",drive=%s", backendAlias);
|
||||||
|
}
|
||||||
|
|
||||||
virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
|
virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
|
||||||
if (bootindex)
|
if (bootindex)
|
||||||
@ -1989,6 +2002,9 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd,
|
|||||||
if (data->driveCmd)
|
if (data->driveCmd)
|
||||||
virCommandAddArgList(cmd, "-drive", data->driveCmd, NULL);
|
virCommandAddArgList(cmd, "-drive", data->driveCmd, NULL);
|
||||||
|
|
||||||
|
if (data->chardevCmd)
|
||||||
|
virCommandAddArgList(cmd, "-chardev", data->chardevCmd, NULL);
|
||||||
|
|
||||||
if (data->storageProps) {
|
if (data->storageProps) {
|
||||||
if (!(tmp = virJSONValueToString(data->storageProps, false)))
|
if (!(tmp = virJSONValueToString(data->storageProps, false)))
|
||||||
return -1;
|
return -1;
|
||||||
@ -2027,7 +2043,10 @@ qemuBuildDiskSourceCommandLine(virCommandPtr cmd,
|
|||||||
g_autofree char *copyOnReadPropsStr = NULL;
|
g_autofree char *copyOnReadPropsStr = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
|
||||||
|
return -1;
|
||||||
|
} else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
||||||
!qemuDiskBusIsSD(disk->bus)) {
|
!qemuDiskBusIsSD(disk->bus)) {
|
||||||
if (virStorageSourceIsEmpty(disk->src))
|
if (virStorageSourceIsEmpty(disk->src))
|
||||||
return 0;
|
return 0;
|
||||||
@ -10296,6 +10315,39 @@ qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBuildStorageSourceAttachPrepareChardev:
|
||||||
|
* @src: disk source to prepare
|
||||||
|
*
|
||||||
|
* Prepare qemuBlockStorageSourceAttachDataPtr for vhost-user disk
|
||||||
|
* to be used with -chardev.
|
||||||
|
*/
|
||||||
|
qemuBlockStorageSourceAttachDataPtr
|
||||||
|
qemuBuildStorageSourceAttachPrepareChardev(virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
|
||||||
|
g_auto(virBuffer) chardev = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
data = g_new0(qemuBlockStorageSourceAttachData, 1);
|
||||||
|
|
||||||
|
data->chardevDef = disk->src->vhostuser;
|
||||||
|
data->chardevAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
||||||
|
|
||||||
|
virBufferAddLit(&chardev, "socket");
|
||||||
|
virBufferAsprintf(&chardev, ",id=%s", data->chardevAlias);
|
||||||
|
virBufferAddLit(&chardev, ",path=");
|
||||||
|
virQEMUBuildBufferEscapeComma(&chardev, disk->src->vhostuser->data.nix.path);
|
||||||
|
|
||||||
|
qemuBuildChrChardevReconnectStr(&chardev,
|
||||||
|
&disk->src->vhostuser->data.nix.reconnect);
|
||||||
|
|
||||||
|
if (!(data->chardevCmd = virBufferContentAndReset(&chardev)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemuBuildStorageSourceAttachPrepareCommon:
|
* qemuBuildStorageSourceAttachPrepareCommon:
|
||||||
* @src: storage source
|
* @src: storage source
|
||||||
@ -10378,6 +10430,31 @@ qemuBuildStorageSourceChainAttachPrepareDrive(virDomainDiskDefPtr disk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBuildStorageSourceChainAttachPrepareChardev:
|
||||||
|
* @src: disk definition
|
||||||
|
*
|
||||||
|
* Prepares qemuBlockStorageSourceChainDataPtr for attaching a vhost-user
|
||||||
|
* disk's backend via -chardev.
|
||||||
|
*/
|
||||||
|
qemuBlockStorageSourceChainDataPtr
|
||||||
|
qemuBuildStorageSourceChainAttachPrepareChardev(virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
g_autoptr(qemuBlockStorageSourceAttachData) elem = NULL;
|
||||||
|
g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
|
||||||
|
|
||||||
|
data = g_new0(qemuBlockStorageSourceChainData, 1);
|
||||||
|
|
||||||
|
if (!(elem = qemuBuildStorageSourceAttachPrepareChardev(disk)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuBuildStorageSourceChainAttachPrepareBlockdevOne(qemuBlockStorageSourceChainData *data,
|
qemuBuildStorageSourceChainAttachPrepareBlockdevOne(qemuBlockStorageSourceChainData *data,
|
||||||
virStorageSourcePtr src,
|
virStorageSourcePtr src,
|
||||||
|
@ -115,6 +115,10 @@ bool qemuDiskBusIsSD(int bus);
|
|||||||
qemuBlockStorageSourceAttachDataPtr
|
qemuBlockStorageSourceAttachDataPtr
|
||||||
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
|
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
|
||||||
virQEMUCapsPtr qemuCaps);
|
virQEMUCapsPtr qemuCaps);
|
||||||
|
|
||||||
|
qemuBlockStorageSourceAttachDataPtr
|
||||||
|
qemuBuildStorageSourceAttachPrepareChardev(virDomainDiskDefPtr disk);
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuBuildStorageSourceAttachPrepareCommon(virStorageSourcePtr src,
|
qemuBuildStorageSourceAttachPrepareCommon(virStorageSourcePtr src,
|
||||||
qemuBlockStorageSourceAttachDataPtr data,
|
qemuBlockStorageSourceAttachDataPtr data,
|
||||||
@ -126,6 +130,10 @@ qemuBuildStorageSourceChainAttachPrepareDrive(virDomainDiskDefPtr disk,
|
|||||||
virQEMUCapsPtr qemuCaps);
|
virQEMUCapsPtr qemuCaps);
|
||||||
|
|
||||||
|
|
||||||
|
qemuBlockStorageSourceChainDataPtr
|
||||||
|
qemuBuildStorageSourceChainAttachPrepareChardev(virDomainDiskDefPtr disk);
|
||||||
|
|
||||||
|
|
||||||
qemuBlockStorageSourceChainDataPtr
|
qemuBlockStorageSourceChainDataPtr
|
||||||
qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSourcePtr top,
|
qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSourcePtr top,
|
||||||
virQEMUCapsPtr qemuCaps);
|
virQEMUCapsPtr qemuCaps);
|
||||||
|
@ -10652,6 +10652,11 @@ qemuDomainPrepareDiskSource(virDomainDiskDefPtr disk,
|
|||||||
qemuDomainObjPrivatePtr priv,
|
qemuDomainObjPrivatePtr priv,
|
||||||
virQEMUDriverConfigPtr cfg)
|
virQEMUDriverConfigPtr cfg)
|
||||||
{
|
{
|
||||||
|
/* Nothing to prepare as it will use -chardev instead
|
||||||
|
* of -blockdev/-drive option. */
|
||||||
|
if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER)
|
||||||
|
return 0;
|
||||||
|
|
||||||
qemuDomainPrepareDiskCachemode(disk);
|
qemuDomainPrepareDiskCachemode(disk);
|
||||||
|
|
||||||
/* set default format for storage pool based disks */
|
/* set default format for storage pool based disks */
|
||||||
@ -11142,6 +11147,13 @@ qemuDomainDiskBlockJobIsSupported(virDomainObjPtr vm,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||||
|
_("block jobs are not supported on vhostuser disk '%s'"),
|
||||||
|
disk->dst);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9821,6 +9821,12 @@ qemuDomainBlockResize(virDomainPtr dom,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("block resize is not supported for vhostuser disk"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
/* qcow2 and qed must be sized on 512 byte blocks/sectors,
|
/* qcow2 and qed must be sized on 512 byte blocks/sectors,
|
||||||
* so adjust size if necessary to round up.
|
* so adjust size if necessary to round up.
|
||||||
*/
|
*/
|
||||||
@ -9913,6 +9919,12 @@ qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("block stats are not supported for vhostuser disk"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
||||||
entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
||||||
} else {
|
} else {
|
||||||
@ -9968,6 +9980,10 @@ qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
|
|||||||
disk = vm->def->disks[i];
|
disk = vm->def->disks[i];
|
||||||
entryname = disk->info.alias;
|
entryname = disk->info.alias;
|
||||||
|
|
||||||
|
/* No stats to report for vhost-user disk */
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName)
|
if (blockdev && QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName)
|
||||||
entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
||||||
|
|
||||||
@ -10616,6 +10632,12 @@ qemuDomainBlockPeek(virDomainPtr dom,
|
|||||||
if (!(disk = qemuDomainDiskByName(vm->def, path)))
|
if (!(disk = qemuDomainDiskByName(vm->def, path)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("peeking is not supported for vhostuser disk"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (disk->src->format != VIR_STORAGE_FILE_RAW) {
|
if (disk->src->format != VIR_STORAGE_FILE_RAW) {
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||||
_("peeking is only supported for disk with 'raw' format not '%s'"),
|
_("peeking is only supported for disk with 'raw' format not '%s'"),
|
||||||
@ -10973,6 +10995,12 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("block info is not supported for vhostuser disk"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
if (virStorageSourceIsEmpty(disk->src)) {
|
if (virStorageSourceIsEmpty(disk->src)) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("disk '%s' does not currently have a source assigned"),
|
_("disk '%s' does not currently have a source assigned"),
|
||||||
@ -15851,6 +15879,19 @@ typedef enum {
|
|||||||
} qemuBlockIoTuneSetFlags;
|
} qemuBlockIoTuneSetFlags;
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
qemuDomainDiskBlockIoTuneIsSupported(virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("a block I/O throttling is not supported for vhostuser disk"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If the user didn't specify bytes limits, inherit previous values;
|
/* If the user didn't specify bytes limits, inherit previous values;
|
||||||
* likewise if the user didn't specify iops limits. */
|
* likewise if the user didn't specify iops limits. */
|
||||||
static int
|
static int
|
||||||
@ -16219,6 +16260,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
|||||||
if (!(disk = qemuDomainDiskByName(def, path)))
|
if (!(disk = qemuDomainDiskByName(def, path)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
||||||
QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
||||||
qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
||||||
@ -16312,6 +16356,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qemuDomainDiskBlockIoTuneIsSupported(conf_disk->src))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
conf_cur_info = qemuDomainFindGroupBlockIoTune(persistentDef, conf_disk, &info);
|
conf_cur_info = qemuDomainFindGroupBlockIoTune(persistentDef, conf_disk, &info);
|
||||||
|
|
||||||
if (qemuDomainSetBlockIoTuneDefaults(&conf_info, conf_cur_info,
|
if (qemuDomainSetBlockIoTuneDefaults(&conf_info, conf_cur_info,
|
||||||
@ -16412,6 +16459,9 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
|
|||||||
if (!(disk = qemuDomainDiskByName(def, path)))
|
if (!(disk = qemuDomainDiskByName(def, path)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
||||||
QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName) {
|
||||||
qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
|
||||||
@ -16434,6 +16484,10 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
|
|||||||
path);
|
path);
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qemuDomainDiskBlockIoTuneIsSupported(disk->src))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
reply = disk->blkdeviotune;
|
reply = disk->blkdeviotune;
|
||||||
|
|
||||||
/* Group name needs to be copied since qemuMonitorGetBlockIoThrottle
|
/* Group name needs to be copied since qemuMonitorGetBlockIoThrottle
|
||||||
@ -18364,6 +18418,18 @@ qemuDomainGetStatsBlockExportDisk(virDomainDiskDefPtr disk,
|
|||||||
params);
|
params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vhost-user disk doesn't support getting block stats */
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
if (qemuDomainGetStatsBlockExportHeader(disk, disk->src, *recordnr,
|
||||||
|
params) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*recordnr)++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
|
for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
|
||||||
g_autofree char *alias = NULL;
|
g_autofree char *alias = NULL;
|
||||||
|
|
||||||
@ -19571,6 +19637,12 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
|
|||||||
if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def, priv->backup)))
|
if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def, priv->backup)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("setting device threshold is not supported for vhostuser disk"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) &&
|
||||||
!src->nodestorage &&
|
!src->nodestorage &&
|
||||||
qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
|
qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
|
||||||
|
@ -714,7 +714,10 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
|
|||||||
if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (blockdev) {
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
|
||||||
|
goto cleanup;
|
||||||
|
} else if (blockdev) {
|
||||||
if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON) {
|
if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON) {
|
||||||
if (!(corProps = qemuBlockStorageGetCopyOnReadProps(disk)))
|
if (!(corProps = qemuBlockStorageGetCopyOnReadProps(disk)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -4314,8 +4317,13 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
|
|||||||
disk->info.alias, vm, vm->def->name);
|
disk->info.alias, vm, vm->def->name);
|
||||||
|
|
||||||
|
|
||||||
if (blockdev &&
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
!qemuDiskBusIsSD(disk->bus)) {
|
char *chardevAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
||||||
|
|
||||||
|
if (!(diskBackend = qemuBlockStorageSourceChainDetachPrepareChardev(chardevAlias)))
|
||||||
|
goto cleanup;
|
||||||
|
} else if (blockdev &&
|
||||||
|
!qemuDiskBusIsSD(disk->bus)) {
|
||||||
corAlias = g_strdup(diskPriv->nodeCopyOnRead);
|
corAlias = g_strdup(diskPriv->nodeCopyOnRead);
|
||||||
|
|
||||||
if (diskPriv->blockjob) {
|
if (diskPriv->blockjob) {
|
||||||
|
@ -2957,6 +2957,19 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_USER_BLK)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("vhostuser disk is not supported with this QEMU binary"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemuValidateDomainDefVhostUserRequireSharedMemory(def, "vhostuser",
|
||||||
|
qemuCaps) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
tests/qemuxml2argvdata/disk-vhostuser.x86_64-latest.args
Normal file
41
tests/qemuxml2argvdata/disk-vhostuser.x86_64-latest.args
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
LC_ALL=C \
|
||||||
|
PATH=/bin \
|
||||||
|
HOME=/tmp/lib/domain--1-QEMUGuest1 \
|
||||||
|
USER=test \
|
||||||
|
LOGNAME=test \
|
||||||
|
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
|
||||||
|
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
|
||||||
|
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
||||||
|
QEMU_AUDIO_DRV=none \
|
||||||
|
/usr/bin/qemu-system-x86_64 \
|
||||||
|
-name guest=QEMUGuest1,debug-threads=on \
|
||||||
|
-S \
|
||||||
|
-object secret,id=masterKey0,format=raw,\
|
||||||
|
file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
|
||||||
|
-machine pc,accel=tcg,usb=off,dump-guest-core=off,memory-backend=pc.ram \
|
||||||
|
-cpu qemu64 \
|
||||||
|
-m 214 \
|
||||||
|
-object memory-backend-memfd,id=pc.ram,share=yes,size=224395264 \
|
||||||
|
-overcommit mem-lock=off \
|
||||||
|
-smp 1,sockets=1,cores=1,threads=1 \
|
||||||
|
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||||
|
-display none \
|
||||||
|
-no-user-config \
|
||||||
|
-nodefaults \
|
||||||
|
-chardev socket,id=charmonitor,fd=1729,server,nowait \
|
||||||
|
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||||
|
-rtc base=utc \
|
||||||
|
-no-shutdown \
|
||||||
|
-no-acpi \
|
||||||
|
-boot strict=on \
|
||||||
|
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
|
||||||
|
-chardev socket,id=chr-vu-virtio-disk0,path=/tmp/vhost1.sock \
|
||||||
|
-device vhost-user-blk-pci,bus=pci.0,addr=0x2,chardev=chr-vu-virtio-disk0,\
|
||||||
|
id=virtio-disk0,bootindex=1 \
|
||||||
|
-chardev socket,id=chr-vu-virtio-disk1,path=/tmp/vhost1.sock,reconnect=10 \
|
||||||
|
-device vhost-user-blk-pci,bus=pci.0,addr=0x3,chardev=chr-vu-virtio-disk1,\
|
||||||
|
id=virtio-disk1 \
|
||||||
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 \
|
||||||
|
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
|
||||||
|
resourcecontrol=deny \
|
||||||
|
-msg timestamp=on
|
@ -1268,6 +1268,7 @@ mymain(void)
|
|||||||
VIR_FREE(driver.config->vxhsTLSx509certdir);
|
VIR_FREE(driver.config->vxhsTLSx509certdir);
|
||||||
DO_TEST("disk-no-boot", NONE);
|
DO_TEST("disk-no-boot", NONE);
|
||||||
DO_TEST_CAPS_LATEST("disk-nvme");
|
DO_TEST_CAPS_LATEST("disk-nvme");
|
||||||
|
DO_TEST_CAPS_LATEST("disk-vhostuser");
|
||||||
DO_TEST_PARSE_ERROR("disk-device-lun-type-invalid",
|
DO_TEST_PARSE_ERROR("disk-device-lun-type-invalid",
|
||||||
QEMU_CAPS_VIRTIO_SCSI);
|
QEMU_CAPS_VIRTIO_SCSI);
|
||||||
DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-attaching-partition-nosupport");
|
DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-attaching-partition-nosupport");
|
||||||
|
Loading…
Reference in New Issue
Block a user