func (p *pathNode) removeWithName(name string, fn func(ref *fidRef)) *pathNode {
	p.childMu.Lock()
	defer p.childMu.Unlock()
	if m, ok := p.childRefs[name]; ok {
		for ref := range m {
			delete(m, ref)
			delete(p.childRefNames, ref)
			fn(ref)
		}
	}
	origPathNode := p.childNodes[name]
	delete(p.childNodes, name)
	return origPathNode
}
removeWithName removes all references with the given name.

The provided function is executed after reference removal. The only method
it may (transitively) call on this pathNode is addChildLocked.

If a child pathNode for name exists, it is removed from this pathNode and
returned by this function. Any operations on the removed tree must use this
value.
package p9
import (
	"fmt"
	"sync"
)
type pathNode struct {
	opMu sync.RWMutex
	childMu sync.RWMutex
	childNodes map[string]*pathNode
	childRefs map[string]map[*fidRef]struct{}
	childRefNames map[*fidRef]string
}
func newPathNode() *pathNode {
	return &pathNode{
		childNodes:    make(map[string]*pathNode),
		childRefs:     make(map[string]map[*fidRef]struct{}),
		childRefNames: make(map[*fidRef]string),
	}
}
func (p *pathNode) forEachChildRef(fn func(ref *fidRef, name string)) {
	p.childMu.RLock()
	defer p.childMu.RUnlock()
	for name, m := range p.childRefs {
		for ref := range m {
			fn(ref, name)
		}
	}
}
func (p *pathNode) forEachChildNode(fn func(pn *pathNode)) {
	p.childMu.RLock()
	defer p.childMu.RUnlock()
	for _, pn := range p.childNodes {
		fn(pn)
	}
}
func (p *pathNode) pathNodeFor(name string) *pathNode {
	p.childMu.RLock()
	if pn, ok := p.childNodes[name]; ok {
		p.childMu.RUnlock()
		return pn
	}
	p.childMu.RUnlock()
	p.childMu.Lock()
	if pn, ok := p.childNodes[name]; ok {
		p.childMu.Unlock()
		return pn
	}
	pn := newPathNode()
	p.childNodes[name] = pn
	p.childMu.Unlock()
	return pn
}
func (p *pathNode) nameFor(ref *fidRef) string {
	p.childMu.RLock()
	n, ok := p.childRefNames[ref]
	p.childMu.RUnlock()
	if !ok {
		panic(fmt.Sprintf("expected name for %+v, none found", ref))
	}
	return n
}
func (p *pathNode) addChildLocked(ref *fidRef, name string) {
	if n, ok := p.childRefNames[ref]; ok {
		panic(fmt.Sprintf("unexpected fidRef %+v with path %q, wanted %q", ref, n, name))
	}
	p.childRefNames[ref] = name
	m, ok := p.childRefs[name]
	if !ok {
		m = make(map[*fidRef]struct{})
		p.childRefs[name] = m
	}
	m[ref] = struct{}{}
}
func (p *pathNode) addChild(ref *fidRef, name string) {
	p.childMu.Lock()
	p.addChildLocked(ref, name)
	p.childMu.Unlock()
}
func (p *pathNode) removeChild(ref *fidRef) {
	p.childMu.Lock()
	if name, ok := p.childRefNames[ref]; ok {
		m, ok := p.childRefs[name]
		if !ok {
			p.childMu.Unlock()
			panic(fmt.Sprintf("name %s missing from childfidRefs", name))
		}
		delete(m, ref)
		if len(m) == 0 {
			delete(p.childRefs, name)
		}
	}
	delete(p.childRefNames, ref)
	p.childMu.Unlock()
}
func (p *pathNode) addPathNodeFor(name string, pn *pathNode) {
	p.childMu.Lock()
	if opn, ok := p.childNodes[name]; ok {
		p.childMu.Unlock()
		panic(fmt.Sprintf("unexpected pathNode %+v with path %q", opn, name))
	}
	p.childNodes[name] = pn
	p.childMu.Unlock()
}