xref: /haiku/src/add-ons/kernel/file_systems/bfs/Volume.h (revision e79e4e7c9e432c90415f79809b7160e864f79001)
1 #ifndef VOLUME_H
2 #define VOLUME_H
3 /* Volume - BFS super block, mounting, etc.
4 **
5 ** Initial version by Axel Dörfler, axeld@pinc-software.de
6 ** This file may be used under the terms of the OpenBeOS License.
7 */
8 
9 
10 #include <KernelExport.h>
11 
12 extern "C" {
13 	#ifndef _IMPEXP_KERNEL
14 	#	define _IMPEXP_KERNEL
15 	#endif
16 	#include "fsproto.h"
17 	#include "lock.h"
18 	#include "cache.h"
19 }
20 
21 #include "bfs.h"
22 #include "BlockAllocator.h"
23 #include "BufferPool.h"
24 #include "Chain.h"
25 
26 class Journal;
27 class Inode;
28 class Query;
29 
30 enum volume_flags {
31 	VOLUME_READ_ONLY	= 0x0001
32 };
33 
34 
35 class Volume {
36 	public:
37 		Volume(nspace_id id);
38 		~Volume();
39 
40 		status_t			Mount(const char *device, uint32 flags);
41 		status_t			Unmount();
42 
43 		bool				IsValidSuperBlock();
44 		bool				IsReadOnly() const;
45 		void				Panic();
46 		RecursiveLock		&Lock();
47 
48 		block_run			Root() const { return fSuperBlock.root_dir; }
49 		Inode				*RootNode() const { return fRootNode; }
50 		block_run			Indices() const { return fSuperBlock.indices; }
51 		Inode				*IndicesNode() const { return fIndicesNode; }
52 		block_run			Log() const { return fSuperBlock.log_blocks; }
53 		vint32				&LogStart() { return fLogStart; }
54 		vint32				&LogEnd() { return fLogEnd; }
55 		int					Device() const { return fDevice; }
56 
57 		nspace_id			ID() const { return fID; }
58 		const char			*Name() const { return fSuperBlock.name; }
59 
60 		off_t				NumBlocks() const { return fSuperBlock.NumBlocks(); }
61 		off_t				UsedBlocks() const { return fSuperBlock.UsedBlocks(); }
62 		off_t				FreeBlocks() const { return NumBlocks() - UsedBlocks(); }
63 
64 		uint32				BlockSize() const { return fBlockSize; }
65 		uint32				BlockShift() const { return fBlockShift; }
66 		uint32				InodeSize() const { return fSuperBlock.InodeSize(); }
67 		uint32				AllocationGroups() const { return fSuperBlock.AllocationGroups(); }
68 		uint32				AllocationGroupShift() const { return fAllocationGroupShift; }
69 		disk_super_block	&SuperBlock() { return fSuperBlock; }
70 
71 		off_t				ToOffset(block_run run) const { return ToBlock(run) << BlockShift(); }
72 		off_t				ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); }
73 		block_run			ToBlockRun(off_t block) const;
74 		status_t			ValidateBlockRun(block_run run);
75 
76 		off_t				ToVnode(block_run run) const { return ToBlock(run); }
77 		off_t				ToVnode(off_t block) const { return block; }
78 		off_t				VnodeToBlock(vnode_id id) const { return (off_t)id; }
79 
80 		status_t			CreateIndicesRoot(Transaction *transaction);
81 
82 		// block bitmap
83 		BlockAllocator		&Allocator();
84 		status_t			AllocateForInode(Transaction *transaction, const Inode *parent,
85 								mode_t type, block_run &run);
86 		status_t			AllocateForInode(Transaction *transaction, const block_run *parent,
87 								mode_t type, block_run &run);
88 		status_t			Allocate(Transaction *transaction,const Inode *inode,
89 								off_t numBlocks, block_run &run, uint16 minimum = 1);
90 		status_t			Free(Transaction *transaction, block_run run);
91 
92 		// cache access
93 		status_t			WriteSuperBlock();
94 		status_t			WriteBlocks(off_t blockNumber, const uint8 *block, uint32 numBlocks);
95 		void				WriteCachedBlocksIfNecessary();
96 		status_t			FlushDevice();
97 
98 		// queries
99 		void				UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
100 								const uint8 *oldKey, size_t oldLength,
101 								const uint8 *newKey, size_t newLength);
102 		bool				CheckForLiveQuery(const char *attribute);
103 		void				AddQuery(Query *query);
104 		void				RemoveQuery(Query *query);
105 
106 		status_t			Sync();
107 		Journal				*GetJournal(off_t refBlock) const;
108 
109 		BufferPool			&Pool();
110 
111 		uint32				GetUniqueID();
112 
113 	protected:
114 		nspace_id			fID;
115 		int					fDevice;
116 		disk_super_block	fSuperBlock;
117 
118 		uint32				fBlockSize;
119 		uint32				fBlockShift;
120 		uint32				fAllocationGroupShift;
121 
122 		BlockAllocator		fBlockAllocator;
123 		RecursiveLock		fLock;
124 		Journal				*fJournal;
125 		vint32				fLogStart, fLogEnd;
126 
127 		Inode				*fRootNode;
128 		Inode				*fIndicesNode;
129 
130 		vint32				fDirtyCachedBlocks;
131 
132 		SimpleLock			fQueryLock;
133 		Chain<Query>		fQueries;
134 
135 		int32				fUniqueID;
136 		uint32				fFlags;
137 
138 		BufferPool			fBufferPool;
139 };
140 
141 
142 // inline functions
143 
144 inline bool
145 Volume::IsReadOnly() const
146 {
147 	 return fFlags & VOLUME_READ_ONLY;
148 }
149 
150 
151 inline RecursiveLock &
152 Volume::Lock()
153 {
154 	 return fLock;
155 }
156 
157 
158 inline BlockAllocator &
159 Volume::Allocator()
160 {
161 	 return fBlockAllocator;
162 }
163 
164 
165 inline status_t
166 Volume::AllocateForInode(Transaction *transaction, const block_run *parent, mode_t type, block_run &run)
167 {
168 	return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
169 }
170 
171 
172 inline status_t
173 Volume::Allocate(Transaction *transaction, const Inode *inode, off_t numBlocks, block_run &run, uint16 minimum)
174 {
175 	return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, minimum);
176 }
177 
178 
179 inline status_t
180 Volume::Free(Transaction *transaction, block_run run)
181 {
182 	return fBlockAllocator.Free(transaction, run);
183 }
184 
185 
186 inline status_t
187 Volume::WriteBlocks(off_t blockNumber, const uint8 *block, uint32 numBlocks)
188 {
189 	atomic_add(&fDirtyCachedBlocks, numBlocks);
190 	return cached_write(fDevice, blockNumber, block, numBlocks, fSuperBlock.block_size);
191 }
192 
193 
194 inline void
195 Volume::WriteCachedBlocksIfNecessary()
196 {
197 	// the specific values are only valid for the current BeOS cache
198 	if (fDirtyCachedBlocks > 128) {
199 		force_cache_flush(fDevice, false);
200 		atomic_add(&fDirtyCachedBlocks, -64);
201 	}
202 }
203 
204 
205 inline status_t
206 Volume::FlushDevice()
207 {
208 	fDirtyCachedBlocks = 0;
209 	return flush_device(fDevice, 0);
210 }
211 
212 
213 inline Journal *
214 Volume::GetJournal(off_t /*refBlock*/) const
215 {
216 	 return fJournal;
217 }
218 
219 
220 inline BufferPool &
221 Volume::Pool()
222 {
223 	 return fBufferPool;
224 }
225 
226 
227 inline uint32
228 Volume::GetUniqueID()
229 {
230 	 return atomic_add(&fUniqueID, 1);
231 }
232 
233 #endif	/* VOLUME_H */
234