Complete olliesrv fid synchronization

This commit is contained in:
Ollie Agent 2026-08-18 07:47:46 +02:00
parent cad1c6be9b
commit a8a6bb5204
1 changed files with 70 additions and 39 deletions

View File

@ -562,7 +562,9 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
f, fidOK := cs.fids[fc.Fid]
var base string
if fidOK {
f.mu.Lock()
base = f.waitBase
f.mu.Unlock()
}
cs.mu.RUnlock()
waitCtx, waitCancel := context.WithTimeout(ctx, 5*time.Second)
@ -595,7 +597,9 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
f, fidOK := cs.fids[fc.Fid]
var base string
if fidOK {
f.mu.Lock()
base = f.waitBase
f.mu.Unlock()
}
cs.mu.RUnlock()
waitCtx, waitCancel := context.WithCancel(ctx)
@ -683,24 +687,28 @@ func write(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
cs.mu.Unlock()
return errFcall(fc, "bad fid")
}
if f.entry != nil && f.entry.RdwrMode() {
f.readCache = nil // clear cached response for next read
cs.mu.Unlock()
if err := f.entry.Write(fc.Data); err != nil {
return errFcall(fc, err.Error())
f.mu.Lock()
entry := f.entry
if entry != nil && entry.RdwrMode() {
f.readCache = nil
}
if entry == nil || !entry.RdwrMode() {
end := int(fc.Offset) + len(fc.Data)
if end > len(f.writeBuf) {
grown := make([]byte, end)
copy(grown, f.writeBuf)
f.writeBuf = grown
}
copy(f.writeBuf[fc.Offset:], fc.Data)
f.mu.Unlock()
cs.mu.Unlock()
return &plan9.Fcall{Type: plan9.Rwrite, Tag: fc.Tag, Count: uint32(len(fc.Data))}
}
end := int(fc.Offset) + len(fc.Data)
if end > len(f.writeBuf) {
grown := make([]byte, end)
copy(grown, f.writeBuf)
f.writeBuf = grown
}
copy(f.writeBuf[fc.Offset:], fc.Data)
f.mu.Unlock()
cs.mu.Unlock()
if err := entry.Write(fc.Data); err != nil {
return errFcall(fc, err.Error())
}
return &plan9.Fcall{Type: plan9.Rwrite, Tag: fc.Tag, Count: uint32(len(fc.Data))}
}
@ -711,13 +719,16 @@ func stat(root *fs.Tree, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
if !ok {
return errFcall(fc, "bad fid")
}
if _, err := root.Stat(f.path[1:]); err != nil {
f.mu.Lock()
path := f.path
f.mu.Unlock()
if _, err := root.Stat(path[1:]); err != nil {
cs.mu.Lock()
delete(cs.fids, fc.Fid)
cs.mu.Unlock()
return errFcall(fc, "file not found")
}
dir := makeStat(root, f.path)
dir := makeStat(root, path)
stat, err := dir.Bytes()
if err != nil {
return errFcall(fc, err.Error())
@ -736,22 +747,29 @@ func wstat(root *fs.Tree, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
if err != nil {
return &plan9.Fcall{Type: plan9.Rwstat, Tag: fc.Tag}
}
oldName := pathBase(f.path)
f.mu.Lock()
path := f.path
f.mu.Unlock()
oldName := pathBase(path)
if newDir.Name == "" || newDir.Name == oldName {
return &plan9.Fcall{Type: plan9.Rwstat, Tag: fc.Tag}
}
if err := root.Rename(f.path[1:], newDir.Name); err != nil {
if err := root.Rename(path[1:], newDir.Name); err != nil {
return errFcall(fc, err.Error())
}
// GC stale fids on this connection referencing the old path
oldPrefix := f.path
oldPrefix := path
var stale []fs.File
cs.mu.Lock()
for id, fid := range cs.fids {
if fid.path == oldPrefix || strings.HasPrefix(fid.path, oldPrefix+"/") {
fid.mu.Lock()
fidPath := fid.path
entry := fid.entry
fid.mu.Unlock()
if fidPath == oldPrefix || strings.HasPrefix(fidPath, oldPrefix+"/") {
delete(cs.fids, id)
if fid.entry != nil {
stale = append(stale, fid.entry)
if entry != nil {
stale = append(stale, entry)
}
}
}
@ -770,20 +788,28 @@ func clunk(root *fs.Tree, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
var writable bool
var isRequest bool
if ok {
if m := f.mode & 3; m == plan9.OWRITE || m == plan9.ORDWR {
path = f.path
f.mu.Lock()
mode := f.mode
path = f.path
data = append([]byte(nil), f.writeBuf...)
entry := f.entry
if mode&3 == plan9.OWRITE || mode&3 == plan9.ORDWR {
writable = true
data = make([]byte, len(f.writeBuf))
copy(data, f.writeBuf)
if f.entry != nil {
isRequest = f.entry.RdwrMode()
if entry != nil {
isRequest = entry.RdwrMode()
}
}
f.mu.Unlock()
delete(cs.fids, fc.Fid)
}
cs.mu.Unlock()
if f != nil && f.entry != nil {
_ = f.entry.Close()
if f != nil {
f.mu.Lock()
entry := f.entry
f.mu.Unlock()
if entry != nil {
_ = entry.Close()
}
}
if writable && !isRequest {
input := strings.TrimSpace(string(data))
@ -805,16 +831,21 @@ func remove(root *fs.Tree, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
delete(cs.fids, fc.Fid)
}
cs.mu.Unlock()
if ok && f.entry != nil {
_ = f.entry.Close()
var entry fs.File
if ok {
f.mu.Lock()
entry = f.entry
path := f.path
f.mu.Unlock()
if entry != nil {
_ = entry.Close()
}
if err := root.Delete(path[1:]); err != nil {
return errFcall(fc, err.Error())
}
return &plan9.Fcall{Type: plan9.Rremove, Tag: fc.Tag}
}
if !ok {
return errFcall(fc, "bad fid")
}
if err := root.Delete(f.path[1:]); err != nil {
return errFcall(fc, err.Error())
}
return &plan9.Fcall{Type: plan9.Rremove, Tag: fc.Tag}
return errFcall(fc, "bad fid")
}
func (s *Server) Kill() {