diff options
author | Ross Lagerwall <ross.lagerwall@citrix.com> | 2016-06-29 10:54:08 +0100 |
---|---|---|
committer | Ross Lagerwall <ross.lagerwall@citrix.com> | 2016-07-14 12:02:55 +0100 |
commit | b0091d3dad6a1dae7874ed33906ac0d64eb6c25b (patch) | |
tree | aa6aa5cae4a4aa7119a73a771b5d0ee842918625 /system | |
parent | 2e0e2cbdb9022b9b2bd2555ee12eec0d1abf8667 (diff) | |
download | vyos-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.go | 76 |
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) + } +} |