summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/overlay.go
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2019-06-27 14:22:40 -0700
committergVisor bot <gvisor-bot@google.com>2019-06-27 14:24:03 -0700
commit085a907565921e84f59dfeb51da49af2d7c36c40 (patch)
treeaef4e9fef70d282291b8efeb5e675bd6085b22cc /pkg/sentry/fs/overlay.go
parente2760839033618410cdea9aeab039e096cde54be (diff)
Cache directory entries in the overlay
Currently, the overlay dirCache is only used for a single logical use of getdents. i.e., it is discard when the FD is closed or seeked back to the beginning. But the initial work of getting the directory contents can be quite expensive (particularly sorting large directories), so we should keep it as long as possible. This is very similar to the readdirCache in fs/gofer. Since the upper filesystem does not have to allow caching readdir entries, the new CacheReaddir MountSourceOperations method controls this behavior. This caching should be trivially movable to all Inodes if desired, though that adds an additional copy step for non-overlay Inodes. (Overlay Inodes already do the extra copy). PiperOrigin-RevId: 255477592
Diffstat (limited to 'pkg/sentry/fs/overlay.go')
-rw-r--r--pkg/sentry/fs/overlay.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/pkg/sentry/fs/overlay.go b/pkg/sentry/fs/overlay.go
index c87f24997..1d3ff39e0 100644
--- a/pkg/sentry/fs/overlay.go
+++ b/pkg/sentry/fs/overlay.go
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/usermem"
"gvisor.dev/gvisor/pkg/syserror"
+ "gvisor.dev/gvisor/third_party/gvsync"
)
// The virtual filesystem implements an overlay configuration. For a high-level
@@ -196,6 +197,12 @@ type overlayEntry struct {
// these locks is sufficient to read upper; holding all three for writing
// is required to mutate it.
upper *Inode
+
+ // dirCacheMu protects dirCache.
+ dirCacheMu gvsync.DowngradableRWMutex `state:"nosave"`
+
+ // dirCache is cache of DentAttrs from upper and lower Inodes.
+ dirCache *SortedDentryMap
}
// newOverlayEntry returns a new overlayEntry.
@@ -258,6 +265,17 @@ func (o *overlayEntry) isMappableLocked() bool {
return o.inodeLocked().Mappable() != nil
}
+// markDirectoryDirty marks any cached data dirty for this directory. This is
+// necessary in order to ensure that this node does not retain stale state
+// throughout its lifetime across multiple open directory handles.
+//
+// Currently this means invalidating any readdir caches.
+func (o *overlayEntry) markDirectoryDirty() {
+ o.dirCacheMu.Lock()
+ o.dirCache = nil
+ o.dirCacheMu.Unlock()
+}
+
// AddMapping implements memmap.Mappable.AddMapping.
func (o *overlayEntry) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, writable bool) error {
o.mapsMu.Lock()