Signed-off-by: Chunyan Liu <cyliu(a)suse.com>
---
src/lxc/lxc_hostdev.c | 320 +++----------------------------------------------
1 files changed, 16 insertions(+), 304 deletions(-)
diff --git a/src/lxc/lxc_hostdev.c b/src/lxc/lxc_hostdev.c
index 8398646..3d9cc04 100644
--- a/src/lxc/lxc_hostdev.c
+++ b/src/lxc/lxc_hostdev.c
@@ -35,269 +35,36 @@ int
virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
virDomainDefPtr def)
{
- virDomainHostdevDefPtr hostdev = NULL;
- size_t i;
- virHostdevManagerPtr hostdev_mgr;
+ virHostdevManagerPtr mgr;
if (!def->nhostdevs)
return 0;
-
- hostdev_mgr = virHostdevManagerGetDefault();
- if (hostdev_mgr == NULL)
+ mgr = virHostdevManagerGetDefault();
+ if (mgr == NULL)
return -1;
- for (i = 0; i < def->nhostdevs; i++) {
- virUSBDevicePtr usb = NULL;
- hostdev = def->hostdevs[i];
-
- 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 ATTRIBUTE_UNUSED,
- const char *name,
- virUSBDeviceList *list)
-{
- size_t i, j;
- unsigned int count;
- virUSBDevicePtr tmp;
- virHostdevManagerPtr hostdev_mgr;
-
- count = virUSBDeviceListCount(list);
-
- hostdev_mgr = virHostdevManagerGetDefault();
- if (hostdev_mgr == NULL)
- return -1;
- 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;
+ return virHostdevUpdateActiveUsbHostdevs(mgr, def->hostdevs, def->nhostdevs,
+ LXC_DRIVER_NAME, def->name);
}
static int
-virLXCPrepareHostUSBDevices(virLXCDriverPtr driver,
+virLXCPrepareHostUSBDevices(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
virDomainDefPtr def)
{
- size_t i;
- int ret = -1;
- virUSBDeviceList *list;
- virUSBDevicePtr tmp;
virDomainHostdevDefPtr *hostdevs = def->hostdevs;
int nhostdevs = def->nhostdevs;
+ const char *dom_name = def->name;
+ unsigned int flags = 0;
+ virHostdevManagerPtr hostdev_mgr;
- /* To prevent situation where USB device is assigned to two domains
- * we need to keep a list of currently assigned USB devices.
- * 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;
+ hostdev_mgr = virHostdevManagerGetDefault();
+ if (hostdev_mgr == NULL)
+ return -1;
-cleanup:
- virObjectUnref(list);
- return ret;
+ return virHostdevPrepareUsbHostdevs(hostdev_mgr, LXC_DRIVER_NAME, dom_name,
+ hostdevs, nhostdevs, flags);
}
-
int virLXCPrepareHostDevices(virLXCDriverPtr driver,
virDomainDefPtr def)
{
@@ -352,75 +119,20 @@ int virLXCPrepareHostDevices(virLXCDriverPtr driver,
return 0;
}
-
static void
virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs)
{
- size_t i;
virHostdevManagerPtr hostdev_mgr;
hostdev_mgr = virHostdevManagerGetDefault();
if (hostdev_mgr == NULL)
return;
- virObjectLock(hostdev_mgr->activeUsbHostdevs);
- for (i = 0; i < nhostdevs; i++) {
- 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);
+ virHostdevReAttachUsbHostdevs(hostdev_mgr, LXC_DRIVER_NAME,
+ name, hostdevs, nhostdevs);
}
void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver,
--
1.6.0.2