diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go index a625a9639..9857a433e 100644 --- a/pkg/sentry/fsimpl/gofer/filesystem.go +++ b/pkg/sentry/fsimpl/gofer/filesystem.go @@ -1757,6 +1757,11 @@ func (fs *filesystem) MountOptions() string { {moptDfltGID, fs.opts.dfltgid}, } + if globalDentryCache != nil { + optsKV = append(optsKV, mopt{moptDcache, fmt.Sprintf("%d-global", globalDentryCache.maxCachedDentries)}) + } else { + optsKV = append(optsKV, mopt{moptDcache, fs.opts.dcache}) + } switch fs.opts.interop { case InteropModeExclusive: optsKV = append(optsKV, mopt{moptCache, cacheFSCache}) diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go index 917188abb..dcdca6f7e 100644 --- a/pkg/sentry/fsimpl/gofer/gofer.go +++ b/pkg/sentry/fsimpl/gofer/gofer.go @@ -81,6 +81,7 @@ const ( moptDfltUID = "dfltuid" moptDfltGID = "dfltgid" moptCache = "cache" + moptDcache = "dcache" moptForcePageCache = "force_page_cache" moptLimitHostFDTranslation = "limit_host_fd_translation" moptOverlayfsStaleRead = "overlayfs_stale_read" @@ -99,7 +100,7 @@ const ( ) // SupportedMountOptions is the set of mount options that can be set externally. -var SupportedMountOptions = []string{moptOverlayfsStaleRead, moptDisableFileHandleSharing} +var SupportedMountOptions = []string{moptOverlayfsStaleRead, moptDisableFileHandleSharing, moptDcache} const ( defaultMaxCachedDentries = 1000 @@ -143,6 +144,9 @@ func (cache *stringFixedCache) add(name string) string { // +stateify savable type dentryCache struct { + // maxCachedDentries is the maximum number of cacheable dentries. + // maxCachedDentries is immutable. + maxCachedDentries uint64 // mu protects the below fields. mu sync.Mutex `state:"nosave"` // dentries contains all dentries with 0 references. Due to race conditions, @@ -150,8 +154,6 @@ type dentryCache struct { dentries dentryList // dentriesLen is the number of dentries in dentries. dentriesLen uint64 - // maxCachedDentries is the maximum number of cacheable dentries. - maxCachedDentries uint64 } // SetDentryCacheSize sets the size of the global gofer dentry cache. @@ -166,7 +168,7 @@ func SetDentryCacheSize(size int) { globalDentryCache = &dentryCache{maxCachedDentries: uint64(size)} } -// globalDentryCache is a global cache of dentries across all gofers. +// globalDentryCache is a global cache of dentries across all gofer clients. var globalDentryCache *dentryCache // Valid values for "trans" mount option. @@ -251,6 +253,10 @@ type filesystemOptions struct { dfltuid auth.KUID dfltgid auth.KGID + // dcache is the maximum number of dentries that can be cached. This is + // effective only if globalDentryCache is not being used. + dcache uint64 + // If forcePageCache is true, host FDs may not be used for application // memory mappings even if available; instead, the client must perform its // own caching of regular file pages. This is primarily useful for testing. @@ -439,6 +445,20 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt } } + // Parse the dentry cache size. + fsopts.dcache = defaultMaxCachedDentries + if dcacheStr, ok := mopts[moptDcache]; ok { + delete(mopts, moptDcache) + dcache, err := strconv.ParseInt(dcacheStr, 10, 64) + if err != nil { + ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid dcache: %s=%s", moptDcache, dcacheStr) + return nil, nil, linuxerr.EINVAL + } + if dcache >= 0 { + fsopts.dcache = uint64(dcache) + } + } + // Parse the default UID and GID. fsopts.dfltuid = _V9FS_DEFUID if dfltuidstr, ok := mopts[moptDfltUID]; ok { @@ -534,7 +554,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt if globalDentryCache != nil { fs.dentryCache = globalDentryCache } else { - fs.dentryCache = &dentryCache{maxCachedDentries: defaultMaxCachedDentries} + fs.dentryCache = &dentryCache{maxCachedDentries: fsopts.dcache} } fs.vfsfs.Init(vfsObj, &fstype, fs) diff --git a/runsc/config/config.go b/runsc/config/config.go index 415b8b908..0d76dfb53 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -292,7 +292,7 @@ type Config struct { // each. FDLimit int `flag:"fdlimit"` - // DCache sets the global dirent cache size. If zero, per-mount caches are + // DCache sets the global dirent cache size. If negative, per-mount caches are // used. DCache int `flag:"dcache"`