diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-08-27 14:25:21 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-27 14:26:29 -0700 |
commit | 0b3bfe2ea30d491a6533f8ee74eb6e3cea707f06 (patch) | |
tree | 1be36b37d8d3f6d47fed0f17af901311eb51bb90 /pkg/sentry/fs/fsutil | |
parent | 5999767d53d6c00d7e0f1966700e2876879f490e (diff) |
fs: Fix remote-revalidate cache policy.
When revalidating a Dirent, if the inode id is the same, then we don't need to
throw away the entire Dirent. We can just update the unstable attributes in
place.
If the inode id has changed, then the remote file has been deleted or moved,
and we have no choice but to throw away the dirent we have a look up another.
In this case, we may still end up losing a mounted dirent that is a child of
the revalidated dirent. However, that seems appropriate here because the entire
mount point has been pulled out from underneath us.
Because gVisor's overlay is at the Inode level rather than the Dirent level, we
must pass the parent Inode and name along with the Inode that is being
revalidated.
PiperOrigin-RevId: 210431270
Change-Id: I705caef9c68900234972d5aac4ae3a78c61c7d42
Diffstat (limited to 'pkg/sentry/fs/fsutil')
-rw-r--r-- | pkg/sentry/fs/fsutil/inode_cached.go | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/pkg/sentry/fs/fsutil/inode_cached.go b/pkg/sentry/fs/fsutil/inode_cached.go index 0a320e2d8..6777c8bf7 100644 --- a/pkg/sentry/fs/fsutil/inode_cached.go +++ b/pkg/sentry/fs/fsutil/inode_cached.go @@ -427,6 +427,47 @@ func (c *CachingInodeOperations) touchStatusChangeTimeLocked(ctx context.Context c.dirtyAttr.StatusChangeTime = true } +// UpdateUnstable updates the cached unstable attributes. Only non-dirty +// attributes are updated. +func (c *CachingInodeOperations) UpdateUnstable(attr fs.UnstableAttr) { + // All attributes are protected by attrMu. + c.attrMu.Lock() + + if !c.dirtyAttr.Usage { + c.attr.Usage = attr.Usage + } + if !c.dirtyAttr.Perms { + c.attr.Perms = attr.Perms + } + if !c.dirtyAttr.UID { + c.attr.Owner.UID = attr.Owner.UID + } + if !c.dirtyAttr.GID { + c.attr.Owner.GID = attr.Owner.GID + } + if !c.dirtyAttr.AccessTime { + c.attr.AccessTime = attr.AccessTime + } + if !c.dirtyAttr.ModificationTime { + c.attr.ModificationTime = attr.ModificationTime + } + if !c.dirtyAttr.StatusChangeTime { + c.attr.StatusChangeTime = attr.StatusChangeTime + } + if !c.dirtyAttr.Links { + c.attr.Links = attr.Links + } + + // Size requires holding attrMu and dataMu. + c.dataMu.Lock() + if !c.dirtyAttr.Size { + c.attr.Size = attr.Size + } + c.dataMu.Unlock() + + c.attrMu.Unlock() +} + // Read reads from frames and otherwise directly from the backing file // into dst starting at offset until dst is full, EOF is reached, or an // error is encountered. |