}
-struct _qemuSharedDeviceEntry {
- size_t ref;
- char **domains; /* array of domain names */
-};
-
-/* Construct the hash key for sharedDevices as "major:minor" */
-char *
-qemuGetSharedDeviceKey(const char *device_path)
-{
- int maj, min;
- int rc;
-
- if ((rc = virGetDeviceID(device_path, &maj, &min)) < 0) {
- virReportSystemError(-rc,
- _("Unable to get minor number of device '%s'"),
- device_path);
- return NULL;
- }
-
- return g_strdup_printf("%d:%d", maj, min);
-}
-
-
-bool
-qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntry *entry,
- const char *name,
- int *idx)
-{
- size_t i;
-
- for (i = 0; i < entry->ref; i++) {
- if (STREQ(entry->domains[i], name)) {
- if (idx)
- *idx = i;
- return true;
- }
- }
-
- return false;
-}
-
-void
-qemuSharedDeviceEntryFree(void *payload)
-{
- qemuSharedDeviceEntry *entry = payload;
- size_t i;
-
- if (!entry)
- return;
-
- for (i = 0; i < entry->ref; i++)
- g_free(entry->domains[i]);
- g_free(entry->domains);
- g_free(entry);
-}
-
-
-static int
-qemuSharedDeviceEntryInsert(virQEMUDriver *driver,
- const char *key,
- const char *name)
-{
- qemuSharedDeviceEntry *entry = NULL;
-
- if ((entry = virHashLookup(driver->sharedDevices, key))) {
- /* Nothing to do if the shared scsi host device is already
- * recorded in the table.
- */
- if (!qemuSharedDeviceEntryDomainExists(entry, name, NULL)) {
- VIR_EXPAND_N(entry->domains, entry->ref, 1);
- entry->domains[entry->ref - 1] = g_strdup(name);
- }
- } else {
- entry = g_new0(qemuSharedDeviceEntry, 1);
- entry->domains = g_new0(char *, 1);
-
- entry->domains[0] = g_strdup(name);
-
- entry->ref = 1;
-
- if (virHashAddEntry(driver->sharedDevices, key, entry) < 0)
- goto error;
- }
-
- return 0;
-
- error:
- qemuSharedDeviceEntryFree(entry);
- return -1;
-}
-
-
-static int
-qemuSharedDeviceEntryRemove(virQEMUDriver *driver,
- const char *key,
- const char *name)
-{
- qemuSharedDeviceEntry *entry = NULL;
- int idx;
-
- if (!(entry = virHashLookup(driver->sharedDevices, key)))
- return -1;
-
- /* Nothing to do if the shared disk is not recorded in the table. */
- if (!qemuSharedDeviceEntryDomainExists(entry, name, &idx))
- return 0;
-
- if (entry->ref != 1) {
- VIR_FREE(entry->domains[idx]);
- VIR_DELETE_ELEMENT(entry->domains, idx, entry->ref);
- } else {
- ignore_value(virHashRemoveEntry(driver->sharedDevices, key));
- }
-
- return 0;
-}
-
-
-static int
-qemuSharedDiskAddRemoveInternal(virQEMUDriver *driver,
- virDomainDiskDef *disk,
- const char *name,
- bool addDisk)
-{
- g_autofree char *key = NULL;
- int ret = -1;
-
- if (virStorageSourceIsEmpty(disk->src) ||
- !disk->src->shared ||
- !virStorageSourceIsBlockLocal(disk->src))
- return 0;
-
- qemuDriverLock(driver);
-
- if (!(key = qemuGetSharedDeviceKey(virDomainDiskGetSource(disk))))
- goto cleanup;
-
- if (addDisk) {
- if (qemuSharedDeviceEntryInsert(driver, key, name) < 0)
- goto cleanup;
- } else {
- if (qemuSharedDeviceEntryRemove(driver, key, name) < 0)
- goto cleanup;
- }
-
- ret = 0;
- cleanup:
- qemuDriverUnlock(driver);
- return ret;
-}
-
-
-/* qemuAddSharedDisk:
- * @driver: Pointer to qemu driver struct
- * @src: disk source
- * @name: The domain name
- *
- * Increase ref count and add the domain name into the list which
- * records all the domains that use the shared device if the entry
- * already exists, otherwise add a new entry.
- */
-int
-qemuAddSharedDisk(virQEMUDriver *driver,
- virDomainDiskDef *disk,
- const char *name)
-{
- return qemuSharedDiskAddRemoveInternal(driver, disk, name, true);
-}
-
-
-static bool
-qemuIsSharedHostdev(virDomainHostdevDef *hostdev)
-{
- return (hostdev->shareable &&
- (virHostdevIsSCSIDevice(hostdev) &&
- hostdev->source.subsys.u.scsi.protocol !=
- VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI));
-}
-
-
-static char *
-qemuGetHostdevPath(virDomainHostdevDef *hostdev)
-{
- virDomainHostdevSubsysSCSI *scsisrc = &hostdev->source.subsys.u.scsi;
- virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
- g_autofree char *dev_name = NULL;
-
- if (!(dev_name = virSCSIDeviceGetDevName(NULL,
- scsihostsrc->adapter,
- scsihostsrc->bus,
- scsihostsrc->target,
- scsihostsrc->unit)))
- return NULL;
-
- return g_strdup_printf("/dev/%s", dev_name);
-}
-
-
-static int
-qemuSharedHostdevAddRemoveInternal(virQEMUDriver *driver,
- virDomainHostdevDef *hostdev,
- const char *name,
- bool addDevice)
-{
- g_autofree char *dev_path = NULL;
- g_autofree char *key = NULL;
- int ret = -1;
-
- if (!qemuIsSharedHostdev(hostdev))
- return 0;
-
- if (!(dev_path = qemuGetHostdevPath(hostdev)) ||
- !(key = qemuGetSharedDeviceKey(dev_path)))
- return -1;
-
- qemuDriverLock(driver);
-
- if (addDevice)
- ret = qemuSharedDeviceEntryInsert(driver, key, name);
- else
- ret = qemuSharedDeviceEntryRemove(driver, key, name);
-
- qemuDriverUnlock(driver);
-
- return ret;
-}
-
-static int
-qemuSharedDeviceAddRemoveInternal(virQEMUDriver *driver,
- virDomainDeviceDef *dev,
- const char *name,
- bool addDevice)
-{
- /* Currently the only conflicts we have to care about for
- * the shared disk and shared host device is "sgio" setting,
- * which is only valid for block disk and scsi host device.
- */
- if (dev->type == VIR_DOMAIN_DEVICE_DISK)
- return qemuSharedDiskAddRemoveInternal(driver, dev->data.disk,
- name, addDevice);
- if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV)
- return qemuSharedHostdevAddRemoveInternal(driver, dev->data.hostdev,
- name, addDevice);
- return 0;
-}
-
-
-/* qemuAddSharedDevice:
- * @driver: Pointer to qemu driver struct
- * @dev: The device def
- * @name: The domain name
- *
- * Increase ref count and add the domain name into the list which
- * records all the domains that use the shared device if the entry
- * already exists, otherwise add a new entry.
- */
-int
-qemuAddSharedDevice(virQEMUDriver *driver,
- virDomainDeviceDef *dev,
- const char *name)
-{
- return qemuSharedDeviceAddRemoveInternal(driver, dev, name, true);
-}
-
-
-int
-qemuRemoveSharedDisk(virQEMUDriver *driver,
- virDomainDiskDef *disk,
- const char *name)
-{
- return qemuSharedDiskAddRemoveInternal(driver, disk, name, false);
-}
-
-
-/* qemuRemoveSharedDevice:
- * @driver: Pointer to qemu driver struct
- * @device: The device def
- * @name: The domain name
- *
- * Decrease ref count and remove the domain name from the list which
- * records all the domains that use the shared device if ref is not
- * 1, otherwise remove the entry.
- */
-int
-qemuRemoveSharedDevice(virQEMUDriver *driver,
- virDomainDeviceDef *dev,
- const char *name)
-{
- return qemuSharedDeviceAddRemoveInternal(driver, dev, name, false);
-}
-
-
int qemuDriverAllocateID(virQEMUDriver *driver)
{
return g_atomic_int_add(&driver->lastvmid, 1) + 1;
virHostdevManager *hostdevMgr;
- /* Immutable pointer. Unsafe APIs. XXX */
- GHashTable *sharedDevices;
-
/* Immutable pointer, immutable object */
virPortAllocatorRange *remotePorts;
virArch arch,
virDomainVirtType virttype);
-typedef struct _qemuSharedDeviceEntry qemuSharedDeviceEntry;
-
-bool qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntry *entry,
- const char *name,
- int *idx)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-
-char *qemuGetSharedDeviceKey(const char *disk_path)
- ATTRIBUTE_NONNULL(1);
-
-void qemuSharedDeviceEntryFree(void *payload);
-
-int qemuAddSharedDisk(virQEMUDriver *driver,
- virDomainDiskDef *disk,
- const char *name)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
-int qemuAddSharedDevice(virQEMUDriver *driver,
- virDomainDeviceDef *dev,
- const char *name)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
-int qemuRemoveSharedDevice(virQEMUDriver *driver,
- virDomainDeviceDef *dev,
- const char *name)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
-int qemuRemoveSharedDisk(virQEMUDriver *driver,
- virDomainDiskDef *disk,
- const char *name)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
int qemuDriverAllocateID(virQEMUDriver *driver);
virDomainXMLOption *virQEMUDriverCreateXMLConf(virQEMUDriver *driver,
const char *defsecmodel);
if (!(qemu_driver->hostdevMgr = virHostdevManagerGetDefault()))
goto error;
- qemu_driver->sharedDevices = virHashNew(qemuSharedDeviceEntryFree);
-
if (qemuMigrationDstErrorInit(qemu_driver) < 0)
goto error;
virPortAllocatorRangeFree(qemu_driver->migrationPorts);
virPortAllocatorRangeFree(qemu_driver->webSocketPorts);
virPortAllocatorRangeFree(qemu_driver->remotePorts);
- g_clear_pointer(&qemu_driver->sharedDevices, g_hash_table_unref);
virObjectUnref(qemu_driver->hostdevMgr);
virObjectUnref(qemu_driver->securityManager);
virObjectUnref(qemu_driver->domainEventState);
virDomainHostdevDef **hostdevs,
int nhostdevs)
{
- size_t i;
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
- /* Loop 1: Add the shared scsi host device to shared device
- * table.
- */
- for (i = 0; i < nhostdevs; i++) {
- virDomainDeviceDef dev;
-
- if (!virHostdevIsSCSIDevice(hostdevs[i]))
- continue;
-
- dev.type = VIR_DOMAIN_DEVICE_HOSTDEV;
- dev.data.hostdev = hostdevs[i];
-
- if (qemuAddSharedDevice(driver, &dev, name) < 0)
- return -1;
- }
-
return virHostdevPrepareSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
name, hostdevs, nhostdevs);
}
virDomainHostdevDef **hostdevs,
int nhostdevs)
{
- size_t i;
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
- for (i = 0; i < nhostdevs; i++) {
- virDomainHostdevDef *hostdev = hostdevs[i];
- virDomainDeviceDef dev;
-
- dev.type = VIR_DOMAIN_DEVICE_HOSTDEV;
- dev.data.hostdev = hostdev;
-
- ignore_value(qemuRemoveSharedDevice(driver, &dev, name));
- }
-
virHostdevReAttachSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
name, hostdevs, nhostdevs);
}
qemuDomainObjPrivate *priv = vm->privateData;
virStorageSource *oldsrc = disk->src;
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
- bool sharedAdded = false;
bool managedpr = virStorageSourceChainHasManagedPR(oldsrc) ||
virStorageSourceChainHasManagedPR(newsrc);
int ret = -1;
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto cleanup;
- if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
- goto cleanup;
-
- sharedAdded = true;
-
if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
goto cleanup;
if (rc < 0)
goto cleanup;
- /* remove the old source from shared device list */
- disk->src = oldsrc;
- ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, oldsrc));
/* media was changed, so we can remove the old media definition now */
virObjectUnref(oldsrc);
oldsrc = NULL;
- disk->src = newsrc;
ret = 0;
cleanup:
/* undo changes to the new disk */
if (ret < 0) {
- if (sharedAdded)
- ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
-
ignore_value(qemuDomainStorageSourceChainAccessRevoke(driver, vm, newsrc));
}
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto cleanup;
- if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
- goto cleanup;
-
if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0)
goto cleanup;
cleanup:
if (ret < 0) {
- ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
-
if (releaseUSB)
virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
{
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
g_autoptr(qemuBlockStorageSourceChainData) diskBackend = NULL;
- virDomainDeviceDef dev;
size_t i;
qemuDomainObjPrivate *priv = vm->privateData;
bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
if (diskBackend)
qemuDomainStorageSourceChainAccessRevoke(driver, vm, disk->src);
- dev.type = VIR_DOMAIN_DEVICE_DISK;
- dev.data.disk = disk;
- ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
-
if (virStorageSourceChainHasManagedPR(disk->src) &&
qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
goto cleanup;
static int
-qemuProcessSetupRawIO(virQEMUDriver *driver,
+qemuProcessSetupRawIO(virQEMUDriver *driver G_GNUC_UNUSED,
virDomainObj *vm,
virCommand *cmd G_GNUC_UNUSED)
{
/* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
for (i = 0; i < vm->def->ndisks; i++) {
- virDomainDeviceDef dev;
virDomainDiskDef *disk = vm->def->disks[i];
if (disk->rawio == VIR_TRISTATE_BOOL_YES) {
break;
#endif
}
-
- dev.type = VIR_DOMAIN_DEVICE_DISK;
- dev.data.disk = disk;
- if (qemuAddSharedDevice(driver, &dev, vm->def->name) < 0)
- goto cleanup;
}
/* If rawio not already set, check hostdevs as well */
ret = 0;
- cleanup:
if (rawio) {
#ifdef CAP_SYS_RAWIO
if (ret == 0)
qemuSecurityRestoreAllLabel(driver, vm,
!!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED));
- for (i = 0; i < vm->def->ndisks; i++) {
- virDomainDeviceDef dev;
- virDomainDiskDef *disk = vm->def->disks[i];
-
- dev.type = VIR_DOMAIN_DEVICE_DISK;
- dev.data.disk = disk;
- ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
- }
-
/* Clear out dynamically assigned labels */
for (i = 0; i < vm->def->nseclabels; i++) {
if (vm->def->seclabels[i]->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
if (qemuDomainInitializePflashStorageSource(obj) < 0)
goto error;
- /* XXX: Need to change as long as lock is introduced for
- * qemu_driver->sharedDevices.
- */
for (i = 0; i < obj->def->ndisks; i++) {
virDomainDiskDef *disk = obj->def->disks[i];
- virDomainDeviceDef dev;
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto error;
} else {
VIR_DEBUG("skipping backing chain detection for '%s'", disk->dst);
}
-
- dev.type = VIR_DOMAIN_DEVICE_DISK;
- dev.data.disk = disk;
- if (qemuAddSharedDevice(driver, &dev, obj->def->name) < 0)
- goto error;
}
for (i = 0; i < obj->def->ngraphics; i++) {