diff options
Diffstat (limited to 'pkg/sentry/fs/tmpfs/inode_file.go')
-rw-r--r-- | pkg/sentry/fs/tmpfs/inode_file.go | 112 |
1 files changed, 51 insertions, 61 deletions
diff --git a/pkg/sentry/fs/tmpfs/inode_file.go b/pkg/sentry/fs/tmpfs/inode_file.go index ca2b4aabb..42d4bc76f 100644 --- a/pkg/sentry/fs/tmpfs/inode_file.go +++ b/pkg/sentry/fs/tmpfs/inode_file.go @@ -22,6 +22,7 @@ import ( "gvisor.googlesource.com/gvisor/pkg/sentry/fs" "gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil" "gvisor.googlesource.com/gvisor/pkg/sentry/kernel" + ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time" "gvisor.googlesource.com/gvisor/pkg/sentry/memmap" "gvisor.googlesource.com/gvisor/pkg/sentry/safemem" "gvisor.googlesource.com/gvisor/pkg/sentry/usage" @@ -46,11 +47,13 @@ import ( // // +stateify savable type fileInodeOperations struct { - fsutil.DeprecatedFileOperations `state:"nosave"` - fsutil.InodeNotDirectory `state:"nosave"` - fsutil.InodeNotSocket `state:"nosave"` - fsutil.InodeNotSymlink `state:"nosave"` - fsutil.NoopWriteOut `state:"nosave"` + fsutil.InodeGenericChecker `state:"nosave"` + fsutil.InodeNoopWriteOut `state:"nosave"` + fsutil.InodeNotDirectory `state:"nosave"` + fsutil.InodeNotSocket `state:"nosave"` + fsutil.InodeNotSymlink `state:"nosave"` + + fsutil.InodeSimpleExtendedAttributes // kernel is used to allocate platform memory that stores the file's contents. kernel *kernel.Kernel @@ -62,10 +65,10 @@ type fileInodeOperations struct { // attr contains the unstable metadata for the file. // - // attr is protected by attrMu. attr.Unstable.Size is protected by both - // attrMu and dataMu; reading it requires locking either mutex, while - // mutating it requires locking both. - attr fsutil.InMemoryAttributes + // attr is protected by attrMu. attr.Size is protected by both attrMu + // and dataMu; reading it requires locking either mutex, while mutating + // it requires locking both. + attr fs.UnstableAttr mapsMu sync.Mutex `state:"nosave"` @@ -83,12 +86,12 @@ type fileInodeOperations struct { data fsutil.FileRangeSet } +var _ fs.InodeOperations = (*fileInodeOperations)(nil) + // NewInMemoryFile returns a new file backed by p.Memory(). func NewInMemoryFile(ctx context.Context, usage usage.MemoryKind, uattr fs.UnstableAttr, k *kernel.Kernel) fs.InodeOperations { return &fileInodeOperations{ - attr: fsutil.InMemoryAttributes{ - Unstable: uattr, - }, + attr: uattr, kernel: k, memUsage: usage, } @@ -121,71 +124,56 @@ func (f *fileInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags f // UnstableAttr returns unstable attributes of this tmpfs file. func (f *fileInodeOperations) UnstableAttr(ctx context.Context, inode *fs.Inode) (fs.UnstableAttr, error) { f.attrMu.Lock() - defer f.attrMu.Unlock() f.dataMu.RLock() - defer f.dataMu.RUnlock() - attr := f.attr.Unstable + attr := f.attr attr.Usage = int64(f.data.Span()) + f.dataMu.RUnlock() + f.attrMu.Unlock() return attr, nil } -// Getxattr implements fs.InodeOperations.Getxattr. -func (f *fileInodeOperations) Getxattr(inode *fs.Inode, name string) ([]byte, error) { - f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.Getxattr(name) -} - -// Setxattr implements fs.InodeOperations.Setxattr. -func (f *fileInodeOperations) Setxattr(inode *fs.Inode, name string, value []byte) error { - f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.Setxattr(name, value) -} - -// Listxattr implements fs.InodeOperations.Listxattr. -func (f *fileInodeOperations) Listxattr(inode *fs.Inode) (map[string]struct{}, error) { - f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.Listxattr() -} - // Check implements fs.InodeOperations.Check. func (f *fileInodeOperations) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool { return fs.ContextCanAccessFile(ctx, inode, p) } // SetPermissions implements fs.InodeOperations.SetPermissions. -func (f *fileInodeOperations) SetPermissions(ctx context.Context, inode *fs.Inode, p fs.FilePermissions) bool { +func (f *fileInodeOperations) SetPermissions(ctx context.Context, _ *fs.Inode, p fs.FilePermissions) bool { f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.SetPermissions(ctx, p) + f.attr.SetPermissions(ctx, p) + f.attrMu.Unlock() + return true } // SetTimestamps implements fs.InodeOperations.SetTimestamps. -func (f *fileInodeOperations) SetTimestamps(ctx context.Context, inode *fs.Inode, ts fs.TimeSpec) error { +func (f *fileInodeOperations) SetTimestamps(ctx context.Context, _ *fs.Inode, ts fs.TimeSpec) error { f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.SetTimestamps(ctx, ts) + f.attr.SetTimestamps(ctx, ts) + f.attrMu.Unlock() + return nil } // SetOwner implements fs.InodeOperations.SetOwner. -func (f *fileInodeOperations) SetOwner(ctx context.Context, inode *fs.Inode, owner fs.FileOwner) error { +func (f *fileInodeOperations) SetOwner(ctx context.Context, _ *fs.Inode, owner fs.FileOwner) error { f.attrMu.Lock() - defer f.attrMu.Unlock() - return f.attr.SetOwner(ctx, owner) + f.attr.SetOwner(ctx, owner) + f.attrMu.Unlock() + return nil } // Truncate implements fs.InodeOperations.Truncate. -func (f *fileInodeOperations) Truncate(ctx context.Context, inode *fs.Inode, size int64) error { +func (f *fileInodeOperations) Truncate(ctx context.Context, _ *fs.Inode, size int64) error { f.attrMu.Lock() defer f.attrMu.Unlock() f.dataMu.Lock() - oldSize := f.attr.Unstable.Size + oldSize := f.attr.Size if oldSize != size { - f.attr.Unstable.Size = size - f.attr.TouchModificationTime(ctx) + f.attr.Size = size + // Update mtime and ctime. + now := ktime.NowFromContext(ctx) + f.attr.ModificationTime = now + f.attr.StatusChangeTime = now } f.dataMu.Unlock() @@ -220,21 +208,21 @@ func (f *fileInodeOperations) Truncate(ctx context.Context, inode *fs.Inode, siz // AddLink implements fs.InodeOperations.AddLink. func (f *fileInodeOperations) AddLink() { f.attrMu.Lock() - f.attr.Unstable.Links++ + f.attr.Links++ f.attrMu.Unlock() } // DropLink implements fs.InodeOperations.DropLink. func (f *fileInodeOperations) DropLink() { f.attrMu.Lock() - f.attr.Unstable.Links-- + f.attr.Links-- f.attrMu.Unlock() } // NotifyStatusChange implements fs.InodeOperations.NotifyStatusChange. func (f *fileInodeOperations) NotifyStatusChange(ctx context.Context) { f.attrMu.Lock() - f.attr.TouchStatusChangeTime(ctx) + f.attr.StatusChangeTime = ktime.NowFromContext(ctx) f.attrMu.Unlock() } @@ -264,7 +252,7 @@ func (f *fileInodeOperations) read(ctx context.Context, dst usermem.IOSequence, // TODO: Separate out f.attr.Size and use atomics instead of // f.dataMu. f.dataMu.RLock() - size := f.attr.Unstable.Size + size := f.attr.Size f.dataMu.RUnlock() if offset >= size { return 0, io.EOF @@ -273,7 +261,7 @@ func (f *fileInodeOperations) read(ctx context.Context, dst usermem.IOSequence, n, err := dst.CopyOutFrom(ctx, &fileReadWriter{f, offset}) // Compare Linux's mm/filemap.c:do_generic_file_read() => file_accessed(). f.attrMu.Lock() - f.attr.TouchAccessTime(ctx) + f.attr.AccessTime = ktime.NowFromContext(ctx) f.attrMu.Unlock() return n, err } @@ -287,7 +275,9 @@ func (f *fileInodeOperations) write(ctx context.Context, src usermem.IOSequence, f.attrMu.Lock() defer f.attrMu.Unlock() // Compare Linux's mm/filemap.c:__generic_file_write_iter() => file_update_time(). - f.attr.TouchModificationTime(ctx) + now := ktime.NowFromContext(ctx) + f.attr.ModificationTime = now + f.attr.StatusChangeTime = now return src.CopyInTo(ctx, &fileReadWriter{f, offset}) } @@ -302,10 +292,10 @@ func (rw *fileReadWriter) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) { defer rw.f.dataMu.RUnlock() // Compute the range to read. - if rw.offset >= rw.f.attr.Unstable.Size { + if rw.offset >= rw.f.attr.Size { return 0, io.EOF } - end := fs.ReadEndOffset(rw.offset, int64(dsts.NumBytes()), rw.f.attr.Unstable.Size) + end := fs.ReadEndOffset(rw.offset, int64(dsts.NumBytes()), rw.f.attr.Size) if end == rw.offset { // dsts.NumBytes() == 0? return 0, nil } @@ -371,8 +361,8 @@ func (rw *fileReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) defer func() { // If the write ends beyond the file's previous size, it causes the // file to grow. - if rw.offset > rw.f.attr.Unstable.Size { - rw.f.attr.Unstable.Size = rw.offset + if rw.offset > rw.f.attr.Size { + rw.f.attr.Size = rw.offset } }() @@ -450,9 +440,9 @@ func (f *fileInodeOperations) Translate(ctx context.Context, required, optional f.dataMu.Lock() defer f.dataMu.Unlock() - // Constrain translations to f.attr.Unstable.Size (rounded up) to prevent + // Constrain translations to f.attr.Size (rounded up) to prevent // translation to pages that may be concurrently truncated. - pgend := fs.OffsetPageEnd(f.attr.Unstable.Size) + pgend := fs.OffsetPageEnd(f.attr.Size) var beyondEOF bool if required.End > pgend { if required.Start >= pgend { |