[libvirt] [PATCH 1/2] qemu: add the USB devices to the cgroup whitelist
by Diego Elio Pettenò
Make sure that the QEmu process within the cgroup can access the device
file for the USB device that has to be connected to the virtual domain.
---
src/qemu/qemu_driver.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a7cce6a..0612e69 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3434,6 +3434,25 @@ static int qemuSetupChardevCgroup(virDomainDefPtr def,
}
+static int qemuSetupHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED,
+ const char *path,
+ void *opaque)
+{
+ virCgroupPtr cgroup = opaque;
+ int rc;
+
+ VIR_DEBUG("Process path '%s' for USB device", path);
+ rc = virCgroupAllowDevicePath(cgroup, path);
+ if (rc != 0) {
+ virReportSystemError(-rc,
+ _("Unable to allow device %s"),
+ path);
+ return -1;
+ }
+
+ return 0;
+}
+
static int qemuSetupCgroup(struct qemud_driver *driver,
virDomainObjPtr vm)
{
@@ -3507,6 +3526,23 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
qemuSetupChardevCgroup,
cgroup) < 0)
goto cleanup;
+
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
+ usbDevice *usb;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
+ continue;
+
+ if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus,
+ hostdev->source.subsys.u.usb.device)) == NULL)
+ goto cleanup;
+
+ if (usbDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup, cgroup) < 0 )
+ goto cleanup;
+ }
}
if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY))) {
@@ -8511,6 +8547,25 @@ static int qemudDomainAttachHostUsbDevice(struct qemud_driver *driver,
goto error;
}
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
+ virCgroupPtr cgroup = NULL;
+ usbDevice *usb;
+
+ if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to find cgroup for %s\n"),
+ vm->def->name);
+ goto error;
+ }
+
+ if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus,
+ hostdev->source.subsys.u.usb.device)) == NULL)
+ goto error;
+
+ if (usbDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup, cgroup) < 0 )
+ goto error;
+ }
+
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
ret = qemuMonitorAddDevice(priv->mon, devstr);
--
1.7.3.2
14 years, 1 month
[libvirt] [PATCH] qemu: add the USB devices to the cgroup whitelist
by Diego Elio Pettenò
Add a new interface to hostusb.h to add an USB device abstraction to a
cgroup whitelist; then use it both when attaching a new USB device and when
adding it to the commandline so that the device can be accessed by the
QEmu-specific cgroup.
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 36 ++++++++++++++++++++++++++++++++++++
src/util/hostusb.c | 6 ++++++
src/util/hostusb.h | 4 +++-
4 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cf06256..0c6f308 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -707,6 +707,7 @@ virMutexUnlock;
# usb.h
+usbAllowDeviceCgroup;
usbDeviceFileIterate;
usbDeviceGetBus;
usbDeviceGetDevno;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1eea3a9..acf319e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3505,6 +3505,23 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
qemuSetupChardevCgroup,
cgroup) < 0)
goto cleanup;
+
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
+ usbDevice *usb;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
+ continue;
+
+ if ((usb = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
+ hostdev->source.subsys.u.usb.product)) == NULL)
+ goto cleanup;
+
+ if (usbAllowDeviceCgroup(usb, cgroup) < 0)
+ goto cleanup;
+ }
}
if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY))) {
@@ -8454,6 +8471,25 @@ static int qemudDomainAttachHostUsbDevice(struct qemud_driver *driver,
goto error;
}
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
+ virCgroupPtr cgroup = NULL;
+ usbDevice *usb;
+
+ if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to find cgroup for %s\n"),
+ vm->def->name);
+ goto error;
+ }
+
+ if ((usb = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
+ hostdev->source.subsys.u.usb.product)) == NULL)
+ goto error;
+
+ if (usbAllowDeviceCgroup(usb, cgroup) < 0)
+ goto error;
+ }
+
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
ret = qemuMonitorAddDevice(priv->mon, devstr);
diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index 2d6e414..2cbe1fb 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -225,3 +225,9 @@ int usbDeviceFileIterate(usbDevice *dev,
{
return (actor)(dev, dev->path, opaque);
}
+
+int usbAllowDeviceCgroup(usbDevice *dev,
+ virCgroupPtr group)
+{
+ return virCgroupAllowDevicePath(group, dev->path);
+}
diff --git a/src/util/hostusb.h b/src/util/hostusb.h
index f4a13ca..12269ad 100644
--- a/src/util/hostusb.h
+++ b/src/util/hostusb.h
@@ -23,6 +23,7 @@
# define __VIR_USB_H__
# include "internal.h"
+# include "cgroup.h"
typedef struct _usbDevice usbDevice;
@@ -48,6 +49,7 @@ typedef int (*usbDeviceFileActor)(usbDevice *dev,
int usbDeviceFileIterate(usbDevice *dev,
usbDeviceFileActor actor,
void *opaque);
-
+int usbAllowDeviceCgroup(usbDevice *dev,
+ virCgroupPtr group);
#endif /* __VIR_USB_H__ */
--
1.7.3.2
14 years, 1 month
Re: [libvirt] SPAM-LOW: Re: Re: Node.GetInfo error
by arnaud.champion@devatom.fr
?Ok,
if you are under windows (like me), use GitExtension (http://sourceforge.net/projects/gitextensions/)
It works, not perfect, but it works.
Arnaud
From: 黄亮
Sent: Monday, November 01, 2010 9:52 AM
To: arnaud.champion(a)devatom.fr
Subject: Re: Re: SPAM-LOW: Re: Re: Node.GetInfo error
Hi Arnaud,
The NodeInfoStructure you sent to me yesterday works, thank you.
I saw your patch file, should I manually apply it to the source code or is there some tools I can use to automatically apply the changes?
Regards
2010-11-01
--------------------------------------------------------------------------------
Lancer
--------------------------------------------------------------------------------
发件人: arnaud.champion(a)devatom.fr
发送时间: 2010-11-01 16:37:17
收件人: 黄亮
抄送: libvir-list
主题: Re: SPAM-LOW: Re: Re: Node.GetInfo error
Hi,
I think the solution is in the last patches I have send (which are not yet in the git). Have you tried the NodeInfoStructure I have sended yesterday ?
Arnaud
From: 黄亮
Sent: Monday, November 01, 2010 3:01 AM
To: arnaud.champion(a)devatom.fr
Cc: libvir-list
Subject: SPAM-LOW: Re: Re: Node.GetInfo error
HI,
I tried
Errors.Error err = Errors.GetLastError();
MessageBox.Show(err.Message);
But IDE shows compilation errors that there is no "Error" defination in "Errors", and "Errors.GetLastError()" returns int.
I made a guess that maybe it was like this:
Error err = Errors.SaveLastError();
MessageBox.Show("Get Info error: " + err.Message);
It can be compiled but "err.Message" has nothing in it.
Did I make a wrong assumption?
Regards
2010-11-01
--------------------------------------------------------------------------------
Lancer
--------------------------------------------------------------------------------
发件人: arnaud.champion(a)devatom.fr
发送时间: 2010-10-31 16:48:15
收件人: 黄亮
抄送: libvir-list(a)redhat.com
主题: Re: Node.GetInfo error
Ok,
at first GetLastError return an Error object. So you should anything like :
Errors.Error err = Errors.GetLastError();
MessageBox.Show(err.Message);
For the NodeInfo structure, I think the problem is the same that was for DomainInfo, I'll check marshaling. Then respond you with the correct infos.
Arnaud
PS : can you also put libvirt-list(a)redhat.com in copy of your mails, to keep everyone in the loop ?
From: 黄亮
Sent: Sunday, October 31, 2010 8:20 AM
To: arnaud.champion
Subject: Node.GetInfo error
Hi,
Sorry for disturbing again. But I get error while using Node.GetInfo.
Code:
NodeInfo aNodeInfo = new NodeInfo();
if (Node.GetInfo(con, aNodeInfo) < 0)
{
//MessageBox.Show("Node Info Error");
MessageBox.Show(Errors.GetLastError().ToString());
return 0f;
}
I'm sure con != IntPtr.Zero. I tried to use Errors.GetLastError(), it returns int. But I don't know what to do with it.
So, any suggestions ? Thanks
Regards
2010-10-31
--------------------------------------------------------------------------------
Lancer
__________ Information from ESET Smart Security, version of virus signature database 5577 (20101030) __________
The message was checked by ESET Smart Security.
http://www.eset.com
14 years, 1 month
Re: [libvirt] Node.GetInfo error
by arnaud.champion@devatom.fr
?Ok,
at first GetLastError return an Error object. So you should anything like :
Errors.Error err = Errors.GetLastError();
MessageBox.Show(err.Message);
For the NodeInfo structure, I think the problem is the same that was for DomainInfo, I'll check marshaling. Then respond you with the correct infos.
Arnaud
PS : can you also put libvirt-list(a)redhat.com in copy of your mails, to keep everyone in the loop ?
From: 黄亮
Sent: Sunday, October 31, 2010 8:20 AM
To: arnaud.champion
Subject: Node.GetInfo error
Hi,
Sorry for disturbing again. But I get error while using Node.GetInfo.
Code:
NodeInfo aNodeInfo = new NodeInfo();
if (Node.GetInfo(con, aNodeInfo) < 0)
{
//MessageBox.Show("Node Info Error");
MessageBox.Show(Errors.GetLastError().ToString());
return 0f;
}
I'm sure con != IntPtr.Zero. I tried to use Errors.GetLastError(), it returns int. But I don't know what to do with it.
So, any suggestions ? Thanks
Regards
2010-10-31
--------------------------------------------------------------------------------
Lancer
14 years, 1 month