Initial commit
Proof-of-concept implementation. Bugs will occur.
This commit is contained in:
128
vendor/github.com/hanwen/go-fuse/v2/fuse/protocol-server.go
generated
vendored
Normal file
128
vendor/github.com/hanwen/go-fuse/v2/fuse/protocol-server.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2024 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// protocolServer bridges from the FUSE datatypes to a RawFileSystem
|
||||
type protocolServer struct {
|
||||
fileSystem RawFileSystem
|
||||
|
||||
interruptMu sync.Mutex
|
||||
reqInflight []*request
|
||||
connectionDead bool
|
||||
|
||||
latencies LatencyMap
|
||||
|
||||
kernelSettings InitIn
|
||||
|
||||
opts *MountOptions
|
||||
|
||||
// in-flight notify-retrieve queries
|
||||
retrieveMu sync.Mutex
|
||||
retrieveNext uint64
|
||||
retrieveTab map[uint64]*retrieveCacheRequest // notifyUnique -> retrieve request
|
||||
}
|
||||
|
||||
func (ms *protocolServer) handleRequest(h *operationHandler, req *request) {
|
||||
ms.addInflight(req)
|
||||
defer ms.dropInflight(req)
|
||||
|
||||
if req.status.Ok() && ms.opts.Debug {
|
||||
ms.opts.Logger.Println(req.InputDebug())
|
||||
}
|
||||
|
||||
if req.inHeader().NodeId == pollHackInode ||
|
||||
req.inHeader().NodeId == FUSE_ROOT_ID && h.FileNames > 0 && req.filename() == pollHackName {
|
||||
doPollHackLookup(ms, req)
|
||||
} else if req.status.Ok() && h.Func == nil {
|
||||
ms.opts.Logger.Printf("Unimplemented opcode %v", operationName(req.inHeader().Opcode))
|
||||
req.status = ENOSYS
|
||||
} else if req.status.Ok() {
|
||||
h.Func(ms, req)
|
||||
}
|
||||
|
||||
// Forget/NotifyReply do not wait for reply from filesystem server.
|
||||
switch req.inHeader().Opcode {
|
||||
case _OP_FORGET, _OP_BATCH_FORGET, _OP_NOTIFY_REPLY:
|
||||
req.suppressReply = true
|
||||
case _OP_INTERRUPT:
|
||||
// ? what other status can interrupt generate?
|
||||
if req.status.Ok() {
|
||||
req.suppressReply = true
|
||||
}
|
||||
}
|
||||
if req.status == EINTR {
|
||||
ms.interruptMu.Lock()
|
||||
dead := ms.connectionDead
|
||||
ms.interruptMu.Unlock()
|
||||
if dead {
|
||||
req.suppressReply = true
|
||||
}
|
||||
}
|
||||
if req.suppressReply {
|
||||
return
|
||||
}
|
||||
if req.fdData != nil && ms.opts.DisableSplice {
|
||||
req.outPayload, req.status = req.fdData.Bytes(req.outPayload)
|
||||
req.fdData = nil
|
||||
}
|
||||
|
||||
req.serializeHeader(req.outPayloadSize())
|
||||
|
||||
if ms.opts.Debug {
|
||||
ms.opts.Logger.Println(req.OutputDebug())
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *protocolServer) addInflight(req *request) {
|
||||
ms.interruptMu.Lock()
|
||||
defer ms.interruptMu.Unlock()
|
||||
req.inflightIndex = len(ms.reqInflight)
|
||||
ms.reqInflight = append(ms.reqInflight, req)
|
||||
}
|
||||
|
||||
func (ms *protocolServer) dropInflight(req *request) {
|
||||
ms.interruptMu.Lock()
|
||||
defer ms.interruptMu.Unlock()
|
||||
this := req.inflightIndex
|
||||
last := len(ms.reqInflight) - 1
|
||||
if last != this {
|
||||
ms.reqInflight[this] = ms.reqInflight[last]
|
||||
ms.reqInflight[this].inflightIndex = this
|
||||
}
|
||||
ms.reqInflight = ms.reqInflight[:last]
|
||||
}
|
||||
|
||||
func (ms *protocolServer) interruptRequest(unique uint64) Status {
|
||||
ms.interruptMu.Lock()
|
||||
defer ms.interruptMu.Unlock()
|
||||
|
||||
// This is slow, but this operation is rare.
|
||||
for _, inflight := range ms.reqInflight {
|
||||
if unique == inflight.inHeader().Unique && !inflight.interrupted {
|
||||
close(inflight.cancel)
|
||||
inflight.interrupted = true
|
||||
return OK
|
||||
}
|
||||
}
|
||||
|
||||
return EAGAIN
|
||||
}
|
||||
|
||||
func (ms *protocolServer) cancelAll() {
|
||||
ms.interruptMu.Lock()
|
||||
defer ms.interruptMu.Unlock()
|
||||
ms.connectionDead = true
|
||||
for _, req := range ms.reqInflight {
|
||||
if !req.interrupted {
|
||||
close(req.cancel)
|
||||
req.interrupted = true
|
||||
}
|
||||
}
|
||||
// Leave ms.reqInflight alone, or dropInflight will barf.
|
||||
}
|
||||
Reference in New Issue
Block a user