diff options
Diffstat (limited to 'pkg/sentry/fs/ext/ext.go')
-rw-r--r-- | pkg/sentry/fs/ext/ext.go | 48 |
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 +} |