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 | |
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>
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | mk/Makefile.deb | 1 | ||||
-rw-r--r-- | mk/Makefile.rpm | 1 | ||||
-rw-r--r-- | mk/Makefile.tgz | 1 | ||||
-rw-r--r-- | system/system.go | 76 | ||||
-rw-r--r-- | xe-daemon/xe-daemon.go | 8 |
6 files changed, 88 insertions, 0 deletions
@@ -30,6 +30,7 @@ endif XE_DAEMON_SOURCES := XE_DAEMON_SOURCES += ./xe-daemon/xe-daemon.go XE_DAEMON_SOURCES += ./syslog/syslog.go +XE_DAEMON_SOURCES += ./system/system.go XE_DAEMON_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.deb b/mk/Makefile.deb index e22a207..496f332 100644 --- a/mk/Makefile.deb +++ b/mk/Makefile.deb @@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.rpm b/mk/Makefile.rpm index d7bd7d5..de1fde2 100644 --- a/mk/Makefile.rpm +++ b/mk/Makefile.rpm @@ -35,6 +35,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.tgz b/mk/Makefile.tgz index 86c6995..7b19f26 100644 --- a/mk/Makefile.tgz +++ b/mk/Makefile.tgz @@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go 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) + } +} diff --git a/xe-daemon/xe-daemon.go b/xe-daemon/xe-daemon.go index 839e454..17c4bfd 100644 --- a/xe-daemon/xe-daemon.go +++ b/xe-daemon/xe-daemon.go @@ -3,6 +3,7 @@ package main import ( guestmetric "../guestmetric" syslog "../syslog" + system "../system" xenstoreclient "../xenstoreclient" "flag" "fmt" @@ -52,6 +53,9 @@ func main() { exitChannel := make(chan os.Signal, 1) signal.Notify(exitChannel, syscall.SIGTERM, syscall.SIGINT) + resumedChannel := make(chan int) + go system.NotifyResumed(resumedChannel) + xs, err := xenstoreclient.NewCachedXenstore(0) if err != nil { message := fmt.Sprintf("NewCachedXenstore error: %v\n", err) @@ -135,6 +139,10 @@ func main() { } return + case <-resumedChannel: + logger.Printf("Trigger refresh after system resume\n") + continue + case <-time.After(time.Duration(*sleepInterval) * time.Second): continue } |