diff options
author | Ayush Ranjan <ayushranjan@google.com> | 2019-07-23 20:34:49 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-07-23 20:36:04 -0700 |
commit | 7e38d643334647fb79c7cc8be35745699de264e6 (patch) | |
tree | f6470d9f953dc7274ee98f1af62736a7493ef68c /pkg/sentry/fs/ext/inode.go | |
parent | d7bb79b6f177e8c58d47695e0ee1a072475463c4 (diff) |
ext: Inode creation logic.
PiperOrigin-RevId: 259666476
Diffstat (limited to 'pkg/sentry/fs/ext/inode.go')
-rw-r--r-- | pkg/sentry/fs/ext/inode.go | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/pkg/sentry/fs/ext/inode.go b/pkg/sentry/fs/ext/inode.go index 5bf9dbfa3..df1ea0bda 100644 --- a/pkg/sentry/fs/ext/inode.go +++ b/pkg/sentry/fs/ext/inode.go @@ -28,12 +28,16 @@ type inode struct { // refs is a reference count. refs is accessed using atomic memory operations. refs int64 + // inodeNum is the inode number of this inode on disk. This is used to + // identify inodes within the ext filesystem. + inodeNum uint32 + // diskInode gives us access to the inode struct on disk. Immutable. diskInode disklayout.Inode // root is the root extent node. This lives in the 60 byte diskInode.Blocks(). - // Immutable. - root disklayout.ExtentNode + // Immutable. Nil if the inode does not use extents. + root *disklayout.ExtentNode } // incRef increments the inode ref count. @@ -54,20 +58,71 @@ func (in *inode) tryIncRef() bool { } } -// decRef decrements the inode ref count. -func (in *inode) decRef() { - if refs := atomic.AddInt64(&in.refs, -1); refs < 0 { +// decRef decrements the inode ref count and releases the inode resources if +// the ref count hits 0. +// +// Preconditions: Must have locked fs.mu. +func (in *inode) decRef(fs *filesystem) { + if refs := atomic.AddInt64(&in.refs, -1); refs == 0 { + delete(fs.inodeCache, in.inodeNum) + } else if refs < 0 { panic("ext.inode.decRef() called without holding a reference") } } +// newInode is the inode constructor. Reads the inode off disk. Identifies +// inodes based on the absolute inode number on disk. +// +// Preconditions: Must hold the mutex of the filesystem containing dev. +func newInode(dev io.ReadSeeker, sb disklayout.SuperBlock, bgs []disklayout.BlockGroup, inodeNum uint32) (*inode, error) { + if inodeNum == 0 { + panic("inode number 0 on ext filesystems is not possible") + } + + in := &inode{refs: 1, inodeNum: inodeNum} + inodeRecordSize := sb.InodeSize() + if inodeRecordSize == disklayout.OldInodeSize { + in.diskInode = &disklayout.InodeOld{} + } else { + in.diskInode = &disklayout.InodeNew{} + } + + // Calculate where the inode is actually placed. + inodesPerGrp := sb.InodesPerGroup() + blkSize := sb.BlockSize() + inodeTableOff := bgs[getBGNum(inodeNum, inodesPerGrp)].InodeTable() * blkSize + inodeOff := inodeTableOff + uint64(uint32(inodeRecordSize)*getBGOff(inodeNum, inodesPerGrp)) + + // Read it from disk and figure out which type of inode this is. + if err := readFromDisk(dev, int64(inodeOff), in.diskInode); err != nil { + return nil, err + } + + if in.diskInode.Flags().Extents { + in.buildExtTree(dev, blkSize) + } + + return in, nil +} + +// getBGNum returns the block group number that a given inode belongs to. +func getBGNum(inodeNum uint32, inodesPerGrp uint32) uint32 { + return (inodeNum - 1) / inodesPerGrp +} + +// getBGOff returns the offset at which the given inode lives in the block +// group's inode table, i.e. the index of the inode in the inode table. +func getBGOff(inodeNum uint32, inodesPerGrp uint32) uint32 { + return (inodeNum - 1) % inodesPerGrp +} + // buildExtTree builds the extent tree by reading it from disk by doing // running a simple DFS. It first reads the root node from the inode struct in // memory. Then it recursively builds the rest of the tree by reading it off // disk. // // Preconditions: -// - Must have mutual exclusion on device fd. +// - Must hold the mutex of the filesystem containing dev. // - Inode flag InExtents must be set. func (in *inode) buildExtTree(dev io.ReadSeeker, blkSize uint64) error { rootNodeData := in.diskInode.Data() @@ -106,7 +161,7 @@ func (in *inode) buildExtTree(dev io.ReadSeeker, blkSize uint64) error { } } - in.root = disklayout.ExtentNode{rootHeader, rootEntries} + in.root = &disklayout.ExtentNode{rootHeader, rootEntries} return nil } @@ -114,7 +169,7 @@ func (in *inode) buildExtTree(dev io.ReadSeeker, blkSize uint64) error { // builds the tree. Performs a simple DFS. It returns the ExtentNode pointed to // by the ExtentEntry. // -// Preconditions: Must have mutual exclusion on device fd. +// Preconditions: Must hold the mutex of the filesystem containing dev. func buildExtTreeFromDisk(dev io.ReadSeeker, entry disklayout.ExtentEntry, blkSize uint64) (*disklayout.ExtentNode, error) { var header disklayout.ExtentHeader off := entry.PhysicalBlock() * blkSize |