diff options
-rw-r--r-- | pkg/sentry/fs/inode_overlay_test.go | 70 | ||||
-rw-r--r-- | pkg/sentry/fs/mounts.go | 4 |
2 files changed, 72 insertions, 2 deletions
diff --git a/pkg/sentry/fs/inode_overlay_test.go b/pkg/sentry/fs/inode_overlay_test.go index a7be9d040..3ee4c9667 100644 --- a/pkg/sentry/fs/inode_overlay_test.go +++ b/pkg/sentry/fs/inode_overlay_test.go @@ -299,6 +299,76 @@ func TestLookupRevalidation(t *testing.T) { } } +func TestCacheFlush(t *testing.T) { + ctx := contexttest.Context(t) + + // Upper and lower each have a file. + upperFileName := "file-from-upper" + lowerFileName := "file-from-lower" + upper := newTestRamfsDir(ctx, []dirContent{{name: upperFileName}}, nil) + lower := newTestRamfsDir(ctx, []dirContent{{name: lowerFileName}}, nil) + + overlay := fs.NewTestOverlayDir(ctx, upper, lower, true /* revalidate */) + + mns, err := fs.NewMountNamespace(ctx, overlay) + if err != nil { + t.Fatalf("NewMountNamespace failed: %v", err) + } + root := mns.Root() + defer root.DecRef() + + ctx = &rootContext{ + Context: ctx, + root: root, + } + + for _, fileName := range []string{upperFileName, lowerFileName} { + // Walk to the file. + dirent, err := mns.FindInode(ctx, root, nil, fileName, 0) + if err != nil { + t.Fatalf("FindInode(%q) failed: %v", fileName, err) + } + + // Get a file from the dirent. + file, err := dirent.Inode.GetFile(ctx, dirent, fs.FileFlags{Read: true}) + if err != nil { + t.Fatalf("GetFile() failed: %v", err) + } + + // The dirent should have 3 refs, one from us, one from the + // file, and one from the dirent cache. + // dirent cache. + if got, want := dirent.ReadRefs(), 3; int(got) != want { + t.Errorf("dirent.ReadRefs() got %d want %d", got, want) + } + + // Drop the file reference. + file.DecRef() + + // Dirent should have 2 refs left. + if got, want := dirent.ReadRefs(), 2; int(got) != want { + t.Errorf("dirent.ReadRefs() got %d want %d", got, want) + } + + // Flush the dirent cache. + mns.FlushMountSourceRefs() + + // Dirent should have 1 ref left from the dirent cache. + if got, want := dirent.ReadRefs(), 1; int(got) != want { + t.Errorf("dirent.ReadRefs() got %d want %d", got, want) + } + + // Drop our ref. + dirent.DecRef() + + // We should be back to zero refs. + if got, want := dirent.ReadRefs(), 0; int(got) != want { + t.Errorf("dirent.ReadRefs() got %d want %d", got, want) + } + } + +} + type dir struct { fs.InodeOperations diff --git a/pkg/sentry/fs/mounts.go b/pkg/sentry/fs/mounts.go index 144d3427d..0318f135d 100644 --- a/pkg/sentry/fs/mounts.go +++ b/pkg/sentry/fs/mounts.go @@ -348,10 +348,10 @@ func (mns *MountNamespace) Unmount(ctx context.Context, node *Dirent, detachOnly // Precondition: the path must be non-empty. func (mns *MountNamespace) FindLink(ctx context.Context, root, wd *Dirent, path string, maxTraversals uint) (*Dirent, error) { if root == nil { - panic("MountNamespace.FindInode: root must not be nil") + panic("MountNamespace.FindLink: root must not be nil") } if len(path) == 0 { - panic("MountNamespace.FindInode: path is empty") + panic("MountNamespace.FindLink: path is empty") } // Split the path. |