mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Plumb restore context to afterLoad()
This allows for external information to be passed to restore code, like host FDs to be remapped. Updates #1956 PiperOrigin-RevId: 612540749
This commit is contained in:
committed by
gVisor bot
parent
c6b06ab1a5
commit
c087777e37
+4
-4
@@ -38,7 +38,7 @@ import (
|
|||||||
"gvisor.dev/gvisor/pkg/sync"
|
"gvisor.dev/gvisor/pkg/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// contextID is the package for context.Context.Value keys.
|
// contextID is the package for anyContext.Context.Value keys.
|
||||||
type contextID int
|
type contextID int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -51,13 +51,13 @@ const (
|
|||||||
_AT_HWCAP2 = 26
|
_AT_HWCAP2 = 26
|
||||||
)
|
)
|
||||||
|
|
||||||
// context represents context.Context.
|
// anyContext represents context.Context.
|
||||||
type context interface {
|
type anyContext interface {
|
||||||
Value(key any) any
|
Value(key any) any
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromContext returns the FeatureSet from the context, if available.
|
// FromContext returns the FeatureSet from the context, if available.
|
||||||
func FromContext(ctx context) FeatureSet {
|
func FromContext(ctx anyContext) FeatureSet {
|
||||||
v := ctx.Value(CtxFeatureSet)
|
v := ctx.Value(CtxFeatureSet)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return FeatureSet{} // Panics if used.
|
return FeatureSet{} // Panics if used.
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package cpuid
|
package cpuid
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// Static is a static CPUID function.
|
// Static is a static CPUID function.
|
||||||
//
|
//
|
||||||
// +stateify savable
|
// +stateify savable
|
||||||
@@ -90,7 +92,7 @@ func (s Static) ToFeatureSet() FeatureSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad calls normalize.
|
// afterLoad calls normalize.
|
||||||
func (s Static) afterLoad() {
|
func (s Static) afterLoad(context.Context) {
|
||||||
s.normalize()
|
s.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package refs_template
|
package refs_template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||||
@@ -156,7 +157,7 @@ func (r *Refs) DecRef(destroy func()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Refs) afterLoad() {
|
func (r *Refs) afterLoad(context.Context) {
|
||||||
if r.ReadRefs() > 0 {
|
if r.ReadRefs() > 0 {
|
||||||
refs.Register(r)
|
refs.Register(r)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
package arch
|
package arch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,6 +37,6 @@ type State struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (s *State) afterLoad() {
|
func (s *State) afterLoad(context.Context) {
|
||||||
s.afterLoadFPState()
|
s.afterLoadFPState()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package nvproxy
|
package nvproxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goContext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/abi/nvgpu"
|
"gvisor.dev/gvisor/pkg/abi/nvgpu"
|
||||||
@@ -30,7 +31,7 @@ func (n *nvproxy) beforeSave() {
|
|||||||
n.objsLive = nil
|
n.objsLive = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *nvproxy) afterLoad() {
|
func (n *nvproxy) afterLoad(goContext.Context) {
|
||||||
Init()
|
Init()
|
||||||
abiCons, ok := abis[n.version]
|
abiCons, ok := abis[n.version]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -14,8 +14,10 @@
|
|||||||
|
|
||||||
package devtmpfs
|
package devtmpfs
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (fst *FilesystemType) afterLoad() {
|
func (fst *FilesystemType) afterLoad(context.Context) {
|
||||||
if fst.fs != nil {
|
if fst.fs != nil {
|
||||||
// Ensure that we don't create another filesystem.
|
// Ensure that we don't create another filesystem.
|
||||||
fst.initOnce.Do(func() {})
|
fst.initOnce.Do(func() {})
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
package fuse
|
package fuse
|
||||||
|
|
||||||
func (fRes *futureResponse) afterLoad() {
|
import "context"
|
||||||
|
|
||||||
|
func (fRes *futureResponse) afterLoad(context.Context) {
|
||||||
fRes.ch = make(chan struct{})
|
fRes.ch = make(chan struct{})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package gofer
|
package gofer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goContext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ func (d *dentry) beforeSave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (d *dentry) afterLoad() {
|
func (d *dentry) afterLoad(goContext.Context) {
|
||||||
d.readFD = atomicbitops.FromInt32(-1)
|
d.readFD = atomicbitops.FromInt32(-1)
|
||||||
d.writeFD = atomicbitops.FromInt32(-1)
|
d.writeFD = atomicbitops.FromInt32(-1)
|
||||||
d.mmapFD = atomicbitops.FromInt32(-1)
|
d.mmapFD = atomicbitops.FromInt32(-1)
|
||||||
@@ -138,12 +139,12 @@ func (d *dentry) afterLoad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (d *directfsDentry) afterLoad() {
|
func (d *directfsDentry) afterLoad(goContext.Context) {
|
||||||
d.controlFD = -1
|
d.controlFD = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (d *dentryPlatformFile) afterLoad() {
|
func (d *dentryPlatformFile) afterLoad(goContext.Context) {
|
||||||
if d.hostFileMapper.IsInited() {
|
if d.hostFileMapper.IsInited() {
|
||||||
// Ensure that we don't call d.hostFileMapper.Init() again.
|
// Ensure that we don't call d.hostFileMapper.Init() again.
|
||||||
d.hostFileMapperInitOnce.Do(func() {})
|
d.hostFileMapperInitOnce.Do(func() {})
|
||||||
@@ -151,7 +152,7 @@ func (d *dentryPlatformFile) afterLoad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (fd *specialFileFD) afterLoad() {
|
func (fd *specialFileFD) afterLoad(goContext.Context) {
|
||||||
fd.handle.fd = -1
|
fd.handle.fd = -1
|
||||||
if fd.hostFileMapper.IsInited() {
|
if fd.hostFileMapper.IsInited() {
|
||||||
// Ensure that we don't call fd.hostFileMapper.Init() again.
|
// Ensure that we don't call fd.hostFileMapper.Init() again.
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package host
|
package host
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ func (i *inode) beforeSave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (i *inode) afterLoad() {
|
func (i *inode) afterLoad(context.Context) {
|
||||||
if i.epollable {
|
if i.epollable {
|
||||||
if err := unix.SetNonblock(i.hostFD, true); err != nil {
|
if err := unix.SetNonblock(i.hostFD, true); err != nil {
|
||||||
panic(fmt.Sprintf("host.inode.afterLoad: failed to set host FD %d non-blocking: %v", i.hostFD, err))
|
panic(fmt.Sprintf("host.inode.afterLoad: failed to set host FD %d non-blocking: %v", i.hostFD, err))
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
package iouringfs
|
package iouringfs
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// beforeSave is invoked by stateify.
|
// beforeSave is invoked by stateify.
|
||||||
func (fd *FileDescription) beforeSave() {
|
func (fd *FileDescription) beforeSave() {
|
||||||
if fd.running.Load() != 0 {
|
if fd.running.Load() != 0 {
|
||||||
@@ -22,7 +24,7 @@ func (fd *FileDescription) beforeSave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (fd *FileDescription) afterLoad() {
|
func (fd *FileDescription) afterLoad(context.Context) {
|
||||||
// Remap shared buffers.
|
// Remap shared buffers.
|
||||||
fd.remap = true
|
fd.remap = true
|
||||||
fd.runC = make(chan struct{}, 1)
|
fd.runC = make(chan struct{}, 1)
|
||||||
|
|||||||
@@ -15,18 +15,20 @@
|
|||||||
package kernfs
|
package kernfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/refs"
|
"gvisor.dev/gvisor/pkg/refs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (d *Dentry) afterLoad() {
|
func (d *Dentry) afterLoad(context.Context) {
|
||||||
if d.refs.Load() >= 0 {
|
if d.refs.Load() >= 0 {
|
||||||
refs.Register(d)
|
refs.Register(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (i *inodePlatformFile) afterLoad() {
|
func (i *inodePlatformFile) afterLoad(context.Context) {
|
||||||
if i.fileMapper.IsInited() {
|
if i.fileMapper.IsInited() {
|
||||||
// Ensure that we don't call i.fileMapper.Init() again.
|
// Ensure that we don't call i.fileMapper.Init() again.
|
||||||
i.fileMapperInitOnce.Do(func() {})
|
i.fileMapperInitOnce.Do(func() {})
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
package overlay
|
package overlay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/refs"
|
"gvisor.dev/gvisor/pkg/refs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *dentry) afterLoad() {
|
func (d *dentry) afterLoad(context.Context) {
|
||||||
if d.refs.Load() != -1 {
|
if d.refs.Load() != -1 {
|
||||||
refs.Register(d)
|
refs.Register(d)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package tmpfs
|
package tmpfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goContext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/context"
|
"gvisor.dev/gvisor/pkg/context"
|
||||||
@@ -23,7 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// afterLoad is called by stateify.
|
// afterLoad is called by stateify.
|
||||||
func (fs *filesystem) afterLoad() {
|
func (fs *filesystem) afterLoad(goContext.Context) {
|
||||||
if !fs.privateMF {
|
if !fs.privateMF {
|
||||||
fs.mf = fs.mfp.MemoryFile()
|
fs.mf = fs.mfp.MemoryFile()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
package fsutil
|
package fsutil
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (f *HostFileMapper) afterLoad() {
|
func (f *HostFileMapper) afterLoad(context.Context) {
|
||||||
f.mappings = make(map[uint64]mapping)
|
f.mappings = make(map[uint64]mapping)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
package inet
|
package inet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goContext "context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/context"
|
"gvisor.dev/gvisor/pkg/context"
|
||||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/nsfs"
|
"gvisor.dev/gvisor/pkg/sentry/fsimpl/nsfs"
|
||||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||||
@@ -151,7 +153,7 @@ func (n *Namespace) init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (n *Namespace) afterLoad() {
|
func (n *Namespace) afterLoad(goContext.Context) {
|
||||||
n.init()
|
n.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,13 @@
|
|||||||
package pipe
|
package pipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/safemem"
|
"gvisor.dev/gvisor/pkg/safemem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// afterLoad is called by stateify.
|
// afterLoad is called by stateify.
|
||||||
func (p *Pipe) afterLoad() {
|
func (p *Pipe) afterLoad(context.Context) {
|
||||||
p.bufBlocks[0] = safemem.BlockFromSafeSlice(p.buf)
|
p.bufBlocks[0] = safemem.BlockFromSafeSlice(p.buf)
|
||||||
p.bufBlocks[1] = p.bufBlocks[0]
|
p.bufBlocks[1] = p.bufBlocks[0]
|
||||||
p.bufBlockSeq = safemem.BlockSeqFromSlice(p.bufBlocks[:])
|
p.bufBlockSeq = safemem.BlockSeqFromSlice(p.bufBlocks[:])
|
||||||
|
|||||||
@@ -630,7 +630,7 @@ func (t *Task) loadSeccomp(seccompData *taskSeccomp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (t *Task) afterLoad() {
|
func (t *Task) afterLoad(gocontext.Context) {
|
||||||
t.updateInfoLocked()
|
t.updateInfoLocked()
|
||||||
if ts := t.seccomp.Load().(*taskSeccomp); ts != nil {
|
if ts := t.seccomp.Load().(*taskSeccomp); ts != nil {
|
||||||
ts.populateCache(t)
|
ts.populateCache(t)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
package kernel
|
package kernel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/sentry/time"
|
"gvisor.dev/gvisor/pkg/sentry/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,6 +38,6 @@ func (t *Timekeeper) beforeSave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (t *Timekeeper) afterLoad() {
|
func (t *Timekeeper) afterLoad(context.Context) {
|
||||||
t.restored = make(chan struct{})
|
t.restored = make(chan struct{})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,52 +126,52 @@ type AIOContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// destroy marks the context dead.
|
// destroy marks the context dead.
|
||||||
func (ctx *AIOContext) destroy() {
|
func (aio *AIOContext) destroy() {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
ctx.dead = true
|
aio.dead = true
|
||||||
ctx.checkForDone()
|
aio.checkForDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preconditions: ctx.mu must be held by caller.
|
// Preconditions: ctx.mu must be held by caller.
|
||||||
func (ctx *AIOContext) checkForDone() {
|
func (aio *AIOContext) checkForDone() {
|
||||||
if ctx.dead && ctx.outstanding == 0 {
|
if aio.dead && aio.outstanding == 0 {
|
||||||
close(ctx.requestReady)
|
close(aio.requestReady)
|
||||||
ctx.requestReady = nil
|
aio.requestReady = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare reserves space for a new request, returning nil if available.
|
// Prepare reserves space for a new request, returning nil if available.
|
||||||
// Returns EAGAIN if the context is busy and EINVAL if the context is dead.
|
// Returns EAGAIN if the context is busy and EINVAL if the context is dead.
|
||||||
func (ctx *AIOContext) Prepare() error {
|
func (aio *AIOContext) Prepare() error {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
if ctx.dead {
|
if aio.dead {
|
||||||
// Context died after the caller looked it up.
|
// Context died after the caller looked it up.
|
||||||
return linuxerr.EINVAL
|
return linuxerr.EINVAL
|
||||||
}
|
}
|
||||||
if ctx.outstanding >= ctx.maxOutstanding {
|
if aio.outstanding >= aio.maxOutstanding {
|
||||||
// Context is busy.
|
// Context is busy.
|
||||||
return linuxerr.EAGAIN
|
return linuxerr.EAGAIN
|
||||||
}
|
}
|
||||||
ctx.outstanding++
|
aio.outstanding++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopRequest pops a completed request if available, this function does not do
|
// PopRequest pops a completed request if available, this function does not do
|
||||||
// any blocking. Returns false if no request is available.
|
// any blocking. Returns false if no request is available.
|
||||||
func (ctx *AIOContext) PopRequest() (any, bool) {
|
func (aio *AIOContext) PopRequest() (any, bool) {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
|
|
||||||
// Is there anything ready?
|
// Is there anything ready?
|
||||||
if e := ctx.results.Front(); e != nil {
|
if e := aio.results.Front(); e != nil {
|
||||||
if ctx.outstanding == 0 {
|
if aio.outstanding == 0 {
|
||||||
panic("AIOContext outstanding is going negative")
|
panic("AIOContext outstanding is going negative")
|
||||||
}
|
}
|
||||||
ctx.outstanding--
|
aio.outstanding--
|
||||||
ctx.results.Remove(e)
|
aio.results.Remove(e)
|
||||||
ctx.checkForDone()
|
aio.checkForDone()
|
||||||
return e.data, true
|
return e.data, true
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
@@ -179,17 +179,17 @@ func (ctx *AIOContext) PopRequest() (any, bool) {
|
|||||||
|
|
||||||
// FinishRequest finishes a pending request. It queues up the data
|
// FinishRequest finishes a pending request. It queues up the data
|
||||||
// and notifies listeners.
|
// and notifies listeners.
|
||||||
func (ctx *AIOContext) FinishRequest(data any) {
|
func (aio *AIOContext) FinishRequest(data any) {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
|
|
||||||
// Push to the list and notify opportunistically. The channel notify
|
// Push to the list and notify opportunistically. The channel notify
|
||||||
// here is guaranteed to be safe because outstanding must be non-zero.
|
// here is guaranteed to be safe because outstanding must be non-zero.
|
||||||
// The requestReady channel is only closed when outstanding reaches zero.
|
// The requestReady channel is only closed when outstanding reaches zero.
|
||||||
ctx.results.PushBack(&ioResult{data: data})
|
aio.results.PushBack(&ioResult{data: data})
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case ctx.requestReady <- struct{}{}:
|
case aio.requestReady <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,46 +197,46 @@ func (ctx *AIOContext) FinishRequest(data any) {
|
|||||||
// WaitChannel returns a channel that is notified when an AIO request is
|
// WaitChannel returns a channel that is notified when an AIO request is
|
||||||
// completed. Returns nil if the context is destroyed and there are no more
|
// completed. Returns nil if the context is destroyed and there are no more
|
||||||
// outstanding requests.
|
// outstanding requests.
|
||||||
func (ctx *AIOContext) WaitChannel() chan struct{} {
|
func (aio *AIOContext) WaitChannel() chan struct{} {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
return ctx.requestReady
|
return aio.requestReady
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dead returns true if the context has been destroyed.
|
// Dead returns true if the context has been destroyed.
|
||||||
func (ctx *AIOContext) Dead() bool {
|
func (aio *AIOContext) Dead() bool {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
return ctx.dead
|
return aio.dead
|
||||||
}
|
}
|
||||||
|
|
||||||
// CancelPendingRequest forgets about a request that hasn't yet completed.
|
// CancelPendingRequest forgets about a request that hasn't yet completed.
|
||||||
func (ctx *AIOContext) CancelPendingRequest() {
|
func (aio *AIOContext) CancelPendingRequest() {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
|
|
||||||
if ctx.outstanding == 0 {
|
if aio.outstanding == 0 {
|
||||||
panic("AIOContext outstanding is going negative")
|
panic("AIOContext outstanding is going negative")
|
||||||
}
|
}
|
||||||
ctx.outstanding--
|
aio.outstanding--
|
||||||
ctx.checkForDone()
|
aio.checkForDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drain drops all completed requests. Pending requests remain untouched.
|
// Drain drops all completed requests. Pending requests remain untouched.
|
||||||
func (ctx *AIOContext) Drain() {
|
func (aio *AIOContext) Drain() {
|
||||||
ctx.mu.Lock()
|
aio.mu.Lock()
|
||||||
defer ctx.mu.Unlock()
|
defer aio.mu.Unlock()
|
||||||
|
|
||||||
if ctx.outstanding == 0 {
|
if aio.outstanding == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
size := uint32(ctx.results.Len())
|
size := uint32(aio.results.Len())
|
||||||
if ctx.outstanding < size {
|
if aio.outstanding < size {
|
||||||
panic("AIOContext outstanding is going negative")
|
panic("AIOContext outstanding is going negative")
|
||||||
}
|
}
|
||||||
ctx.outstanding -= size
|
aio.outstanding -= size
|
||||||
ctx.results.Reset()
|
aio.results.Reset()
|
||||||
ctx.checkForDone()
|
aio.checkForDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// aioMappable implements memmap.MappingIdentity and memmap.Mappable for AIO
|
// aioMappable implements memmap.MappingIdentity and memmap.Mappable for AIO
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
package mm
|
package mm
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// afterLoad is invoked by stateify.
|
// afterLoad is invoked by stateify.
|
||||||
func (ctx *AIOContext) afterLoad() {
|
func (aio *AIOContext) afterLoad(context.Context) {
|
||||||
ctx.requestReady = make(chan struct{}, 1)
|
aio.requestReady = make(chan struct{}, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user