mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
move virHostdevPrepareHostSCSIDevices to virhostdev.c
This commit is contained in:
parent
c82c274581
commit
5035f75fed
@ -1300,6 +1300,7 @@ virHookPresent;
|
||||
#util/virhostdev.h
|
||||
virHostdevManagerGetDefault;
|
||||
virHostdevPreparePCIDevices;
|
||||
virHostdevPrepareSCSIDevices;
|
||||
virHostdevPrepareUSBDevices;
|
||||
virHostdevReAttachPCIDevices;
|
||||
virHostdevUpdateActivePciHostdevs;
|
||||
|
@ -245,117 +245,6 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver,
|
||||
hostdevs, nhostdevs, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
|
||||
const char *drv_name,
|
||||
const char *name,
|
||||
virDomainHostdevDefPtr *hostdevs,
|
||||
int nhostdevs)
|
||||
{
|
||||
size_t i, j;
|
||||
int count;
|
||||
virSCSIDeviceListPtr list;
|
||||
virSCSIDevicePtr tmp;
|
||||
|
||||
/* To prevent situation where SCSI device is assigned to two domains
|
||||
* we need to keep a list of currently assigned SCSI devices.
|
||||
* This is done in several loops which cannot be joined into one big
|
||||
* loop. See virHostdevPreparePCIDevices()
|
||||
*/
|
||||
if (!(list = virSCSIDeviceListNew()))
|
||||
goto cleanup;
|
||||
|
||||
/* Loop 1: build temporary list */
|
||||
for (i = 0; i < nhostdevs; i++) {
|
||||
virDomainHostdevDefPtr hostdev = hostdevs[i];
|
||||
virSCSIDevicePtr scsi;
|
||||
|
||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
|
||||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
|
||||
continue;
|
||||
|
||||
if (hostdev->managed) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("SCSI host device doesn't support managed mode"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(scsi = virSCSIDeviceNew(NULL,
|
||||
hostdev->source.subsys.u.scsi.adapter,
|
||||
hostdev->source.subsys.u.scsi.bus,
|
||||
hostdev->source.subsys.u.scsi.target,
|
||||
hostdev->source.subsys.u.scsi.unit,
|
||||
hostdev->readonly,
|
||||
hostdev->shareable)))
|
||||
goto cleanup;
|
||||
|
||||
if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) {
|
||||
virSCSIDeviceFree(scsi);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop 2: Mark devices in temporary list as used by @name
|
||||
* and add them to driver list. However, if something goes
|
||||
* wrong, perform rollback.
|
||||
*/
|
||||
virObjectLock(hostdev_mgr->activeScsiHostdevs);
|
||||
count = virSCSIDeviceListCount(list);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i);
|
||||
if ((tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs,
|
||||
scsi))) {
|
||||
bool scsi_shareable = virSCSIDeviceGetShareable(scsi);
|
||||
bool tmp_shareable = virSCSIDeviceGetShareable(tmp);
|
||||
|
||||
if (!(scsi_shareable && tmp_shareable)) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("SCSI device %s is already in use by "
|
||||
"other domain(s) as '%s'"),
|
||||
virSCSIDeviceGetName(tmp),
|
||||
tmp_shareable ? "shareable" : "non-shareable");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0)
|
||||
goto error;
|
||||
} else {
|
||||
if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0)
|
||||
goto error;
|
||||
|
||||
VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi));
|
||||
|
||||
if (virSCSIDeviceListAdd(hostdev_mgr->activeScsiHostdevs, scsi) < 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
virObjectUnlock(hostdev_mgr->activeScsiHostdevs);
|
||||
|
||||
/* Loop 3: Temporary list was successfully merged with
|
||||
* driver list, so steal all items to avoid freeing them
|
||||
* when freeing temporary list.
|
||||
*/
|
||||
while (virSCSIDeviceListCount(list) > 0) {
|
||||
tmp = virSCSIDeviceListGet(list, 0);
|
||||
virSCSIDeviceListSteal(list, tmp);
|
||||
}
|
||||
|
||||
virObjectUnref(list);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (j = 0; j < i; j++) {
|
||||
tmp = virSCSIDeviceListGet(list, i);
|
||||
virSCSIDeviceListSteal(hostdev_mgr->activeScsiHostdevs, tmp);
|
||||
}
|
||||
virObjectUnlock(hostdev_mgr->activeScsiHostdevs);
|
||||
cleanup:
|
||||
virObjectUnref(list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver,
|
||||
const char *name,
|
||||
|
@ -1140,3 +1140,114 @@ cleanup:
|
||||
virObjectUnref(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
|
||||
const char *drv_name,
|
||||
const char *name,
|
||||
virDomainHostdevDefPtr *hostdevs,
|
||||
int nhostdevs)
|
||||
{
|
||||
size_t i, j;
|
||||
int count;
|
||||
virSCSIDeviceListPtr list;
|
||||
virSCSIDevicePtr tmp;
|
||||
|
||||
/* To prevent situation where SCSI device is assigned to two domains
|
||||
* we need to keep a list of currently assigned SCSI devices.
|
||||
* This is done in several loops which cannot be joined into one big
|
||||
* loop. See virHostdevPreparePCIDevices()
|
||||
*/
|
||||
if (!(list = virSCSIDeviceListNew()))
|
||||
goto cleanup;
|
||||
|
||||
/* Loop 1: build temporary list */
|
||||
for (i = 0; i < nhostdevs; i++) {
|
||||
virDomainHostdevDefPtr hostdev = hostdevs[i];
|
||||
virSCSIDevicePtr scsi;
|
||||
|
||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
|
||||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
|
||||
continue;
|
||||
|
||||
if (hostdev->managed) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("SCSI host device doesn't support managed mode"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(scsi = virSCSIDeviceNew(NULL,
|
||||
hostdev->source.subsys.u.scsi.adapter,
|
||||
hostdev->source.subsys.u.scsi.bus,
|
||||
hostdev->source.subsys.u.scsi.target,
|
||||
hostdev->source.subsys.u.scsi.unit,
|
||||
hostdev->readonly,
|
||||
hostdev->shareable)))
|
||||
goto cleanup;
|
||||
|
||||
if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) {
|
||||
virSCSIDeviceFree(scsi);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop 2: Mark devices in temporary list as used by @name
|
||||
* and add them to driver list. However, if something goes
|
||||
* wrong, perform rollback.
|
||||
*/
|
||||
virObjectLock(hostdev_mgr->activeScsiHostdevs);
|
||||
count = virSCSIDeviceListCount(list);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i);
|
||||
if ((tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs,
|
||||
scsi))) {
|
||||
bool scsi_shareable = virSCSIDeviceGetShareable(scsi);
|
||||
bool tmp_shareable = virSCSIDeviceGetShareable(tmp);
|
||||
|
||||
if (!(scsi_shareable && tmp_shareable)) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("SCSI device %s is already in use by "
|
||||
"other domain(s) as '%s'"),
|
||||
virSCSIDeviceGetName(tmp),
|
||||
tmp_shareable ? "shareable" : "non-shareable");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0)
|
||||
goto error;
|
||||
} else {
|
||||
if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0)
|
||||
goto error;
|
||||
|
||||
VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi));
|
||||
|
||||
if (virSCSIDeviceListAdd(hostdev_mgr->activeScsiHostdevs, scsi) < 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
virObjectUnlock(hostdev_mgr->activeScsiHostdevs);
|
||||
|
||||
/* Loop 3: Temporary list was successfully merged with
|
||||
* driver list, so steal all items to avoid freeing them
|
||||
* when freeing temporary list.
|
||||
*/
|
||||
while (virSCSIDeviceListCount(list) > 0) {
|
||||
tmp = virSCSIDeviceListGet(list, 0);
|
||||
virSCSIDeviceListSteal(list, tmp);
|
||||
}
|
||||
|
||||
virObjectUnref(list);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (j = 0; j < i; j++) {
|
||||
tmp = virSCSIDeviceListGet(list, i);
|
||||
virSCSIDeviceListSteal(hostdev_mgr->activeScsiHostdevs, tmp);
|
||||
}
|
||||
virObjectUnlock(hostdev_mgr->activeScsiHostdevs);
|
||||
cleanup:
|
||||
virObjectUnref(list);
|
||||
return -1;
|
||||
}
|
||||
|
@ -65,6 +65,12 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr,
|
||||
virDomainHostdevDefPtr *hostdevs,
|
||||
int nhostdevs,
|
||||
unsigned int flags);
|
||||
int
|
||||
virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
|
||||
const char *drv_name,
|
||||
const char *name,
|
||||
virDomainHostdevDefPtr *hostdevs,
|
||||
int nhostdevs);
|
||||
void
|
||||
virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
|
||||
const char *drv_name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user