mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu: Refactor the helpers to track shared scsi host device
This changes the helpers qemu{Add,Remove}SharedDisk into qemu{Add,Remove}SharedDevice, as most of the code in the helpers can be reused for scsi host device. To track the shared scsi host device, first it finds out the device path (e.g. /dev/s[dr]*) which is mapped to the sg device, and use device ID of the found device path (/dev/s[dr]*) as the hash key. This is because of the device ID is not unique between between /dev/s[dr]* and /dev/sg*, e.g. % sg_map /dev/sg0 /dev/sda /dev/sg1 /dev/sr0 % ls -l /dev/sda brw-rw----. 1 root disk 8, 0 May 2 19:26 /dev/sda %ls -l /dev/sg0 crw-rw----. 1 root disk 21, 0 May 2 19:26 /dev/sg0
This commit is contained in:
parent
28d3ad952f
commit
aeda1ff12d
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user