MCPcopy
hub / github.com/google/gvisor / SaveTo

Method SaveTo

pkg/sentry/pgalloc/save_restore.go:99–433  ·  view source on GitHub ↗

SaveTo writes f's state to the given stream.

(ctx context.Context, w io.Writer, opts *SaveOpts)

Source from the content-addressed store, hash-verified

97
98// SaveTo writes f's state to the given stream.
99func (f *MemoryFile) SaveTo(ctx context.Context, w io.Writer, opts *SaveOpts) error {
100 if err := f.AwaitLoadAll(); err != nil {
101 return fmt.Errorf("previous async page loading failed: %w", err)
102 }
103
104 // Wait for memory release.
105 f.mu.Lock()
106 defer f.mu.Unlock()
107 for f.haveWaste {
108 f.mu.Unlock()
109 runtime.Gosched()
110 f.mu.Lock()
111 }
112
113 // Ensure that there are no pending evictions.
114 if len(f.evictable) != 0 {
115 panic(fmt.Sprintf("evictions still pending for %d users; call StartEvictions and WaitForEvictions before SaveTo", len(f.evictable)))
116 }
117
118 // Register this MemoryFile with async page saving if a pages file has been
119 // provided.
120 var amfs *asyncMemoryFileSave
121 if opts.PagesFile != nil {
122 var sf stateio.SourceFile
123 if opts.PagesFile.aw.NeedRegisterSourceFD() {
124 fileSize := uint64(len(f.chunksLoad())) * chunkSize
125 var err error
126 sf, err = opts.PagesFile.aw.RegisterSourceFD(int32(f.file.Fd()), fileSize, f.getClientFileRangeSettings(fileSize))
127 if err != nil {
128 return fmt.Errorf("failed to register MemoryFile with pages file: %w", err)
129 }
130 }
131 amfs = &asyncMemoryFileSave{
132 f: f,
133 pf: opts.PagesFile,
134 sf: sf,
135 }
136 }
137
138 // We only want to explicitly include pages containing non-zero bytes in
139 // the checkpoint, to reduce the size of the checkpoint and improve restore
140 // performance. Scan pages for non-zero bytes and ensure that they are
141 // marked known-committed.
142 //
143 // If async page saving is enabled, emit writes to the pages file during
144 // scanning, which is feasible since the pages metadata file and pages file
145 // are distinct. If async page saving is disabled, we can't do this since
146 // pages would be written to the state file before the metadata needed to
147 // determine where to load them to. (We could instead emit one memAcct
148 // segment at a time, immediately before the contents of the pages it
149 // represents. However, each call to state.Save() writes some overhead
150 // (header and type information), which would bloat the state file and slow
151 // down loading when the number of memAcct segments is large.)
152 timeScanStart := gohacks.Nanotime()
153 var (
154 allocatedBytes uint64
155 alreadyCommittedBytes uint64
156 newCommittedBytes uint64

Callers

nothing calls this directly

Calls 15

AwaitLoadAllMethod · 0.95
chunksLoadMethod · 0.95
decommitFileMethod · 0.95
forEachChunkMethod · 0.95
forEachMappingSliceMethod · 0.95
NanotimeFunction · 0.92
WarningfFunction · 0.92
IsHugePageAlignedFunction · 0.92
InfofFunction · 0.92
SaveFunction · 0.92
WriteHeaderFunction · 0.92

Tested by

no test coverage detected