summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/ext/ext.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs/ext/ext.go')
-rw-r--r--pkg/sentry/fs/ext/ext.go48
1 files changed, 37 insertions, 11 deletions
diff --git a/pkg/sentry/fs/ext/ext.go b/pkg/sentry/fs/ext/ext.go
index 8bc591c8b..7f4287b01 100644
--- a/pkg/sentry/fs/ext/ext.go
+++ b/pkg/sentry/fs/ext/ext.go
@@ -26,21 +26,29 @@ import (
// filesystem implements vfs.FilesystemImpl.
type filesystem struct {
- // dev is the ReadSeeker for the underlying fs device and is protected by mu.
- dev io.ReadSeeker
+ // mu serializes changes to the Dentry tree and the usage of the read seeker.
+ mu sync.Mutex
- // mu synchronizes the usage of dev. The ext filesystems take locality into
- // condsideration, i.e. data blocks of a file will tend to be placed close
- // together. On a spinning disk, locality reduces the amount of movement of
- // the head hence speeding up IO operations. On an SSD there are no moving
- // parts but locality increases the size of each transer request. Hence,
- // having mutual exclusion on the read seeker while reading a file *should*
- // help in achieving the intended performance gains.
+ // dev is the ReadSeeker for the underlying fs device. It is protected by mu.
+ //
+ // The ext filesystems aim to maximize locality, i.e. place all the data
+ // blocks of a file close together. On a spinning disk, locality reduces the
+ // amount of movement of the head hence speeding up IO operations. On an SSD
+ // there are no moving parts but locality increases the size of each transer
+ // request. Hence, having mutual exclusion on the read seeker while reading a
+ // file *should* help in achieving the intended performance gains.
//
// Note: This synchronization was not coupled with the ReadSeeker itself
// because we want to synchronize across read/seek operations for the
// performance gains mentioned above. Helps enforcing one-file-at-a-time IO.
- mu sync.Mutex
+ dev io.ReadSeeker
+
+ // inodeCache maps absolute inode numbers to the corresponding Inode struct.
+ // Inodes should be removed from this once their reference count hits 0.
+ //
+ // Protected by mu because every addition and removal from this corresponds to
+ // a change in the dentry tree.
+ inodeCache map[uint32]*inode
// sb represents the filesystem superblock. Immutable after initialization.
sb disklayout.SuperBlock
@@ -52,7 +60,7 @@ type filesystem struct {
// newFilesystem is the filesystem constructor.
func newFilesystem(dev io.ReadSeeker) (*filesystem, error) {
- fs := filesystem{dev: dev}
+ fs := filesystem{dev: dev, inodeCache: make(map[uint32]*inode)}
var err error
fs.sb, err = readSuperBlock(dev)
@@ -73,3 +81,21 @@ func newFilesystem(dev io.ReadSeeker) (*filesystem, error) {
return &fs, nil
}
+
+// getOrCreateInode gets the inode corresponding to the inode number passed in.
+// It creates a new one with the given inode number if one does not exist.
+//
+// Preconditions: must be holding fs.mu.
+func (fs *filesystem) getOrCreateInode(inodeNum uint32) (*inode, error) {
+ if in, ok := fs.inodeCache[inodeNum]; ok {
+ return in, nil
+ }
+
+ in, err := newInode(fs.dev, fs.sb, fs.bgs, inodeNum)
+ if err != nil {
+ return nil, err
+ }
+
+ fs.inodeCache[inodeNum] = in
+ return in, nil
+}