github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/lisafs/server.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lisafs 16 17 import ( 18 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 19 "github.com/nicocha30/gvisor-ligolo/pkg/sync" 20 ) 21 22 // Server serves a filesystem tree. Multiple connections on different mount 23 // points can be started on a server. The server provides utilities to safely 24 // modify the filesystem tree across its connections (mount points). Note that 25 // it does not support synchronizing filesystem tree mutations across other 26 // servers serving the same filesystem subtree. Server also manages the 27 // lifecycle of all connections. 28 type Server struct { 29 // connWg counts the number of active connections being tracked. 30 connWg sync.WaitGroup 31 32 // renameMu synchronizes rename operations within this filesystem tree. 33 renameMu sync.RWMutex 34 35 // handlers is a list of RPC handlers which can be indexed by the handler's 36 // corresponding MID. 37 handlers []RPCHandler 38 39 // root is the root of the filesystem tree being managed by this server. 40 // root is immutable. Server holds a ref on root for its entire lifetime. 41 root *Node 42 43 // impl is the server implementation which embeds this server. 44 impl ServerImpl 45 46 // opts is the server specific options. This dictates how some of the 47 // messages are handled. 48 opts ServerOpts 49 } 50 51 // ServerOpts defines some server implementation specific behavior. 52 type ServerOpts struct { 53 // WalkStatSupported is set to true if it's safe to call 54 // ControlFDImpl.WalkStat and let the file implementation perform the walk 55 // without holding locks on any of the descendant's Nodes. 56 WalkStatSupported bool 57 58 // SetAttrOnDeleted is set to true if it's safe to call ControlFDImpl.SetStat 59 // for deleted files. 60 SetAttrOnDeleted bool 61 62 // AllocateOnDeleted is set to true if it's safe to call OpenFDImpl.Allocate 63 // for deleted files. 64 AllocateOnDeleted bool 65 } 66 67 // Init must be called before first use of the server. 68 func (s *Server) Init(impl ServerImpl, opts ServerOpts) { 69 s.impl = impl 70 s.opts = opts 71 s.handlers = handlers[:] 72 s.root = &Node{} 73 // s owns the ref on s.root. 74 s.root.InitLocked("", nil) 75 } 76 77 // SetHandlers overrides the server's RPC handlers. Mainly should only be used 78 // for tests. 79 func (s *Server) SetHandlers(handlers []RPCHandler) { 80 s.handlers = handlers 81 } 82 83 // withRenameReadLock invokes fn with the server's rename mutex locked for 84 // reading. This ensures that no rename operations occur concurrently. 85 func (s *Server) withRenameReadLock(fn func() error) error { 86 s.renameMu.RLock() 87 defer s.renameMu.RUnlock() 88 return fn() 89 } 90 91 // StartConnection starts the connection on a separate goroutine and tracks it. 92 func (s *Server) StartConnection(c *Connection) { 93 s.connWg.Add(1) 94 go func() { 95 c.Run() 96 s.connWg.Done() 97 }() 98 } 99 100 // Wait waits for all connections started via StartConnection() to terminate. 101 func (s *Server) Wait() { 102 s.connWg.Wait() 103 } 104 105 // Destroy releases resources being used by this server. 106 func (s *Server) Destroy() { 107 s.root.DecRef(nil) 108 } 109 110 // ServerImpl contains the implementation details for a Server. 111 // Implementations of ServerImpl should contain their associated Server by 112 // value as their first field. 113 type ServerImpl interface { 114 // Mount is called when a Mount RPC is made. It mounts the connection on 115 // mountNode. Mount may optionally donate a host FD to the mount point. 116 // 117 // Mount has a read concurrency guarantee on mountNode. 118 Mount(c *Connection, mountNode *Node) (*ControlFD, linux.Statx, int, error) 119 120 // SupportedMessages returns a list of messages that the server 121 // implementation supports. 122 SupportedMessages() []MID 123 124 // MaxMessageSize is the maximum payload length (in bytes) that can be sent 125 // to this server implementation. 126 MaxMessageSize() uint32 127 }