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();
IsReadOnly()35 bool IsReadOnly() const
36 { return (fFlags & VOLUME_READ_ONLY) != 0; }
37 mutex& Lock();
38 bool HasExtendedAttributes() const;
39
RootNode()40 Inode* RootNode() const { return fRootNode; }
Device()41 int Device() const { return fDevice; }
42
ID()43 dev_t ID() const
44 { return fFSVolume ? fFSVolume->id : -1; }
FSVolume()45 fs_volume* FSVolume() const { return fFSVolume; }
46 const char* Name() const;
47 void SetName(const char* name);
48
NumInodes()49 uint32 NumInodes() const
50 { return fNumInodes; }
NumGroups()51 uint32 NumGroups() const
52 { return fNumGroups; }
NumBlocks()53 fsblock_t NumBlocks() const
54 { return fSuperBlock.NumBlocks(
55 Has64bitFeature()); }
NumFreeBlocks()56 off_t NumFreeBlocks() const
57 { return fFreeBlocks; }
FirstDataBlock()58 uint32 FirstDataBlock() const
59 { return fFirstDataBlock; }
60
BlockSize()61 uint32 BlockSize() const { return fBlockSize; }
BlockShift()62 uint32 BlockShift() const { return fBlockShift; }
BlocksPerGroup()63 uint32 BlocksPerGroup() const
64 { return fSuperBlock.BlocksPerGroup(); }
InodeSize()65 uint32 InodeSize() const
66 { return fSuperBlock.InodeSize(); }
InodesPerGroup()67 uint32 InodesPerGroup() const
68 { return fSuperBlock.InodesPerGroup(); }
SuperBlock()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
GetJournal()78 Journal* GetJournal() { return fJournal; }
79
IndexedDirectories()80 bool IndexedDirectories() const
81 { return (fSuperBlock.CompatibleFeatures()
82 & EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
HasJournalFeature()83 bool HasJournalFeature() const
84 { return (fSuperBlock.CompatibleFeatures()
85 & EXT2_FEATURE_HAS_JOURNAL) != 0; }
Has64bitFeature()86 bool Has64bitFeature() const
87 { return (fSuperBlock.IncompatibleFeatures()
88 & EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
HasExtentsFeature()89 bool HasExtentsFeature() const
90 { return (fSuperBlock.IncompatibleFeatures()
91 & EXT2_INCOMPATIBLE_FEATURE_EXTENTS)
92 != 0; }
HasChecksumFeature()93 bool HasChecksumFeature() const
94 { return (fSuperBlock.ReadOnlyFeatures()
95 & EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; }
HasMetaGroupFeature()96 bool HasMetaGroupFeature() const
97 { return (fSuperBlock.IncompatibleFeatures()
98 & EXT2_INCOMPATIBLE_FEATURE_META_GROUP)
99 != 0; }
HasMetaGroupChecksumFeature()100 bool HasMetaGroupChecksumFeature() const
101 { return (fSuperBlock.ReadOnlyFeatures()
102 & EXT4_READ_ONLY_FEATURE_METADATA_CSUM)
103 != 0; }
HasChecksumSeedFeature()104 bool HasChecksumSeedFeature() const
105 { return (fSuperBlock.IncompatibleFeatures()
106 & EXT2_INCOMPATIBLE_FEATURE_CSUM_SEED)
107 != 0; }
DefaultHashVersion()108 uint8 DefaultHashVersion() const
109 { return fSuperBlock.default_hash_version; }
HugeFiles()110 bool HugeFiles() const
111 { return (fSuperBlock.ReadOnlyFeatures()
112 & EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; }
113 status_t ActivateLargeFiles(Transaction& transaction);
114 status_t ActivateDirNLink(Transaction& transaction);
115
116 status_t SaveOrphan(Transaction& transaction,
117 ino_t newID, ino_t &oldID);
118 status_t RemoveOrphan(Transaction& transaction,
119 ino_t id);
120
121 status_t AllocateInode(Transaction& transaction,
122 Inode* parent, int32 mode, ino_t& id);
123 status_t FreeInode(Transaction& transaction, ino_t id,
124 bool isDirectory);
125
126 status_t AllocateBlocks(Transaction& transaction,
127 uint32 minimum, uint32 maximum,
128 uint32& blockGroup, fsblock_t& start,
129 uint32& length);
130 status_t FreeBlocks(Transaction& transaction,
131 fsblock_t start, uint32 length);
132
133 status_t LoadSuperBlock();
134 status_t WriteSuperBlock(Transaction& transaction);
135
136 // cache access
BlockCache()137 void* BlockCache() { return fBlockCache; }
138
ChecksumSeed()139 uint32 ChecksumSeed() const
140 { return fChecksumSeed; }
GroupDescriptorSize()141 uint16 GroupDescriptorSize() const
142 { return fGroupDescriptorSize; }
143
144 status_t FlushDevice();
145 status_t Sync();
146
147 static status_t Identify(int fd, ext2_super_block* superBlock);
148
149 // TransactionListener functions
150 void TransactionDone(bool success);
151 void RemovedFromTransaction();
152
153 private:
154 static uint32 _UnsupportedIncompatibleFeatures(
155 ext2_super_block& superBlock);
156 static uint32 _UnsupportedReadOnlyFeatures(
157 ext2_super_block& superBlock);
158 uint32 _GroupDescriptorBlock(uint32 blockIndex);
159 uint16 _GroupCheckSum(ext2_block_group *group,
160 int32 index);
161 void _SuperBlockChecksumSeed();
162 bool _VerifySuperBlock();
163
164 private:
165 mutex fLock;
166 fs_volume* fFSVolume;
167 int fDevice;
168 ext2_super_block fSuperBlock;
169
170 BlockAllocator* fBlockAllocator;
171 InodeAllocator fInodeAllocator;
172 Journal* fJournal;
173 Inode* fJournalInode;
174
175 uint32 fFlags;
176 uint32 fBlockSize;
177 uint32 fBlockShift;
178 uint32 fFirstDataBlock;
179
180 uint32 fNumInodes;
181 uint32 fNumGroups;
182 off_t fFreeBlocks;
183 uint32 fFreeInodes;
184 uint32 fGroupsPerBlock;
185 uint8** fGroupBlocks;
186 uint32 fInodesPerBlock;
187 uint16 fGroupDescriptorSize;
188
189 void* fBlockCache;
190 Inode* fRootNode;
191
192 uint32 fChecksumSeed;
193 };
194
195
196 inline mutex&
Lock()197 Volume::Lock()
198 {
199 return fLock;
200 }
201
202 #endif // VOLUME_H
203