mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
proc: show file flags in fdinfo
Currently, there is an attempt to print FD flags, but
they are not decoded into a number, so we see something like this:
/criu # cat /proc/self/fdinfo/0
flags: {%!o(bool=000false)}
Actually, fdinfo has to contain file flags.
Change-Id: Idcbb7db908067447eb9ae6f2c3cfb861f2be1a97
PiperOrigin-RevId: 206794498
This commit is contained in:
@@ -14,6 +14,10 @@
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
// FileFlags encodes file flags.
|
||||
type FileFlags struct {
|
||||
// Direct indicates that I/O should be done directly.
|
||||
@@ -78,3 +82,38 @@ func (f FileFlags) Settable() SettableFileFlags {
|
||||
Async: f.Async,
|
||||
}
|
||||
}
|
||||
|
||||
// ToLinux converts a FileFlags object to a Linux representation.
|
||||
func (f FileFlags) ToLinux() (mask uint) {
|
||||
if f.Direct {
|
||||
mask |= linux.O_DIRECT
|
||||
}
|
||||
if f.NonBlocking {
|
||||
mask |= linux.O_NONBLOCK
|
||||
}
|
||||
if f.Sync {
|
||||
mask |= linux.O_SYNC
|
||||
}
|
||||
if f.Append {
|
||||
mask |= linux.O_APPEND
|
||||
}
|
||||
if f.Directory {
|
||||
mask |= linux.O_DIRECTORY
|
||||
}
|
||||
if f.Async {
|
||||
mask |= linux.O_ASYNC
|
||||
}
|
||||
if f.LargeFile {
|
||||
mask |= linux.O_LARGEFILE
|
||||
}
|
||||
|
||||
switch {
|
||||
case f.Read && f.Write:
|
||||
mask |= linux.O_RDWR
|
||||
case f.Write:
|
||||
mask |= linux.O_WRONLY
|
||||
case f.Read:
|
||||
mask |= linux.O_RDONLY
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -40,16 +40,16 @@ func walkDescriptors(t *kernel.Task, p string, toInode func(*fs.File, kernel.FDF
|
||||
}
|
||||
|
||||
var file *fs.File
|
||||
var flags kernel.FDFlags
|
||||
var fdFlags kernel.FDFlags
|
||||
t.WithMuLocked(func(t *kernel.Task) {
|
||||
if fdm := t.FDMap(); fdm != nil {
|
||||
file, flags = fdm.GetDescriptor(kdefs.FD(n))
|
||||
file, fdFlags = fdm.GetDescriptor(kdefs.FD(n))
|
||||
}
|
||||
})
|
||||
if file == nil {
|
||||
return nil, syserror.ENOENT
|
||||
}
|
||||
return toInode(file, flags), nil
|
||||
return toInode(file, fdFlags), nil
|
||||
}
|
||||
|
||||
// readDescriptors reads fds in the task starting at offset, and calls the
|
||||
@@ -200,17 +200,20 @@ func (f *fdDir) DeprecatedReaddir(ctx context.Context, dirCtx *fs.DirCtx, offset
|
||||
type fdInfo struct {
|
||||
ramfs.File
|
||||
|
||||
flags kernel.FDFlags
|
||||
flags fs.FileFlags
|
||||
fdFlags kernel.FDFlags
|
||||
}
|
||||
|
||||
// newFdInfo returns a new fdInfo based on an existing file.
|
||||
func newFdInfo(t *kernel.Task, _ *fs.File, flags kernel.FDFlags, msrc *fs.MountSource) *fs.Inode {
|
||||
fdi := &fdInfo{flags: flags}
|
||||
func newFdInfo(t *kernel.Task, file *fs.File, fdFlags kernel.FDFlags, msrc *fs.MountSource) *fs.Inode {
|
||||
fdi := &fdInfo{flags: file.Flags(), fdFlags: fdFlags}
|
||||
fdi.InitFile(t, fs.RootOwner, fs.FilePermissions{User: fs.PermMask{Read: true}})
|
||||
// TODO: Get pos, locks, and other data. For now we only
|
||||
// have flags.
|
||||
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
fdi.Append([]byte(fmt.Sprintf("flags: %08o\n", flags)))
|
||||
|
||||
flags := file.Flags().ToLinux() | fdFlags.ToLinuxFileFlags()
|
||||
fdi.Append([]byte(fmt.Sprintf("flags:\t0%o\n", flags)))
|
||||
return newFile(fdi, msrc, fs.SpecialFile, t)
|
||||
}
|
||||
|
||||
@@ -241,8 +244,8 @@ func newFdInfoDir(t *kernel.Task, msrc *fs.MountSource) *fs.Inode {
|
||||
|
||||
// Lookup loads an fd in /proc/TID/fdinfo into a Dirent.
|
||||
func (fdid *fdInfoDir) Lookup(ctx context.Context, dir *fs.Inode, p string) (*fs.Dirent, error) {
|
||||
n, err := walkDescriptors(fdid.t, p, func(file *fs.File, flags kernel.FDFlags) *fs.Inode {
|
||||
return newFdInfo(fdid.t, file, flags, dir.MountSource)
|
||||
n, err := walkDescriptors(fdid.t, p, func(file *fs.File, fdFlags kernel.FDFlags) *fs.Inode {
|
||||
return newFdInfo(fdid.t, file, fdFlags, dir.MountSource)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -51,6 +51,22 @@ type FDFlags struct {
|
||||
CloseOnExec bool
|
||||
}
|
||||
|
||||
// ToLinuxFileFlags converts a kernel.FDFlags object to a Linux file flags representation.
|
||||
func (f FDFlags) ToLinuxFileFlags() (mask uint) {
|
||||
if f.CloseOnExec {
|
||||
mask |= linux.O_CLOEXEC
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ToLinuxFDFlags converts a kernel.FDFlags object to a Linux descriptor flags representation.
|
||||
func (f FDFlags) ToLinuxFDFlags() (mask uint) {
|
||||
if f.CloseOnExec {
|
||||
mask |= linux.FD_CLOEXEC
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// descriptor holds the details about a file descriptor, namely a pointer the
|
||||
// file itself and the descriptor flags.
|
||||
type descriptor struct {
|
||||
|
||||
@@ -17,7 +17,6 @@ package linux
|
||||
import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
|
||||
)
|
||||
|
||||
// flagsToPermissions returns a Permissions object from Linux flags.
|
||||
@@ -35,48 +34,6 @@ func flagsToPermissions(mask uint) (p fs.PermMask) {
|
||||
return
|
||||
}
|
||||
|
||||
// fdFlagsToLinux converts a kernel.FDFlags object to a Linux representation.
|
||||
func fdFlagsToLinux(flags kernel.FDFlags) (mask uint) {
|
||||
if flags.CloseOnExec {
|
||||
mask |= linux.FD_CLOEXEC
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// flagsToLinux converts a FileFlags object to a Linux representation.
|
||||
func flagsToLinux(flags fs.FileFlags) (mask uint) {
|
||||
if flags.Direct {
|
||||
mask |= linux.O_DIRECT
|
||||
}
|
||||
if flags.NonBlocking {
|
||||
mask |= linux.O_NONBLOCK
|
||||
}
|
||||
if flags.Sync {
|
||||
mask |= linux.O_SYNC
|
||||
}
|
||||
if flags.Append {
|
||||
mask |= linux.O_APPEND
|
||||
}
|
||||
if flags.Directory {
|
||||
mask |= linux.O_DIRECTORY
|
||||
}
|
||||
if flags.Async {
|
||||
mask |= linux.O_ASYNC
|
||||
}
|
||||
if flags.LargeFile {
|
||||
mask |= linux.O_LARGEFILE
|
||||
}
|
||||
switch {
|
||||
case flags.Read && flags.Write:
|
||||
mask |= linux.O_RDWR
|
||||
case flags.Write:
|
||||
mask |= linux.O_WRONLY
|
||||
case flags.Read:
|
||||
mask |= linux.O_RDONLY
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// linuxToFlags converts linux file flags to a FileFlags object.
|
||||
func linuxToFlags(mask uint) (flags fs.FileFlags) {
|
||||
return fs.FileFlags{
|
||||
|
||||
@@ -809,14 +809,14 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
|
||||
}
|
||||
return uintptr(fd), nil, nil
|
||||
case linux.F_GETFD:
|
||||
return uintptr(fdFlagsToLinux(flags)), nil, nil
|
||||
return uintptr(flags.ToLinuxFDFlags()), nil, nil
|
||||
case linux.F_SETFD:
|
||||
flags := args[2].Uint()
|
||||
t.FDMap().SetFlags(fd, kernel.FDFlags{
|
||||
CloseOnExec: flags&syscall.FD_CLOEXEC != 0,
|
||||
})
|
||||
case linux.F_GETFL:
|
||||
return uintptr(flagsToLinux(file.Flags())), nil, nil
|
||||
return uintptr(file.Flags().ToLinux()), nil, nil
|
||||
case linux.F_SETFL:
|
||||
flags := uint(args[2].Uint())
|
||||
file.SetFlags(linuxToSettableFlags(flags))
|
||||
|
||||
Reference in New Issue
Block a user