This commit is related to RTC timer device too. HPET is being shared
from host device through `localtime` clock. This timer is available
creating a new timer using `hpet` name.
Signed-off-by: Julio Faracco <jcfaracco(a)gmail.com>
---
docs/formatdomain.html.in | 2 +-
src/lxc/lxc_cgroup.c | 17 +++++++++++++----
src/lxc/lxc_controller.c | 33 +++++++++++++++++++++++++++++----
3 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index b045314917..9822fee0ab 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2464,7 +2464,7 @@
The <code>name</code> attribute selects which timer is
being modified, and can be one of
"platform" (currently unsupported),
- "hpet" (libxl, xen, qemu), "kvmclock" (qemu),
+ "hpet" (libxl, xen, qemu, lxc), "kvmclock" (qemu),
"pit" (qemu), "rtc" (qemu, lxc), "tsc" (libxl,
qemu -
<span class="since">since 3.2.0</span>),
"hypervclock"
(qemu - <span class="since">since 1.2.2</span>) or
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index 752cb4b047..470337e675 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -417,20 +417,19 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
for (i = 0; i < def->clock.ntimers; i++) {
virDomainTimerDefPtr timer = def->clock.timers[i];
+ if (!timer->present)
+ continue;
+
switch ((virDomainTimerNameType)timer->name) {
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
case VIR_DOMAIN_TIMER_NAME_TSC:
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
case VIR_DOMAIN_TIMER_NAME_PIT:
- case VIR_DOMAIN_TIMER_NAME_HPET:
case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
case VIR_DOMAIN_TIMER_NAME_LAST:
break;
case VIR_DOMAIN_TIMER_NAME_RTC:
- if (!timer->present)
- break;
-
if (virFileExists("/dev/rtc")) {
if (virCgroupAllowDevicePath(cgroup, "/dev/rtc",
VIR_CGROUP_DEVICE_READ,
@@ -440,6 +439,16 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
VIR_DEBUG("Ignoring non-existent device /dev/rtc");
}
break;
+ case VIR_DOMAIN_TIMER_NAME_HPET:
+ if (virFileExists("/dev/hpet")) {
+ if (virCgroupAllowDevicePath(cgroup, "/dev/hpet",
+ VIR_CGROUP_DEVICE_READ,
+ false) < 0)
+ return -1;
+ } else {
+ VIR_DEBUG("Ignoring non-existent device /dev/hpet");
+ }
+ break;
}
}
} else {
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 528f2fabf1..b193474767 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1567,13 +1567,15 @@ virLXCControllerSetupTimers(virLXCControllerPtr ctrl)
dev_t dev;
virDomainTimerDefPtr timer = def->clock.timers[i];
+ if (!timer->present)
+ continue;
+
switch ((virDomainTimerNameType)timer->name) {
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
case VIR_DOMAIN_TIMER_NAME_TSC:
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
case VIR_DOMAIN_TIMER_NAME_PIT:
- case VIR_DOMAIN_TIMER_NAME_HPET:
case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
case VIR_DOMAIN_TIMER_NAME_LAST:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -1581,9 +1583,6 @@ virLXCControllerSetupTimers(virLXCControllerPtr ctrl)
virDomainTimerNameTypeToString(timer->name));
return -1;
case VIR_DOMAIN_TIMER_NAME_RTC:
- if (!timer->present)
- break;
-
if (stat("/dev/rtc", &sb) < 0) {
if (errno == EACCES)
goto cleanup;
@@ -1606,6 +1605,32 @@ virLXCControllerSetupTimers(virLXCControllerPtr ctrl)
goto cleanup;
}
+ if (lxcContainerChown(ctrl->def, path) < 0)
+ goto cleanup;
+ break;
+ case VIR_DOMAIN_TIMER_NAME_HPET:
+ if (stat("/dev/hpet", &sb) < 0) {
+ if (errno == EACCES)
+ goto cleanup;
+
+ virReportSystemError(errno,
+ _("Path '%s' is not accessible"),
+ path);
+ goto cleanup;
+ }
+
+ path = g_strdup_printf("/%s/%s.dev/%s", LXC_STATE_DIR,
+ ctrl->def->name, "/hpet");
+
+ dev = makedev(major(sb.st_rdev), minor(sb.st_rdev));
+ if (mknod(path, S_IFCHR, dev) < 0 ||
+ chmod(path, sb.st_mode)) {
+ virReportSystemError(errno,
+ _("Failed to make device %s"),
+ path);
+ goto cleanup;
+ }
+
if (lxcContainerChown(ctrl->def, path) < 0)
goto cleanup;
break;
--
2.20.1