From ed23f547093e705ba3d6f82b2ce49592180f9a5a Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Fri, 29 Mar 2019 12:25:17 -0700 Subject: [PATCH] Treat ENOSPC as a state-file error during save. PiperOrigin-RevId: 241028806 Change-Id: I770bf751a2740869a93c3ab50370a727ae580470 --- pkg/sentry/kernel/kernel.go | 5 +++++ pkg/sentry/state/BUILD | 1 + pkg/sentry/state/state.go | 14 ++++++++++++-- 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} }