1 /* 2 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 3 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 4 * This file may be used under the terms of the MIT License. 5 */ 6 #ifndef VOLUME_H 7 #define VOLUME_H 8 9 10 #include <lock.h> 11 12 #include "ext2.h" 13 #include "BlockAllocator.h" 14 #include "InodeAllocator.h" 15 #include "Transaction.h" 16 17 class Inode; 18 class Journal; 19 20 21 enum volume_flags { 22 VOLUME_READ_ONLY = 0x0001 23 }; 24 25 26 class Volume : public TransactionListener { 27 public: 28 Volume(fs_volume* volume); 29 ~Volume(); 30 31 status_t Mount(const char* device, uint32 flags); 32 status_t Unmount(); 33 34 bool IsValidSuperBlock(); 35 bool IsReadOnly() const 36 { return (fFlags & VOLUME_READ_ONLY) != 0; } 37 mutex& Lock(); 38 bool HasExtendedAttributes() const; 39 40 Inode* RootNode() const { return fRootNode; } 41 int Device() const { return fDevice; } 42 43 dev_t ID() const 44 { return fFSVolume ? fFSVolume->id : -1; } 45 fs_volume* FSVolume() const { return fFSVolume; } 46 const char* Name() const; 47 void SetName(const char* name); 48 49 uint32 NumInodes() const 50 { return fNumInodes; } 51 uint32 NumGroups() const 52 { return fNumGroups; } 53 fsblock_t NumBlocks() const 54 { return fSuperBlock.NumBlocks( 55 Has64bitFeature()); } 56 off_t NumFreeBlocks() const 57 { return fFreeBlocks; } 58 uint32 FirstDataBlock() const 59 { return fFirstDataBlock; } 60 61 uint32 BlockSize() const { return fBlockSize; } 62 uint32 BlockShift() const { return fBlockShift; } 63 uint32 BlocksPerGroup() const 64 { return fSuperBlock.BlocksPerGroup(); } 65 uint32 InodeSize() const 66 { return fSuperBlock.InodeSize(); } 67 uint32 InodesPerGroup() const 68 { return fSuperBlock.InodesPerGroup(); } 69 ext2_super_block& SuperBlock() { return fSuperBlock; } 70 71 status_t GetInodeBlock(ino_t id, off_t& block); 72 uint32 InodeBlockIndex(ino_t id) const; 73 status_t GetBlockGroup(int32 index, 74 ext2_block_group** _group); 75 status_t WriteBlockGroup(Transaction& transaction, 76 int32 index); 77 78 Journal* GetJournal() { return fJournal; } 79 80 bool IndexedDirectories() const 81 { return (fSuperBlock.CompatibleFeatures() 82 & EXT2_FEATURE_DIRECTORY_INDEX) != 0; } 83 bool Has64bitFeature() const 84 { return (fSuperBlock.IncompatibleFeatures() 85 & EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; } 86 bool HasExtentsFeature() const 87 { return (fSuperBlock.IncompatibleFeatures() 88 & EXT2_INCOMPATIBLE_FEATURE_EXTENTS) 89 != 0; } 90 bool HasChecksumFeature() const 91 { return (fSuperBlock.ReadOnlyFeatures() 92 & EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; } 93 bool HasMetaGroupFeature() const 94 { return (fSuperBlock.IncompatibleFeatures() 95 & EXT2_INCOMPATIBLE_FEATURE_META_GROUP) 96 != 0; } 97 bool HasMetaGroupChecksumFeature() const 98 { return (fSuperBlock.ReadOnlyFeatures() 99 & EXT4_READ_ONLY_FEATURE_METADATA_CSUM) 100 != 0; } 101 bool HasChecksumSeedFeature() const 102 { return (fSuperBlock.IncompatibleFeatures() 103 & EXT2_INCOMPATIBLE_FEATURE_CSUM_SEED) 104 != 0; } 105 uint8 DefaultHashVersion() const 106 { return fSuperBlock.default_hash_version; } 107 bool HugeFiles() const 108 { return (fSuperBlock.ReadOnlyFeatures() 109 & EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; } 110 status_t ActivateLargeFiles(Transaction& transaction); 111 status_t ActivateDirNLink(Transaction& transaction); 112 113 status_t SaveOrphan(Transaction& transaction, 114 ino_t newID, ino_t &oldID); 115 status_t RemoveOrphan(Transaction& transaction, 116 ino_t id); 117 118 status_t AllocateInode(Transaction& transaction, 119 Inode* parent, int32 mode, ino_t& id); 120 status_t FreeInode(Transaction& transaction, ino_t id, 121 bool isDirectory); 122 123 status_t AllocateBlocks(Transaction& transaction, 124 uint32 minimum, uint32 maximum, 125 uint32& blockGroup, fsblock_t& start, 126 uint32& length); 127 status_t FreeBlocks(Transaction& transaction, 128 fsblock_t start, uint32 length); 129 130 status_t LoadSuperBlock(); 131 status_t WriteSuperBlock(Transaction& transaction); 132 133 // cache access 134 void* BlockCache() { return fBlockCache; } 135 136 uint32 ChecksumSeed() const 137 { return fChecksumSeed; } 138 uint16 GroupDescriptorSize() const 139 { return fGroupDescriptorSize; } 140 141 status_t FlushDevice(); 142 status_t Sync(); 143 144 static status_t Identify(int fd, ext2_super_block* superBlock); 145 146 // TransactionListener functions 147 void TransactionDone(bool success); 148 void RemovedFromTransaction(); 149 150 private: 151 static uint32 _UnsupportedIncompatibleFeatures( 152 ext2_super_block& superBlock); 153 static uint32 _UnsupportedReadOnlyFeatures( 154 ext2_super_block& superBlock); 155 uint32 _GroupDescriptorBlock(uint32 blockIndex); 156 uint16 _GroupCheckSum(ext2_block_group *group, 157 int32 index); 158 void _SuperBlockChecksumSeed(); 159 bool _VerifySuperBlock(); 160 161 private: 162 mutex fLock; 163 fs_volume* fFSVolume; 164 int fDevice; 165 ext2_super_block fSuperBlock; 166 char fName[32]; 167 168 BlockAllocator* fBlockAllocator; 169 InodeAllocator fInodeAllocator; 170 Journal* fJournal; 171 Inode* fJournalInode; 172 173 uint32 fFlags; 174 uint32 fBlockSize; 175 uint32 fBlockShift; 176 uint32 fFirstDataBlock; 177 178 uint32 fNumInodes; 179 uint32 fNumGroups; 180 off_t fFreeBlocks; 181 uint32 fFreeInodes; 182 uint32 fGroupsPerBlock; 183 uint8** fGroupBlocks; 184 uint32 fInodesPerBlock; 185 uint16 fGroupDescriptorSize; 186 187 void* fBlockCache; 188 Inode* fRootNode; 189 190 uint32 fChecksumSeed; 191 }; 192 193 194 inline mutex& 195 Volume::Lock() 196 { 197 return fLock; 198 } 199 200 #endif // VOLUME_H 201