summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/memfs/directory.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fsimpl/memfs/directory.go')
-rw-r--r--pkg/sentry/fsimpl/memfs/directory.go55
1 files changed, 32 insertions, 23 deletions
diff --git a/pkg/sentry/fsimpl/memfs/directory.go b/pkg/sentry/fsimpl/memfs/directory.go
index b0c3ea39a..c52dc781c 100644
--- a/pkg/sentry/fsimpl/memfs/directory.go
+++ b/pkg/sentry/fsimpl/memfs/directory.go
@@ -23,23 +23,23 @@ import (
)
type directory struct {
- inode Inode
+ inode inode
// childList is a list containing (1) child Dentries and (2) fake Dentries
// (with inode == nil) that represent the iteration position of
// directoryFDs. childList is used to support directoryFD.IterDirents()
- // efficiently. childList is protected by Filesystem.mu.
+ // efficiently. childList is protected by filesystem.mu.
childList dentryList
}
-func (fs *Filesystem) newDirectory(creds *auth.Credentials, mode uint16) *Inode {
+func (fs *filesystem) newDirectory(creds *auth.Credentials, mode uint16) *inode {
dir := &directory{}
dir.inode.init(dir, fs, creds, mode)
dir.inode.nlink = 2 // from "." and parent directory or ".." for root
return &dir.inode
}
-func (i *Inode) isDir() bool {
+func (i *inode) isDir() bool {
_, ok := i.impl.(*directory)
return ok
}
@@ -48,8 +48,8 @@ type directoryFD struct {
fileDescription
vfs.DirectoryFileDescriptionDefaultImpl
- // Protected by Filesystem.mu.
- iter *Dentry
+ // Protected by filesystem.mu.
+ iter *dentry
off int64
}
@@ -68,7 +68,7 @@ func (fd *directoryFD) Release() {
// IterDirents implements vfs.FileDescriptionImpl.IterDirents.
func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback) error {
fs := fd.filesystem()
- d := fd.vfsfd.VirtualDentry().Dentry()
+ vfsd := fd.vfsfd.VirtualDentry().Dentry()
fs.mu.Lock()
defer fs.mu.Unlock()
@@ -77,7 +77,7 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
if !cb.Handle(vfs.Dirent{
Name: ".",
Type: linux.DT_DIR,
- Ino: d.Impl().(*Dentry).inode.ino,
+ Ino: vfsd.Impl().(*dentry).inode.ino,
Off: 0,
}) {
return nil
@@ -85,7 +85,7 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
fd.off++
}
if fd.off == 1 {
- parentInode := d.ParentOrSelf().Impl().(*Dentry).inode
+ parentInode := vfsd.ParentOrSelf().Impl().(*dentry).inode
if !cb.Handle(vfs.Dirent{
Name: "..",
Type: parentInode.direntType(),
@@ -97,12 +97,12 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
fd.off++
}
- dir := d.Impl().(*Dentry).inode.impl.(*directory)
- var child *Dentry
+ dir := vfsd.Impl().(*dentry).inode.impl.(*directory)
+ var child *dentry
if fd.iter == nil {
// Start iteration at the beginning of dir.
child = dir.childList.Front()
- fd.iter = &Dentry{}
+ fd.iter = &dentry{}
} else {
// Continue iteration from where we left off.
child = fd.iter.Next()
@@ -130,32 +130,41 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
// Seek implements vfs.FileDescriptionImpl.Seek.
func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) {
- if whence != linux.SEEK_SET {
- // TODO: Linux also allows SEEK_CUR.
+ fs := fd.filesystem()
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ switch whence {
+ case linux.SEEK_SET:
+ // Use offset as given.
+ case linux.SEEK_CUR:
+ offset += fd.off
+ default:
return 0, syserror.EINVAL
}
if offset < 0 {
return 0, syserror.EINVAL
}
+ // If the offset isn't changing (e.g. due to lseek(0, SEEK_CUR)), don't
+ // seek even if doing so might reposition the iterator due to concurrent
+ // mutation of the directory. Compare fs/libfs.c:dcache_dir_lseek().
+ if fd.off == offset {
+ return offset, nil
+ }
+
fd.off = offset
// Compensate for "." and "..".
- var remChildren int64
- if offset < 2 {
- remChildren = 0
- } else {
+ remChildren := int64(0)
+ if offset >= 2 {
remChildren = offset - 2
}
- fs := fd.filesystem()
dir := fd.inode().impl.(*directory)
- fs.mu.Lock()
- defer fs.mu.Unlock()
-
// Ensure that fd.iter exists and is not linked into dir.childList.
if fd.iter == nil {
- fd.iter = &Dentry{}
+ fd.iter = &dentry{}
} else {
dir.childList.Remove(fd.iter)
}