@@ -26,6 +26,7 @@ import (
2626 "encoding/csv"
2727 "errors"
2828 "fmt"
29+ "net"
2930 "os"
3031 "strconv"
3132 "sync"
@@ -53,8 +54,10 @@ type MemoryManagerCfg struct {
5354type MemoryManager struct {
5455 sync.Mutex
5556 MemoryManagerCfg
56- instances map [string ]* SnapshotState // Indexed by vmID
57- origins map [string ]string // Track parent vm for vm loaded from snapshot
57+ instances map [string ]* SnapshotState // Indexed by vmID
58+ origins map [string ]string // Track parent vm for vm loaded from snapshot
59+ startEpollingCh chan struct {}
60+ startEpollingOnce sync.Once
5861}
5962
6063// NewMemoryManager Initializes a new memory manager
@@ -64,7 +67,9 @@ func NewMemoryManager(cfg MemoryManagerCfg) *MemoryManager {
6467 m := new (MemoryManager )
6568 m .instances = make (map [string ]* SnapshotState )
6669 m .origins = make (map [string ]string )
70+ m .startEpollingCh = make (chan struct {}, 1 )
6771 m .MemoryManagerCfg = cfg
72+ m .startEpollingOnce = sync.Once {}
6873
6974 return m
7075}
@@ -182,21 +187,29 @@ func (m *MemoryManager) Activate(vmID string) error {
182187 return errors .New ("VM already active" )
183188 }
184189
185- if err := state .mapGuestMemory (); err != nil {
186- logger .Error ("Failed to map guest memory" )
187- return err
188- }
190+ select {
191+ case <- m .startEpollingCh :
192+ if err := state .mapGuestMemory (); err != nil {
193+ logger .Error ("Failed to map guest memory" )
194+ return err
195+ }
189196
190- if err := state .getUFFD (); err != nil {
191- logger .Error ("Failed to get uffd" )
192- return err
193- }
197+ if err := state .getUFFD (); err != nil {
198+ logger .Error ("Failed to get uffd" )
199+ return err
200+ }
194201
195- state .setupStateOnActivate ()
202+ state .setupStateOnActivate ()
196203
197- go state .pollUserPageFaults (readyCh )
204+ go state .pollUserPageFaults (readyCh )
198205
199- <- readyCh
206+ <- readyCh
207+
208+ case <- time .After (100 * time .Second ):
209+ return errors .New ("Uffd connection to firecracker timeout" )
210+ default :
211+ return errors .New ("Failed to start epoller" )
212+ }
200213
201214 return nil
202215}
@@ -396,6 +409,39 @@ func (m *MemoryManager) GetUPFLatencyStats(vmID string) ([]*metrics.Metric, erro
396409 return state .latencyMetrics , nil
397410}
398411
412+ func (m * MemoryManager ) ListenUffdSocket (uffdSockAddr string ) error {
413+ log .Debug ("Start listening to uffd socket" )
414+
415+ m .startEpollingOnce .Do (func () {
416+ m .startEpollingCh = make (chan struct {})
417+ })
418+
419+ ln , err := net .Listen ("unix" , uffdSockAddr )
420+ if err != nil {
421+ log .Errorf ("Failed to listen on uffd socket: %v" , err )
422+ return errors .New ("Failed to listen on uffd socket" )
423+ }
424+ defer ln .Close ()
425+
426+ for {
427+ conn , err := ln .Accept ()
428+ if err != nil {
429+ log .Printf ("Failed to accept connection on uffd socket: %v" , err )
430+ continue
431+ }
432+ go func (conn net.Conn ) {
433+ defer conn .Close ()
434+ if err := ln .Close (); err != nil {
435+ log .Printf ("Failed to close uffd socket listener: %v" , err )
436+ }
437+ close (m .startEpollingCh )
438+ }(conn )
439+ break
440+ }
441+
442+ return nil
443+ }
444+
399445// Deprecated
400446// func (m *MemoryManager) GetUPFSockPath(vmID string, isSnapshotReady bool) (string, error) {
401447// logger := log.WithFields(log.Fields{"vmID": vmID})
0 commit comments