mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Skip atime and mtime update when file is backed by host FD
When file is backed by host FD, atime and mtime for the host file and the cached attributes in the Sentry must be close together. In this case, the call to update atime and mtime can be skipped. This is important when host filesystem is using overlay because updating atime and mtime explicitly forces a copy up for every file that is touched. PiperOrigin-RevId: 196176413 Change-Id: I3933ea91637a071ba2ea9db9d8ac7cdba5dc0482
This commit is contained in:
committed by
Shentubot
parent
31a4fefbe0
commit
ac01f245ff
@@ -206,7 +206,7 @@ func (i *inodeFileState) WriteFromBlocksAt(ctx context.Context, srcs safemem.Blo
|
||||
|
||||
// SetMaskedAttributes implements fsutil.CachedFileObject.SetMaskedAttributes.
|
||||
func (i *inodeFileState) SetMaskedAttributes(ctx context.Context, mask fs.AttrMask, attr fs.UnstableAttr) error {
|
||||
if mask.Empty() {
|
||||
if i.skipSetAttr(mask) {
|
||||
return nil
|
||||
}
|
||||
as, ans := attr.AccessTime.Unix()
|
||||
@@ -237,6 +237,35 @@ func (i *inodeFileState) SetMaskedAttributes(ctx context.Context, mask fs.AttrMa
|
||||
})
|
||||
}
|
||||
|
||||
// skipSetAttr checks if attribute change can be skipped. It can be skipped
|
||||
// when:
|
||||
// - Mask is empty
|
||||
// - Mask contains only atime and/or mtime, and host FD exists
|
||||
//
|
||||
// Updates to atime and mtime can be skipped because cached value will be
|
||||
// "close enough" to host value, given that operation went directly to host FD.
|
||||
// Skipping atime updates is particularly important to reduce the number of
|
||||
// operations sent to the Gofer for readonly files.
|
||||
func (i *inodeFileState) skipSetAttr(mask fs.AttrMask) bool {
|
||||
if mask.Empty() {
|
||||
return true
|
||||
}
|
||||
|
||||
cpy := mask
|
||||
cpy.AccessTime = false
|
||||
cpy.ModificationTime = false
|
||||
if !cpy.Empty() {
|
||||
// More than just atime and mtime is being set.
|
||||
return false
|
||||
}
|
||||
|
||||
i.handlesMu.RLock()
|
||||
defer i.handlesMu.RUnlock()
|
||||
return (i.readonly != nil && i.readonly.Host != nil) ||
|
||||
(i.readthrough != nil && i.readthrough.Host != nil) ||
|
||||
(i.writeback != nil && i.writeback.Host != nil)
|
||||
}
|
||||
|
||||
// Sync implements fsutil.CachedFileObject.Sync.
|
||||
func (i *inodeFileState) Sync(ctx context.Context) error {
|
||||
i.handlesMu.RLock()
|
||||
|
||||
+1
-5
@@ -141,10 +141,7 @@ func createMountNamespace(ctx context.Context, spec *specs.Spec, conf *Config, i
|
||||
// createRootMount creates the root filesystem.
|
||||
func createRootMount(ctx context.Context, spec *specs.Spec, conf *Config, fds *fdDispenser) (*fs.Inode, error) {
|
||||
// First construct the filesystem from the spec.Root.
|
||||
mf := fs.MountSourceFlags{
|
||||
ReadOnly: spec.Root.Readonly,
|
||||
NoAtime: true,
|
||||
}
|
||||
mf := fs.MountSourceFlags{ReadOnly: spec.Root.Readonly}
|
||||
|
||||
var (
|
||||
rootInode *fs.Inode
|
||||
@@ -261,7 +258,6 @@ func mountSubmount(ctx context.Context, spec *specs.Spec, conf *Config, mns *fs.
|
||||
// All writes go to upper, be paranoid and make lower readonly.
|
||||
mf.ReadOnly = true
|
||||
}
|
||||
mf.NoAtime = true
|
||||
|
||||
inode, err := filesystem.Mount(ctx, m.Type, mf, strings.Join(data, ","))
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user