1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef USERLAND_FS_FUSE_VOLUME_H 6 #define USERLAND_FS_FUSE_VOLUME_H 7 8 #include <AutoLocker.h> 9 #include <RWLockManager.h> 10 11 #include "Locker.h" 12 13 #include "fuse_fs.h" 14 #include "FUSEEntry.h" 15 #include "FUSEFileSystem.h" 16 17 #include "../Volume.h" 18 19 20 namespace UserlandFS { 21 22 class FUSEFileSystem; 23 24 25 class FUSEVolume : public Volume { 26 public: 27 FUSEVolume(FUSEFileSystem* fileSystem, 28 dev_t id); 29 virtual ~FUSEVolume(); 30 31 status_t Init(); 32 33 void SetFS(fuse_fs* fs) { fFS = fs; } 34 35 // FS 36 virtual status_t Mount(const char* device, uint32 flags, 37 const char* parameters, ino_t* rootID); 38 virtual status_t Unmount(); 39 virtual status_t Sync(); 40 virtual status_t ReadFSInfo(fs_info* info); 41 42 // vnodes 43 virtual status_t Lookup(void* dir, const char* entryName, 44 ino_t* vnid); 45 virtual status_t GetVNodeName(void* node, char* buffer, 46 size_t bufferSize); 47 virtual status_t ReadVNode(ino_t vnid, bool reenter, 48 void** node, int* type, uint32* flags, 49 FSVNodeCapabilities* _capabilities); 50 virtual status_t WriteVNode(void* node, bool reenter); 51 virtual status_t RemoveVNode(void* node, bool reenter); 52 53 // asynchronous I/O 54 virtual status_t DoIO(void* node, void* cookie, 55 const IORequestInfo& requestInfo); 56 57 // nodes 58 virtual status_t SetFlags(void* node, void* cookie, 59 int flags); 60 61 virtual status_t FSync(void* node); 62 63 virtual status_t ReadSymlink(void* node, char* buffer, 64 size_t bufferSize, size_t* bytesRead); 65 virtual status_t CreateSymlink(void* dir, const char* name, 66 const char* target, int mode); 67 68 virtual status_t Link(void* dir, const char* name, 69 void* node); 70 virtual status_t Unlink(void* dir, const char* name); 71 virtual status_t Rename(void* oldDir, const char* oldName, 72 void* newDir, const char* newName); 73 74 virtual status_t Access(void* node, int mode); 75 virtual status_t ReadStat(void* node, struct stat* st); 76 virtual status_t WriteStat(void* node, const struct stat* st, 77 uint32 mask); 78 79 // files 80 virtual status_t Create(void* dir, const char* name, 81 int openMode, int mode, void** cookie, 82 ino_t* vnid); 83 virtual status_t Open(void* node, int openMode, 84 void** cookie); 85 virtual status_t Close(void* node, void* cookie); 86 virtual status_t FreeCookie(void* node, void* cookie); 87 virtual status_t Read(void* node, void* cookie, off_t pos, 88 void* buffer, size_t bufferSize, 89 size_t* bytesRead); 90 virtual status_t Write(void* node, void* cookie, 91 off_t pos, const void* buffer, 92 size_t bufferSize, size_t* bytesWritten); 93 94 // directories 95 virtual status_t CreateDir(void* dir, const char* name, 96 int mode); 97 virtual status_t RemoveDir(void* dir, const char* name); 98 virtual status_t OpenDir(void* node, void** cookie); 99 virtual status_t CloseDir(void* node, void* cookie); 100 virtual status_t FreeDirCookie(void* node, void* cookie); 101 virtual status_t ReadDir(void* node, void* cookie, 102 void* buffer, size_t bufferSize, 103 uint32 count, uint32* countRead); 104 virtual status_t RewindDir(void* node, void* cookie); 105 106 // attribute directories 107 virtual status_t OpenAttrDir(void* node, void** cookie); 108 virtual status_t CloseAttrDir(void* node, void* cookie); 109 virtual status_t FreeAttrDirCookie(void* node, 110 void* cookie); 111 virtual status_t ReadAttrDir(void* node, void* cookie, 112 void* buffer, size_t bufferSize, 113 uint32 count, uint32* countRead); 114 virtual status_t RewindAttrDir(void* node, void* cookie); 115 116 // attributes 117 virtual status_t OpenAttr(void* node, const char* name, 118 int openMode, void** cookie); 119 virtual status_t CloseAttr(void* node, void* cookie); 120 virtual status_t FreeAttrCookie(void* node, void* cookie); 121 virtual status_t ReadAttr(void* node, void* cookie, 122 off_t pos, void* buffer, size_t bufferSize, 123 size_t* bytesRead); 124 virtual status_t ReadAttrStat(void* node, void* cookie, 125 struct stat* st); 126 127 private: 128 struct DirEntryCache; 129 struct DirCookie; 130 struct FileCookie; 131 struct AttrDirCookie; 132 struct AttrCookie; 133 struct ReadDirBuffer; 134 struct LockIterator; 135 struct RWLockableReadLocking; 136 struct RWLockableWriteLocking; 137 struct RWLockableReadLocker; 138 struct RWLockableWriteLocker; 139 struct NodeLocker; 140 struct NodeReadLocker; 141 struct NodeWriteLocker; 142 struct MultiNodeLocker; 143 144 friend struct LockIterator; 145 friend struct RWLockableReadLocking; 146 friend struct RWLockableWriteLocking; 147 friend struct NodeLocker; 148 friend struct MultiNodeLocker; 149 150 private: 151 inline FUSEFileSystem* _FileSystem() const 152 { return static_cast<FUSEFileSystem*>(fFileSystem); } 153 154 ino_t _GenerateNodeID(); 155 156 bool _GetNodeID(FUSENode* dir, const char* entryName, 157 ino_t* _nodeID); 158 status_t _GetNode(FUSENode* dir, const char* entryName, 159 FUSENode** _node); 160 status_t _InternalGetNode(FUSENode* dir, 161 const char* entryName, FUSENode** _node, 162 AutoLocker<Locker>& locker); 163 void _PutNode(FUSENode* node); 164 void _PutNodes(FUSENode* const* nodes, int32 count); 165 166 void _RemoveEntry(FUSEEntry* entry); 167 status_t _RemoveEntry(FUSENode* dir, const char* name); 168 status_t _RenameEntry(FUSENode* oldDir, 169 const char* oldName, FUSENode* newDir, 170 const char* newName); 171 172 status_t _LockNodeChain(FUSENode* node, bool lockParent, 173 bool writeLock); 174 void _UnlockNodeChain(FUSENode* node, bool parent, 175 bool writeLock); 176 void _UnlockNodeChainInternal(FUSENode* node, 177 bool writeLock, FUSENode* stopNode, 178 FUSENode* stopBeforeNode); 179 180 status_t _LockNodeChains(FUSENode* node1, 181 bool lockParent1, bool writeLock1, 182 FUSENode* node2, bool lockParent2, 183 bool writeLock2); 184 status_t _LockNodeChainsInternal(FUSENode* node1, 185 bool lockParent1, bool writeLock1, 186 FUSENode* node2, bool lockParent2, 187 bool writeLock2, bool* _retry); 188 void _UnlockNodeChains(FUSENode* node1, bool parent1, 189 bool writeLock1, FUSENode* node2, 190 bool parent2, bool writeLock2); 191 192 bool _FindCommonAncestor(FUSENode* node1, 193 FUSENode* node2, FUSENode** _commonAncestor, 194 bool* _inverseLockingOrder); 195 bool _GetNodeAncestors(FUSENode* node, 196 FUSENode** ancestors, uint32* _count); 197 198 status_t _BuildPath(FUSENode* dir, const char* entryName, 199 char* path, size_t& pathLen); 200 status_t _BuildPath(FUSENode* node, char* path, 201 size_t& pathLen); 202 203 static int _AddReadDirEntryLowLevel(void* buffer, char* buf, size_t bufsize, 204 const char* name, const struct stat* st, off_t offset); 205 static int _AddReadDirEntry(void* buffer, const char* name, 206 const struct stat* st, off_t offset); 207 static int _AddReadDirEntryGetDir(fuse_dirh_t handle, 208 const char* name, int type, ino_t nodeID); 209 int _AddReadDirEntryLowLevel(ReadDirBuffer* buffer, 210 char* buf, size_t bufSize, const char* name, int type, 211 ino_t nodeID, off_t offset); 212 int _AddReadDirEntry(ReadDirBuffer* buffer, 213 const char* name, int type, ino_t nodeID, 214 off_t offset); 215 status_t _InternalIO(FUSENode* node, FileCookie* cookie, const char* path, 216 off_t pos, char* buffer, size_t& bytes, bool isWrite); 217 218 private: 219 RWLockManager fLockManager; 220 Locker fLock; 221 const fuse_lowlevel_ops* fOps; 222 fuse_fs* fFS; 223 FUSEEntryTable fEntries; 224 FUSENodeTable fNodes; 225 FUSENode* fRootNode; 226 ino_t fNextNodeID; 227 bool fUseNodeIDs; 228 char fName[B_OS_NAME_LENGTH]; 229 }; 230 231 } // namespace UserlandFS 232 233 using UserlandFS::FUSEVolume; 234 235 #endif // USERLAND_FS_FUSE_VOLUME_H 236