Synchronize olliesrv fid read state

This commit is contained in:
Ollie Agent 2026-08-18 07:45:02 +02:00
parent 6c476f4fb8
commit cad1c6be9b
1 changed files with 42 additions and 12 deletions

View File

@ -55,6 +55,7 @@ func (g *GroupTable) IsMember(group, user string) bool {
}
type fid struct {
mu sync.Mutex
path string
qid plan9.Qid
mode uint8
@ -517,16 +518,27 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
cs.mu.RUnlock()
return errFcall(fc, "bad fid")
}
f.mu.Lock()
path := f.path
isDir := f.qid.Type&QTDir != 0
entry := f.entry
f.mu.Unlock()
cs.mu.RUnlock()
if isDir {
if fc.Offset == 0 || f.dirCache == nil {
f.dirCache = buildDirData(root, path)
f.mu.Lock()
cached := f.dirCache
f.mu.Unlock()
if fc.Offset == 0 || cached == nil {
cached = buildDirData(root, path)
f.mu.Lock()
if fc.Offset == 0 || f.dirCache == nil {
f.dirCache = cached
}
cached = f.dirCache
f.mu.Unlock()
}
data := sliceDirData(f.dirCache, fc.Offset, fc.Count)
data := sliceDirData(cached, fc.Offset, fc.Count)
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}
@ -536,11 +548,14 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
if entry.BlockingReadMode() {
// Serve from cache if we already have content (multi-Tread paging).
if f.readCache != nil {
if int(fc.Offset) >= len(f.readCache) {
f.mu.Lock()
cached := f.readCache
f.mu.Unlock()
if cached != nil {
if int(fc.Offset) >= len(cached) {
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: 0}
}
return readSlice(fc, f.readCache)
return readSlice(fc, cached)
}
// First Tread: block for content.
cs.mu.RLock()
@ -563,11 +578,15 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
if nextBase != "" {
cs.mu.Lock()
if f, ok := cs.fids[fc.Fid]; ok {
f.mu.Lock()
f.waitBase = nextBase
f.mu.Unlock()
}
cs.mu.Unlock()
}
f.mu.Lock()
f.readCache = content
f.mu.Unlock()
return readSlice(fc, content)
}
@ -588,7 +607,9 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
if nextBase != "" {
cs.mu.Lock()
if f, ok := cs.fids[fc.Fid]; ok {
f.mu.Lock()
f.waitBase = nextBase
f.mu.Unlock()
}
cs.mu.Unlock()
}
@ -599,11 +620,17 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(count), Data: content[:count]}
}
// Normal file read: cache content on first Tread, serve via readSlice.
// This handles the case where io.ReadAll issues multiple Treads at
// increasing offsets (buffer starts at 512 bytes and grows).
if f.readCache != nil {
return readSlice(fc, f.readCache)
cs.mu.RLock()
f, ok = cs.fids[fc.Fid]
cs.mu.RUnlock()
if !ok {
return errFcall(fc, "bad fid")
}
f.mu.Lock()
cached := f.readCache
f.mu.Unlock()
if cached != nil {
return readSlice(fc, cached)
}
type result struct {
@ -622,8 +649,11 @@ func read(root *fs.Tree, cs *connState, fc *plan9.Fcall, ctx context.Context) *p
if r.err != nil {
return errFcall(fc, r.err.Error())
}
f.mu.Lock()
f.readCache = r.data
return readSlice(fc, r.data)
cached := f.readCache
f.mu.Unlock()
return readSlice(fc, cached)
case <-ctx.Done():
entry.Close()
return errFcall(fc, ctx.Err().Error())