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