summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2019-03-29 12:25:17 -0700
committerShentubot <shentubot@google.com>2019-03-29 12:26:25 -0700
commited23f547093e705ba3d6f82b2ce49592180f9a5a (patch)
tree973becebd4992b41a0d5791a93e3a36745052d82
parent45c54b1f4e2bb6fcad14b8b7734d6a1847329901 (diff)
Treat ENOSPC as a state-file error during save.
PiperOrigin-RevId: 241028806 Change-Id: I770bf751a2740869a93c3ab50370a727ae580470
-rw-r--r--pkg/sentry/kernel/kernel.go5
-rw-r--r--pkg/sentry/state/BUILD1
-rw-r--r--pkg/sentry/state/state.go14
3 files changed, 18 insertions, 2 deletions
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index 3533fd8f7..d9f3f4e24 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -365,6 +365,11 @@ func (ts *TaskSet) flushWritesToFiles(ctx context.Context) error {
syncErr := desc.file.Fsync(ctx, 0, fs.FileMaxOffset, fs.SyncAll)
if err := fs.SaveFileFsyncError(syncErr); err != nil {
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)
}
}
diff --git a/pkg/sentry/state/BUILD b/pkg/sentry/state/BUILD
index 69385e23c..cee18f681 100644
--- a/pkg/sentry/state/BUILD
+++ b/pkg/sentry/state/BUILD
@@ -18,5 +18,6 @@ go_library(
"//pkg/sentry/kernel",
"//pkg/sentry/watchdog",
"//pkg/state/statefile",
+ "//pkg/syserror",
],
)
diff --git a/pkg/sentry/state/state.go b/pkg/sentry/state/state.go
index 67db78a56..224f8b709 100644
--- a/pkg/sentry/state/state.go
+++ b/pkg/sentry/state/state.go
@@ -24,18 +24,20 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
"gvisor.googlesource.com/gvisor/pkg/sentry/watchdog"
"gvisor.googlesource.com/gvisor/pkg/state/statefile"
+ "gvisor.googlesource.com/gvisor/pkg/syserror"
)
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 {
err error
}
// Error implements error.Error().
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.
@@ -76,6 +78,14 @@ func (opts SaveOpts) Save(k *kernel.Kernel, w *watchdog.Watchdog) error {
} else {
// Save the kernel.
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 {
err = ErrStateFile{closeErr}
}