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