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