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 status_t CreateVolumeID(Transaction& transaction); 96 97 InodeList& RemovedInodes() { return fRemovedInodes; } 98 // This list is guarded by the transaction lock 99 100 // block bitmap 101 BlockAllocator& Allocator(); 102 status_t AllocateForInode(Transaction& transaction, 103 const Inode* parent, mode_t type, 104 block_run& run); 105 status_t AllocateForInode(Transaction& transaction, 106 const block_run* parent, mode_t type, 107 block_run& run); 108 status_t Allocate(Transaction& transaction, Inode* inode, 109 off_t numBlocks, block_run& run, 110 uint16 minimum = 1); 111 status_t Free(Transaction& transaction, block_run run); 112 void SetCheckingThread(thread_id thread) 113 { fCheckingThread = thread; } 114 bool IsCheckingThread() const 115 { return find_thread(NULL) == fCheckingThread; } 116 117 // cache access 118 status_t WriteSuperBlock(); 119 status_t FlushDevice(); 120 121 // queries 122 void UpdateLiveQueries(Inode* inode, 123 const char* attribute, int32 type, 124 const uint8* oldKey, size_t oldLength, 125 const uint8* newKey, size_t newLength); 126 void UpdateLiveQueriesRenameMove(Inode* inode, 127 ino_t oldDirectoryID, const char* oldName, 128 ino_t newDirectoryID, const char* newName); 129 130 bool CheckForLiveQuery(const char* attribute); 131 void AddQuery(Query* query); 132 void RemoveQuery(Query* query); 133 134 status_t Sync(); 135 Journal* GetJournal(off_t refBlock) const; 136 137 void* BlockCache() { return fBlockCache; } 138 139 static status_t CheckSuperBlock(const uint8* data, 140 uint32* _offset = NULL); 141 static status_t Identify(int fd, disk_super_block* superBlock); 142 143 protected: 144 fs_volume* fVolume; 145 int fDevice; 146 disk_super_block fSuperBlock; 147 148 uint32 fDeviceBlockSize; 149 uint32 fBlockSize; 150 uint32 fBlockShift; 151 uint32 fAllocationGroupShift; 152 153 BlockAllocator fBlockAllocator; 154 mutex fLock; 155 Journal* fJournal; 156 vint32 fLogStart; 157 vint32 fLogEnd; 158 159 Inode* fRootNode; 160 Inode* fIndicesNode; 161 162 vint32 fDirtyCachedBlocks; 163 164 mutex fQueryLock; 165 SinglyLinkedList<Query> fQueries; 166 167 uint32 fFlags; 168 169 void* fBlockCache; 170 thread_id fCheckingThread; 171 172 InodeList fRemovedInodes; 173 }; 174 175 176 // inline functions 177 178 inline bool 179 Volume::IsReadOnly() const 180 { 181 return fFlags & VOLUME_READ_ONLY; 182 } 183 184 185 inline mutex& 186 Volume::Lock() 187 { 188 return fLock; 189 } 190 191 192 inline BlockAllocator& 193 Volume::Allocator() 194 { 195 return fBlockAllocator; 196 } 197 198 199 inline status_t 200 Volume::AllocateForInode(Transaction& transaction, const block_run* parent, 201 mode_t type, block_run& run) 202 { 203 return fBlockAllocator.AllocateForInode(transaction, parent, type, run); 204 } 205 206 207 inline status_t 208 Volume::Allocate(Transaction& transaction, Inode* inode, off_t numBlocks, 209 block_run& run, uint16 minimum) 210 { 211 return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, 212 minimum); 213 } 214 215 216 inline status_t 217 Volume::Free(Transaction& transaction, block_run run) 218 { 219 return fBlockAllocator.Free(transaction, run); 220 } 221 222 223 inline status_t 224 Volume::FlushDevice() 225 { 226 return block_cache_sync(fBlockCache); 227 } 228 229 230 inline Journal* 231 Volume::GetJournal(off_t /*refBlock*/) const 232 { 233 return fJournal; 234 } 235 236 237 #endif // VOLUME_H 238