diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 0d9c5f30522c3dc5536727b784675d7564a76ab9..c1109df326125d4433e62fbf00bf1ab7955a13c7 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1116,47 +1116,80 @@ cleanup: return NULL; } -/* qemuAddSharedDisk: +/* qemuAddSharedDevice: * @driver: Pointer to qemu driver struct - * @disk: The disk def + * @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 disk if the entry + * records all the domains that use the shared device if the entry * already exists, otherwise add a new entry. */ int -qemuAddSharedDisk(virQEMUDriverPtr driver, - virDomainDiskDefPtr disk, - const char *name) +qemuAddSharedDevice(virQEMUDriverPtr driver, + virDomainDeviceDefPtr dev, + const char *name) { qemuSharedDeviceEntry *entry = NULL; qemuSharedDeviceEntry *new_entry = NULL; + virDomainDiskDefPtr disk = NULL; + virDomainHostdevDefPtr hostdev = NULL; + char *dev_name = NULL; + char *dev_path = NULL; char *key = NULL; int ret = -1; - /* Currently the only conflicts we have to care about - * for the shared disk is "sgio" setting, which is only - * valid for block disk. + /* 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 (!disk->shared || - !disk->src || - (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && - !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && - disk->srcpool && - disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + disk = dev->data.disk; + + if (disk->shared || + !disk->src || + (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && + !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && + disk->srcpool && + disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) + return 0; + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + hostdev = dev->data.hostdev; + + if (!hostdev->shareable || + !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) + return 0; + } else { return 0; + } qemuDriverLock(driver); - if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0) - goto cleanup; + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0) + goto cleanup; - if (!(key = qemuGetSharedDeviceKey(disk->src))) - goto cleanup; + if (!(key = qemuGetSharedDeviceKey(disk->src))) + goto cleanup; + } else { + if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit))) + goto cleanup; + + if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!(key = qemuGetSharedDeviceKey(dev_path))) + goto cleanup; + } if ((entry = virHashLookup(driver->sharedDevices, key))) { - /* Nothing to do if the shared disk is already recorded - * in the table. + /* Nothing to do if the shared scsi host device is already + * recorded in the table. */ if (qemuSharedDeviceEntryDomainExists(entry, name, NULL)) { ret = 0; @@ -1195,41 +1228,77 @@ qemuAddSharedDisk(virQEMUDriverPtr driver, ret = 0; cleanup: qemuDriverUnlock(driver); + VIR_FREE(dev_name); + VIR_FREE(dev_path); VIR_FREE(key); return ret; } -/* qemuRemoveSharedDisk: +/* qemuRemoveSharedDevice: * @driver: Pointer to qemu driver struct - * @disk: The disk def + * @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 disk if ref is not 1, - * otherwise remove the entry. + * records all the domains that use the shared device if ref is not + * 1, otherwise remove the entry. */ int -qemuRemoveSharedDisk(virQEMUDriverPtr driver, - virDomainDiskDefPtr disk, - const char *name) +qemuRemoveSharedDevice(virQEMUDriverPtr driver, + virDomainDeviceDefPtr dev, + const char *name) { qemuSharedDeviceEntryPtr entry = NULL; qemuSharedDeviceEntryPtr new_entry = NULL; + virDomainDiskDefPtr disk = NULL; + virDomainHostdevDefPtr hostdev = NULL; char *key = NULL; + char *dev_name = NULL; + char *dev_path = NULL; int ret = -1; int idx; - if (!disk->shared || - !disk->src || - (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && - !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && - disk->srcpool && - disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + disk = dev->data.disk; + + if (!disk->shared || + !disk->src || + (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && + !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && + disk->srcpool && + disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) + return 0; + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + hostdev = dev->data.hostdev; + + if (!hostdev->shareable || + !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) + return 0; + } else { return 0; + } qemuDriverLock(driver); - if (!(key = qemuGetSharedDeviceKey(disk->src))) - goto cleanup; + + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + if (!(key = qemuGetSharedDeviceKey(disk->src))) + goto cleanup; + } else { + if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit))) + goto cleanup; + + if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!(key = qemuGetSharedDeviceKey(dev_path))) + goto cleanup; + } if (!(entry = virHashLookup(driver->sharedDevices, key))) goto cleanup; @@ -1265,6 +1334,8 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver, ret = 0; cleanup: qemuDriverUnlock(driver); + VIR_FREE(dev_name); + VIR_FREE(dev_path); VIR_FREE(key); return ret; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index ccb3e6c36219e3d6557b0fc5c151b359a939e7c5..4568e6cc9fef82074b14f16f0b08842dc5f8c03b 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -289,22 +289,22 @@ bool qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry, int *index) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int qemuAddSharedDisk(virQEMUDriverPtr driver, - virDomainDiskDefPtr disk, - const char *name) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); - -int qemuRemoveSharedDisk(virQEMUDriverPtr driver, - virDomainDiskDefPtr disk, - const char *name) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); - char * qemuGetSharedDeviceKey(const char *disk_path) ATTRIBUTE_NONNULL(1); void qemuSharedDeviceEntryFree(void *payload, const void *name) ATTRIBUTE_NONNULL(1); +int qemuAddSharedDevice(virQEMUDriverPtr driver, + virDomainDeviceDefPtr dev, + const char *name) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + +int qemuRemoveSharedDevice(virQEMUDriverPtr driver, + virDomainDeviceDefPtr dev, + const char *name) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + int qemuDriverAllocateID(virQEMUDriverPtr driver); virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3e353fdcdf9ea2910eb3642f46b9ce5199f02b96..d1708cea7746ca70896502c8e79468e2f4c397db 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5731,7 +5731,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, if (qemuTranslateDiskSourcePool(conn, disk) < 0) goto end; - if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0) + if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0) goto end; if (qemuSetUnprivSGIO(disk) < 0) @@ -5777,8 +5777,8 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, * if the operation is either ejecting or updating. */ if (ret == 0) - ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk, - vm->def->name)); + ignore_value(qemuRemoveSharedDevice(driver, dev_copy, + vm->def->name)); break; case VIR_DOMAIN_DISK_DEVICE_DISK: case VIR_DOMAIN_DISK_DEVICE_LUN: @@ -5815,7 +5815,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, end: if (ret != 0) - ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); + ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name)); virObjectUnref(caps); virDomainDeviceDefFree(dev_copy); return ret; @@ -5931,7 +5931,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver, } if (ret == 0) - ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); + ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name)); return ret; } @@ -6038,7 +6038,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn, dev->data.disk = tmp; /* Add the new disk src into shared disk hash table */ - if (qemuAddSharedDisk(driver, dev->data.disk, vm->def->name) < 0) + if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0) goto end; ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force); @@ -6051,8 +6051,8 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn, */ if (ret == 0) { dev->data.disk = NULL; - ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk, - vm->def->name)); + ignore_value(qemuRemoveSharedDevice(driver, dev_copy, + vm->def->name)); } break; default: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 976a8e87d5f3224f498cb721f8c5efc2df9cb0f4..52636a15231c268ffdd5c82de9e3f31eba3469cc 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2982,10 +2982,14 @@ qemuProcessReconnect(void *opaque) * qemu_driver->sharedDevices. */ for (i = 0; i < obj->def->ndisks; i++) { + virDomainDeviceDef dev; + if (qemuTranslateDiskSourcePool(conn, obj->def->disks[i]) < 0) goto error; - if (qemuAddSharedDisk(driver, obj->def->disks[i], - obj->def->name) < 0) + + dev.type = VIR_DOMAIN_DEVICE_DISK; + dev.data.disk = obj->def->disks[i]; + if (qemuAddSharedDevice(driver, &dev, obj->def->name) < 0) goto error; } @@ -3686,6 +3690,7 @@ int qemuProcessStart(virConnectPtr conn, /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */ for (i = 0; i < vm->def->ndisks; i++) { + virDomainDeviceDef dev; virDomainDiskDefPtr disk = vm->def->disks[i]; if (vm->def->disks[i]->rawio == 1) @@ -3696,7 +3701,9 @@ int qemuProcessStart(virConnectPtr conn, _("Raw I/O is not supported on this platform")); #endif - if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0) + dev.type = VIR_DOMAIN_DEVICE_DISK; + dev.data.disk = disk; + if (qemuAddSharedDevice(driver, &dev, vm->def->name) < 0) goto cleanup; if (qemuSetUnprivSGIO(disk) < 0) @@ -4107,8 +4114,12 @@ void qemuProcessStop(virQEMUDriverPtr driver, virSecurityManagerReleaseLabel(driver->securityManager, vm->def); for (i = 0; i < vm->def->ndisks; i++) { + virDomainDeviceDef dev; virDomainDiskDefPtr disk = vm->def->disks[i]; - ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); + + dev.type = VIR_DOMAIN_DEVICE_DISK; + dev.data.disk = disk; + ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name)); } /* Clear out dynamically assigned labels */