diff options
author | Jamie Liu <jamieliu@google.com> | 2021-08-30 12:37:33 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-08-30 12:40:08 -0700 |
commit | 574c6542a538bc2917fc95e443cf0976946db1c0 (patch) | |
tree | e21572a4f872a2865cae8213571943037b313105 /pkg/sentry/fsimpl | |
parent | 9625071e6dd6d949f6bd443910eaf56ce1c9762d (diff) |
Use specialFileFD handles in specialFileFD.Stat().
PiperOrigin-RevId: 393831108
Diffstat (limited to 'pkg/sentry/fsimpl')
-rw-r--r-- | pkg/sentry/fsimpl/gofer/gofer.go | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go index bd6b30397..43440ec19 100644 --- a/pkg/sentry/fsimpl/gofer/gofer.go +++ b/pkg/sentry/fsimpl/gofer/gofer.go @@ -995,7 +995,7 @@ func (d *dentry) refreshSizeLocked(ctx context.Context) error { if d.writeFD < 0 { d.handleMu.RUnlock() // Ask the gofer if we don't have a host FD. - return d.updateFromGetattrLocked(ctx) + return d.updateFromGetattrLocked(ctx, p9file{}) } var stat unix.Statx_t @@ -1014,33 +1014,35 @@ func (d *dentry) updateFromGetattr(ctx context.Context) error { // updating stale attributes in d.updateFromP9AttrsLocked(). d.metadataMu.Lock() defer d.metadataMu.Unlock() - return d.updateFromGetattrLocked(ctx) + return d.updateFromGetattrLocked(ctx, p9file{}) } // Preconditions: // * !d.isSynthetic(). // * d.metadataMu is locked. // +checklocks:d.metadataMu -func (d *dentry) updateFromGetattrLocked(ctx context.Context) error { - // Use d.readFile or d.writeFile, which represent 9P FIDs that have been - // opened, in preference to d.file, which represents a 9P fid that has not. - // This may be significantly more efficient in some implementations. Prefer - // d.writeFile over d.readFile since some filesystem implementations may - // update a writable handle's metadata after writes to that handle, without - // making metadata updates immediately visible to read-only handles - // representing the same file. - d.handleMu.RLock() - handleMuRLocked := true - var file p9file - switch { - case !d.writeFile.isNil(): - file = d.writeFile - case !d.readFile.isNil(): - file = d.readFile - default: - file = d.file - d.handleMu.RUnlock() - handleMuRLocked = false +func (d *dentry) updateFromGetattrLocked(ctx context.Context, file p9file) error { + handleMuRLocked := false + if file.isNil() { + // Use d.readFile or d.writeFile, which represent 9P FIDs that have + // been opened, in preference to d.file, which represents a 9P fid that + // has not. This may be significantly more efficient in some + // implementations. Prefer d.writeFile over d.readFile since some + // filesystem implementations may update a writable handle's metadata + // after writes to that handle, without making metadata updates + // immediately visible to read-only handles representing the same file. + d.handleMu.RLock() + switch { + case !d.writeFile.isNil(): + file = d.writeFile + handleMuRLocked = true + case !d.readFile.isNil(): + file = d.readFile + handleMuRLocked = true + default: + file = d.file + d.handleMu.RUnlock() + } } _, attrMask, attr, err := file.getAttr(ctx, dentryAttrMask()) @@ -2044,9 +2046,17 @@ func (fd *fileDescription) Stat(ctx context.Context, opts vfs.StatOptions) (linu d := fd.dentry() const validMask = uint32(linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME | linux.STATX_SIZE | linux.STATX_BLOCKS | linux.STATX_BTIME) if !d.cachedMetadataAuthoritative() && opts.Mask&validMask != 0 && opts.Sync != linux.AT_STATX_DONT_SYNC { - // TODO(jamieliu): Use specialFileFD.handle.file for the getattr if - // available? - if err := d.updateFromGetattr(ctx); err != nil { + // Use specialFileFD.handle.file for the getattr if available, for the + // same reason that we try to use open file handles in + // dentry.updateFromGetattrLocked(). + var file p9file + if sffd, ok := fd.vfsfd.Impl().(*specialFileFD); ok { + file = sffd.handle.file + } + d.metadataMu.Lock() + err := d.updateFromGetattrLocked(ctx, file) + d.metadataMu.Unlock() + if err != nil { return linux.Statx{}, err } } |