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
19namespace UserlandFS {
20
21class FUSEFileSystem;
22
23
24class FUSEVolume : public Volume {
25public:
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	// attributes
112	virtual	status_t			OpenAttr(void* node, const char* name,
113									int openMode, void** cookie);
114	virtual	status_t			CloseAttr(void* node, void* cookie);
115	virtual	status_t			FreeAttrCookie(void* node, void* cookie);
116	virtual	status_t			ReadAttr(void* node, void* cookie,
117									off_t pos, void* buffer, size_t bufferSize,
118									size_t* bytesRead);
119	virtual	status_t			ReadAttrStat(void* node, void* cookie,
120									struct stat* st);
121
122private:
123	struct DirEntryCache;
124	struct DirCookie;
125	struct FileCookie;
126	struct AttrDirCookie;
127	struct AttrCookie;
128	struct ReadDirBuffer;
129	struct LockIterator;
130	struct RWLockableReadLocking;
131	struct RWLockableWriteLocking;
132	struct RWLockableReadLocker;
133	struct RWLockableWriteLocker;
134	struct NodeLocker;
135	struct NodeReadLocker;
136	struct NodeWriteLocker;
137	struct MultiNodeLocker;
138
139	friend struct LockIterator;
140	friend struct RWLockableReadLocking;
141	friend struct RWLockableWriteLocking;
142	friend struct NodeLocker;
143	friend struct MultiNodeLocker;
144
145private:
146	inline	FUSEFileSystem*		_FileSystem() const;
147
148			ino_t				_GenerateNodeID();
149
150			bool				_GetNodeID(FUSENode* dir, const char* entryName,
151									ino_t* _nodeID);
152			status_t			_GetNode(FUSENode* dir, const char* entryName,
153									FUSENode** _node);
154			status_t			_InternalGetNode(FUSENode* dir,
155									const char* entryName, FUSENode** _node,
156									AutoLocker<Locker>& locker);
157			void				_PutNode(FUSENode* node);
158			void				_PutNodes(FUSENode* const* nodes, int32 count);
159
160			void				_RemoveEntry(FUSEEntry* entry);
161			status_t			_RemoveEntry(FUSENode* dir, const char* name);
162			status_t			_RenameEntry(FUSENode* oldDir,
163									const char* oldName, FUSENode* newDir,
164									const char* newName);
165
166			status_t			_LockNodeChain(FUSENode* node, bool lockParent,
167									bool writeLock);
168			void				_UnlockNodeChain(FUSENode* node, bool parent,
169									bool writeLock);
170			void				_UnlockNodeChainInternal(FUSENode* node,
171									bool writeLock, FUSENode* stopNode,
172									FUSENode* stopBeforeNode);
173
174			status_t			_LockNodeChains(FUSENode* node1,
175									bool lockParent1, bool writeLock1,
176									FUSENode* node2, bool lockParent2,
177									bool writeLock2);
178			status_t			_LockNodeChainsInternal(FUSENode* node1,
179									bool lockParent1, bool writeLock1,
180									FUSENode* node2, bool lockParent2,
181									bool writeLock2, bool* _retry);
182			void				_UnlockNodeChains(FUSENode* node1, bool parent1,
183									bool writeLock1, FUSENode* node2,
184									bool parent2, bool writeLock2);
185
186			bool				_FindCommonAncestor(FUSENode* node1,
187									FUSENode* node2, FUSENode** _commonAncestor,
188									bool* _inverseLockingOrder);
189			bool				_GetNodeAncestors(FUSENode* node,
190									FUSENode** ancestors, uint32* _count);
191
192			status_t			_BuildPath(FUSENode* dir, const char* entryName,
193									char* path, size_t& pathLen);
194			status_t			_BuildPath(FUSENode* node, char* path,
195									size_t& pathLen);
196
197	static	int					_AddReadDirEntry(void* buffer, const char* name,
198									const struct stat* st, off_t offset);
199	static	int					_AddReadDirEntryGetDir(fuse_dirh_t handle,
200									const char* name, int type, ino_t nodeID);
201			int					_AddReadDirEntry(ReadDirBuffer* buffer,
202									const char* name, int type, ino_t nodeID,
203									off_t offset);
204
205private:
206			RWLockManager		fLockManager;
207			Locker				fLock;
208			fuse_fs*			fFS;
209			FUSEEntryTable		fEntries;
210			FUSENodeTable		fNodes;
211			FUSENode*			fRootNode;
212			ino_t				fNextNodeID;
213			bool				fUseNodeIDs;	// TODO: Actually read the
214												// option!
215			char				fName[B_OS_NAME_LENGTH];
216};
217
218}	// namespace UserlandFS
219
220using UserlandFS::FUSEVolume;
221
222#endif	// USERLAND_FS_FUSE_VOLUME_H
223