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 // nodes 54 virtual status_t SetFlags(void* node, void* cookie, 55 int flags); 56 57 virtual status_t FSync(void* node); 58 59 virtual status_t ReadSymlink(void* node, char* buffer, 60 size_t bufferSize, size_t* bytesRead); 61 virtual status_t CreateSymlink(void* dir, const char* name, 62 const char* target, int mode); 63 64 virtual status_t Link(void* dir, const char* name, 65 void* node); 66 virtual status_t Unlink(void* dir, const char* name); 67 virtual status_t Rename(void* oldDir, const char* oldName, 68 void* newDir, const char* newName); 69 70 virtual status_t Access(void* node, int mode); 71 virtual status_t ReadStat(void* node, struct stat* st); 72 virtual status_t WriteStat(void* node, const struct stat* st, 73 uint32 mask); 74 75 // files 76 virtual status_t Create(void* dir, const char* name, 77 int openMode, int mode, void** cookie, 78 ino_t* vnid); 79 virtual status_t Open(void* node, int openMode, 80 void** cookie); 81 virtual status_t Close(void* node, void* cookie); 82 virtual status_t FreeCookie(void* node, void* cookie); 83 virtual status_t Read(void* node, void* cookie, off_t pos, 84 void* buffer, size_t bufferSize, 85 size_t* bytesRead); 86 virtual status_t Write(void* node, void* cookie, 87 off_t pos, const void* buffer, 88 size_t bufferSize, size_t* bytesWritten); 89 90 // directories 91 virtual status_t CreateDir(void* dir, const char* name, 92 int mode); 93 virtual status_t RemoveDir(void* dir, const char* name); 94 virtual status_t OpenDir(void* node, void** cookie); 95 virtual status_t CloseDir(void* node, void* cookie); 96 virtual status_t FreeDirCookie(void* node, void* cookie); 97 virtual status_t ReadDir(void* node, void* cookie, 98 void* buffer, size_t bufferSize, 99 uint32 count, uint32* countRead); 100 virtual status_t RewindDir(void* node, void* cookie); 101 102 // attribute directories 103 virtual status_t OpenAttrDir(void* node, void** cookie); 104 virtual status_t CloseAttrDir(void* node, void* cookie); 105 virtual status_t FreeAttrDirCookie(void* node, 106 void* cookie); 107 virtual status_t ReadAttrDir(void* node, void* cookie, 108 void* buffer, size_t bufferSize, 109 uint32 count, uint32* countRead); 110 virtual status_t RewindAttrDir(void* node, void* cookie); 111 112 // attributes 113 virtual status_t OpenAttr(void* node, const char* name, 114 int openMode, void** cookie); 115 virtual status_t CloseAttr(void* node, void* cookie); 116 virtual status_t FreeAttrCookie(void* node, void* cookie); 117 virtual status_t ReadAttr(void* node, void* cookie, 118 off_t pos, void* buffer, size_t bufferSize, 119 size_t* bytesRead); 120 virtual status_t ReadAttrStat(void* node, void* cookie, 121 struct stat* st); 122 123 private: 124 struct DirEntryCache; 125 struct DirCookie; 126 struct FileCookie; 127 struct AttrDirCookie; 128 struct AttrCookie; 129 struct ReadDirBuffer; 130 struct LockIterator; 131 struct RWLockableReadLocking; 132 struct RWLockableWriteLocking; 133 struct RWLockableReadLocker; 134 struct RWLockableWriteLocker; 135 struct NodeLocker; 136 struct NodeReadLocker; 137 struct NodeWriteLocker; 138 struct MultiNodeLocker; 139 140 friend struct LockIterator; 141 friend struct RWLockableReadLocking; 142 friend struct RWLockableWriteLocking; 143 friend struct NodeLocker; 144 friend struct MultiNodeLocker; 145 146 private: 147 inline FUSEFileSystem* _FileSystem() const 148 { return static_cast<FUSEFileSystem*>(fFileSystem); } 149 150 ino_t _GenerateNodeID(); 151 152 bool _GetNodeID(FUSENode* dir, const char* entryName, 153 ino_t* _nodeID); 154 status_t _GetNode(FUSENode* dir, const char* entryName, 155 FUSENode** _node); 156 status_t _InternalGetNode(FUSENode* dir, 157 const char* entryName, FUSENode** _node, 158 AutoLocker<Locker>& locker); 159 void _PutNode(FUSENode* node); 160 void _PutNodes(FUSENode* const* nodes, int32 count); 161 162 void _RemoveEntry(FUSEEntry* entry); 163 status_t _RemoveEntry(FUSENode* dir, const char* name); 164 status_t _RenameEntry(FUSENode* oldDir, 165 const char* oldName, FUSENode* newDir, 166 const char* newName); 167 168 status_t _LockNodeChain(FUSENode* node, bool lockParent, 169 bool writeLock); 170 void _UnlockNodeChain(FUSENode* node, bool parent, 171 bool writeLock); 172 void _UnlockNodeChainInternal(FUSENode* node, 173 bool writeLock, FUSENode* stopNode, 174 FUSENode* stopBeforeNode); 175 176 status_t _LockNodeChains(FUSENode* node1, 177 bool lockParent1, bool writeLock1, 178 FUSENode* node2, bool lockParent2, 179 bool writeLock2); 180 status_t _LockNodeChainsInternal(FUSENode* node1, 181 bool lockParent1, bool writeLock1, 182 FUSENode* node2, bool lockParent2, 183 bool writeLock2, bool* _retry); 184 void _UnlockNodeChains(FUSENode* node1, bool parent1, 185 bool writeLock1, FUSENode* node2, 186 bool parent2, bool writeLock2); 187 188 bool _FindCommonAncestor(FUSENode* node1, 189 FUSENode* node2, FUSENode** _commonAncestor, 190 bool* _inverseLockingOrder); 191 bool _GetNodeAncestors(FUSENode* node, 192 FUSENode** ancestors, uint32* _count); 193 194 status_t _BuildPath(FUSENode* dir, const char* entryName, 195 char* path, size_t& pathLen); 196 status_t _BuildPath(FUSENode* node, char* path, 197 size_t& pathLen); 198 199 static int _AddReadDirEntryLowLevel(void* buffer, char* buf, size_t bufsize, 200 const char* name, const struct stat* st, off_t offset); 201 static int _AddReadDirEntry(void* buffer, const char* name, 202 const struct stat* st, off_t offset); 203 static int _AddReadDirEntryGetDir(fuse_dirh_t handle, 204 const char* name, int type, ino_t nodeID); 205 int _AddReadDirEntryLowLevel(ReadDirBuffer* buffer, 206 char* buf, size_t bufSize, const char* name, int type, 207 ino_t nodeID, off_t offset); 208 int _AddReadDirEntry(ReadDirBuffer* buffer, 209 const char* name, int type, ino_t nodeID, 210 off_t offset); 211 212 private: 213 RWLockManager fLockManager; 214 Locker fLock; 215 const fuse_lowlevel_ops* fOps; 216 fuse_fs* fFS; 217 FUSEEntryTable fEntries; 218 FUSENodeTable fNodes; 219 FUSENode* fRootNode; 220 ino_t fNextNodeID; 221 bool fUseNodeIDs; 222 char fName[B_OS_NAME_LENGTH]; 223 }; 224 225 } // namespace UserlandFS 226 227 using UserlandFS::FUSEVolume; 228 229 #endif // USERLAND_FS_FUSE_VOLUME_H 230