mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 14:35:25 +00:00
change lxc_hostdev.c to use virhostdev common library APIs
This commit is contained in:
parent
cd618e0212
commit
53aba258b2
@ -35,259 +35,28 @@ int
|
|||||||
virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver,
|
virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver,
|
||||||
virDomainDefPtr def)
|
virDomainDefPtr def)
|
||||||
{
|
{
|
||||||
virDomainHostdevDefPtr hostdev = NULL;
|
|
||||||
size_t i;
|
|
||||||
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
||||||
|
|
||||||
if (!def->nhostdevs)
|
if (!def->nhostdevs)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < def->nhostdevs; i++) {
|
return virHostdevUpdateActiveUSBDevices(hostdev_mgr,
|
||||||
virUSBDevicePtr usb = NULL;
|
def->hostdevs, def->nhostdevs,
|
||||||
hostdev = def->hostdevs[i];
|
LXC_DRIVER_NAME, def->name);
|
||||||
|
|
||||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
||||||
continue;
|
|
||||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
NULL);
|
|
||||||
if (!usb) {
|
|
||||||
VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s",
|
|
||||||
hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
def->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
virUSBDeviceSetUsedBy(usb, LXC_DRIVER_NAME, def->name);
|
|
||||||
|
|
||||||
virObjectLock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
if (virUSBDeviceListAdd(hostdev_mgr->activeUSBHostdevs, usb) < 0) {
|
|
||||||
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
virUSBDeviceFree(usb);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
virLXCPrepareHostdevUSBDevices(virLXCDriverPtr driver,
|
|
||||||
const char *name,
|
|
||||||
virUSBDeviceList *list)
|
|
||||||
{
|
|
||||||
size_t i, j;
|
|
||||||
unsigned int count;
|
|
||||||
virUSBDevicePtr tmp;
|
|
||||||
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
|
||||||
|
|
||||||
count = virUSBDeviceListCount(list);
|
|
||||||
|
|
||||||
virObjectLock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
virUSBDevicePtr usb = virUSBDeviceListGet(list, i);
|
|
||||||
if ((tmp = virUSBDeviceListFind(hostdev_mgr->activeUSBHostdevs, usb))) {
|
|
||||||
const char *other_drvname;
|
|
||||||
const char *other_domname;
|
|
||||||
|
|
||||||
virUSBDeviceGetUsedBy(tmp, &other_drvname, &other_domname);
|
|
||||||
if (other_drvname && other_domname)
|
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
||||||
_("USB device %s is in use by "
|
|
||||||
"driver %s, domain %s"),
|
|
||||||
virUSBDeviceGetName(tmp),
|
|
||||||
other_drvname, other_domname);
|
|
||||||
else
|
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
||||||
_("USB device %s is already in use"),
|
|
||||||
virUSBDeviceGetName(tmp));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
virUSBDeviceSetUsedBy(usb, LXC_DRIVER_NAME, name);
|
|
||||||
VIR_DEBUG("Adding %03d.%03d dom=%s to activeUSBHostdevs",
|
|
||||||
virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name);
|
|
||||||
/*
|
|
||||||
* The caller is responsible to steal these usb devices
|
|
||||||
* from the virUSBDeviceList that passed in on success,
|
|
||||||
* perform rollback on failure.
|
|
||||||
*/
|
|
||||||
if (virUSBDeviceListAdd(hostdev_mgr->activeUSBHostdevs, usb) < 0)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
for (j = 0; j < i; j++) {
|
|
||||||
tmp = virUSBDeviceListGet(list, i);
|
|
||||||
virUSBDeviceListSteal(hostdev_mgr->activeUSBHostdevs, tmp);
|
|
||||||
}
|
|
||||||
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
virLXCFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
|
|
||||||
bool mandatory,
|
|
||||||
virUSBDevicePtr *usb)
|
|
||||||
{
|
|
||||||
unsigned vendor = hostdev->source.subsys.u.usb.vendor;
|
|
||||||
unsigned product = hostdev->source.subsys.u.usb.product;
|
|
||||||
unsigned bus = hostdev->source.subsys.u.usb.bus;
|
|
||||||
unsigned device = hostdev->source.subsys.u.usb.device;
|
|
||||||
bool autoAddress = hostdev->source.subsys.u.usb.autoAddress;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
*usb = NULL;
|
|
||||||
|
|
||||||
if (vendor && bus) {
|
|
||||||
rc = virUSBDeviceFind(vendor, product, bus, device,
|
|
||||||
NULL,
|
|
||||||
autoAddress ? false : mandatory,
|
|
||||||
usb);
|
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
|
||||||
} else if (!autoAddress) {
|
|
||||||
goto out;
|
|
||||||
} else {
|
|
||||||
VIR_INFO("USB device %x:%x could not be found at previous"
|
|
||||||
" address (bus:%u device:%u)",
|
|
||||||
vendor, product, bus, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When vendor is specified, its USB address is either unspecified or the
|
|
||||||
* device could not be found at the USB device where it had been
|
|
||||||
* automatically found before.
|
|
||||||
*/
|
|
||||||
if (vendor) {
|
|
||||||
virUSBDeviceList *devs;
|
|
||||||
|
|
||||||
rc = virUSBDeviceFindByVendor(vendor, product,
|
|
||||||
NULL,
|
|
||||||
mandatory, &devs);
|
|
||||||
if (rc < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (rc == 1) {
|
|
||||||
*usb = virUSBDeviceListGet(devs, 0);
|
|
||||||
virUSBDeviceListSteal(devs, *usb);
|
|
||||||
}
|
|
||||||
virObjectUnref(devs);
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
goto out;
|
|
||||||
} else if (rc > 1) {
|
|
||||||
if (autoAddress) {
|
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
||||||
_("Multiple USB devices for %x:%x were found,"
|
|
||||||
" but none of them is at bus:%u device:%u"),
|
|
||||||
vendor, product, bus, device);
|
|
||||||
} else {
|
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
||||||
_("Multiple USB devices for %x:%x, "
|
|
||||||
"use <address> to specify one"),
|
|
||||||
vendor, product);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb);
|
|
||||||
hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb);
|
|
||||||
hostdev->source.subsys.u.usb.autoAddress = true;
|
|
||||||
|
|
||||||
if (autoAddress) {
|
|
||||||
VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
|
|
||||||
" from bus:%u device:%u)",
|
|
||||||
vendor, product,
|
|
||||||
hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
bus, device);
|
|
||||||
}
|
|
||||||
} else if (!vendor && bus) {
|
|
||||||
if (virUSBDeviceFindByBus(bus, device,
|
|
||||||
NULL,
|
|
||||||
mandatory, usb) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (!*usb)
|
|
||||||
hostdev->missing = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virLXCPrepareHostUSBDevices(virLXCDriverPtr driver,
|
virLXCPrepareHostUSBDevices(virLXCDriverPtr driver,
|
||||||
virDomainDefPtr def)
|
virDomainDefPtr def)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
int ret = -1;
|
|
||||||
virUSBDeviceList *list;
|
|
||||||
virUSBDevicePtr tmp;
|
|
||||||
virDomainHostdevDefPtr *hostdevs = def->hostdevs;
|
virDomainHostdevDefPtr *hostdevs = def->hostdevs;
|
||||||
int nhostdevs = def->nhostdevs;
|
int nhostdevs = def->nhostdevs;
|
||||||
|
const char *dom_name = def->name;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
||||||
|
|
||||||
/* To prevent situation where USB device is assigned to two domains
|
return virHostdevPrepareUSBDevices(hostdev_mgr, LXC_DRIVER_NAME, dom_name,
|
||||||
* we need to keep a list of currently assigned USB devices.
|
hostdevs, nhostdevs, flags);
|
||||||
* This is done in several loops which cannot be joined into one big
|
|
||||||
* loop. See virLXCPrepareHostdevPCIDevices()
|
|
||||||
*/
|
|
||||||
if (!(list = virUSBDeviceListNew()))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Loop 1: build temporary list
|
|
||||||
*/
|
|
||||||
for (i = 0; i < nhostdevs; i++) {
|
|
||||||
virDomainHostdevDefPtr hostdev = hostdevs[i];
|
|
||||||
bool required = true;
|
|
||||||
virUSBDevicePtr usb;
|
|
||||||
|
|
||||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
||||||
continue;
|
|
||||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL)
|
|
||||||
required = false;
|
|
||||||
|
|
||||||
if (virLXCFindHostdevUSBDevice(hostdev, required, &usb) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (usb && virUSBDeviceListAdd(list, usb) < 0) {
|
|
||||||
virUSBDeviceFree(usb);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark devices in temporary list as used by @name
|
|
||||||
* and add them do driver list. However, if something goes
|
|
||||||
* wrong, perform rollback.
|
|
||||||
*/
|
|
||||||
if (virLXCPrepareHostdevUSBDevices(driver, def->name, list) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Loop 2: Temporary list was successfully merged with
|
|
||||||
* driver list, so steal all items to avoid freeing them
|
|
||||||
* in cleanup label.
|
|
||||||
*/
|
|
||||||
while (virUSBDeviceListCount(list) > 0) {
|
|
||||||
tmp = virUSBDeviceListGet(list, 0);
|
|
||||||
virUSBDeviceListSteal(list, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virObjectUnref(list);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -352,64 +121,10 @@ virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver,
|
|||||||
virDomainHostdevDefPtr *hostdevs,
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
int nhostdevs)
|
int nhostdevs)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
||||||
|
|
||||||
virObjectLock(hostdev_mgr->activeUSBHostdevs);
|
virHostdevReAttachUSBDevices(hostdev_mgr, LXC_DRIVER_NAME,
|
||||||
for (i = 0; i < nhostdevs; i++) {
|
name, hostdevs, nhostdevs);
|
||||||
virDomainHostdevDefPtr hostdev = hostdevs[i];
|
|
||||||
virUSBDevicePtr usb, tmp;
|
|
||||||
const char *usedby_domname = NULL;
|
|
||||||
const char *usedby_drvname = NULL;
|
|
||||||
|
|
||||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
||||||
continue;
|
|
||||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
||||||
continue;
|
|
||||||
if (hostdev->missing)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!usb) {
|
|
||||||
VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s",
|
|
||||||
hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete only those USB devices which belongs
|
|
||||||
* to domain @name because virLXCProcessStart() might
|
|
||||||
* have failed because USB device is already taken.
|
|
||||||
* Therefore we want to steal only those devices from
|
|
||||||
* the list which were taken by @name */
|
|
||||||
|
|
||||||
tmp = virUSBDeviceListFind(hostdev_mgr->activeUSBHostdevs, usb);
|
|
||||||
virUSBDeviceFree(usb);
|
|
||||||
|
|
||||||
if (!tmp) {
|
|
||||||
VIR_WARN("Unable to find device %03d.%03d "
|
|
||||||
"in list of active USB devices",
|
|
||||||
hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname);
|
|
||||||
if (STREQ_NULLABLE(LXC_DRIVER_NAME, usedby_drvname) &&
|
|
||||||
STREQ_NULLABLE(name, usedby_domname)) {
|
|
||||||
VIR_DEBUG("Removing %03d.%03d dom=%s from activeUSBHostdevs",
|
|
||||||
hostdev->source.subsys.u.usb.bus,
|
|
||||||
hostdev->source.subsys.u.usb.device,
|
|
||||||
name);
|
|
||||||
|
|
||||||
virUSBDeviceListDel(hostdev_mgr->activeUSBHostdevs, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver,
|
void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver,
|
||||||
@ -419,5 +134,5 @@ void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
virLXCDomainReAttachHostUsbDevices(driver, def->name, def->hostdevs,
|
virLXCDomainReAttachHostUsbDevices(driver, def->name, def->hostdevs,
|
||||||
def->nhostdevs);
|
def->nhostdevs);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user