Deleted should be a property of pathNode, not fidRef.

This reduces the work required to do when a file is deleted. Just mark the path
node deleted. All fidRefs pointing to it will read the correct value then.

PiperOrigin-RevId: 421766678
This commit is contained in:
Ayush Ranjan
2022-01-14 01:46:34 -08:00
committed by gVisor bot
parent 8a0c4a9470
commit 0a22b6c29f
3 changed files with 16 additions and 23 deletions
-5
View File
@@ -1249,11 +1249,6 @@ func doWalk(cs *connState, ref *fidRef, names []string, getattr bool) (qids []QI
file: sf,
mode: ref.mode,
pathNode: ref.pathNode,
// For the clone case, the cloned fid must
// preserve the deleted property of the
// original FID.
deleted: ref.deleted,
}
if !ref.isRoot() {
if !newRef.isDeleted() {
+10 -3
View File
@@ -33,10 +33,15 @@ import (
type pathNode struct {
// opMu synchronizes high-level, sematic operations, such as the
// simultaneous creation and deletion of a file.
//
// opMu does not directly protect any fields in pathNode.
opMu sync.RWMutex
// deleted indicates that the backing file has been deleted. We stop many
// operations at the API level if they are incompatible with a file that has
// already been unlinked. deleted is protected by opMu. However, it may be
// changed without opMu if this node is deleted as part of an entire subtree
// on unlink. So deleted must only be accessed/mutated using atomics.
deleted uint32
// childMu protects the fields below.
childMu sync.RWMutex
@@ -211,7 +216,9 @@ func (p *pathNode) removeWithName(name string, fn func(ref *fidRef)) *pathNode {
for ref := range m {
delete(m, ref)
delete(p.childRefNames, ref)
fn(ref)
if fn != nil {
fn(ref)
}
}
}
+6 -15
View File
@@ -179,11 +179,6 @@ type fidRef struct {
// isRoot should be used to check for root over looking at parent
// directly.
parent *fidRef
// deleted indicates that the backing file has been deleted. We stop
// many operations at the API level if they are incompatible with a
// file that has already been unlinked.
deleted uint32
}
// IncRef increases the references on a fid.
@@ -211,8 +206,11 @@ func (f *fidRef) DecRef() {
}
// isDeleted returns true if this fidRef has been deleted.
//
// Precondition: this must be called via safelyRead, safelyWrite or
// safelyGlobal.
func (f *fidRef) isDeleted() bool {
return atomic.LoadUint32(&f.deleted) != 0
return atomic.LoadUint32(&f.pathNode.deleted) != 0
}
// isRoot indicates whether this is a root fid.
@@ -232,10 +230,7 @@ func (f *fidRef) maybeParent() *fidRef {
//
// Precondition: this must be called via safelyWrite or safelyGlobal.
func notifyDelete(pn *pathNode) {
// Call on all local references.
pn.forEachChildRef(func(ref *fidRef, _ string) {
atomic.StoreUint32(&ref.deleted, 1)
})
atomic.StoreUint32(&pn.deleted, 1)
// Call on all subtrees.
pn.forEachChildNode(func(pn *pathNode) {
@@ -247,11 +242,7 @@ func notifyDelete(pn *pathNode) {
//
// Precondition: this must be called via safelyWrite or safelyGlobal.
func (f *fidRef) markChildDeleted(name string) {
origPathNode := f.pathNode.removeWithName(name, func(ref *fidRef) {
atomic.StoreUint32(&ref.deleted, 1)
})
if origPathNode != nil {
if origPathNode := f.pathNode.removeWithName(name, nil); origPathNode != nil {
// Mark all children as deleted.
notifyDelete(origPathNode)
}