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