summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorRoss Lagerwall <ross.lagerwall@citrix.com>2016-06-29 10:54:08 +0100
committerRoss Lagerwall <ross.lagerwall@citrix.com>2016-07-14 12:02:55 +0100
commitb0091d3dad6a1dae7874ed33906ac0d64eb6c25b (patch)
treeaa6aa5cae4a4aa7119a73a771b5d0ee842918625 /system
parent2e0e2cbdb9022b9b2bd2555ee12eec0d1abf8667 (diff)
downloadvyos-xe-guest-utilities-b0091d3dad6a1dae7874ed33906ac0d64eb6c25b.tar.gz
vyos-xe-guest-utilities-b0091d3dad6a1dae7874ed33906ac0d64eb6c25b.zip
CA-202608: Trigger refresh after system resume
If the guest is suspended and then resumed or migrated, trigger a refresh to repopulate the xenstore entries (since the guest will have a new domid). Without doing this, XAPI thinks that the guest does not have PV drivers installed and will refuse to do a vbd-plug operation until then next refresh by the guest agent. Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Diffstat (limited to 'system')
-rw-r--r--system/system.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/system/system.go b/system/system.go
new file mode 100644
index 0000000..b21d000
--- /dev/null
+++ b/system/system.go
@@ -0,0 +1,76 @@
+package sys
+
+import (
+ "math"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+const (
+ CLOCK_REALTIME = 0
+ TFD_CLOEXEC = 02000000
+ TFD_TIMER_ABSTIME = 1
+ TFD_TIMER_CANCEL_ON_SET = 2
+)
+
+type ITimerSpec struct {
+ Interval syscall.Timespec
+ Value syscall.Timespec
+}
+
+// System call wrapper for timerfd_create, generated with mksyscall.pl
+func timerfdCreate(clockid int, flags int) (fd int, err error) {
+ r0, _, e1 := syscall.Syscall(syscall.SYS_TIMERFD_CREATE,
+ uintptr(clockid), uintptr(flags), 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// System call wrapper for timerfd_settime, generated with mksyscall.pl
+func timerfdSettime(fd int, flags int, new_value *ITimerSpec,
+ old_value *ITimerSpec) (err error) {
+ _, _, e1 := syscall.Syscall6(syscall.SYS_TIMERFD_SETTIME, uintptr(fd),
+ uintptr(flags),
+ uintptr(unsafe.Pointer(new_value)),
+ uintptr(unsafe.Pointer(old_value)), 0, 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+/*
+ * Send a notification on @c when the system has just been resumed after
+ * sleep. This is implemented by watching for a change in real time compared
+ * with monotonic time. This may cause a spurious notification if the time
+ * is changed by a user or NTP jump.
+ */
+func NotifyResumed(c chan int) {
+ ts := ITimerSpec{Interval: syscall.Timespec{math.MaxInt32, 0},
+ Value: syscall.Timespec{0, 0}}
+ buf := make([]byte, 8)
+ for {
+ fd, err := timerfdCreate(CLOCK_REALTIME, TFD_CLOEXEC)
+ if err != nil {
+ return
+ }
+
+ err = timerfdSettime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &ts, nil)
+ if err != nil {
+ return
+ }
+
+ _, err = syscall.Read(fd, buf)
+ if err == syscall.ECANCELED {
+ // Wait a bit for the system to settle down after resuming
+ time.Sleep(time.Duration(1) * time.Second)
+ c <- 1
+ }
+
+ syscall.Close(fd)
+ }
+}