* Copyright 2011, JΓ©rΓ΄me Duval, korli@users.berlios.de.
* Copyright 2008-2010, Axel DΓΆrfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef VOLUME_H
#define VOLUME_H
#include <lock.h>
#include "ext2.h"
#include "BlockAllocator.h"
#include "InodeAllocator.h"
#include "Transaction.h"
class Inode;
class Journal;
enum volume_flags {
VOLUME_READ_ONLY = 0x0001
};
class Volume : public TransactionListener {
public:
Volume(fs_volume* volume);
~Volume();
status_t Mount(const char* device, uint32 flags);
status_t Unmount();
bool IsValidSuperBlock();
bool IsReadOnly() const
{ return (fFlags & VOLUME_READ_ONLY) != 0; }
mutex& Lock();
bool HasExtendedAttributes() const;
Inode* RootNode() const { return fRootNode; }
int Device() const { return fDevice; }
dev_t ID() const
{ return fFSVolume ? fFSVolume->id : -1; }
fs_volume* FSVolume() const { return fFSVolume; }
const char* Name() const;
void SetName(const char* name);
uint32 NumInodes() const
{ return fNumInodes; }
uint32 NumGroups() const
{ return fNumGroups; }
fsblock_t NumBlocks() const
{ return fSuperBlock.NumBlocks(
Has64bitFeature()); }
off_t NumFreeBlocks() const
{ return fFreeBlocks; }
uint32 FirstDataBlock() const
{ return fFirstDataBlock; }
uint32 BlockSize() const { return fBlockSize; }
uint32 BlockShift() const { return fBlockShift; }
uint32 BlocksPerGroup() const
{ return fSuperBlock.BlocksPerGroup(); }
uint32 InodeSize() const
{ return fSuperBlock.InodeSize(); }
uint32 InodesPerGroup() const
{ return fSuperBlock.InodesPerGroup(); }
ext2_super_block& SuperBlock() { return fSuperBlock; }
status_t GetInodeBlock(ino_t id, off_t& block);
uint32 InodeBlockIndex(ino_t id) const;
status_t GetBlockGroup(int32 index,
ext2_block_group** _group);
status_t WriteBlockGroup(Transaction& transaction,
int32 index);
Journal* GetJournal() { return fJournal; }
bool IndexedDirectories() const
{ return (fSuperBlock.CompatibleFeatures()
& EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
bool HasJournalFeature() const
{ return (fSuperBlock.CompatibleFeatures()
& EXT2_FEATURE_HAS_JOURNAL) != 0; }
bool Has64bitFeature() const
{ return (fSuperBlock.IncompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
bool HasExtentsFeature() const
{ return (fSuperBlock.IncompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_EXTENTS)
!= 0; }
bool HasChecksumFeature() const
{ return (fSuperBlock.ReadOnlyFeatures()
& EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; }
bool HasMetaGroupFeature() const
{ return (fSuperBlock.IncompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_META_GROUP)
!= 0; }
bool HasMetaGroupChecksumFeature() const
{ return (fSuperBlock.ReadOnlyFeatures()
& EXT4_READ_ONLY_FEATURE_METADATA_CSUM)
!= 0; }
bool HasChecksumSeedFeature() const
{ return (fSuperBlock.IncompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_CSUM_SEED)
!= 0; }
uint8 DefaultHashVersion() const
{ return fSuperBlock.default_hash_version; }
bool HugeFiles() const
{ return (fSuperBlock.ReadOnlyFeatures()
& EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; }
status_t ActivateLargeFiles(Transaction& transaction);
status_t ActivateDirNLink(Transaction& transaction);
status_t AllocateInode(Transaction& transaction,
Inode* parent, int32 mode, ino_t& id);
status_t FreeInode(Transaction& transaction, ino_t id,
bool isDirectory);
status_t AllocateBlocks(Transaction& transaction,
uint32 minimum, uint32 maximum,
uint32& blockGroup, fsblock_t& start,
uint32& length);
status_t FreeBlocks(Transaction& transaction,
fsblock_t start, uint32 length);
status_t LoadSuperBlock();
status_t WriteSuperBlock(Transaction& transaction);
void* BlockCache() { return fBlockCache; }
uint32 ChecksumSeed() const
{ return fChecksumSeed; }
uint16 GroupDescriptorSize() const
{ return fGroupDescriptorSize; }
status_t FlushDevice();
status_t Sync();
static status_t Identify(int fd, ext2_super_block* superBlock);
void TransactionDone(bool success);
void RemovedFromTransaction();
private:
static uint32 _UnsupportedIncompatibleFeatures(
ext2_super_block& superBlock);
static uint32 _UnsupportedReadOnlyFeatures(
ext2_super_block& superBlock);
uint32 _GroupDescriptorBlock(uint32 blockIndex);
uint16 _GroupCheckSum(ext2_block_group *group,
int32 index);
void _SuperBlockChecksumSeed();
bool _VerifySuperBlock();
private:
mutex fLock;
fs_volume* fFSVolume;
int fDevice;
ext2_super_block fSuperBlock;
BlockAllocator* fBlockAllocator;
InodeAllocator fInodeAllocator;
Journal* fJournal;
Inode* fJournalInode;
uint32 fFlags;
uint32 fBlockSize;
uint32 fBlockShift;
uint32 fFirstDataBlock;
uint32 fNumInodes;
uint32 fNumGroups;
off_t fFreeBlocks;
uint32 fFreeInodes;
uint32 fGroupsPerBlock;
uint8** fGroupBlocks;
uint32 fInodesPerBlock;
uint16 fGroupDescriptorSize;
void* fBlockCache;
Inode* fRootNode;
uint32 fChecksumSeed;
};
inline mutex&
Volume::Lock()
{
return fLock;
}
#endif