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