mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[vfs2][gofer] Fix update attributes race condition.
We were getting the file attributes before locking the metadataMu which was causing stale updates to the file attributes. Fixes OpenTest_AppendConcurrentWrite. Updates #2923 PiperOrigin-RevId: 322804438
This commit is contained in:
@@ -150,11 +150,9 @@ afterSymlink:
|
||||
return nil, err
|
||||
}
|
||||
if d != d.parent && !d.cachedMetadataAuthoritative() {
|
||||
_, attrMask, attr, err := d.parent.file.getAttr(ctx, dentryAttrMask())
|
||||
if err != nil {
|
||||
if err := d.parent.updateFromGetattr(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.parent.updateFromP9Attrs(attrMask, &attr)
|
||||
}
|
||||
rp.Advance()
|
||||
return d.parent, nil
|
||||
@@ -209,17 +207,28 @@ func (fs *filesystem) getChildLocked(ctx context.Context, vfsObj *vfs.VirtualFil
|
||||
|
||||
// Preconditions: As for getChildLocked. !parent.isSynthetic().
|
||||
func (fs *filesystem) revalidateChildLocked(ctx context.Context, vfsObj *vfs.VirtualFilesystem, parent *dentry, name string, child *dentry, ds **[]*dentry) (*dentry, error) {
|
||||
if child != nil {
|
||||
// Need to lock child.metadataMu because we might be updating child
|
||||
// metadata. We need to hold the lock *before* getting metadata from the
|
||||
// server and release it after updating local metadata.
|
||||
child.metadataMu.Lock()
|
||||
}
|
||||
qid, file, attrMask, attr, err := parent.file.walkGetAttrOne(ctx, name)
|
||||
if err != nil && err != syserror.ENOENT {
|
||||
if child != nil {
|
||||
child.metadataMu.Unlock()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if child != nil {
|
||||
if !file.isNil() && inoFromPath(qid.Path) == child.ino {
|
||||
// The file at this path hasn't changed. Just update cached metadata.
|
||||
file.close(ctx)
|
||||
child.updateFromP9Attrs(attrMask, &attr)
|
||||
child.updateFromP9AttrsLocked(attrMask, &attr)
|
||||
child.metadataMu.Unlock()
|
||||
return child, nil
|
||||
}
|
||||
child.metadataMu.Unlock()
|
||||
if file.isNil() && child.isSynthetic() {
|
||||
// We have a synthetic file, and no remote file has arisen to
|
||||
// replace it.
|
||||
|
||||
@@ -785,8 +785,8 @@ func (d *dentry) cachedMetadataAuthoritative() bool {
|
||||
|
||||
// updateFromP9Attrs is called to update d's metadata after an update from the
|
||||
// remote filesystem.
|
||||
func (d *dentry) updateFromP9Attrs(mask p9.AttrMask, attr *p9.Attr) {
|
||||
d.metadataMu.Lock()
|
||||
// Precondition: d.metadataMu must be locked.
|
||||
func (d *dentry) updateFromP9AttrsLocked(mask p9.AttrMask, attr *p9.Attr) {
|
||||
if mask.Mode {
|
||||
if got, want := uint32(attr.Mode.FileType()), d.fileType(); got != want {
|
||||
d.metadataMu.Unlock()
|
||||
@@ -822,7 +822,6 @@ func (d *dentry) updateFromP9Attrs(mask p9.AttrMask, attr *p9.Attr) {
|
||||
if mask.Size {
|
||||
d.updateFileSizeLocked(attr.Size)
|
||||
}
|
||||
d.metadataMu.Unlock()
|
||||
}
|
||||
|
||||
// Preconditions: !d.isSynthetic()
|
||||
@@ -834,6 +833,10 @@ func (d *dentry) updateFromGetattr(ctx context.Context) error {
|
||||
file p9file
|
||||
handleMuRLocked bool
|
||||
)
|
||||
// d.metadataMu must be locked *before* we getAttr so that we do not end up
|
||||
// updating stale attributes in d.updateFromP9AttrsLocked().
|
||||
d.metadataMu.Lock()
|
||||
defer d.metadataMu.Unlock()
|
||||
d.handleMu.RLock()
|
||||
if !d.handle.file.isNil() {
|
||||
file = d.handle.file
|
||||
@@ -849,7 +852,7 @@ func (d *dentry) updateFromGetattr(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.updateFromP9Attrs(attrMask, &attr)
|
||||
d.updateFromP9AttrsLocked(attrMask, &attr)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user