Treat ENOSPC as a state-file error during save.
PiperOrigin-RevId: 241028806 Change-Id: I770bf751a2740869a93c3ab50370a727ae580470
This commit is contained in:
parent
45c54b1f4e
commit
ed23f54709
|
@ -365,6 +365,11 @@ func (ts *TaskSet) flushWritesToFiles(ctx context.Context) error {
|
||||||
syncErr := desc.file.Fsync(ctx, 0, fs.FileMaxOffset, fs.SyncAll)
|
syncErr := desc.file.Fsync(ctx, 0, fs.FileMaxOffset, fs.SyncAll)
|
||||||
if err := fs.SaveFileFsyncError(syncErr); err != nil {
|
if err := fs.SaveFileFsyncError(syncErr); err != nil {
|
||||||
name, _ := desc.file.Dirent.FullName(nil /* root */)
|
name, _ := desc.file.Dirent.FullName(nil /* root */)
|
||||||
|
// Wrapping this error not only allows
|
||||||
|
// for a more useful message, but is
|
||||||
|
// required to distinguish Fsync errors
|
||||||
|
// from state file errors in
|
||||||
|
// state.Save.
|
||||||
return fmt.Errorf("%q was not sufficiently synced: %v", name, err)
|
return fmt.Errorf("%q was not sufficiently synced: %v", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,5 +18,6 @@ go_library(
|
||||||
"//pkg/sentry/kernel",
|
"//pkg/sentry/kernel",
|
||||||
"//pkg/sentry/watchdog",
|
"//pkg/sentry/watchdog",
|
||||||
"//pkg/state/statefile",
|
"//pkg/state/statefile",
|
||||||
|
"//pkg/syserror",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,18 +24,20 @@ import (
|
||||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
|
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
|
||||||
"gvisor.googlesource.com/gvisor/pkg/sentry/watchdog"
|
"gvisor.googlesource.com/gvisor/pkg/sentry/watchdog"
|
||||||
"gvisor.googlesource.com/gvisor/pkg/state/statefile"
|
"gvisor.googlesource.com/gvisor/pkg/state/statefile"
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/syserror"
|
||||||
)
|
)
|
||||||
|
|
||||||
var previousMetadata map[string]string
|
var previousMetadata map[string]string
|
||||||
|
|
||||||
// ErrStateFile is returned when the state file cannot be opened.
|
// ErrStateFile is returned when an error is encountered writing the statefile
|
||||||
|
// (which may occur during open or close calls in addition to write).
|
||||||
type ErrStateFile struct {
|
type ErrStateFile struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error implements error.Error().
|
// Error implements error.Error().
|
||||||
func (e ErrStateFile) Error() string {
|
func (e ErrStateFile) Error() string {
|
||||||
return fmt.Sprintf("failed to open statefile: %v", e.err)
|
return fmt.Sprintf("statefile error: %v", e.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveOpts contains save-related options.
|
// SaveOpts contains save-related options.
|
||||||
|
@ -76,6 +78,14 @@ func (opts SaveOpts) Save(k *kernel.Kernel, w *watchdog.Watchdog) error {
|
||||||
} else {
|
} else {
|
||||||
// Save the kernel.
|
// Save the kernel.
|
||||||
err = k.SaveTo(wc)
|
err = k.SaveTo(wc)
|
||||||
|
|
||||||
|
// ENOSPC is a state file error. This error can only come from
|
||||||
|
// writing the state file, and not from fs.FileOperations.Fsync
|
||||||
|
// because we wrap those in kernel.TaskSet.flushWritesToFiles.
|
||||||
|
if err == syserror.ENOSPC {
|
||||||
|
err = ErrStateFile{err}
|
||||||
|
}
|
||||||
|
|
||||||
if closeErr := wc.Close(); err == nil && closeErr != nil {
|
if closeErr := wc.Close(); err == nil && closeErr != nil {
|
||||||
err = ErrStateFile{closeErr}
|
err = ErrStateFile{closeErr}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue