diff options
author | Ian Gudger <igudger@google.com> | 2018-10-03 17:02:05 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-10-03 17:03:09 -0700 |
commit | 4fef31f96c289d5e58c3c2997ee38fcb22c0378f (patch) | |
tree | cc05ab5e2841ff987e126095657db94a1492d12b | |
parent | 9f2ba6ac3e7b56d428ef4369a7326dd85f30642d (diff) |
Add S/R support for FIOASYNC
PiperOrigin-RevId: 215655197
Change-Id: I668b1bc7c29daaf2999f8f759138bcbb09c4de6f
-rw-r--r-- | pkg/sentry/fs/file.go | 10 | ||||
-rw-r--r-- | pkg/sentry/fs/file_state.go | 11 | ||||
-rw-r--r-- | pkg/sentry/kernel/fasync/fasync.go | 4 | ||||
-rw-r--r-- | pkg/waiter/waiter.go | 2 |
4 files changed, 25 insertions, 2 deletions
diff --git a/pkg/sentry/fs/file.go b/pkg/sentry/fs/file.go index 904827a3e..36794d378 100644 --- a/pkg/sentry/fs/file.go +++ b/pkg/sentry/fs/file.go @@ -85,6 +85,9 @@ type File struct { // async handles O_ASYNC notifications. async FileAsync + // saving indicates that this file is in the process of being saved. + saving bool `state:"nosave"` + // mu is dual-purpose: first, to make read(2) and write(2) thread-safe // in conformity with POSIX, and second, to cancel operations before they // begin in response to interruptions (i.e. signals). @@ -127,10 +130,15 @@ func (f *File) DecRef() { // Release a reference on the Dirent. f.Dirent.DecRef() + // Only unregister if we are currently registered. There is nothing + // to register if f.async is nil (this happens when async mode is + // enabled without setting an owner). Also, we unregister during + // save. f.flagsMu.Lock() - if f.flags.Async && f.async != nil { + if !f.saving && f.flags.Async && f.async != nil { f.async.Unregister(f) } + f.async = nil f.flagsMu.Unlock() }) } diff --git a/pkg/sentry/fs/file_state.go b/pkg/sentry/fs/file_state.go index 3384737ab..f848d1b79 100644 --- a/pkg/sentry/fs/file_state.go +++ b/pkg/sentry/fs/file_state.go @@ -14,7 +14,18 @@ package fs +// beforeSave is invoked by stateify. +func (f *File) beforeSave() { + f.saving = true + if f.flags.Async && f.async != nil { + f.async.Unregister(f) + } +} + // afterLoad is invoked by stateify. func (f *File) afterLoad() { f.mu.Init() + if f.flags.Async && f.async != nil { + f.async.Register(f) + } } diff --git a/pkg/sentry/kernel/fasync/fasync.go b/pkg/sentry/kernel/fasync/fasync.go index 69c7970fa..7d01abe90 100644 --- a/pkg/sentry/kernel/fasync/fasync.go +++ b/pkg/sentry/kernel/fasync/fasync.go @@ -32,8 +32,10 @@ func New() fs.FileAsync { } // FileAsync sends signals when the registered file is ready for IO. +// +// +stateify savable type FileAsync struct { - mu sync.Mutex + mu sync.Mutex `state:"nosave"` e waiter.Entry requester *auth.Credentials diff --git a/pkg/waiter/waiter.go b/pkg/waiter/waiter.go index 9825880ca..832b6a5a9 100644 --- a/pkg/waiter/waiter.go +++ b/pkg/waiter/waiter.go @@ -113,6 +113,8 @@ type EntryCallback interface { // Entry represents a waiter that can be add to the a wait queue. It can // only be in one queue at a time, and is added "intrusively" to the queue with // no extra memory allocations. +// +// +stateify savable type Entry struct { // Context stores any state the waiter may wish to store in the entry // itself, which may be used at wake up time. |