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