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
17class Inode;
18class Journal;
19
20
21enum volume_flags {
22	VOLUME_READ_ONLY	= 0x0001
23};
24
25
26class Volume : public TransactionListener {
27public:
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				HasJournalFeature() const
84								{ return (fSuperBlock.CompatibleFeatures()
85									& EXT2_FEATURE_HAS_JOURNAL) != 0; }
86			bool				Has64bitFeature() const
87								{ return (fSuperBlock.IncompatibleFeatures()
88									& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
89			bool				HasExtentsFeature() const
90								{ return (fSuperBlock.IncompatibleFeatures()
91									& EXT2_INCOMPATIBLE_FEATURE_EXTENTS)
92									!= 0; }
93			bool				HasChecksumFeature() const
94								{ return (fSuperBlock.ReadOnlyFeatures()
95									& EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; }
96			bool				HasMetaGroupFeature() const
97								{ return (fSuperBlock.IncompatibleFeatures()
98									& EXT2_INCOMPATIBLE_FEATURE_META_GROUP)
99									!= 0; }
100			bool				HasMetaGroupChecksumFeature() const
101								{ return (fSuperBlock.ReadOnlyFeatures()
102									& EXT4_READ_ONLY_FEATURE_METADATA_CSUM)
103									!= 0; }
104			bool				HasChecksumSeedFeature() const
105								{ return (fSuperBlock.IncompatibleFeatures()
106									& EXT2_INCOMPATIBLE_FEATURE_CSUM_SEED)
107									!= 0; }
108			uint8				DefaultHashVersion() const
109								{ return fSuperBlock.default_hash_version; }
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
137			void*				BlockCache() { return fBlockCache; }
138
139			uint32				ChecksumSeed() const
140									{ return fChecksumSeed; }
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
153private:
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
164private:
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
196inline mutex&
197Volume::Lock()
198{
199	 return fLock;
200}
201
202#endif	// VOLUME_H
203