xref: /haiku/src/add-ons/kernel/file_systems/bfs/Volume.h (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
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 		Semaphore			&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.num_blocks; }
61 		off_t				UsedBlocks() const { return fSuperBlock.used_blocks; }
62 		off_t				FreeBlocks() const { return fSuperBlock.num_blocks - fSuperBlock.used_blocks; }
63 
64 		uint32				BlockSize() const { return fSuperBlock.block_size; }
65 		uint32				BlockShift() const { return fSuperBlock.block_shift; }
66 		uint32				InodeSize() const { return fSuperBlock.inode_size; }
67 		uint32				AllocationGroups() const { return fSuperBlock.num_ags; }
68 		uint32				AllocationGroupShift() const { return fSuperBlock.ag_shift; }
69 		disk_super_block	&SuperBlock() { return fSuperBlock; }
70 
71 		off_t				ToOffset(block_run run) const { return ToBlock(run) << fSuperBlock.block_shift; }
72 		off_t				ToBlock(block_run run) const { return ((((off_t)run.allocation_group) << fSuperBlock.ag_shift) | (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 		void				AddQuery(Query *query);
103 		void				RemoveQuery(Query *query);
104 
105 		status_t			Sync();
106 		Journal				*GetJournal(off_t refBlock) const;
107 
108 		BufferPool			&Pool();
109 
110 		uint32				GetUniqueID();
111 
112 	protected:
113 		nspace_id			fID;
114 		int					fDevice;
115 		disk_super_block	fSuperBlock;
116 		BlockAllocator		fBlockAllocator;
117 		Semaphore			fLock;
118 		Journal				*fJournal;
119 		vint32				fLogStart, fLogEnd;
120 
121 		Inode				*fRootNode;
122 		Inode				*fIndicesNode;
123 
124 		vint32				fDirtyCachedBlocks;
125 
126 		SimpleLock			fQueryLock;
127 		Chain<Query>		fQueries;
128 
129 		int32				fUniqueID;
130 		uint32				fFlags;
131 
132 		BufferPool			fBufferPool;
133 };
134 
135 
136 // inline functions
137 
138 inline bool
139 Volume::IsReadOnly() const
140 {
141 	 return fFlags & VOLUME_READ_ONLY;
142 }
143 
144 
145 inline Semaphore &
146 Volume::Lock()
147 {
148 	 return fLock;
149 }
150 
151 
152 inline BlockAllocator &
153 Volume::Allocator()
154 {
155 	 return fBlockAllocator;
156 }
157 
158 
159 inline status_t
160 Volume::AllocateForInode(Transaction *transaction, const block_run *parent, mode_t type, block_run &run)
161 {
162 	return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
163 }
164 
165 
166 inline status_t
167 Volume::Allocate(Transaction *transaction, const Inode *inode, off_t numBlocks, block_run &run, uint16 minimum)
168 {
169 	return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, minimum);
170 }
171 
172 
173 inline status_t
174 Volume::Free(Transaction *transaction, block_run run)
175 {
176 	return fBlockAllocator.Free(transaction, run);
177 }
178 
179 
180 inline status_t
181 Volume::WriteBlocks(off_t blockNumber, const uint8 *block, uint32 numBlocks)
182 {
183 	atomic_add(&fDirtyCachedBlocks, numBlocks);
184 	return cached_write(fDevice, blockNumber, block, numBlocks, fSuperBlock.block_size);
185 }
186 
187 
188 inline void
189 Volume::WriteCachedBlocksIfNecessary()
190 {
191 	// the specific values are only valid for the current BeOS cache
192 	if (fDirtyCachedBlocks > 128) {
193 		force_cache_flush(fDevice, false);
194 		atomic_add(&fDirtyCachedBlocks, -64);
195 	}
196 }
197 
198 
199 inline status_t
200 Volume::FlushDevice()
201 {
202 	fDirtyCachedBlocks = 0;
203 	return flush_device(fDevice, 0);
204 }
205 
206 
207 inline Journal *
208 Volume::GetJournal(off_t /*refBlock*/) const
209 {
210 	 return fJournal;
211 }
212 
213 
214 inline BufferPool &
215 Volume::Pool()
216 {
217 	 return fBufferPool;
218 }
219 
220 
221 inline uint32
222 Volume::GetUniqueID()
223 {
224 	 return atomic_add(&fUniqueID, 1);
225 }
226 
227 #endif	/* VOLUME_H */
228