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