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