Set file mode and type to attribute

Makes less error prone to find file type.

Updates #1197

PiperOrigin-RevId: 302974244
This commit is contained in:
Fabricio Voznika 2020-03-25 14:44:18 -07:00 committed by gVisor bot
parent 2e09f2bdce
commit c7f5673529
6 changed files with 27 additions and 23 deletions

View File

@ -15,6 +15,8 @@
package tmpfs
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@ -33,6 +35,14 @@ func (fs *filesystem) newDeviceFile(creds *auth.Credentials, mode linux.FileMode
major: major,
minor: minor,
}
switch kind {
case vfs.BlockDevice:
mode |= linux.S_IFBLK
case vfs.CharDevice:
mode |= linux.S_IFCHR
default:
panic(fmt.Sprintf("invalid DeviceKind: %v", kind))
}
file.inode.init(file, fs, creds, mode)
file.inode.nlink = 1 // from parent directory
return &file.inode

View File

@ -34,16 +34,11 @@ type directory struct {
func (fs *filesystem) newDirectory(creds *auth.Credentials, mode linux.FileMode) *inode {
dir := &directory{}
dir.inode.init(dir, fs, creds, mode)
dir.inode.init(dir, fs, creds, linux.S_IFDIR|mode)
dir.inode.nlink = 2 // from "." and parent directory or ".." for root
return &dir.inode
}
func (i *inode) isDir() bool {
_, ok := i.impl.(*directory)
return ok
}
type directoryFD struct {
fileDescription
vfs.DirectoryFileDescriptionDefaultImpl

View File

@ -34,7 +34,7 @@ type namedPipe struct {
// * rp.Mount().CheckBeginWrite() has been called successfully.
func (fs *filesystem) newNamedPipe(creds *auth.Credentials, mode linux.FileMode) *inode {
file := &namedPipe{pipe: pipe.NewVFSPipe(pipe.DefaultPipeSize, usermem.PageSize)}
file.inode.init(file, fs, creds, mode)
file.inode.init(file, fs, creds, linux.S_IFIFO|mode)
file.inode.nlink = 1 // Only the parent has a link.
return &file.inode
}

View File

@ -89,7 +89,7 @@ func (fs *filesystem) newRegularFile(creds *auth.Credentials, mode linux.FileMod
file := &regularFile{
memFile: fs.memFile,
}
file.inode.init(file, fs, creds, mode)
file.inode.init(file, fs, creds, linux.S_IFREG|mode)
file.inode.nlink = 1 // from parent directory
return &file.inode
}

View File

@ -15,6 +15,7 @@
package tmpfs
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
)
@ -27,7 +28,7 @@ func (fs *filesystem) newSymlink(creds *auth.Credentials, target string) *inode
link := &symlink{
target: target,
}
link.inode.init(link, fs, creds, 0777)
link.inode.init(link, fs, creds, linux.S_IFLNK|0777)
link.inode.nlink = 1 // from parent directory
return &link.inode
}

View File

@ -144,7 +144,7 @@ type inode struct {
// Inode metadata. Writing multiple fields atomically requires holding
// mu, othewise atomic operations can be used.
mu sync.Mutex
mode uint32 // excluding file type bits, which are based on impl
mode uint32 // file type and mode
nlink uint32 // protected by filesystem.mu instead of inode.mu
uid uint32 // auth.KUID, but stored as raw uint32 for sync/atomic
gid uint32 // auth.KGID, but ...
@ -168,6 +168,9 @@ type inode struct {
const maxLinks = math.MaxUint32
func (i *inode) init(impl interface{}, fs *filesystem, creds *auth.Credentials, mode linux.FileMode) {
if mode.FileType() == 0 {
panic("file type is required in FileMode")
}
i.clock = fs.clock
i.refs = 1
i.mode = uint32(mode)
@ -269,31 +272,21 @@ func (i *inode) statTo(stat *linux.Statx) {
// TODO(gvisor.dev/issues/1197): Device number.
switch impl := i.impl.(type) {
case *regularFile:
stat.Mode |= linux.S_IFREG
stat.Mask |= linux.STATX_SIZE | linux.STATX_BLOCKS
stat.Size = uint64(atomic.LoadUint64(&impl.size))
// In tmpfs, this will be FileRangeSet.Span() / 512 (but also cached in
// a uint64 accessed using atomic memory operations to avoid taking
// locks).
stat.Blocks = allocatedBlocksForSize(stat.Size)
case *directory:
stat.Mode |= linux.S_IFDIR
case *symlink:
stat.Mode |= linux.S_IFLNK
stat.Mask |= linux.STATX_SIZE | linux.STATX_BLOCKS
stat.Size = uint64(len(impl.target))
stat.Blocks = allocatedBlocksForSize(stat.Size)
case *namedPipe:
stat.Mode |= linux.S_IFIFO
case *deviceFile:
switch impl.kind {
case vfs.BlockDevice:
stat.Mode |= linux.S_IFBLK
case vfs.CharDevice:
stat.Mode |= linux.S_IFCHR
}
stat.RdevMajor = impl.major
stat.RdevMinor = impl.minor
case *directory, *namedPipe:
// Nothing to do.
default:
panic(fmt.Sprintf("unknown inode type: %T", i.impl))
}
@ -316,7 +309,8 @@ func (i *inode) setStat(ctx context.Context, creds *auth.Credentials, stat *linu
)
mask := stat.Mask
if mask&linux.STATX_MODE != 0 {
atomic.StoreUint32(&i.mode, uint32(stat.Mode))
ft := atomic.LoadUint32(&i.mode) & linux.S_IFMT
atomic.StoreUint32(&i.mode, ft|uint32(stat.Mode&^linux.S_IFMT))
needsCtimeBump = true
}
if mask&linux.STATX_UID != 0 {
@ -439,6 +433,10 @@ func (i *inode) direntType() uint8 {
}
}
func (i *inode) isDir() bool {
return linux.FileMode(i.mode).FileType() == linux.S_IFDIR
}
// fileDescription is embedded by tmpfs implementations of
// vfs.FileDescriptionImpl.
type fileDescription struct {