xref: /haiku/src/add-ons/kernel/file_systems/bfs/Volume.h (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2001-2012, Axel Dörfler, axeld@pinc-software.de.
3  * This file may be used under the terms of the MIT License.
4  */
5 #ifndef VOLUME_H
6 #define VOLUME_H
7 
8 
9 #include "system_dependencies.h"
10 
11 #include "bfs.h"
12 #include "BlockAllocator.h"
13 
14 
15 class CheckVisitor;
16 class Journal;
17 class Inode;
18 class Query;
19 
20 
21 enum volume_flags {
22 	VOLUME_READ_ONLY	= 0x0001
23 };
24 
25 enum volume_initialize_flags {
26 	VOLUME_NO_INDICES	= 0x0001,
27 };
28 
29 typedef DoublyLinkedList<Inode> InodeList;
30 
31 
32 class Volume {
33 public:
34 							Volume(fs_volume* volume);
35 							~Volume();
36 
37 			status_t		Mount(const char* device, uint32 flags);
38 			status_t		Unmount();
39 			status_t		Initialize(int fd, const char* name,
40 								uint32 blockSize, uint32 flags);
41 
42 			bool			IsInitializing() const { return fVolume == NULL; }
43 
44 			bool			IsValidSuperBlock() const;
45 			bool			IsValidInodeBlock(off_t block) const;
46 			bool			IsReadOnly() const;
47 			void			Panic();
48 			mutex&			Lock();
49 
50 			block_run		Root() const { return fSuperBlock.root_dir; }
51 			Inode*			RootNode() const { return fRootNode; }
52 			block_run		Indices() const { return fSuperBlock.indices; }
53 			Inode*			IndicesNode() const { return fIndicesNode; }
54 			block_run		Log() const { return fSuperBlock.log_blocks; }
55 			vint32&			LogStart() { return fLogStart; }
56 			vint32&			LogEnd() { return fLogEnd; }
57 			int				Device() const { return fDevice; }
58 
59 			dev_t			ID() const { return fVolume ? fVolume->id : -1; }
60 			fs_volume*		FSVolume() const { return fVolume; }
61 			const char*		Name() const { return fSuperBlock.name; }
62 
63 			off_t			NumBlocks() const
64 								{ return fSuperBlock.NumBlocks(); }
65 			off_t			UsedBlocks() const
66 								{ return fSuperBlock.UsedBlocks(); }
67 			off_t			FreeBlocks() const
68 								{ return NumBlocks() - UsedBlocks(); }
69 			off_t			NumBitmapBlocks() const
70 								{ return (NumBlocks() + fBlockSize * 8 - 1)
71 									/ (fBlockSize * 8); }
72 
73 			uint32			DeviceBlockSize() const { return fDeviceBlockSize; }
74 			uint32			BlockSize() const { return fBlockSize; }
75 			uint32			BlockShift() const { return fBlockShift; }
76 			uint32			InodeSize() const
77 								{ return fSuperBlock.InodeSize(); }
78 			uint32			AllocationGroups() const
79 								{ return fSuperBlock.AllocationGroups(); }
80 			uint32			AllocationGroupShift() const
81 								{ return fAllocationGroupShift; }
82 			disk_super_block& SuperBlock() { return fSuperBlock; }
83 
84 			off_t			ToOffset(block_run run) const
85 								{ return ToBlock(run) << BlockShift(); }
86 			off_t			ToBlock(block_run run) const
87 								{ return ((((off_t)run.AllocationGroup())
88 										<< AllocationGroupShift())
89 									| (off_t)run.Start()); }
90 			block_run		ToBlockRun(off_t block) const;
91 			status_t		ValidateBlockRun(block_run run);
92 
93 			off_t			ToVnode(block_run run) const
94 								{ return ToBlock(run); }
95 			off_t			ToVnode(off_t block) const { return block; }
96 			off_t			VnodeToBlock(ino_t id) const { return (off_t)id; }
97 
98 			status_t		CreateIndicesRoot(Transaction& transaction);
99 
100 			status_t		CreateVolumeID(Transaction& transaction);
101 
102 			InodeList&		RemovedInodes() { return fRemovedInodes; }
103 				// This list is guarded by the transaction lock
104 
105 			// block bitmap
106 			BlockAllocator&	Allocator();
107 			status_t		AllocateForInode(Transaction& transaction,
108 								const Inode* parent, mode_t type,
109 								block_run& run);
110 			status_t		AllocateForInode(Transaction& transaction,
111 								const block_run* parent, mode_t type,
112 								block_run& run);
113 			status_t		Allocate(Transaction& transaction, Inode* inode,
114 								off_t numBlocks, block_run& run,
115 								uint16 minimum = 1);
116 			status_t		Free(Transaction& transaction, block_run run);
117 			void			SetCheckingThread(thread_id thread)
118 								{ fCheckingThread = thread; }
119 			bool			IsCheckingThread() const
120 								{ return find_thread(NULL) == fCheckingThread; }
121 			status_t		CreateCheckVisitor();
122 			void			DeleteCheckVisitor();
123 			::CheckVisitor*	CheckVisitor() { return fCheckVisitor; }
124 
125 			// cache access
126 			status_t		WriteSuperBlock();
127 			status_t		FlushDevice();
128 
129 			// queries
130 			void			UpdateLiveQueries(Inode* inode,
131 								const char* attribute, int32 type,
132 								const uint8* oldKey, size_t oldLength,
133 								const uint8* newKey, size_t newLength);
134 			void			UpdateLiveQueriesRenameMove(Inode* inode,
135 								ino_t oldDirectoryID, const char* oldName,
136 								ino_t newDirectoryID, const char* newName);
137 
138 			bool			CheckForLiveQuery(const char* attribute);
139 			void			AddQuery(Query* query);
140 			void			RemoveQuery(Query* query);
141 
142 			status_t		Sync();
143 			Journal*		GetJournal(off_t refBlock) const;
144 
145 			void*			BlockCache() { return fBlockCache; }
146 
147 	static	status_t		CheckSuperBlock(const uint8* data,
148 								uint32* _offset = NULL);
149 	static	status_t		Identify(int fd, disk_super_block* superBlock);
150 
151 private:
152 			status_t		_EraseUnusedBootBlock();
153 
154 protected:
155 			fs_volume*		fVolume;
156 			int				fDevice;
157 			disk_super_block fSuperBlock;
158 
159 			uint32			fDeviceBlockSize;
160 			uint32			fBlockSize;
161 			uint32			fBlockShift;
162 			uint32			fAllocationGroupShift;
163 
164 			BlockAllocator	fBlockAllocator;
165 			mutex			fLock;
166 			Journal*		fJournal;
167 			vint32			fLogStart;
168 			vint32			fLogEnd;
169 
170 			Inode*			fRootNode;
171 			Inode*			fIndicesNode;
172 
173 			vint32			fDirtyCachedBlocks;
174 
175 			mutex			fQueryLock;
176 			DoublyLinkedList<Query> fQueries;
177 
178 			uint32			fFlags;
179 
180 			void*			fBlockCache;
181 			thread_id		fCheckingThread;
182 			::CheckVisitor*	fCheckVisitor;
183 
184 			InodeList		fRemovedInodes;
185 };
186 
187 
188 // inline functions
189 
190 inline bool
191 Volume::IsReadOnly() const
192 {
193 	 return fFlags & VOLUME_READ_ONLY;
194 }
195 
196 
197 inline mutex&
198 Volume::Lock()
199 {
200 	 return fLock;
201 }
202 
203 
204 inline BlockAllocator&
205 Volume::Allocator()
206 {
207 	 return fBlockAllocator;
208 }
209 
210 
211 inline status_t
212 Volume::AllocateForInode(Transaction& transaction, const block_run* parent,
213 	mode_t type, block_run& run)
214 {
215 	return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
216 }
217 
218 
219 inline status_t
220 Volume::Allocate(Transaction& transaction, Inode* inode, off_t numBlocks,
221 	block_run& run, uint16 minimum)
222 {
223 	return fBlockAllocator.Allocate(transaction, inode, numBlocks, run,
224 		minimum);
225 }
226 
227 
228 inline status_t
229 Volume::Free(Transaction& transaction, block_run run)
230 {
231 	return fBlockAllocator.Free(transaction, run);
232 }
233 
234 
235 inline status_t
236 Volume::FlushDevice()
237 {
238 	return block_cache_sync(fBlockCache);
239 }
240 
241 
242 inline Journal*
243 Volume::GetJournal(off_t /*refBlock*/) const
244 {
245 	 return fJournal;
246 }
247 
248 
249 #endif	// VOLUME_H
250