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