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.CompatibleFeatures() 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 uint8 DefaultHashVersion() const 98 { return fSuperBlock.default_hash_version; } 99 bool HugeFiles() const 100 { return (fSuperBlock.ReadOnlyFeatures() 101 & EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; } 102 status_t ActivateLargeFiles(Transaction& transaction); 103 status_t ActivateDirNLink(Transaction& transaction); 104 105 status_t SaveOrphan(Transaction& transaction, 106 ino_t newID, ino_t &oldID); 107 status_t RemoveOrphan(Transaction& transaction, 108 ino_t id); 109 110 status_t AllocateInode(Transaction& transaction, 111 Inode* parent, int32 mode, ino_t& id); 112 status_t FreeInode(Transaction& transaction, ino_t id, 113 bool isDirectory); 114 115 status_t AllocateBlocks(Transaction& transaction, 116 uint32 minimum, uint32 maximum, 117 uint32& blockGroup, fsblock_t& start, 118 uint32& length); 119 status_t FreeBlocks(Transaction& transaction, 120 fsblock_t start, uint32 length); 121 122 status_t LoadSuperBlock(); 123 status_t WriteSuperBlock(Transaction& transaction); 124 125 // cache access 126 void* BlockCache() { return fBlockCache; } 127 128 status_t FlushDevice(); 129 status_t Sync(); 130 131 static status_t Identify(int fd, ext2_super_block* superBlock); 132 133 // TransactionListener functions 134 void TransactionDone(bool success); 135 void RemovedFromTransaction(); 136 137 private: 138 static uint32 _UnsupportedIncompatibleFeatures( 139 ext2_super_block& superBlock); 140 static uint32 _UnsupportedReadOnlyFeatures( 141 ext2_super_block& superBlock); 142 uint32 _GroupDescriptorBlock(uint32 blockIndex); 143 uint16 _GroupDescriptorSize() 144 { return fGroupDescriptorSize; } 145 uint16 _GroupCheckSum(ext2_block_group *group, 146 int32 index); 147 148 private: 149 mutex fLock; 150 fs_volume* fFSVolume; 151 int fDevice; 152 ext2_super_block fSuperBlock; 153 char fName[32]; 154 155 BlockAllocator* fBlockAllocator; 156 InodeAllocator fInodeAllocator; 157 Journal* fJournal; 158 Inode* fJournalInode; 159 160 uint32 fFlags; 161 uint32 fBlockSize; 162 uint32 fBlockShift; 163 uint32 fFirstDataBlock; 164 165 uint32 fNumInodes; 166 uint32 fNumGroups; 167 off_t fFreeBlocks; 168 uint32 fFreeInodes; 169 uint32 fGroupsPerBlock; 170 uint8** fGroupBlocks; 171 uint32 fInodesPerBlock; 172 uint16 fGroupDescriptorSize; 173 174 void* fBlockCache; 175 Inode* fRootNode; 176 }; 177 178 179 inline mutex& 180 Volume::Lock() 181 { 182 return fLock; 183 } 184 185 #endif // VOLUME_H 186