mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
switch fsimpl/ from sync/atomic to atomicbitops for 32 bit values
PiperOrigin-RevId: 443535714
This commit is contained in:
committed by
gVisor bot
parent
3b917921d7
commit
9050184c20
@@ -75,7 +75,7 @@ type connection struct {
|
||||
// initialized after receiving FUSE_INIT reply.
|
||||
// Until it's set, suspend sending FUSE requests.
|
||||
// Use SetInitialized() and IsInitialized() for atomic access.
|
||||
initialized int32
|
||||
initialized atomicbitops.Int32
|
||||
|
||||
// initializedChan is used to block requests before initialization.
|
||||
initializedChan chan struct{} `state:".(bool)"`
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
@@ -65,13 +63,13 @@ func (conn *connection) SetInitialized() {
|
||||
// And it prevents the newer tasks from gaining
|
||||
// unnecessary higher chance to be issued before the blocked one.
|
||||
|
||||
atomic.StoreInt32(&(conn.initialized), int32(1))
|
||||
conn.initialized.Store(1)
|
||||
}
|
||||
|
||||
// IsInitialized atomically check if the connection is initialized.
|
||||
// pairs with SetInitialized().
|
||||
// Initialized atomically check if the connection is initialized. pairs with
|
||||
// SetInitialized().
|
||||
func (conn *connection) Initialized() bool {
|
||||
return atomic.LoadInt32(&(conn.initialized)) != 0
|
||||
return conn.initialized.Load() != 0
|
||||
}
|
||||
|
||||
// InitSend sends a FUSE_INIT request.
|
||||
|
||||
@@ -16,7 +16,6 @@ package gofer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
@@ -116,18 +115,18 @@ func (d *dentry) createSyntheticChildLocked(opts *createSyntheticOpts) {
|
||||
refs: atomicbitops.FromInt64(1), // held by d
|
||||
fs: d.fs,
|
||||
ino: d.fs.nextIno(),
|
||||
mode: uint32(opts.mode),
|
||||
uid: uint32(opts.kuid),
|
||||
gid: uint32(opts.kgid),
|
||||
blockSize: hostarch.PageSize, // arbitrary
|
||||
mode: atomicbitops.FromUint32(uint32(opts.mode)),
|
||||
uid: atomicbitops.FromUint32(uint32(opts.kuid)),
|
||||
gid: atomicbitops.FromUint32(uint32(opts.kgid)),
|
||||
blockSize: atomicbitops.FromUint32(hostarch.PageSize), // arbitrary
|
||||
atime: atomicbitops.FromInt64(now),
|
||||
mtime: atomicbitops.FromInt64(now),
|
||||
ctime: atomicbitops.FromInt64(now),
|
||||
btime: atomicbitops.FromInt64(now),
|
||||
readFD: -1,
|
||||
writeFD: -1,
|
||||
mmapFD: -1,
|
||||
nlink: uint32(2),
|
||||
readFD: atomicbitops.FromInt32(-1),
|
||||
writeFD: atomicbitops.FromInt32(-1),
|
||||
mmapFD: atomicbitops.FromInt32(-1),
|
||||
nlink: atomicbitops.FromUint32(2),
|
||||
}
|
||||
refsvfs2.Register(child)
|
||||
switch opts.mode.FileType() {
|
||||
@@ -228,7 +227,7 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
|
||||
},
|
||||
{
|
||||
Name: "..",
|
||||
Type: uint8(atomic.LoadUint32(&parent.mode) >> 12),
|
||||
Type: uint8(parent.mode.Load() >> 12),
|
||||
Ino: uint64(parent.ino),
|
||||
NextOff: 2,
|
||||
},
|
||||
@@ -338,7 +337,7 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
|
||||
}
|
||||
dirents = append(dirents, vfs.Dirent{
|
||||
Name: child.name,
|
||||
Type: uint8(atomic.LoadUint32(&child.mode) >> 12),
|
||||
Type: uint8(child.mode.Load() >> 12),
|
||||
Ino: uint64(child.ino),
|
||||
NextOff: int64(len(dirents) + 1),
|
||||
})
|
||||
|
||||
@@ -19,10 +19,10 @@ import (
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
@@ -625,7 +625,7 @@ func (fs *filesystem) unlinkAt(ctx context.Context, rp *vfs.ResolvingPath, dir b
|
||||
// Load child if sticky bit is set because we need to determine whether
|
||||
// deletion is allowed.
|
||||
var child *dentry
|
||||
if atomic.LoadUint32(&parent.mode)&linux.ModeSticky == 0 {
|
||||
if parent.mode.Load()&linux.ModeSticky == 0 {
|
||||
var ok bool
|
||||
child, ok = parent.children[name]
|
||||
if ok && child == nil {
|
||||
@@ -821,16 +821,16 @@ func (fs *filesystem) LinkAt(ctx context.Context, rp *vfs.ResolvingPath, vd vfs.
|
||||
if d.isDir() {
|
||||
return linuxerr.EPERM
|
||||
}
|
||||
gid := auth.KGID(atomic.LoadUint32(&d.gid))
|
||||
uid := auth.KUID(atomic.LoadUint32(&d.uid))
|
||||
mode := linux.FileMode(atomic.LoadUint32(&d.mode))
|
||||
gid := auth.KGID(d.gid.Load())
|
||||
uid := auth.KUID(d.uid.Load())
|
||||
mode := linux.FileMode(d.mode.Load())
|
||||
if err := vfs.MayLink(rp.Credentials(), mode, uid, gid); err != nil {
|
||||
return err
|
||||
}
|
||||
if d.nlink == 0 {
|
||||
if d.nlink.Load() == 0 {
|
||||
return linuxerr.ENOENT
|
||||
}
|
||||
if d.nlink == math.MaxUint32 {
|
||||
if d.nlink.Load() == math.MaxUint32 {
|
||||
return linuxerr.EMLINK
|
||||
}
|
||||
if fs.opts.lisaEnabled {
|
||||
@@ -858,8 +858,8 @@ func (fs *filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
|
||||
// rather than the caller's and enable setgid.
|
||||
kgid := creds.EffectiveKGID
|
||||
mode := opts.Mode
|
||||
if atomic.LoadUint32(&parent.mode)&linux.S_ISGID != 0 {
|
||||
kgid = auth.KGID(atomic.LoadUint32(&parent.gid))
|
||||
if parent.mode.Load()&linux.S_ISGID != 0 {
|
||||
kgid = auth.KGID(parent.gid.Load())
|
||||
mode |= linux.S_ISGID
|
||||
}
|
||||
var err error
|
||||
@@ -1130,7 +1130,7 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.Open
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if atomic.LoadInt32(&d.readFD) >= 0 {
|
||||
if d.readFD.Load() >= 0 {
|
||||
fsmetric.GoferOpensHost.Increment()
|
||||
} else {
|
||||
fsmetric.GoferOpens9P.Increment()
|
||||
@@ -1280,8 +1280,8 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
||||
// If the parent is a setgid directory, use the parent's GID rather
|
||||
// than the caller's.
|
||||
kgid := creds.EffectiveKGID
|
||||
if atomic.LoadUint32(&d.mode)&linux.S_ISGID != 0 {
|
||||
kgid = auth.KGID(atomic.LoadUint32(&d.gid))
|
||||
if d.mode.Load()&linux.S_ISGID != 0 {
|
||||
kgid = auth.KGID(d.gid.Load())
|
||||
}
|
||||
|
||||
var child *dentry
|
||||
@@ -1357,14 +1357,14 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
||||
child.readFile = openP9File
|
||||
child.readFDLisa = d.fs.clientLisa.NewFD(openLisaFD)
|
||||
if openHostFD != -1 {
|
||||
child.readFD = openHostFD
|
||||
child.mmapFD = openHostFD
|
||||
child.readFD = atomicbitops.FromInt32(openHostFD)
|
||||
child.mmapFD = atomicbitops.FromInt32(openHostFD)
|
||||
}
|
||||
}
|
||||
if vfs.MayWriteFileWithOpenFlags(opts.Flags) {
|
||||
child.writeFile = openP9File
|
||||
child.writeFDLisa = d.fs.clientLisa.NewFD(openLisaFD)
|
||||
child.writeFD = openHostFD
|
||||
child.writeFD = atomicbitops.FromInt32(openHostFD)
|
||||
}
|
||||
child.handleMu.Unlock()
|
||||
}
|
||||
|
||||
+139
-137
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
@@ -59,10 +58,10 @@ func newRegularFileFD(mnt *vfs.Mount, d *dentry, flags uint32) (*regularFileFD,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fd.vfsfd.IsWritable() && (atomic.LoadUint32(&d.mode)&0111 != 0) {
|
||||
if fd.vfsfd.IsWritable() && (d.mode.Load()&0111 != 0) {
|
||||
metric.SuspiciousOperationsMetric.Increment("opened_write_execute_file")
|
||||
}
|
||||
if atomic.LoadInt32(&d.mmapFD) >= 0 {
|
||||
if d.mmapFD.Load() >= 0 {
|
||||
fsmetric.GoferOpensHost.Increment()
|
||||
} else {
|
||||
fsmetric.GoferOpens9P.Increment()
|
||||
@@ -128,7 +127,7 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
||||
start := fsmetric.StartReadWait()
|
||||
d := fd.dentry()
|
||||
defer func() {
|
||||
if atomic.LoadInt32(&d.readFD) >= 0 {
|
||||
if d.readFD.Load() >= 0 {
|
||||
fsmetric.GoferReadsHost.Increment()
|
||||
fsmetric.FinishReadWait(fsmetric.GoferReadWaitHost, start)
|
||||
} else {
|
||||
@@ -286,11 +285,11 @@ func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off
|
||||
|
||||
// As with Linux, writing clears the setuid and setgid bits.
|
||||
if n > 0 {
|
||||
oldMode := atomic.LoadUint32(&d.mode)
|
||||
oldMode := d.mode.Load()
|
||||
// If setuid or setgid were set, update d.mode and propagate
|
||||
// changes to the host.
|
||||
if newMode := vfs.ClearSUIDAndSGID(oldMode); newMode != oldMode {
|
||||
atomic.StoreUint32(&d.mode, newMode)
|
||||
d.mode.Store(newMode)
|
||||
if d.fs.opts.lisaEnabled {
|
||||
stat := linux.Statx{Mask: linux.STATX_MODE, Mode: uint16(newMode)}
|
||||
failureMask, failureErr, err := d.controlFDLisa.SetStat(ctx, &stat)
|
||||
@@ -399,7 +398,7 @@ func (rw *dentryReadWriter) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error)
|
||||
// dentry.readHandleLocked() without locking dentry.dataMu.
|
||||
rw.d.handleMu.RLock()
|
||||
h := rw.d.readHandleLocked()
|
||||
if (rw.d.mmapFD >= 0 && !rw.d.fs.opts.forcePageCache) || rw.d.fs.opts.interop == InteropModeShared || rw.direct {
|
||||
if (rw.d.mmapFD.RacyLoad() >= 0 && !rw.d.fs.opts.forcePageCache) || rw.d.fs.opts.interop == InteropModeShared || rw.direct {
|
||||
n, err := h.readToBlocksAt(rw.ctx, dsts, rw.off)
|
||||
rw.d.handleMu.RUnlock()
|
||||
rw.off += n
|
||||
@@ -519,7 +518,7 @@ func (rw *dentryReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, erro
|
||||
// without locking dentry.dataMu.
|
||||
rw.d.handleMu.RLock()
|
||||
h := rw.d.writeHandleLocked()
|
||||
if (rw.d.mmapFD >= 0 && !rw.d.fs.opts.forcePageCache) || rw.d.fs.opts.interop == InteropModeShared || rw.direct {
|
||||
if (rw.d.mmapFD.RacyLoad() >= 0 && !rw.d.fs.opts.forcePageCache) || rw.d.fs.opts.interop == InteropModeShared || rw.direct {
|
||||
n, err := h.writeFromBlocksAt(rw.ctx, srcs, rw.off)
|
||||
rw.off += n
|
||||
rw.d.dataMu.Lock()
|
||||
@@ -720,7 +719,7 @@ func (fd *regularFileFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpt
|
||||
case InteropModeShared:
|
||||
// All mappings require a host FD to be coherent with other
|
||||
// filesystem users.
|
||||
if atomic.LoadInt32(&d.mmapFD) < 0 {
|
||||
if d.mmapFD.Load() < 0 {
|
||||
return linuxerr.ENODEV
|
||||
}
|
||||
default:
|
||||
@@ -790,7 +789,7 @@ func (d *dentry) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR,
|
||||
// Translate implements memmap.Mappable.Translate.
|
||||
func (d *dentry) Translate(ctx context.Context, required, optional memmap.MappableRange, at hostarch.AccessType) ([]memmap.Translation, error) {
|
||||
d.handleMu.RLock()
|
||||
if d.mmapFD >= 0 && !d.fs.opts.forcePageCache {
|
||||
if d.mmapFD.RacyLoad() >= 0 && !d.fs.opts.forcePageCache {
|
||||
d.handleMu.RUnlock()
|
||||
mr := optional
|
||||
if d.fs.opts.limitHostFDTranslation {
|
||||
@@ -981,12 +980,12 @@ func (d *dentryPlatformFile) DecRef(fr memmap.FileRange) {
|
||||
func (d *dentryPlatformFile) MapInternal(fr memmap.FileRange, at hostarch.AccessType) (safemem.BlockSeq, error) {
|
||||
d.handleMu.RLock()
|
||||
defer d.handleMu.RUnlock()
|
||||
return d.hostFileMapper.MapInternal(fr, int(d.mmapFD), at.Write)
|
||||
return d.hostFileMapper.MapInternal(fr, int(d.mmapFD.RacyLoad()), at.Write)
|
||||
}
|
||||
|
||||
// FD implements memmap.File.FD.
|
||||
func (d *dentryPlatformFile) FD() int {
|
||||
d.handleMu.RLock()
|
||||
defer d.handleMu.RUnlock()
|
||||
return int(d.mmapFD)
|
||||
return int(d.mmapFD.RacyLoad())
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ package gofer
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
@@ -100,7 +100,7 @@ func (fd *specialFileFD) savePipeData(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
if len(fd.buf) != 0 {
|
||||
atomic.StoreUint32(&fd.haveBuf, 1)
|
||||
fd.haveBuf.Store(1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -149,9 +149,9 @@ func (d *dentry) beforeSave() {
|
||||
|
||||
// afterLoad is invoked by stateify.
|
||||
func (d *dentry) afterLoad() {
|
||||
d.readFD = -1
|
||||
d.writeFD = -1
|
||||
d.mmapFD = -1
|
||||
d.readFD = atomicbitops.FromInt32(-1)
|
||||
d.writeFD = atomicbitops.FromInt32(-1)
|
||||
d.mmapFD = atomicbitops.FromInt32(-1)
|
||||
if d.refs.Load() != -1 {
|
||||
refsvfs2.Register(d)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ package gofer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
@@ -74,10 +74,9 @@ type specialFileFD struct {
|
||||
|
||||
// If haveBuf is non-zero, this FD represents a pipe, and buf contains data
|
||||
// read from the pipe from previous calls to specialFileFD.savePipeData().
|
||||
// haveBuf and buf are protected by bufMu. haveBuf is accessed using atomic
|
||||
// memory operations.
|
||||
// haveBuf and buf are protected by bufMu.
|
||||
bufMu sync.Mutex `state:"nosave"`
|
||||
haveBuf uint32
|
||||
haveBuf atomicbitops.Uint32
|
||||
buf []byte
|
||||
|
||||
// If handle.fd >= 0, hostFileMapper caches mappings of handle.fd, and
|
||||
@@ -119,7 +118,7 @@ func newSpecialFileFD(h handle, mnt *vfs.Mount, d *dentry, flags uint32) (*speci
|
||||
d.fs.syncMu.Lock()
|
||||
d.fs.specialFileFDs[fd] = struct{}{}
|
||||
d.fs.syncMu.Unlock()
|
||||
if fd.vfsfd.IsWritable() && (atomic.LoadUint32(&d.mode)&0111 != 0) {
|
||||
if fd.vfsfd.IsWritable() && (d.mode.Load()&0111 != 0) {
|
||||
metric.SuspiciousOperationsMetric.Increment("opened_write_execute_file")
|
||||
}
|
||||
if h.fd >= 0 {
|
||||
@@ -239,7 +238,7 @@ func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
||||
}
|
||||
|
||||
bufN := int64(0)
|
||||
if atomic.LoadUint32(&fd.haveBuf) != 0 {
|
||||
if fd.haveBuf.Load() != 0 {
|
||||
var err error
|
||||
fd.bufMu.Lock()
|
||||
if len(fd.buf) != 0 {
|
||||
@@ -248,7 +247,7 @@ func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
||||
dst = dst.DropFirst(n)
|
||||
fd.buf = fd.buf[n:]
|
||||
if len(fd.buf) == 0 {
|
||||
atomic.StoreUint32(&fd.haveBuf, 0)
|
||||
fd.haveBuf.Store(0)
|
||||
fd.buf = nil
|
||||
}
|
||||
bufN = int64(n)
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
package gofer
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
@@ -40,7 +38,7 @@ func (d *dentry) touchAtime(mnt *vfs.Mount) {
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
d.metadataMu.Lock()
|
||||
d.atime.Store(now)
|
||||
atomic.StoreUint32(&d.atimeDirty, 1)
|
||||
d.atimeDirty.Store(1)
|
||||
d.metadataMu.Unlock()
|
||||
mnt.EndWrite()
|
||||
}
|
||||
@@ -55,7 +53,7 @@ func (d *dentry) touchAtimeLocked(mnt *vfs.Mount) {
|
||||
}
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
d.atime.Store(now)
|
||||
atomic.StoreUint32(&d.atimeDirty, 1)
|
||||
d.atimeDirty.Store(1)
|
||||
mnt.EndWrite()
|
||||
}
|
||||
|
||||
@@ -77,7 +75,7 @@ func (d *dentry) touchCMtime() {
|
||||
d.metadataMu.Lock()
|
||||
d.mtime.Store(now)
|
||||
d.ctime.Store(now)
|
||||
atomic.StoreUint32(&d.mtimeDirty, 1)
|
||||
d.mtimeDirty.Store(1)
|
||||
d.metadataMu.Unlock()
|
||||
}
|
||||
|
||||
@@ -88,5 +86,5 @@ func (d *dentry) touchCMtimeLocked() {
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
d.mtime.Store(now)
|
||||
d.ctime.Store(now)
|
||||
atomic.StoreUint32(&d.mtimeDirty, 1)
|
||||
d.mtimeDirty.Store(1)
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ package host
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
@@ -55,23 +55,23 @@ type virtualOwner struct {
|
||||
// mu protects the fields below and they can be accessed using atomic memory
|
||||
// operations.
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
uid uint32
|
||||
gid uint32
|
||||
uid atomicbitops.Uint32
|
||||
gid atomicbitops.Uint32
|
||||
// mode is also stored, otherwise setting the host file to `0000` could remove
|
||||
// access to the file.
|
||||
mode uint32
|
||||
mode atomicbitops.Uint32
|
||||
}
|
||||
|
||||
func (v *virtualOwner) atomicUID() uint32 {
|
||||
return atomic.LoadUint32(&v.uid)
|
||||
return v.uid.Load()
|
||||
}
|
||||
|
||||
func (v *virtualOwner) atomicGID() uint32 {
|
||||
return atomic.LoadUint32(&v.gid)
|
||||
return v.gid.Load()
|
||||
}
|
||||
|
||||
func (v *virtualOwner) atomicMode() uint32 {
|
||||
return atomic.LoadUint32(&v.mode)
|
||||
return v.mode.Load()
|
||||
}
|
||||
|
||||
func isEpollable(fd int) bool {
|
||||
@@ -153,10 +153,9 @@ type inode struct {
|
||||
|
||||
// If haveBuf is non-zero, hostFD represents a pipe, and buf contains data
|
||||
// read from the pipe from previous calls to inode.beforeSave(). haveBuf
|
||||
// and buf are protected by bufMu. haveBuf is accessed using atomic memory
|
||||
// operations.
|
||||
// and buf are protected by bufMu.
|
||||
bufMu sync.Mutex `state:"nosave"`
|
||||
haveBuf uint32
|
||||
haveBuf atomicbitops.Uint32
|
||||
buf []byte
|
||||
}
|
||||
|
||||
@@ -249,9 +248,9 @@ func NewFD(ctx context.Context, mnt *vfs.Mount, hostFD int, opts *NewFDOptions)
|
||||
}
|
||||
if opts.VirtualOwner {
|
||||
i.virtualOwner.enabled = true
|
||||
i.virtualOwner.uid = uint32(opts.UID)
|
||||
i.virtualOwner.gid = uint32(opts.GID)
|
||||
i.virtualOwner.mode = stat.Mode
|
||||
i.virtualOwner.uid = atomicbitops.FromUint32(uint32(opts.UID))
|
||||
i.virtualOwner.gid = atomicbitops.FromUint32(uint32(opts.GID))
|
||||
i.virtualOwner.mode = atomicbitops.FromUint32(stat.Mode)
|
||||
}
|
||||
|
||||
d := &kernfs.Dentry{}
|
||||
@@ -521,7 +520,8 @@ func (i *inode) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Cre
|
||||
|
||||
if m&linux.STATX_MODE != 0 {
|
||||
if i.virtualOwner.enabled {
|
||||
i.virtualOwner.mode = uint32(opts.Stat.Mode)
|
||||
// We hold i.virtualOwner.mu.
|
||||
i.virtualOwner.mode = atomicbitops.FromUint32(uint32(opts.Stat.Mode))
|
||||
} else {
|
||||
if err := unix.Fchmod(i.hostFD, uint32(s.Mode)); err != nil {
|
||||
return err
|
||||
@@ -555,10 +555,12 @@ func (i *inode) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Cre
|
||||
}
|
||||
if i.virtualOwner.enabled {
|
||||
if m&linux.STATX_UID != 0 {
|
||||
i.virtualOwner.uid = opts.Stat.UID
|
||||
// We hold i.virtualOwner.mu.
|
||||
i.virtualOwner.uid = atomicbitops.FromUint32(opts.Stat.UID)
|
||||
}
|
||||
if m&linux.STATX_GID != 0 {
|
||||
i.virtualOwner.gid = opts.Stat.GID
|
||||
// We hold i.virtualOwner.mu.
|
||||
i.virtualOwner.gid = atomicbitops.FromUint32(opts.Stat.GID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -757,7 +759,7 @@ func (f *fileDescription) Read(ctx context.Context, dst usermem.IOSequence, opts
|
||||
}
|
||||
|
||||
func (i *inode) readFromBuf(ctx context.Context, dst *usermem.IOSequence) (int64, error) {
|
||||
if atomic.LoadUint32(&i.haveBuf) == 0 {
|
||||
if i.haveBuf.Load() == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
i.bufMu.Lock()
|
||||
@@ -769,7 +771,7 @@ func (i *inode) readFromBuf(ctx context.Context, dst *usermem.IOSequence) (int64
|
||||
*dst = dst.DropFirst(n)
|
||||
i.buf = i.buf[n:]
|
||||
if len(i.buf) == 0 {
|
||||
atomic.StoreUint32(&i.haveBuf, 0)
|
||||
i.haveBuf.Store(0)
|
||||
i.buf = nil
|
||||
}
|
||||
return int64(n), err
|
||||
|
||||
@@ -17,7 +17,6 @@ package host
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
@@ -52,7 +51,7 @@ func (i *inode) beforeSave() {
|
||||
}
|
||||
}
|
||||
if len(i.buf) != 0 {
|
||||
atomic.StoreUint32(&i.haveBuf, 1)
|
||||
i.haveBuf.Store(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package kernfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
@@ -178,11 +177,11 @@ type InodeAttrs struct {
|
||||
devMajor uint32
|
||||
devMinor uint32
|
||||
ino atomicbitops.Uint64
|
||||
mode uint32
|
||||
uid uint32
|
||||
gid uint32
|
||||
nlink uint32
|
||||
blockSize uint32
|
||||
mode atomicbitops.Uint32
|
||||
uid atomicbitops.Uint32
|
||||
gid atomicbitops.Uint32
|
||||
nlink atomicbitops.Uint32
|
||||
blockSize atomicbitops.Uint32
|
||||
|
||||
// Timestamps, all nsecs from the Unix epoch.
|
||||
atime atomicbitops.Int64
|
||||
@@ -203,11 +202,11 @@ func (a *InodeAttrs) Init(ctx context.Context, creds *auth.Credentials, devMajor
|
||||
a.devMajor = devMajor
|
||||
a.devMinor = devMinor
|
||||
a.ino.Store(ino)
|
||||
atomic.StoreUint32(&a.mode, uint32(mode))
|
||||
atomic.StoreUint32(&a.uid, uint32(creds.EffectiveKUID))
|
||||
atomic.StoreUint32(&a.gid, uint32(creds.EffectiveKGID))
|
||||
atomic.StoreUint32(&a.nlink, nlink)
|
||||
atomic.StoreUint32(&a.blockSize, hostarch.PageSize)
|
||||
a.mode.Store(uint32(mode))
|
||||
a.uid.Store(uint32(creds.EffectiveKUID))
|
||||
a.gid.Store(uint32(creds.EffectiveKGID))
|
||||
a.nlink.Store(nlink)
|
||||
a.blockSize.Store(hostarch.PageSize)
|
||||
now := ktime.NowFromContext(ctx).Nanoseconds()
|
||||
a.atime.Store(now)
|
||||
a.mtime.Store(now)
|
||||
@@ -231,12 +230,12 @@ func (a *InodeAttrs) Ino() uint64 {
|
||||
|
||||
// Mode implements Inode.Mode.
|
||||
func (a *InodeAttrs) Mode() linux.FileMode {
|
||||
return linux.FileMode(atomic.LoadUint32(&a.mode))
|
||||
return linux.FileMode(a.mode.Load())
|
||||
}
|
||||
|
||||
// Links returns the link count.
|
||||
func (a *InodeAttrs) Links() uint32 {
|
||||
return atomic.LoadUint32(&a.nlink)
|
||||
return a.nlink.Load()
|
||||
}
|
||||
|
||||
// TouchAtime updates a.atime to the current time.
|
||||
@@ -270,10 +269,10 @@ func (a *InodeAttrs) Stat(context.Context, *vfs.Filesystem, vfs.StatOptions) (li
|
||||
stat.DevMinor = a.devMinor
|
||||
stat.Ino = a.ino.Load()
|
||||
stat.Mode = uint16(a.Mode())
|
||||
stat.UID = atomic.LoadUint32(&a.uid)
|
||||
stat.GID = atomic.LoadUint32(&a.gid)
|
||||
stat.Nlink = atomic.LoadUint32(&a.nlink)
|
||||
stat.Blksize = atomic.LoadUint32(&a.blockSize)
|
||||
stat.UID = a.uid.Load()
|
||||
stat.GID = a.gid.Load()
|
||||
stat.Nlink = a.nlink.Load()
|
||||
stat.Blksize = a.blockSize.Load()
|
||||
stat.Atime = linux.NsecToStatxTimestamp(a.atime.Load())
|
||||
stat.Mtime = linux.NsecToStatxTimestamp(a.mtime.Load())
|
||||
stat.Ctime = linux.NsecToStatxTimestamp(a.ctime.Load())
|
||||
@@ -296,29 +295,29 @@ func (a *InodeAttrs) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *aut
|
||||
if opts.Stat.Mask&linux.STATX_SIZE != 0 && a.Mode().IsDir() {
|
||||
return linuxerr.EISDIR
|
||||
}
|
||||
if err := vfs.CheckSetStat(ctx, creds, &opts, a.Mode(), auth.KUID(atomic.LoadUint32(&a.uid)), auth.KGID(atomic.LoadUint32(&a.gid))); err != nil {
|
||||
if err := vfs.CheckSetStat(ctx, creds, &opts, a.Mode(), auth.KUID(a.uid.Load()), auth.KGID(a.gid.Load())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clearSID := false
|
||||
stat := opts.Stat
|
||||
if stat.Mask&linux.STATX_UID != 0 {
|
||||
atomic.StoreUint32(&a.uid, stat.UID)
|
||||
a.uid.Store(stat.UID)
|
||||
clearSID = true
|
||||
}
|
||||
if stat.Mask&linux.STATX_GID != 0 {
|
||||
atomic.StoreUint32(&a.gid, stat.GID)
|
||||
a.gid.Store(stat.GID)
|
||||
clearSID = true
|
||||
}
|
||||
if stat.Mask&linux.STATX_MODE != 0 {
|
||||
for {
|
||||
old := atomic.LoadUint32(&a.mode)
|
||||
old := a.mode.Load()
|
||||
ft := old & linux.S_IFMT
|
||||
newMode := ft | uint32(stat.Mode & ^uint16(linux.S_IFMT))
|
||||
if clearSID {
|
||||
newMode = vfs.ClearSUIDAndSGID(newMode)
|
||||
}
|
||||
if swapped := atomic.CompareAndSwapUint32(&a.mode, old, newMode); swapped {
|
||||
if swapped := a.mode.CompareAndSwap(old, newMode); swapped {
|
||||
clearSID = false
|
||||
break
|
||||
}
|
||||
@@ -329,9 +328,9 @@ func (a *InodeAttrs) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *aut
|
||||
// STATX_MODE.
|
||||
if clearSID {
|
||||
for {
|
||||
old := atomic.LoadUint32(&a.mode)
|
||||
old := a.mode.Load()
|
||||
newMode := vfs.ClearSUIDAndSGID(old)
|
||||
if swapped := atomic.CompareAndSwapUint32(&a.mode, old, newMode); swapped {
|
||||
if swapped := a.mode.CompareAndSwap(old, newMode); swapped {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -360,21 +359,21 @@ func (a *InodeAttrs) CheckPermissions(_ context.Context, creds *auth.Credentials
|
||||
creds,
|
||||
ats,
|
||||
a.Mode(),
|
||||
auth.KUID(atomic.LoadUint32(&a.uid)),
|
||||
auth.KGID(atomic.LoadUint32(&a.gid)),
|
||||
auth.KUID(a.uid.Load()),
|
||||
auth.KGID(a.gid.Load()),
|
||||
)
|
||||
}
|
||||
|
||||
// IncLinks implements Inode.IncLinks.
|
||||
func (a *InodeAttrs) IncLinks(n uint32) {
|
||||
if atomic.AddUint32(&a.nlink, n) <= n {
|
||||
if a.nlink.Add(n) <= n {
|
||||
panic("InodeLink.IncLinks called with no existing links")
|
||||
}
|
||||
}
|
||||
|
||||
// DecLinks implements Inode.DecLinks.
|
||||
func (a *InodeAttrs) DecLinks() {
|
||||
if nlink := atomic.AddUint32(&a.nlink, ^uint32(0)); nlink == ^uint32(0) {
|
||||
if nlink := a.nlink.Add(^uint32(0)); nlink == ^uint32(0) {
|
||||
// Negative overflow
|
||||
panic("Inode.DecLinks called at 0 links")
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ package kernfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
@@ -221,8 +220,8 @@ type Dentry struct {
|
||||
fs *Filesystem
|
||||
|
||||
// flags caches useful information about the dentry from the inode. See the
|
||||
// dflags* consts above. Must be accessed by atomic ops.
|
||||
flags uint32
|
||||
// dflags* consts above.
|
||||
flags atomicbitops.Uint32
|
||||
|
||||
parent *Dentry
|
||||
name string
|
||||
@@ -459,10 +458,10 @@ func (d *Dentry) Init(fs *Filesystem, inode Inode) {
|
||||
d.refs.Store(1)
|
||||
ftype := inode.Mode().FileType()
|
||||
if ftype == linux.ModeDirectory {
|
||||
d.flags |= dflagsIsDir
|
||||
d.flags = atomicbitops.FromUint32(d.flags.RacyLoad() | dflagsIsDir)
|
||||
}
|
||||
if ftype == linux.ModeSymlink {
|
||||
d.flags |= dflagsIsSymlink
|
||||
d.flags = atomicbitops.FromUint32(d.flags.RacyLoad() | dflagsIsSymlink)
|
||||
}
|
||||
refsvfs2.Register(d)
|
||||
}
|
||||
@@ -474,12 +473,12 @@ func (d *Dentry) VFSDentry() *vfs.Dentry {
|
||||
|
||||
// isDir checks whether the dentry points to a directory inode.
|
||||
func (d *Dentry) isDir() bool {
|
||||
return atomic.LoadUint32(&d.flags)&dflagsIsDir != 0
|
||||
return d.flags.Load()&dflagsIsDir != 0
|
||||
}
|
||||
|
||||
// isSymlink checks whether the dentry points to a symlink inode.
|
||||
func (d *Dentry) isSymlink() bool {
|
||||
return atomic.LoadUint32(&d.flags)&dflagsIsSymlink != 0
|
||||
return d.flags.Load()&dflagsIsSymlink != 0
|
||||
}
|
||||
|
||||
// InotifyWithParent implements vfs.DentryImpl.InotifyWithParent.
|
||||
|
||||
@@ -16,7 +16,6 @@ package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
func (d *dentry) isCopiedUp() bool {
|
||||
return atomic.LoadUint32(&d.copiedUp) != 0
|
||||
return d.copiedUp.Load() != 0
|
||||
}
|
||||
|
||||
// copyUpLocked ensures that d exists on the upper layer, i.e. d.upperVD.Ok().
|
||||
@@ -49,7 +48,7 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
// credentials from context rather an take an explicit creds parameter.
|
||||
ctx = auth.ContextWithCredentials(ctx, d.fs.creds)
|
||||
|
||||
ftype := atomic.LoadUint32(&d.mode) & linux.S_IFMT
|
||||
ftype := d.mode.Load() & linux.S_IFMT
|
||||
switch ftype {
|
||||
case linux.S_IFREG, linux.S_IFDIR, linux.S_IFLNK, linux.S_IFBLK, linux.S_IFCHR:
|
||||
// Can be copied-up.
|
||||
@@ -126,7 +125,8 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
defer oldFD.DecRef(ctx)
|
||||
newFD, err := vfsObj.OpenAt(ctx, d.fs.creds, &newpop, &vfs.OpenOptions{
|
||||
Flags: linux.O_WRONLY | linux.O_CREAT | linux.O_EXCL,
|
||||
Mode: linux.FileMode(d.mode &^ linux.S_IFMT),
|
||||
// d.mode can be read because d.copyMu is locked.
|
||||
Mode: linux.FileMode(d.mode.RacyLoad() &^ linux.S_IFMT),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -157,9 +157,10 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
}
|
||||
if err := newFD.SetStat(ctx, vfs.SetStatOptions{
|
||||
Stat: linux.Statx{
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
UID: d.uid,
|
||||
GID: d.gid,
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
// d.uid and d.gid can be read because d.copyMu is locked.
|
||||
UID: d.uid.RacyLoad(),
|
||||
GID: d.gid.RacyLoad(),
|
||||
Atime: oldStat.Atime,
|
||||
Mtime: oldStat.Mtime,
|
||||
},
|
||||
@@ -172,16 +173,18 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
|
||||
case linux.S_IFDIR:
|
||||
if err := vfsObj.MkdirAt(ctx, d.fs.creds, &newpop, &vfs.MkdirOptions{
|
||||
Mode: linux.FileMode(d.mode &^ linux.S_IFMT),
|
||||
// d.mode can be read because d.copyMu is locked.
|
||||
Mode: linux.FileMode(d.mode.RacyLoad() &^ linux.S_IFMT),
|
||||
ForSyntheticMountpoint: forSyntheticMountpoint,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := vfsObj.SetStatAt(ctx, d.fs.creds, &newpop, &vfs.SetStatOptions{
|
||||
Stat: linux.Statx{
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
UID: d.uid,
|
||||
GID: d.gid,
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
// d.uid and d.gid can be read because d.copyMu is locked.
|
||||
UID: d.uid.RacyLoad(),
|
||||
GID: d.gid.RacyLoad(),
|
||||
Atime: oldStat.Atime,
|
||||
Mtime: oldStat.Mtime,
|
||||
},
|
||||
@@ -206,10 +209,11 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
}
|
||||
if err := vfsObj.SetStatAt(ctx, d.fs.creds, &newpop, &vfs.SetStatOptions{
|
||||
Stat: linux.Statx{
|
||||
Mask: linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
Mode: uint16(d.mode),
|
||||
UID: d.uid,
|
||||
GID: d.gid,
|
||||
Mask: linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
// d.{uid,gid,mode} can be read because d.copyMu is locked.
|
||||
Mode: uint16(d.mode.RacyLoad()),
|
||||
UID: d.uid.RacyLoad(),
|
||||
GID: d.gid.RacyLoad(),
|
||||
Atime: oldStat.Atime,
|
||||
Mtime: oldStat.Mtime,
|
||||
},
|
||||
@@ -226,7 +230,8 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
|
||||
case linux.S_IFBLK, linux.S_IFCHR:
|
||||
if err := vfsObj.MknodAt(ctx, d.fs.creds, &newpop, &vfs.MknodOptions{
|
||||
Mode: linux.FileMode(d.mode),
|
||||
// d.mode can be read because d.copyMu is locked.
|
||||
Mode: linux.FileMode(d.mode.RacyLoad()),
|
||||
DevMajor: oldStat.RdevMajor,
|
||||
DevMinor: oldStat.RdevMinor,
|
||||
}); err != nil {
|
||||
@@ -234,9 +239,10 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
}
|
||||
if err := vfsObj.SetStatAt(ctx, d.fs.creds, &newpop, &vfs.SetStatOptions{
|
||||
Stat: linux.Statx{
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
UID: d.uid,
|
||||
GID: d.gid,
|
||||
Mask: linux.STATX_UID | linux.STATX_GID | oldStat.Mask×tampsMask,
|
||||
// d.uid and d.gid can be read because d.copyMu is locked.
|
||||
UID: d.uid.RacyLoad(),
|
||||
GID: d.gid.RacyLoad(),
|
||||
Atime: oldStat.Atime,
|
||||
Mtime: oldStat.Mtime,
|
||||
},
|
||||
@@ -278,8 +284,8 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
cleanupUndoCopyUp()
|
||||
return linuxerr.EREMOTE
|
||||
}
|
||||
atomic.StoreUint32(&d.devMajor, upperStat.DevMajor)
|
||||
atomic.StoreUint32(&d.devMinor, upperStat.DevMinor)
|
||||
d.devMajor.Store(upperStat.DevMajor)
|
||||
d.devMinor.Store(upperStat.DevMinor)
|
||||
d.ino.Store(upperStat.Ino)
|
||||
}
|
||||
|
||||
@@ -339,7 +345,7 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
|
||||
d.lowerMappings.RemoveAll()
|
||||
}
|
||||
|
||||
atomic.StoreUint32(&d.copiedUp, 1)
|
||||
d.copiedUp.Store(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
package overlay
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
@@ -26,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
func (d *dentry) isDir() bool {
|
||||
return atomic.LoadUint32(&d.mode)&linux.S_IFMT == linux.S_IFDIR
|
||||
return d.mode.Load()&linux.S_IFMT == linux.S_IFDIR
|
||||
}
|
||||
|
||||
// Preconditions:
|
||||
@@ -168,7 +166,7 @@ func (d *dentry) getDirentsLocked(ctx context.Context) ([]vfs.Dirent, error) {
|
||||
},
|
||||
{
|
||||
Name: "..",
|
||||
Type: uint8(atomic.LoadUint32(&parent.mode) >> 12),
|
||||
Type: uint8(parent.mode.Load() >> 12),
|
||||
Ino: parent.ino.Load(),
|
||||
NextOff: 2,
|
||||
},
|
||||
|
||||
@@ -17,7 +17,6 @@ package overlay
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
@@ -272,7 +271,7 @@ func (fs *filesystem) lookupLocked(ctx context.Context, parent *dentry, name str
|
||||
childVD.IncRef()
|
||||
if isUpper {
|
||||
child.upperVD = childVD
|
||||
child.copiedUp = 1
|
||||
child.copiedUp = atomicbitops.FromUint32(1)
|
||||
} else {
|
||||
child.lowerVDs = append(child.lowerVDs, childVD)
|
||||
}
|
||||
@@ -282,11 +281,11 @@ func (fs *filesystem) lookupLocked(ctx context.Context, parent *dentry, name str
|
||||
} else {
|
||||
topLookupLayer = lookupLayerLower
|
||||
}
|
||||
child.mode = uint32(stat.Mode)
|
||||
child.uid = stat.UID
|
||||
child.gid = stat.GID
|
||||
child.devMajor = stat.DevMajor
|
||||
child.devMinor = stat.DevMinor
|
||||
child.mode = atomicbitops.FromUint32(uint32(stat.Mode))
|
||||
child.uid = atomicbitops.FromUint32(stat.UID)
|
||||
child.gid = atomicbitops.FromUint32(stat.GID)
|
||||
child.devMajor = atomicbitops.FromUint32(stat.DevMajor)
|
||||
child.devMinor = atomicbitops.FromUint32(stat.DevMinor)
|
||||
child.ino = atomicbitops.FromUint64(stat.Ino)
|
||||
}
|
||||
|
||||
@@ -319,14 +318,15 @@ func (fs *filesystem) lookupLocked(ctx context.Context, parent *dentry, name str
|
||||
|
||||
// Device and inode numbers were copied from the topmost layer above. Remap
|
||||
// the device number to an appropriate overlay-private one.
|
||||
childDevMinor, err := fs.getPrivateDevMinor(child.devMajor, child.devMinor)
|
||||
// We can use RacyLoad() because child is still being initialized.
|
||||
childDevMinor, err := fs.getPrivateDevMinor(child.devMajor.RacyLoad(), child.devMinor.RacyLoad())
|
||||
if err != nil {
|
||||
ctx.Infof("overlay.filesystem.lookupLocked: failed to map layer device number (%d, %d) to an overlay-specific device number: %v", child.devMajor, child.devMinor, err)
|
||||
ctx.Infof("overlay.filesystem.lookupLocked: failed to map layer device number (%d, %d) to an overlay-specific device number: %v", child.devMajor.RacyLoad(), child.devMinor.RacyLoad(), err)
|
||||
child.destroyLocked(ctx)
|
||||
return nil, topLookupLayer, err
|
||||
}
|
||||
child.devMajor = linux.UNNAMED_MAJOR
|
||||
child.devMinor = childDevMinor
|
||||
child.devMajor = atomicbitops.FromUint32(linux.UNNAMED_MAJOR)
|
||||
child.devMinor = atomicbitops.FromUint32(childDevMinor)
|
||||
|
||||
parent.IncRef()
|
||||
child.parent = parent
|
||||
@@ -887,7 +887,7 @@ func (d *dentry) openCopiedUp(ctx context.Context, rp *vfs.ResolvingPath, opts *
|
||||
|
||||
// Directory FDs open FDs from each layer when directory entries are read,
|
||||
// so they don't require opening an FD from d.topLayer() up front.
|
||||
ftype := atomic.LoadUint32(&d.mode) & linux.S_IFMT
|
||||
ftype := d.mode.Load() & linux.S_IFMT
|
||||
if ftype == linux.S_IFDIR {
|
||||
// Can't open directories with O_CREAT.
|
||||
if opts.Flags&linux.O_CREAT != 0 {
|
||||
@@ -1440,8 +1440,8 @@ func (fs *filesystem) SetStatAt(ctx context.Context, rp *vfs.ResolvingPath, opts
|
||||
|
||||
// Precondition: d.fs.renameMu must be held for reading.
|
||||
func (d *dentry) setStatLocked(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.SetStatOptions) error {
|
||||
mode := linux.FileMode(atomic.LoadUint32(&d.mode))
|
||||
if err := vfs.CheckSetStat(ctx, rp.Credentials(), &opts, mode, auth.KUID(atomic.LoadUint32(&d.uid)), auth.KGID(atomic.LoadUint32(&d.gid))); err != nil {
|
||||
mode := linux.FileMode(d.mode.Load())
|
||||
if err := vfs.CheckSetStat(ctx, rp.Credentials(), &opts, mode, auth.KUID(d.uid.Load()), auth.KGID(d.gid.Load())); err != nil {
|
||||
return err
|
||||
}
|
||||
mnt := rp.Mount()
|
||||
|
||||
@@ -36,7 +36,6 @@ package overlay
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
@@ -254,7 +253,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
root.refs = atomicbitops.FromInt64(1)
|
||||
if fs.opts.UpperRoot.Ok() {
|
||||
fs.opts.UpperRoot.IncRef()
|
||||
root.copiedUp = 1
|
||||
root.copiedUp = atomicbitops.FromUint32(1)
|
||||
root.upperVD = fs.opts.UpperRoot
|
||||
}
|
||||
for _, lowerRoot := range fs.opts.LowerRoots {
|
||||
@@ -286,10 +285,10 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
fs.vfsfs.DecRef(ctx)
|
||||
return nil, nil, linuxerr.EINVAL
|
||||
}
|
||||
root.mode = uint32(rootStat.Mode)
|
||||
root.uid = rootStat.UID
|
||||
root.gid = rootStat.GID
|
||||
root.devMajor = linux.UNNAMED_MAJOR
|
||||
root.mode = atomicbitops.FromUint32(uint32(rootStat.Mode))
|
||||
root.uid = atomicbitops.FromUint32(rootStat.UID)
|
||||
root.gid = atomicbitops.FromUint32(rootStat.GID)
|
||||
root.devMajor = atomicbitops.FromUint32(linux.UNNAMED_MAJOR)
|
||||
rootDevMinor, err := fs.getPrivateDevMinor(rootStat.DevMajor, rootStat.DevMinor)
|
||||
if err != nil {
|
||||
ctx.Infof("overlay.FilesystemType.GetFilesystem: failed to get device number for root: %v", err)
|
||||
@@ -297,7 +296,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
fs.vfsfs.DecRef(ctx)
|
||||
return nil, nil, err
|
||||
}
|
||||
root.devMinor = rootDevMinor
|
||||
root.devMinor = atomicbitops.FromUint32(rootDevMinor)
|
||||
root.ino.Store(rootStat.Ino)
|
||||
|
||||
return &fs.vfsfs, &root.vfsd, nil
|
||||
@@ -386,14 +385,14 @@ type dentry struct {
|
||||
// mode, uid, and gid are the file mode, owner, and group of the file in
|
||||
// the topmost layer (and therefore the overlay file as well), and are used
|
||||
// for permission checks on this dentry. These fields are protected by
|
||||
// copyMu and accessed using atomic memory operations.
|
||||
mode uint32
|
||||
uid uint32
|
||||
gid uint32
|
||||
// copyMu.
|
||||
mode atomicbitops.Uint32
|
||||
uid atomicbitops.Uint32
|
||||
gid atomicbitops.Uint32
|
||||
|
||||
// copiedUp is 1 if this dentry has been copied-up (i.e. upperVD.Ok()) and
|
||||
// 0 otherwise. copiedUp is accessed using atomic memory operations.
|
||||
copiedUp uint32
|
||||
// 0 otherwise.
|
||||
copiedUp atomicbitops.Uint32
|
||||
|
||||
// parent is the dentry corresponding to this dentry's parent directory.
|
||||
// name is this dentry's name in parent. If this dentry is a filesystem
|
||||
@@ -426,10 +425,9 @@ type dentry struct {
|
||||
inlineLowerVDs [1]vfs.VirtualDentry
|
||||
|
||||
// devMajor, devMinor, and ino are the device major/minor and inode numbers
|
||||
// used by this dentry. These fields are protected by copyMu and accessed
|
||||
// using atomic memory operations.
|
||||
devMajor uint32
|
||||
devMinor uint32
|
||||
// used by this dentry. These fields are protected by copyMu.
|
||||
devMajor atomicbitops.Uint32
|
||||
devMinor atomicbitops.Uint32
|
||||
ino atomicbitops.Uint64
|
||||
|
||||
// If this dentry represents a regular file, then:
|
||||
@@ -459,7 +457,7 @@ type dentry struct {
|
||||
lowerMappings memmap.MappingSet
|
||||
dataMu sync.RWMutex `state:"nosave"`
|
||||
wrappedMappable memmap.Mappable
|
||||
isMappable uint32
|
||||
isMappable atomicbitops.Uint32
|
||||
|
||||
locks vfs.FileLocks
|
||||
|
||||
@@ -688,13 +686,13 @@ func (d *dentry) topLookupLayer() lookupLayer {
|
||||
}
|
||||
|
||||
func (d *dentry) checkPermissions(creds *auth.Credentials, ats vfs.AccessTypes) error {
|
||||
return vfs.GenericCheckPermissions(creds, ats, linux.FileMode(atomic.LoadUint32(&d.mode)), auth.KUID(atomic.LoadUint32(&d.uid)), auth.KGID(atomic.LoadUint32(&d.gid)))
|
||||
return vfs.GenericCheckPermissions(creds, ats, linux.FileMode(d.mode.Load()), auth.KUID(d.uid.Load()), auth.KGID(d.gid.Load()))
|
||||
}
|
||||
|
||||
func (d *dentry) checkXattrPermissions(creds *auth.Credentials, name string, ats vfs.AccessTypes) error {
|
||||
mode := linux.FileMode(atomic.LoadUint32(&d.mode))
|
||||
kuid := auth.KUID(atomic.LoadUint32(&d.uid))
|
||||
kgid := auth.KGID(atomic.LoadUint32(&d.gid))
|
||||
mode := linux.FileMode(d.mode.Load())
|
||||
kuid := auth.KUID(d.uid.Load())
|
||||
kgid := auth.KGID(d.gid.Load())
|
||||
if err := vfs.GenericCheckPermissions(creds, ats, mode, kuid, kgid); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -716,34 +714,34 @@ func (d *dentry) statInternalTo(ctx context.Context, opts *vfs.StatOptions, stat
|
||||
// and some of our tests expect this.
|
||||
stat.Nlink = 2
|
||||
}
|
||||
stat.UID = atomic.LoadUint32(&d.uid)
|
||||
stat.GID = atomic.LoadUint32(&d.gid)
|
||||
stat.Mode = uint16(atomic.LoadUint32(&d.mode))
|
||||
stat.UID = d.uid.Load()
|
||||
stat.GID = d.gid.Load()
|
||||
stat.Mode = uint16(d.mode.Load())
|
||||
stat.Ino = d.ino.Load()
|
||||
stat.DevMajor = atomic.LoadUint32(&d.devMajor)
|
||||
stat.DevMinor = atomic.LoadUint32(&d.devMinor)
|
||||
stat.DevMajor = d.devMajor.Load()
|
||||
stat.DevMinor = d.devMinor.Load()
|
||||
}
|
||||
|
||||
// Preconditions: d.copyMu must be locked for writing.
|
||||
func (d *dentry) updateAfterSetStatLocked(opts *vfs.SetStatOptions) {
|
||||
if opts.Stat.Mask&linux.STATX_MODE != 0 {
|
||||
atomic.StoreUint32(&d.mode, (d.mode&linux.S_IFMT)|uint32(opts.Stat.Mode&^linux.S_IFMT))
|
||||
d.mode.Store((d.mode.RacyLoad() & linux.S_IFMT) | uint32(opts.Stat.Mode&^linux.S_IFMT))
|
||||
}
|
||||
if opts.Stat.Mask&linux.STATX_UID != 0 {
|
||||
atomic.StoreUint32(&d.uid, opts.Stat.UID)
|
||||
d.uid.Store(opts.Stat.UID)
|
||||
}
|
||||
if opts.Stat.Mask&linux.STATX_GID != 0 {
|
||||
atomic.StoreUint32(&d.gid, opts.Stat.GID)
|
||||
d.gid.Store(opts.Stat.GID)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dentry) mayDelete(creds *auth.Credentials, child *dentry) error {
|
||||
return vfs.CheckDeleteSticky(
|
||||
creds,
|
||||
linux.FileMode(atomic.LoadUint32(&d.mode)),
|
||||
auth.KUID(atomic.LoadUint32(&d.uid)),
|
||||
auth.KUID(atomic.LoadUint32(&child.uid)),
|
||||
auth.KGID(atomic.LoadUint32(&child.gid)),
|
||||
linux.FileMode(d.mode.Load()),
|
||||
auth.KUID(d.uid.Load()),
|
||||
auth.KUID(child.uid.Load()),
|
||||
auth.KGID(child.gid.Load()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -758,8 +756,8 @@ func (d *dentry) newChildOwnerStat(mode linux.FileMode, creds *auth.Credentials)
|
||||
// Set GID and possibly the SGID bit if the parent is an SGID directory.
|
||||
d.copyMu.RLock()
|
||||
defer d.copyMu.RUnlock()
|
||||
if atomic.LoadUint32(&d.mode)&linux.ModeSetGID == linux.ModeSetGID {
|
||||
stat.GID = atomic.LoadUint32(&d.gid)
|
||||
if d.mode.Load()&linux.ModeSetGID == linux.ModeSetGID {
|
||||
stat.GID = d.gid.Load()
|
||||
if stat.Mode&linux.ModeDirectory == linux.ModeDirectory {
|
||||
stat.Mode = uint16(mode) | linux.ModeSetGID
|
||||
stat.Mask |= linux.STATX_MODE
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
package overlay
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
@@ -32,11 +30,11 @@ import (
|
||||
)
|
||||
|
||||
func (d *dentry) isRegularFile() bool {
|
||||
return atomic.LoadUint32(&d.mode)&linux.S_IFMT == linux.S_IFREG
|
||||
return d.mode.Load()&linux.S_IFMT == linux.S_IFREG
|
||||
}
|
||||
|
||||
func (d *dentry) isSymlink() bool {
|
||||
return atomic.LoadUint32(&d.mode)&linux.S_IFMT == linux.S_IFLNK
|
||||
return d.mode.Load()&linux.S_IFMT == linux.S_IFLNK
|
||||
}
|
||||
|
||||
func (d *dentry) readlink(ctx context.Context) (string, error) {
|
||||
@@ -169,8 +167,8 @@ func (fd *regularFileFD) Allocate(ctx context.Context, mode, offset, length uint
|
||||
// SetStat implements vfs.FileDescriptionImpl.SetStat.
|
||||
func (fd *regularFileFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) error {
|
||||
d := fd.dentry()
|
||||
mode := linux.FileMode(atomic.LoadUint32(&d.mode))
|
||||
if err := vfs.CheckSetStat(ctx, auth.CredentialsFromContext(ctx), &opts, mode, auth.KUID(atomic.LoadUint32(&d.uid)), auth.KGID(atomic.LoadUint32(&d.gid))); err != nil {
|
||||
mode := linux.FileMode(d.mode.Load())
|
||||
if err := vfs.CheckSetStat(ctx, auth.CredentialsFromContext(ctx), &opts, mode, auth.KUID(d.uid.Load()), auth.KGID(d.gid.Load())); err != nil {
|
||||
return err
|
||||
}
|
||||
mnt := fd.vfsfd.Mount()
|
||||
@@ -332,7 +330,7 @@ func (fd *regularFileFD) updateSetUserGroupIDs(ctx context.Context, wrappedFD *v
|
||||
// Writing can clear the setuid and/or setgid bits. We only have to
|
||||
// check this if something was written and one of those bits was set.
|
||||
dentry := fd.dentry()
|
||||
if written == 0 || atomic.LoadUint32(&dentry.mode)&(linux.S_ISUID|linux.S_ISGID) == 0 {
|
||||
if written == 0 || dentry.mode.Load()&(linux.S_ISUID|linux.S_ISGID) == 0 {
|
||||
return written, nil
|
||||
}
|
||||
stat, err := wrappedFD.Stat(ctx, vfs.StatOptions{Mask: linux.STATX_MODE})
|
||||
@@ -341,7 +339,7 @@ func (fd *regularFileFD) updateSetUserGroupIDs(ctx context.Context, wrappedFD *v
|
||||
}
|
||||
dentry.copyMu.Lock()
|
||||
defer dentry.copyMu.Unlock()
|
||||
atomic.StoreUint32(&dentry.mode, uint32(stat.Mode))
|
||||
dentry.mode.Store(uint32(stat.Mode))
|
||||
return written, nil
|
||||
}
|
||||
|
||||
@@ -398,13 +396,13 @@ func (fd *regularFileFD) ensureMappable(ctx context.Context, opts *memmap.MMapOp
|
||||
d := fd.dentry()
|
||||
|
||||
// Fast path if we already have a Mappable for the current top layer.
|
||||
if atomic.LoadUint32(&d.isMappable) != 0 {
|
||||
if d.isMappable.Load() != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Only permit mmap of regular files, since other file types may have
|
||||
// unpredictable behavior when mmapped (e.g. /dev/zero).
|
||||
if atomic.LoadUint32(&d.mode)&linux.S_IFMT != linux.S_IFREG {
|
||||
if d.mode.Load()&linux.S_IFMT != linux.S_IFREG {
|
||||
return linuxerr.ENODEV
|
||||
}
|
||||
|
||||
@@ -413,7 +411,7 @@ func (fd *regularFileFD) ensureMappable(ctx context.Context, opts *memmap.MMapOp
|
||||
defer fd.mu.Unlock()
|
||||
d.copyMu.RLock()
|
||||
defer d.copyMu.RUnlock()
|
||||
if atomic.LoadUint32(&d.isMappable) != 0 {
|
||||
if d.isMappable.Load() != 0 {
|
||||
return nil
|
||||
}
|
||||
wrappedFD, err := fd.currentFDLocked(ctx)
|
||||
@@ -435,7 +433,7 @@ func (fd *regularFileFD) ensureMappable(ctx context.Context, opts *memmap.MMapOp
|
||||
defer d.dataMu.Unlock()
|
||||
if d.wrappedMappable == nil {
|
||||
d.wrappedMappable = opts.Mappable
|
||||
atomic.StoreUint32(&d.isMappable, 1)
|
||||
d.isMappable.Store(1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ package proc
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
@@ -44,14 +44,14 @@ type yamaPtraceScope struct {
|
||||
kernfs.DynamicBytesFile
|
||||
|
||||
// level is the ptrace_scope level.
|
||||
level *int32
|
||||
level *atomicbitops.Int32
|
||||
}
|
||||
|
||||
var _ vfs.WritableDynamicBytesSource = (*yamaPtraceScope)(nil)
|
||||
|
||||
// Generate implements vfs.DynamicBytesSource.Generate.
|
||||
func (s *yamaPtraceScope) Generate(ctx context.Context, buf *bytes.Buffer) error {
|
||||
_, err := fmt.Fprintf(buf, "%d\n", atomic.LoadInt32(s.level))
|
||||
_, err := fmt.Fprintf(buf, "%d\n", s.level.Load())
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -79,6 +79,6 @@ func (s *yamaPtraceScope) Write(ctx context.Context, _ *vfs.FileDescription, src
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
atomic.StoreInt32(s.level, v)
|
||||
s.level.Store(v)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
@@ -45,6 +46,6 @@ func (fs *filesystem) newDeviceFile(kuid auth.KUID, kgid auth.KGID, mode linux.F
|
||||
panic(fmt.Sprintf("invalid DeviceKind: %v", kind))
|
||||
}
|
||||
file.inode.init(file, fs, kuid, kgid, mode, parentDir)
|
||||
file.inode.nlink = 1 // from parent directory
|
||||
file.inode.nlink = atomicbitops.FromUint32(1) // from parent directory
|
||||
return &file.inode
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user