mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Pass information about map writableness to filesystems.
This is necessary to implement file seals for memfds. PiperOrigin-RevId: 225239394 Change-Id: Ib3f1ab31385afc4b24e96cd81a05ef1bebbcbb70
This commit is contained in:
@@ -302,7 +302,7 @@ func (bp *Proc) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArgum
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (bp *Proc) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (bp *Proc) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, _ bool) error {
|
||||
bp.mu.Lock()
|
||||
defer bp.mu.Unlock()
|
||||
if bp.mapped.Length() != 0 {
|
||||
@@ -320,12 +320,12 @@ func (bp *Proc) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar userm
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (bp *Proc) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (*Proc) RemoveMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, uint64, bool) {
|
||||
// Nothing to do. Notably, we don't free bp.mapped to allow another mmap.
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (bp *Proc) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
func (bp *Proc) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, _ bool) error {
|
||||
// Nothing to do. Notably, this is one case where CopyMapping isn't
|
||||
// equivalent to AddMapping, as AddMapping would return EBUSY.
|
||||
return nil
|
||||
|
||||
@@ -270,13 +270,13 @@ func copyUpLocked(ctx context.Context, parent *Dirent, next *Dirent) error {
|
||||
for seg := next.Inode.overlay.mappings.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
|
||||
added := make(memmap.MappingsOfRange)
|
||||
for m := range seg.Value() {
|
||||
if err := upperMappable.AddMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start()); err != nil {
|
||||
if err := upperMappable.AddMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start(), m.Writable); err != nil {
|
||||
for m := range added {
|
||||
upperMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start())
|
||||
upperMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start(), m.Writable)
|
||||
}
|
||||
for mr, mappings := range allAdded {
|
||||
for m := range mappings {
|
||||
upperMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, mr.Start)
|
||||
upperMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, mr.Start, m.Writable)
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -301,7 +301,7 @@ func copyUpLocked(ctx context.Context, parent *Dirent, next *Dirent) error {
|
||||
if lowerMappable != nil {
|
||||
for seg := next.Inode.overlay.mappings.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
|
||||
for m := range seg.Value() {
|
||||
lowerMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start())
|
||||
lowerMappable.RemoveMapping(ctx, m.MappingSpace, m.AddrRange, seg.Start(), m.Writable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,10 +686,10 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (c *CachingInodeOperations) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (c *CachingInodeOperations) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) error {
|
||||
// Hot path. Avoid defers.
|
||||
c.mapsMu.Lock()
|
||||
mapped := c.mappings.AddMapping(ms, ar, offset)
|
||||
mapped := c.mappings.AddMapping(ms, ar, offset, writable)
|
||||
// Do this unconditionally since whether we have c.backingFile.FD() >= 0
|
||||
// can change across save/restore.
|
||||
for _, r := range mapped {
|
||||
@@ -705,10 +705,10 @@ func (c *CachingInodeOperations) AddMapping(ctx context.Context, ms memmap.Mappi
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (c *CachingInodeOperations) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (c *CachingInodeOperations) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) {
|
||||
// Hot path. Avoid defers.
|
||||
c.mapsMu.Lock()
|
||||
unmapped := c.mappings.RemoveMapping(ms, ar, offset)
|
||||
unmapped := c.mappings.RemoveMapping(ms, ar, offset, writable)
|
||||
for _, r := range unmapped {
|
||||
c.hostFileMapper.DecRefOn(r)
|
||||
}
|
||||
@@ -739,8 +739,8 @@ func (c *CachingInodeOperations) RemoveMapping(ctx context.Context, ms memmap.Ma
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (c *CachingInodeOperations) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
return c.AddMapping(ctx, ms, dstAR, offset)
|
||||
func (c *CachingInodeOperations) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, writable bool) error {
|
||||
return c.AddMapping(ctx, ms, dstAR, offset, writable)
|
||||
}
|
||||
|
||||
// Translate implements memmap.Mappable.Translate.
|
||||
|
||||
@@ -305,7 +305,7 @@ func TestRead(t *testing.T) {
|
||||
// be cached.
|
||||
var ms noopMappingSpace
|
||||
ar := usermem.AddrRange{usermem.PageSize, 2 * usermem.PageSize}
|
||||
if err := iops.AddMapping(ctx, ms, ar, usermem.PageSize); err != nil {
|
||||
if err := iops.AddMapping(ctx, ms, ar, usermem.PageSize, true); err != nil {
|
||||
t.Fatalf("AddMapping got %v, want nil", err)
|
||||
}
|
||||
mr := memmap.MappableRange{usermem.PageSize, 2 * usermem.PageSize}
|
||||
@@ -334,7 +334,7 @@ func TestRead(t *testing.T) {
|
||||
|
||||
// Delete the memory mapping and expect it to cause the cached page to be
|
||||
// uncached.
|
||||
iops.RemoveMapping(ctx, ms, ar, usermem.PageSize)
|
||||
iops.RemoveMapping(ctx, ms, ar, usermem.PageSize, true)
|
||||
if cached := iops.cache.Span(); cached != 0 {
|
||||
t.Fatalf("Span got %d, want 0", cached)
|
||||
}
|
||||
@@ -363,10 +363,10 @@ func TestWrite(t *testing.T) {
|
||||
// Translate to force them to be cached.
|
||||
var ms noopMappingSpace
|
||||
ar := usermem.AddrRange{usermem.PageSize, 3 * usermem.PageSize}
|
||||
if err := iops.AddMapping(ctx, ms, ar, usermem.PageSize); err != nil {
|
||||
if err := iops.AddMapping(ctx, ms, ar, usermem.PageSize, true); err != nil {
|
||||
t.Fatalf("AddMapping got %v, want nil", err)
|
||||
}
|
||||
defer iops.RemoveMapping(ctx, ms, ar, usermem.PageSize)
|
||||
defer iops.RemoveMapping(ctx, ms, ar, usermem.PageSize, true)
|
||||
mr := memmap.MappableRange{usermem.PageSize, 3 * usermem.PageSize}
|
||||
if _, err := iops.Translate(ctx, mr, mr, usermem.Read); err != nil {
|
||||
t.Fatalf("Translate got %v, want nil", err)
|
||||
|
||||
@@ -259,32 +259,32 @@ func (o *overlayEntry) isMappableLocked() bool {
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (o *overlayEntry) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (o *overlayEntry) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) error {
|
||||
o.mapsMu.Lock()
|
||||
defer o.mapsMu.Unlock()
|
||||
if err := o.inodeLocked().Mappable().AddMapping(ctx, ms, ar, offset); err != nil {
|
||||
if err := o.inodeLocked().Mappable().AddMapping(ctx, ms, ar, offset, writable); err != nil {
|
||||
return err
|
||||
}
|
||||
o.mappings.AddMapping(ms, ar, offset)
|
||||
o.mappings.AddMapping(ms, ar, offset, writable)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (o *overlayEntry) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (o *overlayEntry) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) {
|
||||
o.mapsMu.Lock()
|
||||
defer o.mapsMu.Unlock()
|
||||
o.inodeLocked().Mappable().RemoveMapping(ctx, ms, ar, offset)
|
||||
o.mappings.RemoveMapping(ms, ar, offset)
|
||||
o.inodeLocked().Mappable().RemoveMapping(ctx, ms, ar, offset, writable)
|
||||
o.mappings.RemoveMapping(ms, ar, offset, writable)
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (o *overlayEntry) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
func (o *overlayEntry) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, writable bool) error {
|
||||
o.mapsMu.Lock()
|
||||
defer o.mapsMu.Unlock()
|
||||
if err := o.inodeLocked().Mappable().CopyMapping(ctx, ms, srcAR, dstAR, offset); err != nil {
|
||||
if err := o.inodeLocked().Mappable().CopyMapping(ctx, ms, srcAR, dstAR, offset, writable); err != nil {
|
||||
return err
|
||||
}
|
||||
o.mappings.AddMapping(ms, dstAR, offset)
|
||||
o.mappings.AddMapping(ms, dstAR, offset, writable)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -426,23 +426,23 @@ func (rw *fileReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error)
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (f *fileInodeOperations) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (f *fileInodeOperations) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) error {
|
||||
f.mapsMu.Lock()
|
||||
defer f.mapsMu.Unlock()
|
||||
f.mappings.AddMapping(ms, ar, offset)
|
||||
f.mappings.AddMapping(ms, ar, offset, writable)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (f *fileInodeOperations) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (f *fileInodeOperations) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) {
|
||||
f.mapsMu.Lock()
|
||||
defer f.mapsMu.Unlock()
|
||||
f.mappings.RemoveMapping(ms, ar, offset)
|
||||
f.mappings.RemoveMapping(ms, ar, offset, writable)
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (f *fileInodeOperations) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
return f.AddMapping(ctx, ms, dstAR, offset)
|
||||
func (f *fileInodeOperations) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, writable bool) error {
|
||||
return f.AddMapping(ctx, ms, dstAR, offset, writable)
|
||||
}
|
||||
|
||||
// Translate implements memmap.Mappable.Translate.
|
||||
|
||||
@@ -375,7 +375,7 @@ func (s *Shm) Msync(context.Context, memmap.MappableRange) error {
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (s *Shm) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (s *Shm) AddMapping(ctx context.Context, _ memmap.MappingSpace, _ usermem.AddrRange, _ uint64, _ bool) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.attachTime = ktime.NowFromContext(ctx)
|
||||
@@ -390,7 +390,7 @@ func (s *Shm) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (s *Shm) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (s *Shm) RemoveMapping(ctx context.Context, _ memmap.MappingSpace, _ usermem.AddrRange, _ uint64, _ bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// TODO: RemoveMapping may be called during task exit, when ctx
|
||||
@@ -411,7 +411,7 @@ func (s *Shm) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar user
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (s *Shm) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
func (*Shm) CopyMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, usermem.AddrRange, uint64, bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ type MappingsOfRange map[MappingOfRange]struct{}
|
||||
type MappingOfRange struct {
|
||||
MappingSpace MappingSpace
|
||||
AddrRange usermem.AddrRange
|
||||
Writable bool
|
||||
}
|
||||
|
||||
func (r MappingOfRange) invalidate(opts InvalidateOpts) {
|
||||
@@ -92,6 +93,7 @@ func (mappingSetFunctions) Merge(r1 MappableRange, val1 MappingsOfRange, r2 Mapp
|
||||
Start: k1.AddrRange.End,
|
||||
End: k1.AddrRange.End + usermem.Addr(r2.Length()),
|
||||
},
|
||||
Writable: k1.Writable,
|
||||
}
|
||||
if _, ok := val2[k2]; !ok {
|
||||
return nil, false
|
||||
@@ -104,6 +106,7 @@ func (mappingSetFunctions) Merge(r1 MappableRange, val1 MappingsOfRange, r2 Mapp
|
||||
Start: k1.AddrRange.Start,
|
||||
End: k2.AddrRange.End,
|
||||
},
|
||||
Writable: k1.Writable,
|
||||
}] = struct{}{}
|
||||
}
|
||||
|
||||
@@ -129,6 +132,7 @@ func (mappingSetFunctions) Split(r MappableRange, val MappingsOfRange, split uin
|
||||
Start: k.AddrRange.Start,
|
||||
End: k.AddrRange.Start + offset,
|
||||
},
|
||||
Writable: k.Writable,
|
||||
}
|
||||
m1[k1] = struct{}{}
|
||||
|
||||
@@ -138,6 +142,7 @@ func (mappingSetFunctions) Split(r MappableRange, val MappingsOfRange, split uin
|
||||
Start: k.AddrRange.Start + offset,
|
||||
End: k.AddrRange.End,
|
||||
},
|
||||
Writable: k.Writable,
|
||||
}
|
||||
m2[k2] = struct{}{}
|
||||
}
|
||||
@@ -152,7 +157,7 @@ func (mappingSetFunctions) Split(r MappableRange, val MappingsOfRange, split uin
|
||||
// indicating that ms maps addresses [0x4000, 0x6000) to MappableRange [0x0,
|
||||
// 0x2000). Then for subsetRange = [0x1000, 0x2000), subsetMapping returns a
|
||||
// MappingOfRange for which AddrRange = [0x5000, 0x6000).
|
||||
func subsetMapping(wholeRange, subsetRange MappableRange, ms MappingSpace, addr usermem.Addr) MappingOfRange {
|
||||
func subsetMapping(wholeRange, subsetRange MappableRange, ms MappingSpace, addr usermem.Addr, writable bool) MappingOfRange {
|
||||
if !wholeRange.IsSupersetOf(subsetRange) {
|
||||
panic(fmt.Sprintf("%v is not a superset of %v", wholeRange, subsetRange))
|
||||
}
|
||||
@@ -165,6 +170,7 @@ func subsetMapping(wholeRange, subsetRange MappableRange, ms MappingSpace, addr
|
||||
Start: start,
|
||||
End: start + usermem.Addr(subsetRange.Length()),
|
||||
},
|
||||
Writable: writable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +178,7 @@ func subsetMapping(wholeRange, subsetRange MappableRange, ms MappingSpace, addr
|
||||
// previously had no mappings.
|
||||
//
|
||||
// Preconditions: As for Mappable.AddMapping.
|
||||
func (s *MappingSet) AddMapping(ms MappingSpace, ar usermem.AddrRange, offset uint64) []MappableRange {
|
||||
func (s *MappingSet) AddMapping(ms MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) []MappableRange {
|
||||
mr := MappableRange{offset, offset + uint64(ar.Length())}
|
||||
var mapped []MappableRange
|
||||
seg, gap := s.Find(mr.Start)
|
||||
@@ -180,7 +186,7 @@ func (s *MappingSet) AddMapping(ms MappingSpace, ar usermem.AddrRange, offset ui
|
||||
switch {
|
||||
case seg.Ok() && seg.Start() < mr.End:
|
||||
seg = s.Isolate(seg, mr)
|
||||
seg.Value()[subsetMapping(mr, seg.Range(), ms, ar.Start)] = struct{}{}
|
||||
seg.Value()[subsetMapping(mr, seg.Range(), ms, ar.Start, writable)] = struct{}{}
|
||||
seg, gap = seg.NextNonEmpty()
|
||||
|
||||
case gap.Ok() && gap.Start() < mr.End:
|
||||
@@ -199,7 +205,7 @@ func (s *MappingSet) AddMapping(ms MappingSpace, ar usermem.AddrRange, offset ui
|
||||
// MappableRanges that now have no mappings.
|
||||
//
|
||||
// Preconditions: As for Mappable.RemoveMapping.
|
||||
func (s *MappingSet) RemoveMapping(ms MappingSpace, ar usermem.AddrRange, offset uint64) []MappableRange {
|
||||
func (s *MappingSet) RemoveMapping(ms MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) []MappableRange {
|
||||
mr := MappableRange{offset, offset + uint64(ar.Length())}
|
||||
var unmapped []MappableRange
|
||||
|
||||
@@ -213,7 +219,7 @@ func (s *MappingSet) RemoveMapping(ms MappingSpace, ar usermem.AddrRange, offset
|
||||
|
||||
// Remove this part of the mapping.
|
||||
mappings := seg.Value()
|
||||
delete(mappings, subsetMapping(mr, seg.Range(), ms, ar.Start))
|
||||
delete(mappings, subsetMapping(mr, seg.Range(), ms, ar.Start, writable))
|
||||
|
||||
if len(mappings) == 0 {
|
||||
unmapped = append(unmapped, seg.Range())
|
||||
@@ -231,7 +237,7 @@ func (s *MappingSet) Invalidate(mr MappableRange, opts InvalidateOpts) {
|
||||
for seg := s.LowerBoundSegment(mr.Start); seg.Ok() && seg.Start() < mr.End; seg = seg.NextSegment() {
|
||||
segMR := seg.Range()
|
||||
for m := range seg.Value() {
|
||||
region := subsetMapping(segMR, segMR.Intersect(mr), m.MappingSpace, m.AddrRange.Start)
|
||||
region := subsetMapping(segMR, segMR.Intersect(mr), m.MappingSpace, m.AddrRange.Start, m.Writable)
|
||||
region.invalidate(opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
set := MappingSet{}
|
||||
ms := &testMappingSpace{}
|
||||
|
||||
mapped := set.AddMapping(ms, usermem.AddrRange{0x10000, 0x12000}, 0x1000)
|
||||
mapped := set.AddMapping(ms, usermem.AddrRange{0x10000, 0x12000}, 0x1000, true)
|
||||
if got, want := mapped, []MappableRange{{0x1000, 0x3000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AddMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x10000, 0x12000) => [0x1000, 0x3000)
|
||||
t.Log(&set)
|
||||
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000)
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000, true)
|
||||
if len(mapped) != 0 {
|
||||
t.Errorf("AddMapping: got %+v, wanted []", mapped)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x11000, 0x12000) and [0x20000, 0x21000) => [0x2000, 0x3000)
|
||||
t.Log(&set)
|
||||
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x30000, 0x31000}, 0x4000)
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x30000, 0x31000}, 0x4000, true)
|
||||
if got, want := mapped, []MappableRange{{0x4000, 0x5000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AddMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x30000, 0x31000) => [0x4000, 0x5000)
|
||||
t.Log(&set)
|
||||
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x12000, 0x15000}, 0x3000)
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x12000, 0x15000}, 0x3000, true)
|
||||
if got, want := mapped, []MappableRange{{0x3000, 0x4000}, {0x5000, 0x6000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AddMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x14000, 0x15000) => [0x5000, 0x6000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped := set.RemoveMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0x1000)
|
||||
unmapped := set.RemoveMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0x1000, true)
|
||||
if got, want := unmapped, []MappableRange{{0x1000, 0x2000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x14000, 0x15000) => [0x5000, 0x6000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000)
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000, true)
|
||||
if len(unmapped) != 0 {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted []", unmapped)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x14000, 0x15000) => [0x5000, 0x6000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x11000, 0x15000}, 0x2000)
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x11000, 0x15000}, 0x2000, true)
|
||||
if got, want := unmapped, []MappableRange{{0x2000, 0x4000}, {0x5000, 0x6000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -115,7 +115,7 @@ func TestAddRemoveMapping(t *testing.T) {
|
||||
// [0x30000, 0x31000) => [0x4000, 0x5000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x30000, 0x31000}, 0x4000)
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x30000, 0x31000}, 0x4000, true)
|
||||
if got, want := unmapped, []MappableRange{{0x4000, 0x5000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
@@ -125,7 +125,7 @@ func TestInvalidateWholeMapping(t *testing.T) {
|
||||
set := MappingSet{}
|
||||
ms := &testMappingSpace{}
|
||||
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0)
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0, true)
|
||||
// Mappings:
|
||||
// [0x10000, 0x11000) => [0, 0x1000)
|
||||
t.Log(&set)
|
||||
@@ -139,7 +139,7 @@ func TestInvalidatePartialMapping(t *testing.T) {
|
||||
set := MappingSet{}
|
||||
ms := &testMappingSpace{}
|
||||
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x13000}, 0)
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x13000}, 0, true)
|
||||
// Mappings:
|
||||
// [0x10000, 0x13000) => [0, 0x3000)
|
||||
t.Log(&set)
|
||||
@@ -153,8 +153,8 @@ func TestInvalidateMultipleMappings(t *testing.T) {
|
||||
set := MappingSet{}
|
||||
ms := &testMappingSpace{}
|
||||
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0)
|
||||
set.AddMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000)
|
||||
set.AddMapping(ms, usermem.AddrRange{0x10000, 0x11000}, 0, true)
|
||||
set.AddMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000, true)
|
||||
// Mappings:
|
||||
// [0x10000, 0x11000) => [0, 0x1000)
|
||||
// [0x12000, 0x13000) => [0x2000, 0x3000)
|
||||
@@ -170,8 +170,8 @@ func TestInvalidateOverlappingMappings(t *testing.T) {
|
||||
ms1 := &testMappingSpace{}
|
||||
ms2 := &testMappingSpace{}
|
||||
|
||||
set.AddMapping(ms1, usermem.AddrRange{0x10000, 0x12000}, 0)
|
||||
set.AddMapping(ms2, usermem.AddrRange{0x20000, 0x22000}, 0x1000)
|
||||
set.AddMapping(ms1, usermem.AddrRange{0x10000, 0x12000}, 0, true)
|
||||
set.AddMapping(ms2, usermem.AddrRange{0x20000, 0x22000}, 0x1000, true)
|
||||
// Mappings:
|
||||
// ms1:[0x10000, 0x12000) => [0, 0x2000)
|
||||
// ms2:[0x11000, 0x13000) => [0x1000, 0x3000)
|
||||
@@ -184,3 +184,77 @@ func TestInvalidateOverlappingMappings(t *testing.T) {
|
||||
t.Errorf("Invalidate: ms1: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMixedWritableMappings(t *testing.T) {
|
||||
set := MappingSet{}
|
||||
ms := &testMappingSpace{}
|
||||
|
||||
mapped := set.AddMapping(ms, usermem.AddrRange{0x10000, 0x12000}, 0x1000, true)
|
||||
if got, want := mapped, []MappableRange{{0x1000, 0x3000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AddMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
|
||||
// Mappings:
|
||||
// [0x10000, 0x12000) writable => [0x1000, 0x3000)
|
||||
t.Log(&set)
|
||||
|
||||
mapped = set.AddMapping(ms, usermem.AddrRange{0x20000, 0x22000}, 0x2000, false)
|
||||
if got, want := mapped, []MappableRange{{0x3000, 0x4000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AddMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
|
||||
// Mappings:
|
||||
// [0x10000, 0x11000) writable => [0x1000, 0x2000)
|
||||
// [0x11000, 0x12000) writable and [0x20000, 0x21000) readonly => [0x2000, 0x3000)
|
||||
// [0x21000, 0x22000) readonly => [0x3000, 0x4000)
|
||||
t.Log(&set)
|
||||
|
||||
// Unmap should fail because we specified the readonly map address range, but
|
||||
// asked to unmap a writable segment.
|
||||
unmapped := set.RemoveMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000, true)
|
||||
if len(unmapped) != 0 {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted []", unmapped)
|
||||
}
|
||||
|
||||
// Readonly mapping removed, but writable mapping still exists in the range,
|
||||
// so no mappable range fully unmapped.
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x20000, 0x21000}, 0x2000, false)
|
||||
if len(unmapped) != 0 {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted []", unmapped)
|
||||
}
|
||||
|
||||
// Mappings:
|
||||
// [0x10000, 0x12000) writable => [0x1000, 0x3000)
|
||||
// [0x21000, 0x22000) readonly => [0x3000, 0x4000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x11000, 0x12000}, 0x2000, true)
|
||||
if got, want := unmapped, []MappableRange{{0x2000, 0x3000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
|
||||
// Mappings:
|
||||
// [0x10000, 0x12000) writable => [0x1000, 0x3000)
|
||||
// [0x21000, 0x22000) readonly => [0x3000, 0x4000)
|
||||
t.Log(&set)
|
||||
|
||||
// Unmap should fail since writable bit doesn't match.
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x10000, 0x12000}, 0x1000, false)
|
||||
if len(unmapped) != 0 {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted []", unmapped)
|
||||
}
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x10000, 0x12000}, 0x1000, true)
|
||||
if got, want := unmapped, []MappableRange{{0x1000, 0x2000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
|
||||
// Mappings:
|
||||
// [0x21000, 0x22000) readonly => [0x3000, 0x4000)
|
||||
t.Log(&set)
|
||||
|
||||
unmapped = set.RemoveMapping(ms, usermem.AddrRange{0x21000, 0x22000}, 0x3000, false)
|
||||
if got, want := unmapped, []MappableRange{{0x3000, 0x4000}}; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,16 +36,22 @@ type Mappable interface {
|
||||
// AddMapping notifies the Mappable of a mapping from addresses ar in ms to
|
||||
// offsets [offset, offset+ar.Length()) in this Mappable.
|
||||
//
|
||||
// The writable flag indicates whether the backing data for a Mappable can
|
||||
// be modified through the mapping. Effectively, this means a shared mapping
|
||||
// where Translate may be called with at.Write == true. This is a property
|
||||
// established at mapping creation and must remain constant throughout the
|
||||
// lifetime of the mapping.
|
||||
//
|
||||
// Preconditions: offset+ar.Length() does not overflow.
|
||||
AddMapping(ctx context.Context, ms MappingSpace, ar usermem.AddrRange, offset uint64) error
|
||||
AddMapping(ctx context.Context, ms MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) error
|
||||
|
||||
// RemoveMapping notifies the Mappable of the removal of a mapping from
|
||||
// addresses ar in ms to offsets [offset, offset+ar.Length()) in this
|
||||
// Mappable.
|
||||
//
|
||||
// Preconditions: offset+ar.Length() does not overflow. The removed mapping
|
||||
// must exist.
|
||||
RemoveMapping(ctx context.Context, ms MappingSpace, ar usermem.AddrRange, offset uint64)
|
||||
// must exist. writable must match the corresponding call to AddMapping.
|
||||
RemoveMapping(ctx context.Context, ms MappingSpace, ar usermem.AddrRange, offset uint64, writable bool)
|
||||
|
||||
// CopyMapping notifies the Mappable of an attempt to copy a mapping in ms
|
||||
// from srcAR to dstAR. For most Mappables, this is equivalent to
|
||||
@@ -56,8 +62,9 @@ type Mappable interface {
|
||||
// MappingSpace; it is analogous to Linux's vm_operations_struct::mremap.
|
||||
//
|
||||
// Preconditions: offset+srcAR.Length() and offset+dstAR.Length() do not
|
||||
// overflow. The mapping at srcAR must exist.
|
||||
CopyMapping(ctx context.Context, ms MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error
|
||||
// overflow. The mapping at srcAR must exist. writable must match the
|
||||
// corresponding call to AddMapping.
|
||||
CopyMapping(ctx context.Context, ms MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, writable bool) error
|
||||
|
||||
// Translate returns the Mappable's current mappings for at least the range
|
||||
// of offsets specified by required, and at most the range of offsets
|
||||
|
||||
@@ -244,7 +244,7 @@ func (m *aioMappable) Msync(ctx context.Context, mr memmap.MappableRange) error
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (m *aioMappable) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (m *aioMappable) AddMapping(_ context.Context, _ memmap.MappingSpace, ar usermem.AddrRange, offset uint64, _ bool) error {
|
||||
// Don't allow mappings to be expanded (in Linux, fs/aio.c:aio_ring_mmap()
|
||||
// sets VM_DONTEXPAND).
|
||||
if offset != 0 || uint64(ar.Length()) != aioRingBufferSize {
|
||||
@@ -254,11 +254,11 @@ func (m *aioMappable) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (m *aioMappable) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (m *aioMappable) RemoveMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, uint64, bool) {
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (m *aioMappable) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
func (m *aioMappable) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, _ bool) error {
|
||||
// Don't allow mappings to be expanded (in Linux, fs/aio.c:aio_ring_mmap()
|
||||
// sets VM_DONTEXPAND).
|
||||
if offset != 0 || uint64(dstAR.Length()) != aioRingBufferSize {
|
||||
|
||||
@@ -81,7 +81,7 @@ func (mm *MemoryManager) Fork(ctx context.Context) (*MemoryManager, error) {
|
||||
vmaAR := srcvseg.Range()
|
||||
// Inform the Mappable, if any, of the new mapping.
|
||||
if vma.mappable != nil {
|
||||
if err := vma.mappable.AddMapping(ctx, mm2, vmaAR, vma.off); err != nil {
|
||||
if err := vma.mappable.AddMapping(ctx, mm2, vmaAR, vma.off, vma.isMappableAsWritable()); err != nil {
|
||||
mm2.removeVMAsLocked(ctx, mm2.applicationAddrRange())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -349,6 +349,10 @@ func (v *vma) loadRealPerms(b int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *vma) isMappableAsWritable() bool {
|
||||
return !v.private && v.maxPerms.Write
|
||||
}
|
||||
|
||||
// pma represents a platform mapping area.
|
||||
//
|
||||
// +stateify savable
|
||||
|
||||
@@ -76,16 +76,16 @@ func (m *SpecialMappable) Msync(ctx context.Context, mr memmap.MappableRange) er
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
func (m *SpecialMappable) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) error {
|
||||
func (*SpecialMappable) AddMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, uint64, bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveMapping implements memmap.Mappable.RemoveMapping.
|
||||
func (m *SpecialMappable) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64) {
|
||||
func (*SpecialMappable) RemoveMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, uint64, bool) {
|
||||
}
|
||||
|
||||
// CopyMapping implements memmap.Mappable.CopyMapping.
|
||||
func (m *SpecialMappable) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64) error {
|
||||
func (*SpecialMappable) CopyMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, usermem.AddrRange, uint64, bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -443,7 +443,7 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr usermem.Addr, oldSi
|
||||
return 0, syserror.EINVAL
|
||||
}
|
||||
// Inform the Mappable, if any, of the new mapping.
|
||||
if err := vma.mappable.CopyMapping(ctx, mm, oldAR, newAR, vseg.mappableOffsetAt(oldAR.Start)); err != nil {
|
||||
if err := vma.mappable.CopyMapping(ctx, mm, oldAR, newAR, vseg.mappableOffsetAt(oldAR.Start), vma.isMappableAsWritable()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,7 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr usermem.Addr, oldSi
|
||||
// Now that pmas have been moved to newAR, we can notify vma.mappable that
|
||||
// oldAR is no longer mapped.
|
||||
if vma.mappable != nil {
|
||||
vma.mappable.RemoveMapping(ctx, mm, oldAR, vma.off)
|
||||
vma.mappable.RemoveMapping(ctx, mm, oldAR, vma.off, vma.isMappableAsWritable())
|
||||
}
|
||||
|
||||
return newAR.Start, nil
|
||||
|
||||
@@ -65,7 +65,7 @@ func (mm *MemoryManager) createVMALocked(ctx context.Context, opts memmap.MMapOp
|
||||
|
||||
// Inform the Mappable, if any, of the new mapping.
|
||||
if opts.Mappable != nil {
|
||||
if err := opts.Mappable.AddMapping(ctx, mm, ar, opts.Offset); err != nil {
|
||||
if err := opts.Mappable.AddMapping(ctx, mm, ar, opts.Offset, !opts.Private && opts.MaxPerms.Write); err != nil {
|
||||
return vmaIterator{}, usermem.AddrRange{}, err
|
||||
}
|
||||
}
|
||||
@@ -332,7 +332,7 @@ func (mm *MemoryManager) removeVMAsLocked(ctx context.Context, ar usermem.AddrRa
|
||||
vmaAR := vseg.Range()
|
||||
vma := vseg.ValuePtr()
|
||||
if vma.mappable != nil {
|
||||
vma.mappable.RemoveMapping(ctx, mm, vmaAR, vma.off)
|
||||
vma.mappable.RemoveMapping(ctx, mm, vmaAR, vma.off, vma.isMappableAsWritable())
|
||||
}
|
||||
if vma.id != nil {
|
||||
vma.id.DecRef()
|
||||
|
||||
Reference in New Issue
Block a user