summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/kernel
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2019-03-14 08:11:36 -0700
committerShentubot <shentubot@google.com>2019-03-14 08:12:48 -0700
commit8f4634997bd97810a85a70b71f000378d9db2e55 (patch)
tree903096f91ee8f201fa622296e0f04cf7c7cd9013 /pkg/sentry/kernel
parentfb9919881c7dc98eaf97cad2a70d187bd78f1566 (diff)
Decouple filemem from platform and move it to pgalloc.MemoryFile.
This is in preparation for improved page cache reclaim, which requires greater integration between the page cache and page allocator. PiperOrigin-RevId: 238444706 Change-Id: Id24141b3678d96c7d7dc24baddd9be555bffafe4
Diffstat (limited to 'pkg/sentry/kernel')
-rw-r--r--pkg/sentry/kernel/BUILD3
-rw-r--r--pkg/sentry/kernel/contexttest/BUILD1
-rw-r--r--pkg/sentry/kernel/contexttest/contexttest.go2
-rw-r--r--pkg/sentry/kernel/kernel.go57
-rw-r--r--pkg/sentry/kernel/memevent/memory_events.go2
-rw-r--r--pkg/sentry/kernel/shm/BUILD1
-rw-r--r--pkg/sentry/kernel/shm/shm.go19
-rw-r--r--pkg/sentry/kernel/task.go5
-rw-r--r--pkg/sentry/kernel/task_context.go2
-rw-r--r--pkg/sentry/kernel/timekeeper.go5
-rw-r--r--pkg/sentry/kernel/timekeeper_test.go8
-rw-r--r--pkg/sentry/kernel/vdso.go17
12 files changed, 73 insertions, 49 deletions
diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD
index d9bbfb556..4d34bc733 100644
--- a/pkg/sentry/kernel/BUILD
+++ b/pkg/sentry/kernel/BUILD
@@ -173,6 +173,7 @@ go_library(
"//pkg/sentry/loader",
"//pkg/sentry/memmap",
"//pkg/sentry/mm",
+ "//pkg/sentry/pgalloc",
"//pkg/sentry/platform",
"//pkg/sentry/safemem",
"//pkg/sentry/socket/netlink/port",
@@ -212,7 +213,7 @@ go_test(
"//pkg/sentry/kernel/kdefs",
"//pkg/sentry/kernel/sched",
"//pkg/sentry/limits",
- "//pkg/sentry/platform",
+ "//pkg/sentry/pgalloc",
"//pkg/sentry/time",
"//pkg/sentry/usage",
"//pkg/sentry/usermem",
diff --git a/pkg/sentry/kernel/contexttest/BUILD b/pkg/sentry/kernel/contexttest/BUILD
index 5769a3b28..bfb2a0b73 100644
--- a/pkg/sentry/kernel/contexttest/BUILD
+++ b/pkg/sentry/kernel/contexttest/BUILD
@@ -12,6 +12,7 @@ go_library(
"//pkg/sentry/context",
"//pkg/sentry/context/contexttest",
"//pkg/sentry/kernel",
+ "//pkg/sentry/pgalloc",
"//pkg/sentry/platform",
],
)
diff --git a/pkg/sentry/kernel/contexttest/contexttest.go b/pkg/sentry/kernel/contexttest/contexttest.go
index 9eb18e7e8..eb56a6a07 100644
--- a/pkg/sentry/kernel/contexttest/contexttest.go
+++ b/pkg/sentry/kernel/contexttest/contexttest.go
@@ -22,6 +22,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/context/contexttest"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
)
@@ -33,6 +34,7 @@ func Context(tb testing.TB) context.Context {
k := &kernel.Kernel{
Platform: platform.FromContext(ctx),
}
+ k.SetMemoryFile(pgalloc.MemoryFileFromContext(ctx))
ctx.(*contexttest.TestContext).RegisterValue(kernel.CtxKernel, k)
return ctx
}
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index c6afae2e6..3533fd8f7 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -58,6 +58,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/limits"
"gvisor.googlesource.com/gvisor/pkg/sentry/loader"
"gvisor.googlesource.com/gvisor/pkg/sentry/mm"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
"gvisor.googlesource.com/gvisor/pkg/sentry/socket/netlink/port"
sentrytime "gvisor.googlesource.com/gvisor/pkg/sentry/time"
@@ -89,12 +90,14 @@ type Kernel struct {
// All of the following fields are immutable unless otherwise specified.
- // Platform is the platform that is used to execute tasks in the
- // created Kernel. It is embedded so that Kernel can directly serve as
- // Platform in mm logic and also serve as platform.MemoryProvider in
- // filemem S/R logic.
+ // Platform is the platform that is used to execute tasks in the created
+ // Kernel. See comment on pgalloc.MemoryFileProvider for why Platform is
+ // embedded anonymously (the same issue applies).
platform.Platform `state:"nosave"`
+ // mf provides application memory.
+ mf *pgalloc.MemoryFile `state:"nosave"`
+
// See InitKernelArgs for the meaning of these fields.
featureSet *cpuid.FeatureSet
timekeeper *Timekeeper
@@ -229,7 +232,8 @@ type InitKernelArgs struct {
// Init initialize the Kernel with no tasks.
//
-// Callers must manually set Kernel.Platform before caling Init.
+// Callers must manually set Kernel.Platform and call Kernel.SetMemoryFile
+// before calling Init.
func (k *Kernel) Init(args InitKernelArgs) error {
if args.FeatureSet == nil {
return fmt.Errorf("FeatureSet is nil")
@@ -332,15 +336,9 @@ func (k *Kernel) SaveTo(w io.Writer) error {
log.Infof("Kernel save stats: %s", &stats)
log.Infof("Kernel save took [%s].", time.Since(kernelStart))
- // Save the memory state.
- //
- // FIXME: In the future, this should not be dispatched via
- // an abstract memory type. This should be dispatched to a single
- // memory implementation that belongs to the kernel. (There is
- // currently a single implementation anyways, it just needs to be
- // "unabstracted" and reparented appropriately.)
+ // Save the memory file's state.
memoryStart := time.Now()
- if err := k.Platform.Memory().SaveTo(w); err != nil {
+ if err := k.mf.SaveTo(w); err != nil {
return err
}
log.Infof("Memory save took [%s].", time.Since(memoryStart))
@@ -418,13 +416,9 @@ func (ts *TaskSet) unregisterEpollWaiters() {
}
// LoadFrom returns a new Kernel loaded from args.
-func (k *Kernel) LoadFrom(r io.Reader, p platform.Platform, net inet.Stack) error {
+func (k *Kernel) LoadFrom(r io.Reader, net inet.Stack) error {
loadStart := time.Now()
- if p == nil {
- return fmt.Errorf("Platform is nil")
- }
- k.Platform = p
k.networkStack = net
initAppCores := k.applicationCores
@@ -438,11 +432,9 @@ func (k *Kernel) LoadFrom(r io.Reader, p platform.Platform, net inet.Stack) erro
log.Infof("Kernel load stats: %s", &stats)
log.Infof("Kernel load took [%s].", time.Since(kernelStart))
- // Load the memory state.
- //
- // See the note in SaveTo.
+ // Load the memory file's state.
memoryStart := time.Now()
- if err := k.Platform.Memory().LoadFrom(r); err != nil {
+ if err := k.mf.LoadFrom(r); err != nil {
return err
}
log.Infof("Memory load took [%s].", time.Since(memoryStart))
@@ -597,6 +589,10 @@ func (ctx *createProcessContext) Value(key interface{}) interface{} {
return ctx.k.RealtimeClock()
case limits.CtxLimits:
return ctx.args.Limits
+ case pgalloc.CtxMemoryFile:
+ return ctx.k.mf
+ case pgalloc.CtxMemoryFileProvider:
+ return ctx.k
case platform.CtxPlatform:
return ctx.k
case uniqueid.CtxGlobalUniqueID:
@@ -1018,6 +1014,17 @@ func (k *Kernel) NowMonotonic() int64 {
return now
}
+// SetMemoryFile sets Kernel.mf. SetMemoryFile must be called before Init or
+// LoadFrom.
+func (k *Kernel) SetMemoryFile(mf *pgalloc.MemoryFile) {
+ k.mf = mf
+}
+
+// MemoryFile implements pgalloc.MemoryFileProvider.MemoryFile.
+func (k *Kernel) MemoryFile() *pgalloc.MemoryFile {
+ return k.mf
+}
+
// SupervisorContext returns a Context with maximum privileges in k. It should
// only be used by goroutines outside the control of the emulated kernel
// defined by e.
@@ -1083,7 +1090,7 @@ func (k *Kernel) ListSockets(family int) []*refs.WeakRef {
socks := []*refs.WeakRef{}
if table, ok := k.socketTable[family]; ok {
socks = make([]*refs.WeakRef, 0, len(table))
- for s, _ := range table {
+ for s := range table {
socks = append(socks, s)
}
}
@@ -1123,6 +1130,10 @@ func (ctx supervisorContext) Value(key interface{}) interface{} {
case limits.CtxLimits:
// No limits apply.
return limits.NewLimitSet()
+ case pgalloc.CtxMemoryFile:
+ return ctx.k.mf
+ case pgalloc.CtxMemoryFileProvider:
+ return ctx.k
case platform.CtxPlatform:
return ctx.k
case uniqueid.CtxGlobalUniqueID:
diff --git a/pkg/sentry/kernel/memevent/memory_events.go b/pkg/sentry/kernel/memevent/memory_events.go
index b6283c5d1..d09d6debf 100644
--- a/pkg/sentry/kernel/memevent/memory_events.go
+++ b/pkg/sentry/kernel/memevent/memory_events.go
@@ -95,7 +95,7 @@ func (m *MemoryEvents) run() {
}
func (m *MemoryEvents) emit() {
- totalPlatform, err := m.k.Platform.Memory().TotalUsage()
+ totalPlatform, err := m.k.MemoryFile().TotalUsage()
if err != nil {
log.Warningf("Failed to fetch memory usage for memory events: %v", err)
return
diff --git a/pkg/sentry/kernel/shm/BUILD b/pkg/sentry/kernel/shm/BUILD
index f45770eef..bc2089872 100644
--- a/pkg/sentry/kernel/shm/BUILD
+++ b/pkg/sentry/kernel/shm/BUILD
@@ -20,6 +20,7 @@ go_library(
"//pkg/sentry/kernel/auth",
"//pkg/sentry/kernel/time",
"//pkg/sentry/memmap",
+ "//pkg/sentry/pgalloc",
"//pkg/sentry/platform",
"//pkg/sentry/usage",
"//pkg/sentry/usermem",
diff --git a/pkg/sentry/kernel/shm/shm.go b/pkg/sentry/kernel/shm/shm.go
index 96414d060..4525aabf4 100644
--- a/pkg/sentry/kernel/shm/shm.go
+++ b/pkg/sentry/kernel/shm/shm.go
@@ -45,6 +45,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/auth"
ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
"gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
"gvisor.googlesource.com/gvisor/pkg/sentry/usage"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
@@ -199,19 +200,19 @@ func (r *Registry) FindOrCreate(ctx context.Context, pid int32, key Key, size ui
//
// Precondition: Caller must hold r.mu.
func (r *Registry) newShm(ctx context.Context, pid int32, key Key, creator fs.FileOwner, perms fs.FilePermissions, size uint64) (*Shm, error) {
- p := platform.FromContext(ctx)
- if p == nil {
- panic(fmt.Sprintf("context.Context %T lacks non-nil value for key %T", ctx, platform.CtxPlatform))
+ mfp := pgalloc.MemoryFileProviderFromContext(ctx)
+ if mfp == nil {
+ panic(fmt.Sprintf("context.Context %T lacks non-nil value for key %T", ctx, pgalloc.CtxMemoryFileProvider))
}
effectiveSize := uint64(usermem.Addr(size).MustRoundUp())
- fr, err := p.Memory().Allocate(effectiveSize, usage.Anonymous)
+ fr, err := mfp.MemoryFile().Allocate(effectiveSize, usage.Anonymous)
if err != nil {
return nil, err
}
shm := &Shm{
- p: p,
+ mfp: mfp,
registry: r,
creator: creator,
size: size,
@@ -312,7 +313,7 @@ type Shm struct {
// destruction.
refs.AtomicRefCount
- p platform.Platform
+ mfp pgalloc.MemoryFileProvider
// registry points to the shm registry containing this segment. Immutable.
registry *Registry
@@ -333,7 +334,7 @@ type Shm struct {
// Invariant: effectiveSize must be a multiple of usermem.PageSize.
effectiveSize uint64
- // fr is the offset into platform.Memory() that backs this contents of this
+ // fr is the offset into mfp.MemoryFile() that backs this contents of this
// segment. Immutable.
fr platform.FileRange
@@ -452,7 +453,7 @@ func (s *Shm) Translate(ctx context.Context, required, optional memmap.MappableR
return []memmap.Translation{
{
Source: source,
- File: s.p.Memory(),
+ File: s.mfp.MemoryFile(),
Offset: s.fr.Start + source.Start,
},
}, err
@@ -599,7 +600,7 @@ func (s *Shm) Set(ctx context.Context, ds *linux.ShmidDS) error {
}
func (s *Shm) destroy() {
- s.p.Memory().DecRef(s.fr)
+ s.mfp.MemoryFile().DecRef(s.fr)
s.registry.remove(s)
}
diff --git a/pkg/sentry/kernel/task.go b/pkg/sentry/kernel/task.go
index 702e40cce..e9f133c0b 100644
--- a/pkg/sentry/kernel/task.go
+++ b/pkg/sentry/kernel/task.go
@@ -29,6 +29,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/sched"
ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
"gvisor.googlesource.com/gvisor/pkg/sentry/limits"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
"gvisor.googlesource.com/gvisor/pkg/sentry/unimpl"
"gvisor.googlesource.com/gvisor/pkg/sentry/uniqueid"
@@ -587,6 +588,10 @@ func (t *Task) Value(key interface{}) interface{} {
return t.k.RealtimeClock()
case limits.CtxLimits:
return t.tg.limits
+ case pgalloc.CtxMemoryFile:
+ return t.k.mf
+ case pgalloc.CtxMemoryFileProvider:
+ return t.k
case platform.CtxPlatform:
return t.k
case uniqueid.CtxGlobalUniqueID:
diff --git a/pkg/sentry/kernel/task_context.go b/pkg/sentry/kernel/task_context.go
index ee3e49d17..d1c82f2aa 100644
--- a/pkg/sentry/kernel/task_context.go
+++ b/pkg/sentry/kernel/task_context.go
@@ -144,7 +144,7 @@ func (t *Task) Stack() *arch.Stack {
// * fs: Binary FeatureSet
func (k *Kernel) LoadTaskImage(ctx context.Context, mounts *fs.MountNamespace, root, wd *fs.Dirent, maxTraversals *uint, filename string, argv, envv []string, fs *cpuid.FeatureSet) (*TaskContext, *syserr.Error) {
// Prepare a new user address space to load into.
- m := mm.NewMemoryManager(k)
+ m := mm.NewMemoryManager(k, k)
defer m.DecUsers(ctx)
os, ac, name, err := loader.Load(ctx, m, mounts, root, wd, maxTraversals, fs, filename, argv, envv, k.extraAuxv, k.vdso)
diff --git a/pkg/sentry/kernel/timekeeper.go b/pkg/sentry/kernel/timekeeper.go
index 6bff80f13..d7bd85e78 100644
--- a/pkg/sentry/kernel/timekeeper.go
+++ b/pkg/sentry/kernel/timekeeper.go
@@ -21,6 +21,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/log"
ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
sentrytime "gvisor.googlesource.com/gvisor/pkg/sentry/time"
)
@@ -85,9 +86,9 @@ type Timekeeper struct {
// NewTimekeeper does not take ownership of paramPage.
//
// SetClocks must be called on the returned Timekeeper before it is usable.
-func NewTimekeeper(platform platform.Platform, paramPage platform.FileRange) (*Timekeeper, error) {
+func NewTimekeeper(mfp pgalloc.MemoryFileProvider, paramPage platform.FileRange) (*Timekeeper, error) {
return &Timekeeper{
- params: NewVDSOParamPage(platform, paramPage),
+ params: NewVDSOParamPage(mfp, paramPage),
}, nil
}
diff --git a/pkg/sentry/kernel/timekeeper_test.go b/pkg/sentry/kernel/timekeeper_test.go
index 71674c21c..6084bcb18 100644
--- a/pkg/sentry/kernel/timekeeper_test.go
+++ b/pkg/sentry/kernel/timekeeper_test.go
@@ -18,7 +18,7 @@ import (
"testing"
"gvisor.googlesource.com/gvisor/pkg/sentry/context/contexttest"
- "gvisor.googlesource.com/gvisor/pkg/sentry/platform"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
sentrytime "gvisor.googlesource.com/gvisor/pkg/sentry/time"
"gvisor.googlesource.com/gvisor/pkg/sentry/usage"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
@@ -53,13 +53,13 @@ func (c *mockClocks) GetTime(id sentrytime.ClockID) (int64, error) {
// SetClocks called.
func stateTestClocklessTimekeeper(tb testing.TB) *Timekeeper {
ctx := contexttest.Context(tb)
- p := platform.FromContext(ctx)
- fr, err := p.Memory().Allocate(usermem.PageSize, usage.Anonymous)
+ mfp := pgalloc.MemoryFileProviderFromContext(ctx)
+ fr, err := mfp.MemoryFile().Allocate(usermem.PageSize, usage.Anonymous)
if err != nil {
tb.Fatalf("failed to allocate memory: %v", err)
}
return &Timekeeper{
- params: NewVDSOParamPage(p, fr),
+ params: NewVDSOParamPage(mfp, fr),
}
}
diff --git a/pkg/sentry/kernel/vdso.go b/pkg/sentry/kernel/vdso.go
index 0ec858a4a..3a35f1d00 100644
--- a/pkg/sentry/kernel/vdso.go
+++ b/pkg/sentry/kernel/vdso.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.googlesource.com/gvisor/pkg/binary"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/pgalloc"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
"gvisor.googlesource.com/gvisor/pkg/sentry/safemem"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
@@ -55,9 +56,9 @@ type vdsoParams struct {
//
// +stateify savable
type VDSOParamPage struct {
- // The parameter page is fr, allocated from platform.Memory().
- platform platform.Platform
- fr platform.FileRange
+ // The parameter page is fr, allocated from mfp.MemoryFile().
+ mfp pgalloc.MemoryFileProvider
+ fr platform.FileRange
// seq is the current sequence count written to the page.
//
@@ -73,20 +74,20 @@ type VDSOParamPage struct {
//
// Preconditions:
//
-// * fr is a single page allocated from platform.Memory(). VDSOParamPage does
+// * fr is a single page allocated from mfp.MemoryFile(). VDSOParamPage does
// not take ownership of fr; it must remain allocated for the lifetime of the
// VDSOParamPage.
//
// * VDSOParamPage must be the only writer to fr.
//
-// * platform.Memory().MapInternal(fr) must return a single safemem.Block.
-func NewVDSOParamPage(platform platform.Platform, fr platform.FileRange) *VDSOParamPage {
- return &VDSOParamPage{platform: platform, fr: fr}
+// * mfp.MemoryFile().MapInternal(fr) must return a single safemem.Block.
+func NewVDSOParamPage(mfp pgalloc.MemoryFileProvider, fr platform.FileRange) *VDSOParamPage {
+ return &VDSOParamPage{mfp: mfp, fr: fr}
}
// access returns a mapping of the param page.
func (v *VDSOParamPage) access() (safemem.Block, error) {
- bs, err := v.platform.Memory().MapInternal(v.fr, usermem.ReadWrite)
+ bs, err := v.mfp.MemoryFile().MapInternal(v.fr, usermem.ReadWrite)
if err != nil {
return safemem.Block{}, err
}