mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix memmap.MappingIdentity.Device/InodeID() lock ordering.
For vfs.FileDescriptions for which FileDescriptionOptions.UseDentryMetadata is true, memmap.MappingIdentity.Device/InodeID() => FileDescription.Stat() => FilesystemImpl.StatAt() takes fsimpl locks for path traversal, which violates the lock ordering and is unnecessary since no path is being traversed. Fix this by carving out a special case where FilesystemImpl.Stat() (and FileDescriptionImpl.Stat()) are required to meet the lock ordering requirements of memmap.MappingIdentity.Device/InodeID(), and implement that special case by skipping path traversal (and gofer revalidation) locks when not required. PiperOrigin-RevId: 698608924
This commit is contained in:
@@ -1578,6 +1578,12 @@ func (fs *filesystem) SetStatAt(ctx context.Context, rp *vfs.ResolvingPath, opts
|
||||
|
||||
// StatAt implements vfs.FilesystemImpl.StatAt.
|
||||
func (fs *filesystem) StatAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.StatOptions) (linux.Statx, error) {
|
||||
if rp.Done() && opts.Sync == linux.AT_STATX_DONT_SYNC {
|
||||
var stat linux.Statx
|
||||
rp.Start().Impl().(*dentry).statTo(&stat)
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
var ds *[]*dentry
|
||||
fs.renameMu.RLock()
|
||||
defer fs.renameMuRUnlockAndCheckCaching(ctx, &ds)
|
||||
|
||||
@@ -915,6 +915,10 @@ func (fs *Filesystem) SetStatAt(ctx context.Context, rp *vfs.ResolvingPath, opts
|
||||
|
||||
// StatAt implements vfs.FilesystemImpl.StatAt.
|
||||
func (fs *Filesystem) StatAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.StatOptions) (linux.Statx, error) {
|
||||
if rp.Done() && opts.Sync == linux.AT_STATX_DONT_SYNC {
|
||||
return rp.Start().Impl().(*Dentry).inode.Stat(ctx, fs.VFSFilesystem(), opts)
|
||||
}
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.processDeferredDecRefs(ctx)
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
@@ -1548,17 +1548,24 @@ func (d *dentry) setStatLocked(ctx context.Context, rp *vfs.ResolvingPath, opts
|
||||
|
||||
// StatAt implements vfs.FilesystemImpl.StatAt.
|
||||
func (fs *filesystem) StatAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.StatOptions) (linux.Statx, error) {
|
||||
var ds *[]*dentry
|
||||
fs.renameMu.RLock()
|
||||
defer fs.renameMuRUnlockAndCheckDrop(ctx, &ds)
|
||||
d, err := fs.resolveLocked(ctx, rp, &ds)
|
||||
if err != nil {
|
||||
return linux.Statx{}, err
|
||||
var d *dentry
|
||||
if rp.Done() {
|
||||
d = rp.Start().Impl().(*dentry)
|
||||
} else {
|
||||
var ds *[]*dentry
|
||||
fs.renameMu.RLock()
|
||||
defer fs.renameMuRUnlockAndCheckDrop(ctx, &ds)
|
||||
var err error
|
||||
d, err = fs.resolveLocked(ctx, rp, &ds)
|
||||
if err != nil {
|
||||
return linux.Statx{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var stat linux.Statx
|
||||
if layerMask := opts.Mask &^ statInternalMask; layerMask != 0 {
|
||||
layerVD := d.topLayer()
|
||||
var err error
|
||||
stat, err = fs.vfsfs.VirtualFilesystem().StatAt(ctx, fs.creds, &vfs.PathOperation{
|
||||
Root: layerVD,
|
||||
Start: layerVD,
|
||||
|
||||
@@ -757,11 +757,17 @@ func (fs *filesystem) SetStatAt(ctx context.Context, rp *vfs.ResolvingPath, opts
|
||||
|
||||
// StatAt implements vfs.FilesystemImpl.StatAt.
|
||||
func (fs *filesystem) StatAt(ctx context.Context, rp *vfs.ResolvingPath, opts vfs.StatOptions) (linux.Statx, error) {
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
d, err := resolveLocked(ctx, rp)
|
||||
if err != nil {
|
||||
return linux.Statx{}, err
|
||||
var d *dentry
|
||||
if rp.Done() {
|
||||
d = rp.Start().Impl().(*dentry)
|
||||
} else {
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
var err error
|
||||
d, err = resolveLocked(ctx, rp)
|
||||
if err != nil {
|
||||
return linux.Statx{}, err
|
||||
}
|
||||
}
|
||||
var stat linux.Statx
|
||||
d.inode.statTo(&stat)
|
||||
|
||||
@@ -334,6 +334,9 @@ type FileDescriptionImpl interface {
|
||||
OnClose(ctx context.Context) error
|
||||
|
||||
// Stat returns metadata for the file represented by the FileDescription.
|
||||
//
|
||||
// If opts.Sync == linux.AT_STATX_SYNC_DONT_SYNC, Stat cannot take locks
|
||||
// preceding memmap.MappingIdentity locks.
|
||||
Stat(ctx context.Context, opts StatOptions) (linux.Statx, error)
|
||||
|
||||
// SetStat updates metadata for the file represented by the
|
||||
|
||||
@@ -365,6 +365,10 @@ type FilesystemImpl interface {
|
||||
SetStatAt(ctx context.Context, rp *ResolvingPath, opts SetStatOptions) error
|
||||
|
||||
// StatAt returns metadata for the file at rp.
|
||||
//
|
||||
// If rp.Done() (i.e. rp refers to the dentry rp.Start()) and opts.Sync ==
|
||||
// linux.AT_STATX_DONT_SYNC, StatAt cannot take locks preceding
|
||||
// memmap.MappingIdentity locks.
|
||||
StatAt(ctx context.Context, rp *ResolvingPath, opts StatOptions) (linux.Statx, error)
|
||||
|
||||
// StatFSAt returns metadata for the filesystem containing the file at rp.
|
||||
|
||||
Reference in New Issue
Block a user