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 static status_t CheckSuperBlock(const uint8* data, 130 uint32* _offset = NULL); 131 static status_t Identify(int fd, disk_super_block* superBlock); 132 133 protected: 134 fs_volume* fVolume; 135 int fDevice; 136 disk_super_block fSuperBlock; 137 138 uint32 fBlockSize; 139 uint32 fBlockShift; 140 uint32 fAllocationGroupShift; 141 142 BlockAllocator fBlockAllocator; 143 mutex fLock; 144 Journal* fJournal; 145 vint32 fLogStart; 146 vint32 fLogEnd; 147 148 Inode* fRootNode; 149 Inode* fIndicesNode; 150 151 vint32 fDirtyCachedBlocks; 152 153 mutex fQueryLock; 154 SinglyLinkedList<Query> fQueries; 155 156 uint32 fFlags; 157 158 void* fBlockCache; 159 thread_id fCheckingThread; 160 161 InodeList fRemovedInodes; 162 }; 163 164 165 // inline functions 166 167 inline bool 168 Volume::IsReadOnly() const 169 { 170 return fFlags & VOLUME_READ_ONLY; 171 } 172 173 174 inline mutex& 175 Volume::Lock() 176 { 177 return fLock; 178 } 179 180 181 inline BlockAllocator& 182 Volume::Allocator() 183 { 184 return fBlockAllocator; 185 } 186 187 188 inline status_t 189 Volume::AllocateForInode(Transaction& transaction, const block_run* parent, 190 mode_t type, block_run& run) 191 { 192 return fBlockAllocator.AllocateForInode(transaction, parent, type, run); 193 } 194 195 196 inline status_t 197 Volume::Allocate(Transaction& transaction, Inode* inode, off_t numBlocks, 198 block_run& run, uint16 minimum) 199 { 200 return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, 201 minimum); 202 } 203 204 205 inline status_t 206 Volume::Free(Transaction& transaction, block_run run) 207 { 208 return fBlockAllocator.Free(transaction, run); 209 } 210 211 212 inline status_t 213 Volume::FlushDevice() 214 { 215 return block_cache_sync(fBlockCache); 216 } 217 218 219 inline Journal* 220 Volume::GetJournal(off_t /*refBlock*/) const 221 { 222 return fJournal; 223 } 224 225 226 #endif // VOLUME_H 227