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