From 6c476f4fb8310749d8aa98ef6ac910ebe83fc3e5 Mon Sep 17 00:00:00 2001 From: Ollie Agent Date: Tue, 18 Aug 2026 07:41:59 +0200 Subject: [PATCH] Synchronize toolsrv fid state --- cmd/toolsrv/p9.go | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/cmd/toolsrv/p9.go b/cmd/toolsrv/p9.go index 78cb8ba..cb099b7 100644 --- a/cmd/toolsrv/p9.go +++ b/cmd/toolsrv/p9.go @@ -17,6 +17,7 @@ import ( // fid represents an open file handle. type fid struct { + mu sync.Mutex path string qid plan9.Qid mode uint8 @@ -393,20 +394,28 @@ func handleRead(cs *connState, fc *plan9.Fcall, tree *virtfs.Tree) *plan9.Fcall if !isFid { return errFcall(fc, "unknown fid") } - if !f.opened { + f.mu.Lock() + opened := f.opened + qid := f.qid + entry := f.entry + f.mu.Unlock() + if !opened { return errFcall(fc, "not open") } - if f.qid.Type&plan9.QTDIR != 0 { + if qid.Type&plan9.QTDIR != 0 { return handleDirRead(cs, f, fc, tree) } - if f.entry == nil { + if entry == nil { return errFcall(fc, "no entry") } // For rdwr files, check if we've already read - if f.entry.RdwrMode() && f.readDone { + f.mu.Lock() + readDone := entry.RdwrMode() && f.readDone + f.mu.Unlock() + if readDone { return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Data: nil} } @@ -494,8 +503,12 @@ func readSlice(fc *plan9.Fcall, content []byte) *plan9.Fcall { } func handleDirRead(cs *connState, f *fid, fc *plan9.Fcall, tree *virtfs.Tree) *plan9.Fcall { - if fc.Offset == 0 || f.dirCache == nil { - path := f.path + f.mu.Lock() + path := f.path + qidPath := f.path + cached := f.dirCache + f.mu.Unlock() + if fc.Offset == 0 || cached == nil { if path == "/" { path = "" } else { @@ -517,7 +530,7 @@ func handleDirRead(cs *connState, f *fid, fc *plan9.Fcall, tree *virtfs.Tree) *p } dir := plan9.Dir{ Name: e.Name(), - Qid: plan9.Qid{Type: qt, Path: pathHash(f.path + "/" + e.Name())}, + Qid: plan9.Qid{Type: qt, Path: pathHash(qidPath + "/" + e.Name())}, Mode: mode, Uid: "toolsrv", Gid: "toolsrv", @@ -525,20 +538,25 @@ func handleDirRead(cs *connState, f *fid, fc *plan9.Fcall, tree *virtfs.Tree) *p data, _ := dir.Bytes() buf = append(buf, data...) } - f.dirCache = buf + f.mu.Lock() + if fc.Offset == 0 || f.dirCache == nil { + f.dirCache = buf + } + cached = f.dirCache + f.mu.Unlock() } offset := int(fc.Offset) - if offset >= len(f.dirCache) { + if offset >= len(cached) { return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Data: nil} } end := offset + int(fc.Count) - if end > len(f.dirCache) { - end = len(f.dirCache) + if end > len(cached) { + end = len(cached) } - return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Data: f.dirCache[offset:end]} + return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Data: cached[offset:end]} } func handleWrite(cs *connState, fc *plan9.Fcall, tree *virtfs.Tree) *plan9.Fcall {