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